73 {
74
76
77 static FILE *out;
78
79 static char filter[
LEN], pertname[
LEN], set[
LEN];
80
81 static double bt4_mean, bt4_var, bt8_min, dpres, dpresbest, dwind,
83 lonbest, lonsat, lonstorm, nedt, pres_wmo[
NSTORM][
NTIME],
84 pres, presbest, r2best = 1e100, wind_wmo[
NSTORM][
NTIME], wind,
87 xs[3], z;
88
89 static int dimid, n, ncid, nobs[
NSTORM], varid;
90
91 static size_t nstorm, ntime;
92
93
94 if (argc < 5)
95 ERRMSG(
"Give parameters: <ctl> <hurr.tab> <ibtracs.nc>"
96 " <pert1.nc> [<pert2.nc> ...]");
97
98
99 scan_ctl(argc, argv,
"SET", -1,
"full", set);
100 scan_ctl(argc, argv,
"PERTNAME", -1,
"4mu", pertname);
101 scan_ctl(argc, argv,
"FILTER", -1,
"both", filter);
102 const double dt230 =
scan_ctl(argc, argv,
"DT230", -1,
"0.16", NULL);
103 const double nu =
scan_ctl(argc, argv,
"NU", -1,
"2345.0", NULL);
104 const double rmax =
scan_ctl(argc, argv,
"RMAX", -1,
"500", NULL);
105 const int dt = (int)
scan_ctl(argc, argv,
"DT", -1,
"0", NULL);
106 const int st = (int)
scan_ctl(argc, argv,
"ST", -1,
"0", NULL);
107
108
110
111
112
113
114
115
116 printf("Read hurricane tracks: %s\n", argv[3]);
117
118
119 NC(nc_open(argv[3], NC_NOWRITE, &ncid));
120
121
122 NC(nc_inq_dimid(ncid,
"storm", &dimid));
123 NC(nc_inq_dimlen(ncid, dimid, &nstorm));
124 NC(nc_inq_dimid(ncid,
"time", &dimid));
125 NC(nc_inq_dimlen(ncid, dimid, &ntime));
127 ERRMSG(
"Too many storms!");
129 ERRMSG(
"Too many time steps!");
130
131
132 NC(nc_inq_varid(ncid,
"numObs", &varid));
133 NC(nc_get_var_int(ncid, varid, nobs));
134
135
136 read_var(ncid,
"lat_wmo", nstorm, nobs, lat_wmo);
137 read_var(ncid,
"lon_wmo", nstorm, nobs, lon_wmo);
138 read_var(ncid,
"time_wmo", nstorm, nobs, time_wmo);
139 read_var(ncid,
"wind_wmo", nstorm, nobs, wind_wmo);
140 read_var(ncid,
"pres_wmo", nstorm, nobs, pres_wmo);
141
142
143 for (size_t istorm = 0; istorm < nstorm; istorm++)
144 for (int iobs = 0; iobs < nobs[istorm]; iobs++) {
145 time_wmo[istorm][iobs] *= 86400.;
146 time_wmo[istorm][iobs] -= 4453401600.00;
147 lon_wmo[istorm][iobs] *= 0.01;
148 lat_wmo[istorm][iobs] *= 0.01;
149 wind_wmo[istorm][iobs] *= 0.0514444;
150 pres_wmo[istorm][iobs] *= 0.1;
151 }
152
153
154 for (size_t istorm = 0; istorm < nstorm; istorm++)
155 for (int iobs = 0; iobs < nobs[istorm]; iobs++) {
156 if (pres_wmo[istorm][iobs] <= 800 || pres_wmo[istorm][iobs] >= 1200)
157 pres_wmo[istorm][iobs] = GSL_NAN;
158 if (wind_wmo[istorm][iobs] <= 0.1)
159 wind_wmo[istorm][iobs] = GSL_NAN;
160 }
161
162
163 for (size_t istorm = 0; istorm < nstorm; istorm++) {
164 double pmin = 1e100;
165 time_max_pres[istorm] = GSL_NAN;
166 for (int iobs = 0; iobs < nobs[istorm]; iobs++)
167 if (gsl_finite(pres_wmo[istorm][iobs]) && pres_wmo[istorm][iobs] < pmin) {
168 pmin = pres_wmo[istorm][iobs];
169 time_max_pres[istorm] = time_wmo[istorm][iobs];
170 }
171 }
172
173
174 for (size_t istorm = 0; istorm < nstorm; istorm++) {
175 double wmax = -1e100;
176 time_max_wind[istorm] = GSL_NAN;
177 for (int iobs = 0; iobs < nobs[istorm]; iobs++)
178 if (gsl_finite(wind_wmo[istorm][iobs]) && wind_wmo[istorm][iobs] > wmax) {
179 wmax = wind_wmo[istorm][iobs];
180 time_max_wind[istorm] = time_wmo[istorm][iobs];
181 }
182 }
183
184
186
187
188
189
190
191
192 printf("Write hurricane data: %s\n", argv[2]);
193 if (!(out = fopen(argv[2], "w")))
194 ERRMSG(
"Cannot create file!");
195
196
197 fprintf(out,
198 "# $1 = storm number\n"
199 "# $2 = storm time since first report [hr]\n"
200 "# $3 = storm time since wind maximum [hr]\n"
201 "# $4 = storm time since pressure minimum [hr]\n"
202 "# $5 = match time [s]\n"
203 "# $6 = match longitude [deg]\n"
204 "# $7 = match latitude [deg]\n"
205 "# $8 = match distance [km]\n"
206 "# $9 = wind speed [m/s]\n"
207 "# $10 = wind speed change [m/s/hr]\n");
208 fprintf(out,
209 "# $11 = pressure [hPa]\n"
210 "# $12 = pressure change [hPa/hr]\n"
211 "# $13 = 8.1 micron BT minimum [K]\n"
212 "# $14 = 4.3 micron BT variance [K^2]\n"
213 "# $15 = 4.3 micron BT variance (noise-corrected) [K^2]\n"
214 "# $16 = number of footprints\n\n");
215
216
217 for (int iarg = 4; iarg < argc; iarg++) {
218
219
220 FILE *in;
221 if (!(in = fopen(argv[iarg], "r")))
222 continue;
223 else {
224 fclose(in);
226 }
227
228
229 for (
int itrack2 = 0; itrack2 < pert->
ntrack; itrack2++)
230 for (
int ixtrack2 = 0; ixtrack2 < pert->
nxtrack; ixtrack2++)
232 pert->
lat[itrack2][ixtrack2], xf[itrack2][ixtrack2]);
233
234
235 for (size_t istorm = 0; istorm < nstorm; istorm++) {
236
237
238 for (
int itrack = 0; itrack < pert->
ntrack; itrack++) {
239
240
241 if (
get_storm_pos(nobs[istorm], time_wmo[istorm], lon_wmo[istorm],
242 lat_wmo[istorm], wind_wmo[istorm], pres_wmo[istorm],
244 &wind, &dwind, &pres, &dpres)) {
245
246
248
249
250 if (r2 < r2best) {
251
252
253 r2best = r2;
255 cart2geo(xs, &z, &lonbest, &latbest);
256
257
258 windbest = wind;
259 dwindbest = dwind;
260 presbest = pres;
261 dpresbest = dpres;
262
263
264 n = 0;
265 bt8_min = 1e100;
266 bt4_mean = 0;
267 bt4_var = 0;
268 for (int itrack2 = GSL_MAX(itrack - ((int)(rmax / 17) + 1), 0);
269 itrack2 <= GSL_MIN(itrack + ((int) (rmax / 17) + 1),
270 pert->
ntrack - 1); itrack2++)
271 for (
int ixtrack2 = 0; ixtrack2 < pert->
nxtrack; ixtrack2++) {
272
273
274 if (pert->
time[itrack2][ixtrack2] < 0
275 || pert->
lon[itrack2][ixtrack2] < -180
276 || pert->
lon[itrack2][ixtrack2] > 180
277 || pert->
lat[itrack2][ixtrack2] < -90
278 || pert->
lat[itrack2][ixtrack2] > 90
279 || pert->
pt[itrack2][ixtrack2] < -100
280 || pert->
pt[itrack2][ixtrack2] > 100
281 || !gsl_finite(pert->
bt[itrack2][ixtrack2])
282 || !gsl_finite(pert->
pt[itrack2][ixtrack2])
283 || !gsl_finite(pert->
var[itrack2][ixtrack2])
284 || !gsl_finite(pert->
dc[itrack2][ixtrack2]))
285 continue;
286
287
288 lonsat = pert->
lon[itrack2][ixtrack2];
289 while (lonsat < 20)
290 lonsat += 360;
291 lonstorm = lonbest;
292 while (lonstorm < 20)
293 lonstorm += 360;
294 if ((filter[0] == 'e' || filter[0] == 'E')
295 && lonsat < lonstorm)
296 continue;
297 if ((filter[0] == 'w' || filter[0] == 'W')
298 && lonsat > lonstorm)
299 continue;
300
301
302 if (
DIST2(xs, xf[itrack2][ixtrack2]) < rmax * rmax) {
303 bt8_min = GSL_MIN(bt8_min, pert->
dc[itrack2][ixtrack2]);
304 bt4_mean += pert->
bt[itrack2][ixtrack2];
305 bt4_var += gsl_pow_2(pert->
pt[itrack2][ixtrack2]);
306 n++;
307 }
308 }
309 }
310 }
311
312
313 if (fabs(pert->
lat[itrack][pert->
nxtrack / 2]) > 80.) {
314
315
316 const int asc =
317 (pert->
lat[itrack > 0 ? itrack : itrack + 1][pert->
nxtrack / 2]
319 0 ? itrack - 1 : itrack][pert->
nxtrack / 2]);
320 if ((set[0] == 'f' || set[0] == 'F')
321 || ((set[0] == 'a' || set[0] == 'A') && asc)
322 || ((set[0] == 'd' || set[0] == 'D') && !asc)) {
323
324
325 if (r2best < 890. * 890.) {
326
327
328 if (dt230 > 0) {
329 const double nesr =
331 nedt =
332 BRIGHT(
PLANCK(bt4_mean / n, nu) + nesr, nu) - bt4_mean / n;
333 }
334
335
336 if (n > 0)
337 fprintf(out,
338 "%lu %g %g %g %.2f %g %g %g %g %g %g %g %g %g %g %d\n",
339 istorm, (timebest - time_wmo[istorm][0]) / 3600.,
340 (timebest - time_max_wind[istorm]) / 3600.,
341 (timebest - time_max_pres[istorm]) / 3600.,
342 timebest, lonbest, latbest, sqrt(r2best), windbest,
343 dwindbest, presbest, dpresbest, bt8_min, bt4_var / n,
344 bt4_var / n - gsl_pow_2(nedt), n);
345 }
346 }
347
348
349 r2best = 1e100;
350 }
351 }
352 }
353 }
354
355
356 fclose(out);
357
358
359 free(pert);
360
361 return EXIT_SUCCESS;
362}
int get_storm_pos(int nobs, double time_wmo[NTIME], double lon_wmo[NTIME], double lat_wmo[NTIME], double wind_wmo[NTIME], double pres_wmo[NTIME], double t, int dt, int st, double x[3], double *wind, double *dwind, double *pres, double *dpres)
void read_var(int ncid, const char varname[], size_t nstorm, int nobs[NSTORM], double x[NSTORM][NTIME])
void cart2geo(const double *x, double *z, double *lon, double *lat)
Convert Cartesian coordinates to geolocation.
double scan_ctl(int argc, char *argv[], const char *varname, int arridx, const char *defvalue, char *value)
Search control parameter file for variable entry.
#define LEN
Maximum length of ASCII data lines.
#define BRIGHT(rad, nu)
Compute brightness temperature.
#define ERRMSG(...)
Print error message and quit program.
#define ALLOC(ptr, type, n)
Allocate memory.
#define PLANCK(T, nu)
Compute Planck function.
#define DIST2(a, b)
Compute squared distance between two vectors.
void read_pert(char *filename, char *pertname, pert_t *pert)
Read radiance perturbation data.
#define PERT_NXTRACK
Across-track size of perturbation data.
#define PERT_NTRACK
Along-track size of perturbation data.
double var[PERT_NTRACK][PERT_NXTRACK]
Brightness temperature variance (4 or 15 micron) [K].
double pt[PERT_NTRACK][PERT_NXTRACK]
Brightness temperature perturbation (4 or 15 micron) [K].
double time[PERT_NTRACK][PERT_NXTRACK]
Time (seconds since 2000-01-01T00:00Z).
double dc[PERT_NTRACK][PERT_NXTRACK]
Brightness temperature (8 micron) [K].
int ntrack
Number of along-track values.
int nxtrack
Number of across-track values.
double lon[PERT_NTRACK][PERT_NXTRACK]
Longitude [deg].
double bt[PERT_NTRACK][PERT_NXTRACK]
Brightness temperature (4 or 15 micron) [K].
double lat[PERT_NTRACK][PERT_NXTRACK]
Latitude [deg].