45 atm_t *atm, *atm_filt;
49 double latm, lonm, t, t0 = NAN, qm[
NQ], *work, zm, *zs;
66 ERRMSG(
"Missing or invalid command-line arguments.\n\n"
67 "Usage: atm_stat <ctl> <stat.tab> <param> <atm1> [<atm2> ...]\n\n"
68 "Use -h for full help.");
73 (int)
scan_ctl(argv[1], argc, argv,
"STAT_ENS", -1,
"-999", NULL);
75 P(
scan_ctl(argv[1], argc, argv,
"STAT_Z0", -1,
"-1000", NULL));
77 P(
scan_ctl(argv[1], argc, argv,
"STAT_Z1", -1,
"1000", NULL));
79 scan_ctl(argv[1], argc, argv,
"STAT_LAT0", -1,
"-1000", NULL);
81 scan_ctl(argv[1], argc, argv,
"STAT_LAT1", -1,
"1000", NULL);
83 scan_ctl(argv[1], argc, argv,
"STAT_LON0", -1,
"-1000", NULL);
85 scan_ctl(argv[1], argc, argv,
"STAT_LON1", -1,
"1000", NULL);
88 LOG(1,
"Write air parcel statistics: %s", argv[2]);
91 if (!(out = fopen(argv[2],
"w")))
92 ERRMSG(
"Cannot create file!");
97 "# $2 = time difference [s]\n"
98 "# $3 = altitude (%s) [km]\n"
99 "# $4 = longitude (%s) [deg]\n"
100 "# $5 = latitude (%s) [deg]\n", argv[3], argv[3], argv[3]);
101 for (
int iq = 0; iq < ctl.
nq; iq++)
102 fprintf(out,
"# $%d = %s (%s) [%s]\n", iq + 6,
104 fprintf(out,
"# $%d = number of particles\n\n", ctl.
nq + 6);
107 for (
int f = 4; f < argc; f++) {
124 for (
int ip = 0; ip < atm->
np; ip++) {
127 if (!isfinite(atm->
time[ip]))
135 if (atm->
p[ip] > p0 || atm->
p[ip] < p1
136 || atm->
lon[ip] < lon0 || atm->
lon[ip] > lon1
137 || atm->
lat[ip] < lat0 || atm->
lat[ip] > lat1)
142 atm_filt->
p[atm_filt->
np] = atm->
p[ip];
143 atm_filt->
lon[atm_filt->
np] = atm->
lon[ip];
144 atm_filt->
lat[atm_filt->
np] = atm->
lat[ip];
145 for (
int iq = 0; iq < ctl.
nq; iq++)
146 atm_filt->
q[iq][atm_filt->
np] = atm->
q[iq][ip];
151 for (
int ip = 0; ip < atm_filt->
np; ip++)
152 zs[ip] =
Z(atm_filt->
p[ip]);
155 if (strcasecmp(argv[3],
"mean") == 0) {
156 zm = gsl_stats_mean(zs, 1, (
size_t) atm_filt->
np);
157 lonm = gsl_stats_mean(atm_filt->
lon, 1, (
size_t) atm_filt->
np);
158 latm = gsl_stats_mean(atm_filt->
lat, 1, (
size_t) atm_filt->
np);
159 for (
int iq = 0; iq < ctl.
nq; iq++)
160 qm[iq] = gsl_stats_mean(atm_filt->
q[iq], 1, (
size_t) atm_filt->
np);
161 }
else if (strcasecmp(argv[3],
"stddev") == 0) {
162 zm = gsl_stats_sd(zs, 1, (
size_t) atm_filt->
np);
163 lonm = gsl_stats_sd(atm_filt->
lon, 1, (
size_t) atm_filt->
np);
164 latm = gsl_stats_sd(atm_filt->
lat, 1, (
size_t) atm_filt->
np);
165 for (
int iq = 0; iq < ctl.
nq; iq++)
166 qm[iq] = gsl_stats_sd(atm_filt->
q[iq], 1, (
size_t) atm_filt->
np);
167 }
else if (strcasecmp(argv[3],
"min") == 0) {
168 zm = gsl_stats_min(zs, 1, (
size_t) atm_filt->
np);
169 lonm = gsl_stats_min(atm_filt->
lon, 1, (
size_t) atm_filt->
np);
170 latm = gsl_stats_min(atm_filt->
lat, 1, (
size_t) atm_filt->
np);
171 for (
int iq = 0; iq < ctl.
nq; iq++)
172 qm[iq] = gsl_stats_min(atm_filt->
q[iq], 1, (
size_t) atm_filt->
np);
173 }
else if (strcasecmp(argv[3],
"max") == 0) {
174 zm = gsl_stats_max(zs, 1, (
size_t) atm_filt->
np);
175 lonm = gsl_stats_max(atm_filt->
lon, 1, (
size_t) atm_filt->
np);
176 latm = gsl_stats_max(atm_filt->
lat, 1, (
size_t) atm_filt->
np);
177 for (
int iq = 0; iq < ctl.
nq; iq++)
178 qm[iq] = gsl_stats_max(atm_filt->
q[iq], 1, (
size_t) atm_filt->
np);
179 }
else if (strcasecmp(argv[3],
"skew") == 0) {
180 zm = gsl_stats_skew(zs, 1, (
size_t) atm_filt->
np);
181 lonm = gsl_stats_skew(atm_filt->
lon, 1, (
size_t) atm_filt->
np);
182 latm = gsl_stats_skew(atm_filt->
lat, 1, (
size_t) atm_filt->
np);
183 for (
int iq = 0; iq < ctl.
nq; iq++)
184 qm[iq] = gsl_stats_skew(atm_filt->
q[iq], 1, (
size_t) atm_filt->
np);
185 }
else if (strcasecmp(argv[3],
"kurt") == 0) {
186 zm = gsl_stats_kurtosis(zs, 1, (
size_t) atm_filt->
np);
187 lonm = gsl_stats_kurtosis(atm_filt->
lon, 1, (
size_t) atm_filt->
np);
188 latm = gsl_stats_kurtosis(atm_filt->
lat, 1, (
size_t) atm_filt->
np);
189 for (
int iq = 0; iq < ctl.
nq; iq++)
191 gsl_stats_kurtosis(atm_filt->
q[iq], 1, (
size_t) atm_filt->
np);
192 }
else if (strcasecmp(argv[3],
"median") == 0) {
193 zm = gsl_stats_median(zs, 1, (
size_t) atm_filt->
np);
194 lonm = gsl_stats_median(atm_filt->
lon, 1, (
size_t) atm_filt->
np);
195 latm = gsl_stats_median(atm_filt->
lat, 1, (
size_t) atm_filt->
np);
196 for (
int iq = 0; iq < ctl.
nq; iq++)
197 qm[iq] = gsl_stats_median(atm_filt->
q[iq], 1, (
size_t) atm_filt->
np);
198 }
else if (strcasecmp(argv[3],
"absdev") == 0) {
199 zm = gsl_stats_absdev(zs, 1, (
size_t) atm_filt->
np);
200 lonm = gsl_stats_absdev(atm_filt->
lon, 1, (
size_t) atm_filt->
np);
201 latm = gsl_stats_absdev(atm_filt->
lat, 1, (
size_t) atm_filt->
np);
202 for (
int iq = 0; iq < ctl.
nq; iq++)
203 qm[iq] = gsl_stats_absdev(atm_filt->
q[iq], 1, (
size_t) atm_filt->
np);
204 }
else if (strcasecmp(argv[3],
"mad") == 0) {
205 zm = gsl_stats_mad0(zs, 1, (
size_t) atm_filt->
np, work);
206 lonm = gsl_stats_mad0(atm_filt->
lon, 1, (
size_t) atm_filt->
np, work);
207 latm = gsl_stats_mad0(atm_filt->
lat, 1, (
size_t) atm_filt->
np, work);
208 for (
int iq = 0; iq < ctl.
nq; iq++)
210 gsl_stats_mad0(atm_filt->
q[iq], 1, (
size_t) atm_filt->
np, work);
212 ERRMSG(
"Unknown parameter!");
215 fprintf(out,
"%.2f %.2f %g %g %g", t, t - t0, zm, lonm, latm);
216 for (
int iq = 0; iq < ctl.
nq; iq++) {
220 fprintf(out,
" %d\n", atm_filt->
np);
241 printf(
"\nMPTRAC atm_stat tool.\n\n");
242 printf(
"Calculate air parcel statistics.\n");
245 printf(
" atm_stat <ctl> <stat.tab> <param> <atm1> [<atm2> ...]\n");
247 printf(
"Arguments:\n");
248 printf(
" <ctl> Control file.\n");
249 printf(
" <stat.tab> Output table.\n");
251 (
" <param> Statistic: mean, stddev, min, max, skew, kurt, absdev,\n");
252 printf(
" median, or mad.\n");
253 printf(
" <atm*> Atmospheric input files.\n");
254 printf(
"\nFurther information:\n");
255 printf(
" Manual: https://slcs-jsc.github.io/mptrac/\n");
int main(int argc, char *argv[])
void usage(void)
Print command-line help.
double scan_ctl(const char *filename, int argc, char *argv[], const char *varname, const int arridx, const char *defvalue, char *value)
Scans a control file or command-line arguments for a specified variable.
double time_from_filename(const char *filename, const int offset)
Extracts and converts a timestamp from a filename to Julian seconds.
int mptrac_read_atm(const char *filename, const ctl_t *ctl, atm_t *atm)
Reads air parcel data from a specified file into the given atmospheric structure.
void mptrac_read_ctl(const char *filename, int argc, char *argv[], ctl_t *ctl)
Reads control parameters from a configuration file and populates the given structure.
MPTRAC library declarations.
#define ERRMSG(...)
Print an error message with contextual information and terminate the program.
#define USAGE
Print usage information on -h or --help.
#define Z(p)
Convert pressure to altitude.
#define P(z)
Compute pressure at given altitude.
#define NQ
Maximum number of quantities per data point.
#define ALLOC(ptr, type, n)
Allocate memory for a pointer with error handling.
#define NP
Maximum number of atmospheric data points.
#define LOG(level,...)
Print a log message with a specified logging level.
double lat[NP]
Latitude [deg].
double lon[NP]
Longitude [deg].
int np
Number of air parcels.
double q[NQ][NP]
Quantity data (for various, user-defined attributes).
double p[NP]
Pressure [hPa].
char qnt_format[NQ][LEN]
Quantity output format.
int atm_type
Type of atmospheric data files (0=ASCII, 1=binary, 2=netCDF, 3=CLaMS_traj, 4=CLaMS_pos).
char qnt_unit[NQ][LEN]
Quantity units.
char qnt_name[NQ][LEN]
Quantity names.
int qnt_ens
Quantity array index for ensemble IDs.
int nq
Number of quantities.