agwx_biophys 0.0.1 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/agwx_biophys.gemspec +1 -0
- data/calccumdd.c +944 -0
- data/getstndd.c +186 -0
- data/lib/agwx_biophys.rb +2 -2
- data/lib/agwx_biophys/degree_days.rb +347 -0
- data/lib/agwx_biophys/et.rb +5 -0
- data/lib/agwx_biophys/version.rb +1 -1
- data/test/grids/WIMNTAvg2012 +8057 -0
- data/test/grids/WIMNTMax2012 +8057 -0
- data/test/grids/WIMNTMin2012 +8057 -0
- data/test/rect_dd_seq_2012.rb +105 -0
- data/test/test_dds.rb +96 -0
- metadata +29 -4
- data/test/test_et.rb +0 -232
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f5b7941c684dc65e3369705c68acec24a292ee9
|
4
|
+
data.tar.gz: b311a850c49cdd1ee4e2a54c92fdf3449355f535
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b582c22b9631410d8e3701f8fc90067759479cd5aa3e49462f5779d819435971a8d6e60b2a31da37155af13d6453abccf8497e3c2b05a8a9bbf816b32278b102
|
7
|
+
data.tar.gz: 24c2fa0c996dc09f659a30305824d01ca5f9959f4f3e9dadbd667e0b1cf9c27742b285554313a12e09ce7feebea71afad29cf02818d5d609c8d532e822644e49
|
data/.gitignore
CHANGED
data/agwx_biophys.gemspec
CHANGED
data/calccumdd.c
ADDED
@@ -0,0 +1,944 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include <math.h>
|
5
|
+
#include <unistd.h>
|
6
|
+
|
7
|
+
#include <awsdir.h>
|
8
|
+
#include <awstime.h>
|
9
|
+
#include <awserror.h>
|
10
|
+
#include <grid/grid.h>
|
11
|
+
|
12
|
+
|
13
|
+
#ifndef M_PI
|
14
|
+
# define M_PI 3.14159265358979323846
|
15
|
+
#endif
|
16
|
+
#ifndef M_PI_2
|
17
|
+
# define M_PI_2 1.57079632679489661923
|
18
|
+
#endif
|
19
|
+
#ifndef M_1_PI
|
20
|
+
# define M_1_PI 0.31830988618379067154
|
21
|
+
#endif
|
22
|
+
|
23
|
+
#ifndef O_RDWR
|
24
|
+
# define O_RDWR 0000002 /* Open for reading or writing */
|
25
|
+
# define O_CREAT 0000400 /* Open with file create (uses third open arg) */
|
26
|
+
#endif
|
27
|
+
|
28
|
+
#define VIEW_RADIUS 1.2
|
29
|
+
|
30
|
+
#define DD_MAX_TEMP 86.0
|
31
|
+
|
32
|
+
float RectDD (float TMin, float TMax, float BaseTemp);
|
33
|
+
float RectAvgDD (float TAvg, float BaseTemp);
|
34
|
+
float ModBaseDD (float TMin, float TMax, float BaseTemp);
|
35
|
+
float ModBaseNoMaxDD (float TMin, float TMax, float BaseTemp);
|
36
|
+
float SineDD (float TMin, float TMax, float BaseTemp);
|
37
|
+
float p (float t);
|
38
|
+
float PdayDD (float TMin, float TMax);
|
39
|
+
Grid *CalcCumDD (char *prefix, int StartDoy,
|
40
|
+
int EndDoy, int Year, int Method, float BaseTemp,
|
41
|
+
int Subset, float xLowSub, float xHighSub, float yLowSub,
|
42
|
+
float yHighSub);
|
43
|
+
|
44
|
+
/*-------------------------------------------------------------------------
|
45
|
+
RectDD()
|
46
|
+
*/
|
47
|
+
float
|
48
|
+
RectDD (float TMin, float TMax, float BaseTemp)
|
49
|
+
{
|
50
|
+
float dd;
|
51
|
+
dd = (TMin + TMax) / 2.0 - BaseTemp;
|
52
|
+
if (dd < 0.0)
|
53
|
+
{
|
54
|
+
dd = 0.0;
|
55
|
+
}
|
56
|
+
return dd;
|
57
|
+
}
|
58
|
+
|
59
|
+
/*-------------------------------------------------------------------------
|
60
|
+
RectAvgDD()
|
61
|
+
*/
|
62
|
+
float
|
63
|
+
RectAvgDD (float TAvg, float BaseTemp)
|
64
|
+
{
|
65
|
+
float dd;
|
66
|
+
dd = TAvg - BaseTemp;
|
67
|
+
if (dd < 0.0)
|
68
|
+
{
|
69
|
+
dd = 0.0;
|
70
|
+
}
|
71
|
+
return dd;
|
72
|
+
}
|
73
|
+
|
74
|
+
/*-------------------------------------------------------------------------
|
75
|
+
ModBaseDD()
|
76
|
+
*/
|
77
|
+
float
|
78
|
+
ModBaseDD (float TMin, float TMax, float BaseTemp)
|
79
|
+
{
|
80
|
+
if (TMin < BaseTemp)
|
81
|
+
TMin = BaseTemp;
|
82
|
+
if (TMax < BaseTemp)
|
83
|
+
TMax = BaseTemp;
|
84
|
+
if (TMin > DD_MAX_TEMP)
|
85
|
+
TMin = DD_MAX_TEMP;
|
86
|
+
if (TMax > DD_MAX_TEMP)
|
87
|
+
TMax = DD_MAX_TEMP;
|
88
|
+
|
89
|
+
return (TMin + TMax) / 2.0 - BaseTemp;
|
90
|
+
}
|
91
|
+
|
92
|
+
/*-------------------------------------------------------------------------
|
93
|
+
ModBaseNoMaxDD()
|
94
|
+
*/
|
95
|
+
float
|
96
|
+
ModBaseNoMaxDD (float TMin, float TMax, float BaseTemp)
|
97
|
+
{
|
98
|
+
if (TMin < BaseTemp)
|
99
|
+
TMin = BaseTemp;
|
100
|
+
if (TMax < BaseTemp)
|
101
|
+
TMax = BaseTemp;
|
102
|
+
|
103
|
+
return (TMin + TMax) / 2.0 - BaseTemp;
|
104
|
+
}
|
105
|
+
|
106
|
+
/*-------------------------------------------------------------------------
|
107
|
+
SineDD()
|
108
|
+
*/
|
109
|
+
float
|
110
|
+
SineDD (float TMin, float TMax, float BaseTemp)
|
111
|
+
{
|
112
|
+
float alpha;
|
113
|
+
float o1, o2;
|
114
|
+
float dd;
|
115
|
+
float avg;
|
116
|
+
|
117
|
+
/*-----------------------
|
118
|
+
* Source Degree-Days: The Calculation and Use
|
119
|
+
* of Heat Units in Pest management
|
120
|
+
*/
|
121
|
+
if (TMin > TMax)
|
122
|
+
{
|
123
|
+
RegErr ("CalcDayDD:SineDD:", "", "Tmin > Tmax");
|
124
|
+
return -9999999;
|
125
|
+
}
|
126
|
+
if (TMin >= DD_MAX_TEMP)
|
127
|
+
{
|
128
|
+
return DD_MAX_TEMP - BaseTemp;
|
129
|
+
}
|
130
|
+
if (TMax <= BaseTemp)
|
131
|
+
{
|
132
|
+
return 0;
|
133
|
+
}
|
134
|
+
if (TMax <= DD_MAX_TEMP && TMin >= BaseTemp)
|
135
|
+
{
|
136
|
+
return (TMax + TMin) / 2 - BaseTemp;
|
137
|
+
}
|
138
|
+
alpha = (TMax - TMin) / 2;
|
139
|
+
avg = (TMax + TMin) / 2;
|
140
|
+
|
141
|
+
if (TMax <= DD_MAX_TEMP && TMin < BaseTemp)
|
142
|
+
{
|
143
|
+
o1 = asin ((BaseTemp - avg) / alpha);
|
144
|
+
return M_1_PI * ((avg - BaseTemp) * (M_PI_2 - o1) + alpha * cos (o1));
|
145
|
+
}
|
146
|
+
if (TMax > DD_MAX_TEMP && TMin >= BaseTemp)
|
147
|
+
{
|
148
|
+
o2 = asin ((DD_MAX_TEMP - avg) / alpha);
|
149
|
+
return M_1_PI * ((avg - BaseTemp) * (o2 + M_1_PI) +
|
150
|
+
(DD_MAX_TEMP - BaseTemp) * (M_PI_2 - o2) -
|
151
|
+
alpha * cos (o2));
|
152
|
+
}
|
153
|
+
if (TMax > DD_MAX_TEMP && TMin < BaseTemp)
|
154
|
+
{
|
155
|
+
o1 = asin ((BaseTemp - avg) / alpha);
|
156
|
+
o2 = asin ((DD_MAX_TEMP - avg) / alpha);
|
157
|
+
return M_1_PI * ((avg - BaseTemp) * (o2 - o1) +
|
158
|
+
alpha * (cos (o1) - cos (o2)) + (DD_MAX_TEMP -
|
159
|
+
BaseTemp) * (M_PI_2 -
|
160
|
+
o2));
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
/*-------------------------------------------------------------------------
|
165
|
+
p()
|
166
|
+
Function needed to calculate p-days, page B-81 of the PCM manual
|
167
|
+
*/
|
168
|
+
float
|
169
|
+
p (float t)
|
170
|
+
{
|
171
|
+
t = (t - 32.) * 5. / 9.;
|
172
|
+
if (t < 7)
|
173
|
+
return 0.0;
|
174
|
+
if (t < 21)
|
175
|
+
return 10 * (1. - ((t - 21.) * (t - 21.)) / 196.);
|
176
|
+
if (t < 30)
|
177
|
+
return 10 * (1. - ((t - 21.) * (t - 21.)) / 81.);
|
178
|
+
return 0.0;
|
179
|
+
}
|
180
|
+
|
181
|
+
/*-------------------------------------------------------------------------
|
182
|
+
PdayDD()
|
183
|
+
P-day thermal time calculation
|
184
|
+
*/
|
185
|
+
float
|
186
|
+
PdayDD (float TMin, float TMax)
|
187
|
+
{
|
188
|
+
return (1. / 24.) * (5 * p (TMin) + 8 * p (2 * TMin / 3 + TMax / 3) +
|
189
|
+
8 * p (2 * TMax / 3 + TMin / 3) + 3 * p (TMax));
|
190
|
+
}
|
191
|
+
|
192
|
+
/*-------------------------------------------------------------------------
|
193
|
+
CalcCumDD()
|
194
|
+
Calculates cumulative DD between StartDoy & EndDoy using
|
195
|
+
Method and BaseTemp. Returns a grid with the cumDDs in
|
196
|
+
layer 1.
|
197
|
+
*/
|
198
|
+
Grid *
|
199
|
+
CalcCumDD (char *prefix, int StartDoy,
|
200
|
+
int EndDoy, int Year, int Method, float BaseTemp,
|
201
|
+
int Subset, float xLowSub, float xHighSub, float yLowSub,
|
202
|
+
float yHighSub)
|
203
|
+
{
|
204
|
+
|
205
|
+
char Sub[40];
|
206
|
+
|
207
|
+
char buf[255];
|
208
|
+
|
209
|
+
char TMinFileName[255];
|
210
|
+
char TMaxFileName[255];
|
211
|
+
char TAvgFileName[255];
|
212
|
+
char GradCtlFile[100];
|
213
|
+
char GradDatFile[100];
|
214
|
+
char GridTmpFile[100];
|
215
|
+
char Date[100];
|
216
|
+
int fd;
|
217
|
+
FILE *fhctl;
|
218
|
+
|
219
|
+
Grid *pTMinG = NULL;
|
220
|
+
Grid *pTMaxG = NULL;
|
221
|
+
Grid *pTAvgG = NULL;
|
222
|
+
Grid *pDDG = NULL;
|
223
|
+
GridCursor *pTMinGC = NULL;
|
224
|
+
GridCursor *pTMaxGC = NULL;
|
225
|
+
GridCursor *pTAvgGC = NULL;
|
226
|
+
GLayer *pDDL = NULL;
|
227
|
+
GLView *pGLV = NULL;
|
228
|
+
GLayer *pGL = NULL;
|
229
|
+
|
230
|
+
float TMin;
|
231
|
+
float TMax;
|
232
|
+
float TAvg;
|
233
|
+
int TMinErr;
|
234
|
+
int TMaxErr;
|
235
|
+
int TAvgErr;
|
236
|
+
float DD;
|
237
|
+
|
238
|
+
int doy;
|
239
|
+
int earlydoy;
|
240
|
+
|
241
|
+
int srcdoy;
|
242
|
+
int TMinDoy, TMaxDoy, TAvgDoy;
|
243
|
+
float xPos, yPos;
|
244
|
+
int xIdx, yIdx;
|
245
|
+
float Val;
|
246
|
+
int FoundMin;
|
247
|
+
int FoundMax;
|
248
|
+
int FoundAvg;
|
249
|
+
|
250
|
+
int xNo, yNo;
|
251
|
+
int xNoSave, yNoSave;
|
252
|
+
float xLow, xHigh, yLow, yHigh;
|
253
|
+
int xStrt, xEnd, yStrt, yEnd;
|
254
|
+
|
255
|
+
float xIncr, yIncr, zIncr;
|
256
|
+
int lStrt, lEnd;
|
257
|
+
float BadValue;
|
258
|
+
int mnth, day;
|
259
|
+
int DecPlace;
|
260
|
+
|
261
|
+
int x, y, l;
|
262
|
+
int i, j;
|
263
|
+
|
264
|
+
float **CumDD = NULL;
|
265
|
+
|
266
|
+
strcpy (Sub, "CalcCumDD");
|
267
|
+
|
268
|
+
|
269
|
+
|
270
|
+
/*-------------------------------
|
271
|
+
* Generate Temperature Grid File Names
|
272
|
+
*/
|
273
|
+
sprintf (TMinFileName, "%s/%sTMin%d", ASOS_GRID_DIR, prefix, Year);
|
274
|
+
sprintf (TMaxFileName, "%s/%sTMax%d", ASOS_GRID_DIR, prefix, Year);
|
275
|
+
sprintf (TAvgFileName, "%s/%sTAvg%d", ASOS_GRID_DIR, prefix, Year);
|
276
|
+
sprintf (GridTmpFile, "ddgrid.tmp");
|
277
|
+
|
278
|
+
/*------------------------------
|
279
|
+
* Load Grids and Create Cursors
|
280
|
+
*/
|
281
|
+
if ((pTMinG = LoadGrid (TMinFileName)) == NULL)
|
282
|
+
{
|
283
|
+
RegErr (Sub, TMinFileName, "Couldn't Load Grid File");
|
284
|
+
goto ERROR;
|
285
|
+
}
|
286
|
+
if ((pTMinGC = CreateGridCursor (pTMinG)) == NULL)
|
287
|
+
{
|
288
|
+
RegErr (Sub, TMinFileName, "Couldn't Load Grid Cursor");
|
289
|
+
goto ERROR;
|
290
|
+
}
|
291
|
+
|
292
|
+
if ((pTMaxG = LoadGrid (TMaxFileName)) == NULL)
|
293
|
+
{
|
294
|
+
RegErr (Sub, TMaxFileName, "Couldn't Load Grid File");
|
295
|
+
goto ERROR;
|
296
|
+
}
|
297
|
+
if ((pTMaxGC = CreateGridCursor (pTMaxG)) == NULL)
|
298
|
+
{
|
299
|
+
RegErr (Sub, TMaxFileName, "Couldn't Load Grid Cursor");
|
300
|
+
goto ERROR;
|
301
|
+
}
|
302
|
+
|
303
|
+
if ((pTAvgG = LoadGrid (TAvgFileName)) == NULL)
|
304
|
+
{
|
305
|
+
RegErr (Sub, TAvgFileName, "Couldn't Load Grid File");
|
306
|
+
goto ERROR;
|
307
|
+
}
|
308
|
+
if ((pTAvgGC = CreateGridCursor (pTAvgG)) == NULL)
|
309
|
+
{
|
310
|
+
RegErr (Sub, TAvgFileName, "Couldn't Load Grid Cursor");
|
311
|
+
goto ERROR;
|
312
|
+
}
|
313
|
+
|
314
|
+
|
315
|
+
/*---------------------------------------
|
316
|
+
* Get the Dimensions of the temp grids
|
317
|
+
* (from TMAX; TMIN had better be the same)
|
318
|
+
*/
|
319
|
+
xNo = GetGridXDim (pTMaxG);
|
320
|
+
yNo = GetGridYDim (pTMaxG);
|
321
|
+
xLow = GetGridXMin (pTMaxG);
|
322
|
+
xHigh = GetGridXMax (pTMaxG);
|
323
|
+
yLow = GetGridYMin (pTMaxG);
|
324
|
+
yHigh = GetGridYMax (pTMaxG);
|
325
|
+
lStrt = GetGridZMin (pTMaxG);
|
326
|
+
lEnd = GetGridZMax (pTMaxG);
|
327
|
+
xIncr = (xHigh - xLow) / (xNo - 1);
|
328
|
+
yIncr = (yHigh - yLow) / (yNo - 1);
|
329
|
+
BadValue = GetGridBadVal (pTMaxG);
|
330
|
+
DecPlace = GetGridDecPlace (pTMaxG);
|
331
|
+
xNoSave = xNo;
|
332
|
+
yNoSave = yNo;
|
333
|
+
|
334
|
+
/*---------------------------------------
|
335
|
+
* If this is a subset extraction then
|
336
|
+
* set limits.
|
337
|
+
*/
|
338
|
+
if (Subset == TRUE)
|
339
|
+
{
|
340
|
+
|
341
|
+
/*----------------------
|
342
|
+
* Check for ridiculous values
|
343
|
+
if (xLowSub >= xHighSub) {
|
344
|
+
printf("error xLowSub %f >= xHighSub Value %f\n",xLowSub,
|
345
|
+
xHighSub);
|
346
|
+
goto ERROR;
|
347
|
+
}
|
348
|
+
if (xLowSub > xHigh) {
|
349
|
+
printf("Bad xLowSub Value %f \n",xLowSub);
|
350
|
+
goto ERROR;
|
351
|
+
}
|
352
|
+
if (xHighSub < xLow) {
|
353
|
+
printf("Bad xHighSub Value %f \n",xHighSub);
|
354
|
+
goto ERROR;
|
355
|
+
}
|
356
|
+
|
357
|
+
if (yLowSub >= yHighSub) {
|
358
|
+
printf("error yLowSub %f >= yHighSub Value %f\n",yLowSub,
|
359
|
+
yHighSub);
|
360
|
+
goto ERROR;
|
361
|
+
}
|
362
|
+
if (yLowSub > yHigh) {
|
363
|
+
printf("Bad yLowSub Value %f \n",yLowSub);
|
364
|
+
goto ERROR;
|
365
|
+
}
|
366
|
+
if (yHighSub < yLow) {
|
367
|
+
printf("Bad yHighSub Value %f \n",yHighSub);
|
368
|
+
goto ERROR;
|
369
|
+
}
|
370
|
+
|
371
|
+
/*----------------------
|
372
|
+
* Set to limits if exceeded
|
373
|
+
*/
|
374
|
+
if (xLowSub < xLow)
|
375
|
+
xLowSub = xLow;
|
376
|
+
if (xHighSub > xHigh)
|
377
|
+
xHighSub = xHigh;
|
378
|
+
if (yLowSub < yLow)
|
379
|
+
yLowSub = yLow;
|
380
|
+
if (yHighSub > yHigh)
|
381
|
+
yHighSub = yHigh;
|
382
|
+
|
383
|
+
/*--------------------
|
384
|
+
* Find indices - All "rounding" is down when converting
|
385
|
+
* to integer. We check to see if it just (10% of the grid increment)
|
386
|
+
* misses a grid location
|
387
|
+
*
|
388
|
+
*/
|
389
|
+
xStrt = (xLowSub - xLow) / xIncr;
|
390
|
+
if (xLowSub - (xIncr * xStrt + xLow) > xIncr * 0.1)
|
391
|
+
xStrt++;
|
392
|
+
xEnd = (xHighSub - xLow) / xIncr;
|
393
|
+
if ((xIncr * (xEnd + 1) + xLow - xHighSub) < xIncr * 0.1)
|
394
|
+
xEnd++;
|
395
|
+
yStrt = (yLowSub - yLow) / yIncr;
|
396
|
+
if (yLowSub - (yIncr * yStrt + yLow) > yIncr * 0.1)
|
397
|
+
yStrt++;
|
398
|
+
yEnd = (yHighSub - yLow) / yIncr;
|
399
|
+
if ((yIncr * (yEnd + 1) + yLow - yHighSub) < yIncr * 0.1)
|
400
|
+
yEnd++;
|
401
|
+
/* printf("Actual Limits Are %f %f %f and %f\n"
|
402
|
+
,xStrt*xIncr+xLow,xEnd*xIncr+xLow
|
403
|
+
,yStrt*yIncr+yLow,yEnd*yIncr+yLow); */
|
404
|
+
xHigh = xEnd * xIncr + xLow;
|
405
|
+
xLow = xStrt * xIncr + xLow;
|
406
|
+
xNo = xEnd - xStrt + 1;
|
407
|
+
yHigh = yEnd * yIncr + yLow;
|
408
|
+
yLow = yStrt * yIncr + yLow;
|
409
|
+
yNo = yEnd - yStrt + 1;
|
410
|
+
|
411
|
+
}
|
412
|
+
else
|
413
|
+
{
|
414
|
+
xStrt = 0;
|
415
|
+
xEnd = xNo - 1;
|
416
|
+
yStrt = 0;
|
417
|
+
yEnd = yNo - 1;
|
418
|
+
}
|
419
|
+
|
420
|
+
/*---------------------------------------
|
421
|
+
* Allocate temporary CumDD Array.
|
422
|
+
*/
|
423
|
+
if ((CumDD = malloc (sizeof (float *) * xNoSave)) == NULL)
|
424
|
+
{
|
425
|
+
RegErr (Sub, "CumDD", AWSERR_MALLOC);
|
426
|
+
goto ERROR;
|
427
|
+
}
|
428
|
+
for (i = 0; i < xNoSave; i++)
|
429
|
+
{
|
430
|
+
CumDD[i] = NULL;
|
431
|
+
}
|
432
|
+
for (i = 0; i < xNoSave; i++)
|
433
|
+
{
|
434
|
+
if ((CumDD[i] = malloc (sizeof (float) * yNoSave)) == NULL)
|
435
|
+
{
|
436
|
+
RegErr (Sub, "CumDD sub", AWSERR_MALLOC);
|
437
|
+
goto ERROR;
|
438
|
+
}
|
439
|
+
for (j = 0; j < yNoSave; j++)
|
440
|
+
{
|
441
|
+
CumDD[i][j] = 0.0;
|
442
|
+
}
|
443
|
+
}
|
444
|
+
|
445
|
+
/*---------------------------------------
|
446
|
+
* Create the Output CumDD Grid with 1 layer.
|
447
|
+
*/
|
448
|
+
zIncr = 1;
|
449
|
+
if ((pDDG = CreateGrid (GridTmpFile, xLow, xHigh, xNo, yLow, yHigh, yNo,
|
450
|
+
zIncr, BadValue, DecPlace)) == NULL)
|
451
|
+
{
|
452
|
+
RegErr (Sub, "", "Creating Temporary Grid");
|
453
|
+
goto ERROR;
|
454
|
+
}
|
455
|
+
if ((pDDL = CreateGLayer (pDDG, 1)) == NULL)
|
456
|
+
{
|
457
|
+
RegErr (Sub, "", "Creating Temporary Grid Layer");
|
458
|
+
goto ERROR;
|
459
|
+
}
|
460
|
+
if ((AddGLayer (pDDG, pDDL, FALSE)) != AWS_OK)
|
461
|
+
{
|
462
|
+
RegErr (Sub, "", "Adding Temporary Grid Layer");
|
463
|
+
goto ERROR;
|
464
|
+
}
|
465
|
+
|
466
|
+
/*===========================================================
|
467
|
+
* THE MAIN LOOP. For Each Day in the DD Calculation Range
|
468
|
+
*/
|
469
|
+
|
470
|
+
for (doy = StartDoy; doy <= EndDoy; doy++)
|
471
|
+
{
|
472
|
+
|
473
|
+
/*----------------------------
|
474
|
+
* Set The Source TMin And TMax
|
475
|
+
* Cursors. If doy is not available
|
476
|
+
* Go back to doy-1 and onward to
|
477
|
+
* doy-5. If you go back past
|
478
|
+
* doy-5 then it is an error.
|
479
|
+
*/
|
480
|
+
TMinDoy = doy;
|
481
|
+
earlydoy = doy - 5;
|
482
|
+
if (earlydoy < 1)
|
483
|
+
earlydoy = 1;
|
484
|
+
|
485
|
+
while (SetGCLayer (pTMinGC, TMinDoy) != AWS_OK)
|
486
|
+
{
|
487
|
+
if (TMinDoy <= earlydoy)
|
488
|
+
{
|
489
|
+
sprintf (buf, "Can Not Find a Layer between %d and %d",
|
490
|
+
earlydoy, doy);
|
491
|
+
RegErr (Sub, TMinFileName, buf);
|
492
|
+
goto ERROR;
|
493
|
+
}
|
494
|
+
TMinDoy--;
|
495
|
+
}
|
496
|
+
|
497
|
+
TMaxDoy = doy;
|
498
|
+
earlydoy = doy - 5;
|
499
|
+
if (earlydoy < 1)
|
500
|
+
earlydoy = 1;
|
501
|
+
|
502
|
+
while (SetGCLayer (pTMaxGC, TMaxDoy) != AWS_OK)
|
503
|
+
{
|
504
|
+
if (TMaxDoy <= earlydoy)
|
505
|
+
{
|
506
|
+
sprintf (buf, "Can Not Find a Layer between %d and %d",
|
507
|
+
earlydoy, doy);
|
508
|
+
RegErr (Sub, TMaxFileName, buf);
|
509
|
+
goto ERROR;
|
510
|
+
}
|
511
|
+
TMaxDoy--;
|
512
|
+
}
|
513
|
+
|
514
|
+
TAvgDoy = doy;
|
515
|
+
earlydoy = doy - 5;
|
516
|
+
if (earlydoy < 1)
|
517
|
+
earlydoy = 1;
|
518
|
+
|
519
|
+
while (SetGCLayer (pTAvgGC, TAvgDoy) != AWS_OK)
|
520
|
+
{
|
521
|
+
if (TAvgDoy <= earlydoy)
|
522
|
+
{
|
523
|
+
sprintf (buf, "Can Not Find a Layer between %d and %d",
|
524
|
+
earlydoy, doy);
|
525
|
+
RegErr (Sub, TAvgFileName, buf);
|
526
|
+
goto ERROR;
|
527
|
+
}
|
528
|
+
TAvgDoy--;
|
529
|
+
}
|
530
|
+
|
531
|
+
/*-------------------------------------------------
|
532
|
+
* With Source Days Set Now Loop Through All Locations
|
533
|
+
* on the Grid Layer
|
534
|
+
*/
|
535
|
+
TMinErr = FirstGC (pTMinGC, &TMin);
|
536
|
+
TMaxErr = FirstGC (pTMaxGC, &TMax);
|
537
|
+
TAvgErr = FirstGC (pTAvgGC, &TAvg);
|
538
|
+
do
|
539
|
+
{
|
540
|
+
if (GetGCPos (pTMinGC, &xPos, &yPos) != AWS_OK)
|
541
|
+
{
|
542
|
+
RegErr (Sub, "", "Couldn't Get Position of the TMin Cursor");
|
543
|
+
goto ERROR;
|
544
|
+
}
|
545
|
+
|
546
|
+
/* Extract data only within requested limits */
|
547
|
+
if (GetGCPosIndex (pTMinGC, &xIdx, &yIdx) != AWS_OK)
|
548
|
+
{
|
549
|
+
RegErr (Sub, "",
|
550
|
+
"Couldn't Get Position Index of the TMin Cursor");
|
551
|
+
goto ERROR;
|
552
|
+
}
|
553
|
+
if (xIdx < xStrt || xIdx > xEnd || yIdx < yStrt || yIdx > yEnd)
|
554
|
+
{
|
555
|
+
continue;
|
556
|
+
}
|
557
|
+
|
558
|
+
/*----------------------
|
559
|
+
* If The Grid Position Has returned a bad value code
|
560
|
+
* we need to know if this an area that MICIS does not
|
561
|
+
* cover. We define that to be a location that has not had
|
562
|
+
* a value for 6 days. If a value at that location is
|
563
|
+
* found in the last 6 days then we take an average of the
|
564
|
+
* surounding area (defined by VIEW_RADIUS) if that returns a
|
565
|
+
* bad value, go to previous days. If you end up at the date
|
566
|
+
* of begining cumulation then Error.
|
567
|
+
*
|
568
|
+
* NOTE: the view area is a square. I use the term radius
|
569
|
+
* to suggest that the length is half way across.
|
570
|
+
*/
|
571
|
+
FoundMin = TRUE;
|
572
|
+
if (TMinErr != AWS_OK)
|
573
|
+
{
|
574
|
+
FoundMin = FALSE;
|
575
|
+
srcdoy = TMinDoy;
|
576
|
+
earlydoy = TMinDoy - 5;
|
577
|
+
if (earlydoy < 1)
|
578
|
+
earlydoy = 1;
|
579
|
+
for (srcdoy = TMinDoy; srcdoy >= earlydoy; srcdoy--)
|
580
|
+
{
|
581
|
+
if ((pGL = GetGLayer (pTMinG, srcdoy)) != NULL)
|
582
|
+
{
|
583
|
+
if (GetGLVal (pTMinG, pGL, xPos, yPos, &Val) == AWS_OK)
|
584
|
+
{
|
585
|
+
FoundMin = TRUE;
|
586
|
+
break;
|
587
|
+
}
|
588
|
+
}
|
589
|
+
}
|
590
|
+
}
|
591
|
+
if ((FoundMin == TRUE) && (TMinErr != AWS_OK))
|
592
|
+
{
|
593
|
+
srcdoy = TMinDoy;
|
594
|
+
while (TMinErr != AWS_OK)
|
595
|
+
{
|
596
|
+
if ((pGLV = CreateGLView (pTMinG, srcdoy,
|
597
|
+
xPos - VIEW_RADIUS,
|
598
|
+
xPos + VIEW_RADIUS,
|
599
|
+
yPos - VIEW_RADIUS,
|
600
|
+
yPos + VIEW_RADIUS)) != NULL)
|
601
|
+
{
|
602
|
+
if ((TMinErr = AverageGLV (pGLV, &TMin)) != AWS_OK)
|
603
|
+
{
|
604
|
+
if (srcdoy <= 1)
|
605
|
+
{
|
606
|
+
sprintf (buf,
|
607
|
+
"Couldn't get tmin value for x=%f y=%f between %d and %d",
|
608
|
+
xPos, yPos, 1, doy);
|
609
|
+
RegErr (Sub, "", buf);
|
610
|
+
goto ERROR;
|
611
|
+
}
|
612
|
+
}
|
613
|
+
}
|
614
|
+
srcdoy--;
|
615
|
+
}
|
616
|
+
}
|
617
|
+
if (FoundMin == FALSE)
|
618
|
+
{
|
619
|
+
/*--------------------------
|
620
|
+
* Found is False for locations
|
621
|
+
* where Micis does not have coverage.
|
622
|
+
* Set these locations ot the BadValue code.
|
623
|
+
*/
|
624
|
+
TMin = GetGridBadVal (pTMinG);
|
625
|
+
}
|
626
|
+
|
627
|
+
/*----------------------
|
628
|
+
* Now do the same for TMax if there
|
629
|
+
* was a problem.
|
630
|
+
*/
|
631
|
+
if (GetGCPos (pTMaxGC, &xPos, &yPos) != AWS_OK)
|
632
|
+
{
|
633
|
+
RegErr (Sub, "", "Couldn't Get Position for TMax Cursor");
|
634
|
+
goto ERROR;
|
635
|
+
}
|
636
|
+
FoundMax = TRUE;
|
637
|
+
if (TMaxErr != AWS_OK)
|
638
|
+
{
|
639
|
+
FoundMax = FALSE;
|
640
|
+
srcdoy = TMaxDoy;
|
641
|
+
earlydoy = TMaxDoy - 5;
|
642
|
+
if (earlydoy < 1)
|
643
|
+
earlydoy = 1;
|
644
|
+
for (srcdoy = TMaxDoy; srcdoy >= earlydoy; srcdoy--)
|
645
|
+
{
|
646
|
+
if ((pGL = GetGLayer (pTMaxG, srcdoy)) != NULL)
|
647
|
+
{
|
648
|
+
if (GetGLVal (pTMaxG, pGL, xPos, yPos, &Val) == AWS_OK)
|
649
|
+
{
|
650
|
+
FoundMax = TRUE;
|
651
|
+
break;
|
652
|
+
}
|
653
|
+
}
|
654
|
+
}
|
655
|
+
}
|
656
|
+
if ((FoundMax == TRUE) && (TMaxErr != AWS_OK))
|
657
|
+
{
|
658
|
+
srcdoy = TMaxDoy;
|
659
|
+
while (TMaxErr != AWS_OK)
|
660
|
+
{
|
661
|
+
if ((pGLV = CreateGLView (pTMaxG, srcdoy,
|
662
|
+
xPos - VIEW_RADIUS,
|
663
|
+
xPos + VIEW_RADIUS,
|
664
|
+
yPos - VIEW_RADIUS,
|
665
|
+
yPos + VIEW_RADIUS)) != NULL)
|
666
|
+
{
|
667
|
+
if ((TMaxErr = AverageGLV (pGLV, &TMax)) != AWS_OK)
|
668
|
+
{
|
669
|
+
if (srcdoy <= 1)
|
670
|
+
{
|
671
|
+
sprintf (buf,
|
672
|
+
"Couldn't get tmax value for x=%f y=%f between %d and %d",
|
673
|
+
xPos, yPos, 1, doy);
|
674
|
+
RegErr (Sub, "", buf);
|
675
|
+
goto ERROR;
|
676
|
+
}
|
677
|
+
}
|
678
|
+
}
|
679
|
+
srcdoy--;
|
680
|
+
}
|
681
|
+
}
|
682
|
+
if (FoundMax == FALSE)
|
683
|
+
{
|
684
|
+
/*--------------------------
|
685
|
+
* Found is False for locations
|
686
|
+
* where Micis does not have coverage.
|
687
|
+
* Set these locations ot the BadValue code.
|
688
|
+
*/
|
689
|
+
TMax = GetGridBadVal (pTMaxG);
|
690
|
+
}
|
691
|
+
/*----------------------
|
692
|
+
* Now do the same for TAvg if there
|
693
|
+
* was a problem.
|
694
|
+
*/
|
695
|
+
if (GetGCPos (pTAvgGC, &xPos, &yPos) != AWS_OK)
|
696
|
+
{
|
697
|
+
RegErr (Sub, "", "Couldn't Get Position for TAvg Cursor");
|
698
|
+
goto ERROR;
|
699
|
+
}
|
700
|
+
FoundAvg = TRUE;
|
701
|
+
if (TAvgErr != AWS_OK)
|
702
|
+
{
|
703
|
+
FoundAvg = FALSE;
|
704
|
+
srcdoy = TAvgDoy;
|
705
|
+
earlydoy = TAvgDoy - 5;
|
706
|
+
if (earlydoy < 1)
|
707
|
+
earlydoy = 1;
|
708
|
+
for (srcdoy = TAvgDoy; srcdoy >= earlydoy; srcdoy--)
|
709
|
+
{
|
710
|
+
if ((pGL = GetGLayer (pTAvgG, srcdoy)) != NULL)
|
711
|
+
{
|
712
|
+
if (GetGLVal (pTAvgG, pGL, xPos, yPos, &Val) == AWS_OK)
|
713
|
+
{
|
714
|
+
FoundAvg = TRUE;
|
715
|
+
break;
|
716
|
+
}
|
717
|
+
}
|
718
|
+
}
|
719
|
+
}
|
720
|
+
if ((FoundAvg == TRUE) && (TAvgErr != AWS_OK))
|
721
|
+
{
|
722
|
+
srcdoy = TAvgDoy;
|
723
|
+
while (TAvgErr != AWS_OK)
|
724
|
+
{
|
725
|
+
if ((pGLV = CreateGLView (pTAvgG, srcdoy,
|
726
|
+
xPos - VIEW_RADIUS,
|
727
|
+
xPos + VIEW_RADIUS,
|
728
|
+
yPos - VIEW_RADIUS,
|
729
|
+
yPos + VIEW_RADIUS)) != NULL)
|
730
|
+
{
|
731
|
+
if ((TAvgErr = AverageGLV (pGLV, &TAvg)) != AWS_OK)
|
732
|
+
{
|
733
|
+
if (srcdoy <= 1)
|
734
|
+
{
|
735
|
+
sprintf (buf,
|
736
|
+
"Couldn't get tmax value for x=%f y=%f between %d and %d",
|
737
|
+
xPos, yPos, 1, doy);
|
738
|
+
RegErr (Sub, "", buf);
|
739
|
+
goto ERROR;
|
740
|
+
}
|
741
|
+
}
|
742
|
+
}
|
743
|
+
srcdoy--;
|
744
|
+
}
|
745
|
+
}
|
746
|
+
if (FoundAvg == FALSE)
|
747
|
+
{
|
748
|
+
/*--------------------------
|
749
|
+
* Found is False for locations
|
750
|
+
* where Micis does not have coverage.
|
751
|
+
* Set these locations ot the BadValue code.
|
752
|
+
*/
|
753
|
+
TAvg = GetGridBadVal (pTAvgG);
|
754
|
+
}
|
755
|
+
|
756
|
+
if ((FoundMax == TRUE) && (FoundMin == TRUE) && (FoundAvg == TRUE))
|
757
|
+
{
|
758
|
+
/*-----------------------
|
759
|
+
* Convert from Celsius to Fahrenheit
|
760
|
+
*/
|
761
|
+
TMax = TMax * 1.8 + 32.0;
|
762
|
+
TMin = TMin * 1.8 + 32.0;
|
763
|
+
TAvg = TAvg * 1.8 + 32.0;
|
764
|
+
|
765
|
+
/*------------------------
|
766
|
+
* Some times the grids get
|
767
|
+
* weird and the max is less than the min.
|
768
|
+
*/
|
769
|
+
if (TMax < TMin)
|
770
|
+
{
|
771
|
+
Val = TMax;
|
772
|
+
TMax = TMin;
|
773
|
+
TMin = TMax;
|
774
|
+
|
775
|
+
}
|
776
|
+
/*-----------------------
|
777
|
+
* OK. Now we Have a Good
|
778
|
+
* TMin and TMax. Calculate DD
|
779
|
+
*/
|
780
|
+
switch (Method)
|
781
|
+
{
|
782
|
+
case GRD_DD_RECTANGULAR:
|
783
|
+
DD = RectDD (TMin, TMax, BaseTemp);
|
784
|
+
break;
|
785
|
+
case GRD_DD_RECT_AVG:
|
786
|
+
DD = RectAvgDD (TAvg, BaseTemp);
|
787
|
+
break;
|
788
|
+
case GRD_DD_SINE_WAVE:
|
789
|
+
DD = SineDD (TMin, TMax, BaseTemp);
|
790
|
+
break;
|
791
|
+
case GRD_DD_MODIFIED_BASE:
|
792
|
+
DD = ModBaseDD (TMin, TMax, BaseTemp);
|
793
|
+
break;
|
794
|
+
case GRD_DD_PDAY:
|
795
|
+
DD = PdayDD (TMin, TMax);
|
796
|
+
break;
|
797
|
+
case GRD_DD_MODIFIED_BASE_NOMAX:
|
798
|
+
DD = ModBaseNoMaxDD (TMin, TMax, BaseTemp);
|
799
|
+
break;
|
800
|
+
}
|
801
|
+
}
|
802
|
+
else
|
803
|
+
{
|
804
|
+
DD = BadValue;
|
805
|
+
}
|
806
|
+
|
807
|
+
/*------------------------
|
808
|
+
* Add DD to cumulative sum at that location
|
809
|
+
*/
|
810
|
+
|
811
|
+
if (DD != BadValue && CumDD[xIdx][yIdx] != BadValue)
|
812
|
+
{
|
813
|
+
CumDD[xIdx][yIdx] += DD;
|
814
|
+
}
|
815
|
+
else
|
816
|
+
{
|
817
|
+
CumDD[xIdx][yIdx] = BadValue;
|
818
|
+
}
|
819
|
+
|
820
|
+
}
|
821
|
+
while (((TMinErr = NextGC (pTMinGC, &TMin)) != AWS_ENDOFSTREAM)
|
822
|
+
&& ((TMaxErr = NextGC (pTMaxGC, &TMax)) != AWS_ENDOFSTREAM)
|
823
|
+
&& ((TAvgErr = NextGC (pTAvgGC, &TAvg)) != AWS_ENDOFSTREAM));
|
824
|
+
|
825
|
+
}
|
826
|
+
/*
|
827
|
+
* END OF DOY LOOP
|
828
|
+
*============================================================*/
|
829
|
+
|
830
|
+
/*-------------------------
|
831
|
+
Enter CumDD data into grid,
|
832
|
+
which may be a subset of the temp grids
|
833
|
+
*/
|
834
|
+
yIdx = 0;
|
835
|
+
for (y = yStrt; y <= yEnd; y++)
|
836
|
+
{
|
837
|
+
xIdx = 0;
|
838
|
+
for (x = xStrt; x <= xEnd; x++)
|
839
|
+
{
|
840
|
+
if (PutGLValByIndex (pDDG, pDDL, xIdx, yIdx, CumDD[x][y]) != AWS_OK)
|
841
|
+
{
|
842
|
+
RegErr (Sub, "Error filling temporary CumDD grid", buf);
|
843
|
+
goto ERROR;
|
844
|
+
}
|
845
|
+
xIdx++;
|
846
|
+
}
|
847
|
+
yIdx++;
|
848
|
+
}
|
849
|
+
|
850
|
+
/*---------------------------
|
851
|
+
* Clean Up And Leave
|
852
|
+
*/
|
853
|
+
|
854
|
+
if (pTMinG != NULL)
|
855
|
+
{
|
856
|
+
CloseGrid (pTMinG);
|
857
|
+
free (pTMinG);
|
858
|
+
pTMinG = NULL;
|
859
|
+
}
|
860
|
+
if (pTMaxG != NULL)
|
861
|
+
{
|
862
|
+
CloseGrid (pTMaxG);
|
863
|
+
free (pTMaxG);
|
864
|
+
pTMaxG = NULL;
|
865
|
+
}
|
866
|
+
if (pTAvgG != NULL)
|
867
|
+
{
|
868
|
+
CloseGrid (pTAvgG);
|
869
|
+
free (pTAvgG);
|
870
|
+
pTAvgG = NULL;
|
871
|
+
}
|
872
|
+
if (pTMinGC != NULL)
|
873
|
+
{
|
874
|
+
free (pTMinGC);
|
875
|
+
pTMinGC == NULL;
|
876
|
+
}
|
877
|
+
if (pTMaxGC != NULL)
|
878
|
+
{
|
879
|
+
free (pTMaxGC);
|
880
|
+
pTMaxGC == NULL;
|
881
|
+
}
|
882
|
+
if (pTAvgGC != NULL)
|
883
|
+
{
|
884
|
+
free (pTAvgGC);
|
885
|
+
pTAvgGC == NULL;
|
886
|
+
}
|
887
|
+
|
888
|
+
if (CumDD != NULL)
|
889
|
+
{
|
890
|
+
for (i = 0; i < xNoSave; i++)
|
891
|
+
{
|
892
|
+
free (CumDD[i]);
|
893
|
+
}
|
894
|
+
free (CumDD);
|
895
|
+
}
|
896
|
+
|
897
|
+
return pDDG;
|
898
|
+
|
899
|
+
ERROR:
|
900
|
+
if (pTMinG != NULL)
|
901
|
+
{
|
902
|
+
ClearGrid (pTMinG);
|
903
|
+
free (pTMinG);
|
904
|
+
pTMinG = NULL;
|
905
|
+
}
|
906
|
+
if (pTMaxG != NULL)
|
907
|
+
{
|
908
|
+
ClearGrid (pTMaxG);
|
909
|
+
free (pTMaxG);
|
910
|
+
pTMaxG = NULL;
|
911
|
+
}
|
912
|
+
if (pTAvgG != NULL)
|
913
|
+
{
|
914
|
+
ClearGrid (pTAvgG);
|
915
|
+
free (pTAvgG);
|
916
|
+
pTAvgG = NULL;
|
917
|
+
}
|
918
|
+
if (pTMinGC != NULL)
|
919
|
+
{
|
920
|
+
free (pTMinGC);
|
921
|
+
pTMinGC == NULL;
|
922
|
+
}
|
923
|
+
if (pTMaxGC != NULL)
|
924
|
+
{
|
925
|
+
free (pTMaxGC);
|
926
|
+
pTMaxGC == NULL;
|
927
|
+
}
|
928
|
+
if (pTAvgGC != NULL)
|
929
|
+
{
|
930
|
+
free (pTAvgGC);
|
931
|
+
pTAvgGC == NULL;
|
932
|
+
}
|
933
|
+
|
934
|
+
if (CumDD != NULL)
|
935
|
+
{
|
936
|
+
for (i = 0; i < xNoSave; i++)
|
937
|
+
{
|
938
|
+
free (CumDD[i]);
|
939
|
+
}
|
940
|
+
free (CumDD);
|
941
|
+
}
|
942
|
+
|
943
|
+
return NULL;
|
944
|
+
}
|