45 double time_wmo[
NTIME],
46 double lon_wmo[
NTIME],
47 double lat_wmo[
NTIME],
48 double wind_wmo[
NTIME],
49 double pres_wmo[
NTIME],
79 static char filter[
LEN], pertname[
LEN], set[
LEN];
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,
89 static int dimid, n, ncid, nobs[
NSTORM], varid;
91 static size_t nstorm, ntime;
95 ERRMSG(
"Give parameters: <ctl> <hurr.tab> <ibtracs.nc>"
96 " <pert1.nc> [<pert2.nc> ...]");
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);
116 printf(
"Read hurricane tracks: %s\n", argv[3]);
119 NC(nc_open(argv[3], NC_NOWRITE, &ncid));
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!");
132 NC(nc_inq_varid(ncid,
"numObs", &varid));
133 NC(nc_get_var_int(ncid, varid, nobs));
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);
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;
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;
163 for (
size_t istorm = 0; istorm < nstorm; istorm++) {
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];
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];
192 printf(
"Write hurricane data: %s\n", argv[2]);
193 if (!(out = fopen(argv[2],
"w")))
194 ERRMSG(
"Cannot create file!");
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");
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");
217 for (
int iarg = 4; iarg < argc; iarg++) {
221 if (!(in = fopen(argv[iarg],
"r")))
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]);
235 for (
size_t istorm = 0; istorm < nstorm; istorm++) {
238 for (
int itrack = 0; itrack < pert->
ntrack; itrack++) {
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)) {
255 cart2geo(xs, &z, &lonbest, &latbest);
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++) {
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]))
288 lonsat = pert->
lon[itrack2][ixtrack2];
292 while (lonstorm < 20)
294 if ((filter[0] ==
'e' || filter[0] ==
'E')
295 && lonsat < lonstorm)
297 if ((filter[0] ==
'w' || filter[0] ==
'W')
298 && lonsat > lonstorm)
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]);
313 if (fabs(pert->
lat[itrack][pert->
nxtrack / 2]) > 80.) {
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)) {
325 if (r2best < 890. * 890.) {
332 BRIGHT(
PLANCK(bt4_mean / n, nu) + nesr, nu) - bt4_mean / n;
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);
368 double time_wmo[
NTIME],
369 double lon_wmo[
NTIME],
370 double lat_wmo[
NTIME],
371 double wind_wmo[
NTIME],
372 double pres_wmo[
NTIME],
385 if (t < time_wmo[0] || t > time_wmo[nobs - 1])
390 double w = (t - time_wmo[i]) / (time_wmo[i + 1] - time_wmo[i]);
391 geo2cart(0, lon_wmo[i], lat_wmo[i], x0);
392 geo2cart(0, lon_wmo[i + 1], lat_wmo[i + 1], x1);
393 x[0] = (1 - w) * x0[0] + w * x1[0];
394 x[1] = (1 - w) * x0[1] + w * x1[1];
395 x[2] = (1 - w) * x0[2] + w * x1[2];
398 *pres = (1 - w) * pres_wmo[i] + w * pres_wmo[i + 1];
399 *wind = (1 - w) * wind_wmo[i] + w * wind_wmo[i + 1];
402 *dpres = (pres_wmo[i + 1 + st] - pres_wmo[GSL_MAX(i - dt + st, 0)])
403 / (time_wmo[i + 1 + st] - time_wmo[GSL_MAX(i - dt + st, 0)]) * 3600.;
404 *dwind = (wind_wmo[i + 1 + st] - wind_wmo[GSL_MAX(i - dt + st, 0)])
405 / (time_wmo[i + 1 + st] - time_wmo[GSL_MAX(i - dt + st, 0)]) * 3600.;
414 const char varname[],
421 size_t count[2], start[2];
424 NC(nc_inq_varid(ncid, varname, &varid));
425 for (
size_t istorm = 0; istorm < nstorm; istorm++) {
429 count[1] = (size_t) nobs[istorm];
430 NC(nc_get_vara_double(ncid, varid, start, count, x[istorm]));
#define NC(cmd)
Execute netCDF library command and check result.
int main(int argc, char *argv[])
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])
int locate_irr(const double *xx, const int n, const double x)
Find array index for irregular grid.
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.
void geo2cart(const double z, const double lon, const double lat, double *x)
Convert geolocation to Cartesian coordinates.
#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.
AIRS Code Collection library declarations.
#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].