00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <jsoc_main.h>
00034 #include "keystuff.c"
00035 #include "earth_ephem.c"
00036 #include "soho_ephem.c"
00037
00038 char *module_name = "xtrackd";
00039 char *module_desc = "extract subset from tracked region";
00040 char *version_id = "0.8";
00041
00042 ModuleArgs_t module_args[] = {
00043 {ARG_DATASET, "in", "", "input data set: tracked cubes"},
00044 {ARG_STRING, "out", "", "output data series"},
00045 {ARG_INT, "length", "", "length in timesteps", "(0,)"},
00046 {ARG_TIME, "tmid", "mid-point",
00047 "midpoint of extraction interval, in either CR:CL or standard date_time format"},
00048 {ARG_FLOATS, "mai", "NaN", "Magnetic Activity Indices"},
00049 {ARG_FLAG, "n", "", "do not save output (for testing)"},
00050 {ARG_FLAG, "v", "", "verbose mode"},
00051 {}
00052 };
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 int check_seginfo (DRMS_Record_t *rec, int *axis, int *datasegnum,
00066 int *logsegnum) {
00067 DRMS_Segment_t *seg;
00068 static int need_check = 0;
00069 int segfound, status;
00070 int i, n;
00071
00072 if (*datasegnum < 0 && *logsegnum < 0) {
00073 int segct= rec->segments.num_total;
00074
00075 if (segct < 1) {
00076 fprintf (stderr, "Error: series %s lacks data segments\n",
00077 rec->seriesinfo->seriesname);
00078 return -1;
00079 }
00080 segfound = 0;
00081 for (n = 0; n < segct; n++) {
00082 seg = drms_segment_lookupnum (rec, n);
00083 if (seg->info->protocol == DRMS_GENERIC) continue;
00084 if (seg->info->scope == DRMS_CONSTANT) continue;
00085 if (seg->info->naxis != 3) continue;
00086 if (!segfound) {
00087 *datasegnum = n;
00088 for (i = 0; i < 3; i++) axis[i] = seg->axis[i];
00089 if (seg->info->scope == DRMS_VARDIM) need_check = 1;
00090 }
00091 segfound++;
00092 }
00093 if (!segfound) {
00094 fprintf (stderr, "Error: series %s lacks 3-dimensional data segment\n",
00095 rec->seriesinfo->seriesname);
00096 return -1;
00097 }
00098 if (segfound > 1) fprintf (stderr,
00099 "Warning: series %s contains more than one 3-d segment; using %s\n",
00100 rec->seriesinfo->seriesname, seg->info->name);
00101 segfound = 0;
00102 for (n = 0; n < segct; n++) {
00103 seg = drms_segment_lookupnum (rec, n);
00104 if (seg->info->scope == DRMS_CONSTANT) continue;
00105 if (seg->info->protocol != DRMS_GENERIC) continue;
00106 if (!segfound) *logsegnum = n;
00107 segfound++;
00108 }
00109 if (!segfound) {
00110 fprintf (stderr, "Warning: series %s lacks segment for log\n",
00111 rec->seriesinfo->seriesname);
00112 }
00113 if (segfound > 1) fprintf (stderr,
00114 "Warning: series %s contains more than one generic segment; using %s\n",
00115 seg->record->seriesinfo->seriesname, seg->info->name);
00116 return 0;
00117 }
00118
00119 if (need_check) {
00120 seg = drms_segment_lookupnum (rec, *datasegnum);
00121 for (i = 0; i < 3; i++) axis[i] = seg->axis[i];
00122 }
00123 return 0;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 void analyze_log_file (char *fname, int start, int planes, float *coverage,
00135 int *firstvalid, int *lastvalid) {
00136 FILE *log = fopen (fname, "r");
00137 int counting = 0, ngood = 0, ntot = 0;
00138 int nrec, rdum, status;
00139 char *line = NULL;
00140 char dsdum[DRMS_MAXQUERYLEN];
00141 size_t len;
00142
00143 if (!log) return;
00144 while (getline (&line, &len, log) > 0) {
00145 if (sscanf (line, "step %d ", &nrec) < 1) continue;
00146 if (nrec == start) counting = 1;
00147 if (counting) {
00148 status = sscanf (line, "step %d mapped from image %s", &rdum, dsdum);
00149 if (status == 2) {
00150 if (!ntot) *firstvalid = ntot;
00151 *lastvalid = ntot;
00152 ngood++;
00153 }
00154 ntot++;
00155 if (status == 0) {
00156 fprintf (stderr,
00157 "Error: unexpected line in log file: coverage may be erroneous\n");
00158 fprintf (stderr, " %s", line);
00159 }
00160 }
00161 if (ntot == planes) break;
00162 }
00163 *coverage = (double)ngood / (double)ntot;
00164 fclose (log);
00165 }
00166
00167 int set_stat_keys (DRMS_Record_t *rec, DRMS_Array_t *data) {
00168 long long n, ntot, valid;
00169 double *dv;
00170 double vmn, vmx, sum, sum2, sum3, sum4, v2;
00171 double scal, avg, var, skew, kurt;
00172 float *fv;
00173 int i;
00174 int kstat = 0;
00175
00176 ntot = (data->naxis) ? 1 : 0;
00177 for (i = 0; i < data->naxis; i++) ntot *= data->axis[i];
00178 if (ntot < 1) return 0;
00179 valid = ntot;
00180 vmn = 1.0 / 0.0;
00181 vmx = -vmn;
00182 sum = sum2 = sum3 = sum4 = 0.0;
00183 switch (data->type) {
00184 case DRMS_TYPE_DOUBLE:
00185 dv = (double *)data->data;
00186 for (n = 0; n < ntot; n++) {
00187 if (isfinite (dv[n])) {
00188 if (dv[n] > vmx) vmx = dv[n];
00189 if (dv[n] < vmn) vmn = dv[n];
00190 sum += dv[n];
00191 v2 = dv[n] * dv[n];
00192 sum2 += v2;
00193 sum3 += v2 * dv[n];
00194 sum4 += v2 * v2;
00195 } else {
00196 valid--;
00197 }
00198 }
00199 break;
00200 case DRMS_TYPE_FLOAT:
00201 fv = (float *)data->data;
00202 for (n = 0; n < ntot; n++) {
00203 if (isfinite (fv[n])) {
00204 if (fv[n] > vmx) vmx = fv[n];
00205 if (fv[n] < vmn) vmn = fv[n];
00206 sum += fv[n];
00207 v2 = fv[n] * fv[n];
00208 sum2 += v2;
00209 sum3 += v2 * fv[n];
00210 sum4 += v2 * v2;
00211 } else {
00212 valid--;
00213 }
00214 }
00215 break;
00216 default:
00217 return 0;
00218 }
00219
00220 kstat += check_and_set_key_int (rec, "DATAVALS", valid);
00221 kstat += check_and_set_key_int (rec, "MISSVALS", ntot - valid);
00222 if (valid <= 0) return kstat;
00223
00224 kstat += check_and_set_key_double (rec, "DATAMIN", vmn);
00225 kstat += check_and_set_key_double (rec, "DATAMAX", vmx);
00226
00227 scal = 1.0 / valid;
00228 avg = scal * sum;
00229 var = scal * sum2 - avg * avg;
00230 skew = scal * sum3 - 3 * var * avg - avg * avg * avg;
00231 kurt = scal * sum4 - 4 * skew * avg - 6 * avg * avg * var -
00232 avg * avg * avg * avg;
00233 kstat += check_and_set_key_double (rec, "DATAMEAN", avg);
00234 if (var < 0.0) return kstat;
00235 kstat += check_and_set_key_double (rec, "DATARMS", sqrt (var));
00236 if (var == 0.0) return kstat;
00237 skew /= var * sqrt (var);
00238 kurt /= var * var;
00239 kurt -= 3.0;
00240 kstat += check_and_set_key_double (rec, "DATASKEW", skew);
00241 kstat += check_and_set_key_double (rec, "DATAKURT", kurt);
00242
00243 return kstat;
00244 }
00245
00246 int DoIt (void) {
00247 CmdParams_t *params = &cmdparams;
00248 DRMS_RecordSet_t *drs;
00249 DRMS_Record_t *irec, *orec;
00250 DRMS_Segment_t *iseg, *oseg, *ilog, *olog;
00251 DRMS_Array_t *data;
00252 TIME ttmid, ttstrt, ttstop;
00253 double tmid_cl, rsunm;
00254 float *mai;
00255 float coverage, pmid, tstep;
00256 float merid_v, zonal_v, lon_cm;
00257 int axis[3], start[3], stop[3];
00258 int tmid_cr;
00259 int pfirst, plast;
00260 int i, n, reci, reco, recs;
00261 int idatasegnum = -1, ilogsegnum = -1, odatasegnum = -1, ologsegnum = -1;
00262 int kstat, status;
00263 int need_stats, setmais;
00264 char pathname[2*DRMS_MAXPATHLEN+1];
00265 char source[DRMS_MAXQUERYLEN];
00266 char key[64], tbuf[64];
00267 char module_ident[64];
00268
00269 double degrad = 180.0 / M_PI;
00270 int tfrominp = 0;
00271
00272 char *inset = strdup (params_get_str (params, "in"));
00273 char *oser = strdup (params_get_str (params, "out"));
00274 TIME tmid = params_get_time (params, "tmid");
00275 int lngth = params_get_int (params, "length");
00276 int maict = params_get_int (params, "mai_nvals");
00277 int no_save = params_isflagset (params, "n");
00278 int verbose = params_isflagset (params, "v");
00279 int dispose = (no_save) ? DRMS_FREE_RECORD : DRMS_INSERT_RECORD;
00280
00281 snprintf (module_ident, 64, "%s v %s", module_name, version_id);
00282 if (verbose) printf ("%s: JSOC version %s\n", module_ident, jsoc_version);
00283 if (time_is_invalid (tmid)) {
00284
00285 char *tstr = strdup (params_get_str (params, "tmid"));
00286 if (sscanf (tstr, "%d:%lf", &tmid_cr, &tmid_cl) == 2) {
00287 tmid = earth_meridian_crossing (tmid_cl, tmid_cr);
00288 } else {
00289
00290 fprintf (stderr,
00291 "tmid not in standard format; using midtime from input record(s)\n");
00292 tfrominp = 1;
00293 }
00294 } else {
00295 double rsun, vr, vn, vw, img_lat;
00296 earth_ephemeris (tmid, &rsun, &img_lat, &tmid_cl, &vr, &vn, &vw);
00297 tmid_cr = carrington_rots (tmid, 0);
00298 }
00299
00300 if (!(drs = drms_open_records (drms_env, inset, &status))) {
00301 fprintf (stderr, "Error (%s): unable to open input data set %s\n",
00302 module_ident, inset);
00303 fprintf (stderr, " status = %d\n", status);
00304 return 1;
00305 }
00306 recs = drs->n;
00307 setmais = (maict == recs);
00308 if (setmais) {
00309 mai = (float *)malloc (maict * sizeof (float));
00310 for (i = 0; i < maict; i++) {
00311 snprintf (key, 64, "mai_%d_value", i);
00312 mai[i] = params_get_float (params, key);
00313 }
00314 }
00315
00316 for (reci = 0; reci < recs; reci++) {
00317 irec = drs->records[reci];
00318 drms_sprint_rec_query (source, irec);
00319 if (verbose) printf ("processing input record %s\n", source);
00320 if (check_seginfo (irec, axis, &idatasegnum, &ilogsegnum)) {
00321 drms_close_records (drs, DRMS_FREE_RECORD);
00322 return 1;
00323 }
00324 if (!(iseg = drms_segment_lookupnum (irec, idatasegnum))) {
00325 fprintf (stderr, "Error: could not find data segment in record:\n");
00326 fprintf (stderr, " %s\n", source);
00327 drms_close_records (drs, DRMS_FREE_RECORD);
00328 return 1;
00329 }
00330 for (n = 0; n < 2; n++) {
00331 start[n] = 0;
00332 stop[n] = axis[n] - 1;
00333 }
00334
00335 orec = drms_create_record (drms_env, oser, DRMS_PERMANENT, &status);
00336 if (status) {
00337 fprintf (stderr, "Error: drms_create_record returned %d for data series:\n",
00338 status);
00339 fprintf (stderr, " %s\n", oser);
00340 drms_close_records (drs, DRMS_FREE_RECORD);
00341 return 1;
00342 }
00343 if (check_seginfo (orec, axis, &odatasegnum, &ologsegnum)) {
00344 drms_close_records (drs, DRMS_FREE_RECORD);
00345 return 1;
00346 }
00347 if (!(oseg = drms_segment_lookupnum (orec, odatasegnum))) {
00348 fprintf (stderr, "Error: could not open output data segment\n");
00349 drms_close_records (drs, DRMS_FREE_RECORD);
00350 drms_close_record (orec, DRMS_FREE_RECORD);
00351 return 1;
00352 }
00353 if (reci == 0) need_stats = (drms_keyword_lookup (orec, "DATAMIN", 1) ||
00354 drms_keyword_lookup (orec, "DATAMAX", 1) ||
00355 drms_keyword_lookup (orec, "DATAMEAN", 1) ||
00356 drms_keyword_lookup (orec, "DATARMS", 1) ||
00357 drms_keyword_lookup (orec, "DATASKEW", 1) ||
00358 drms_keyword_lookup (orec, "DATAKURT", 1) ||
00359 drms_keyword_lookup (orec, "DATAVALS", 1) ||
00360 drms_keyword_lookup (orec, "MISSVALS", 1));
00361
00362 ttmid = (TIME)drms_getkey_double (irec, "CRVAL3", &status);
00363 tstep = drms_getkey_float (irec, "CDELT3", &status);
00364 ttstrt = drms_getkey_time (irec, "T_START", &status);
00365 ttstop = drms_getkey_time (irec, "T_STOP", &status);
00366 if (time_is_invalid (ttmid)) ttmid = 0.5 * (ttstrt = ttstop);
00367 if (tfrominp) {
00368 double rsun, vr, vn, vw, img_lat;
00369
00370
00371
00372
00373
00374
00375
00376 tmid = ttmid;
00377 earth_ephemeris (tmid, &rsun, &img_lat, &tmid_cl, &vr, &vn, &vw);
00378 tmid_cr = carrington_rots (tmid, 0);
00379
00380
00381
00382
00383 }
00384 pmid = drms_getkey_float (irec, "CRPIX3", &status);
00385 start[2] = pmid - 0.5 * lngth + 0.5;
00386 stop[2] = start[2] + lngth - 1;
00387 start[2] += (tmid - ttmid) / tstep;
00388 stop[2] += (tmid - ttmid) / tstep;
00389 if (start[2] < 0 || stop[2] >= iseg->axis[2]) {
00390 fprintf (stderr,
00391 "Error: output interval not contained within input cube:\n");
00392 fprintf (stderr, " [%d, %d] outside [0, %d]\n", start[2], stop[2],
00393 iseg->axis[2] - 1);
00394 drms_close_record (orec, DRMS_FREE_RECORD);
00395 continue;
00396 }
00397
00398
00399
00400 data = drms_segment_readslice (iseg, DRMS_TYPE_FLOAT, start, stop, &status);
00401 status = drms_segment_write (oseg, data, 0);
00402 if (ilogsegnum >= 0) {
00403 ilog = drms_segment_lookupnum (irec, ilogsegnum);
00404 drms_record_directory (irec, pathname, 1);
00405 strcat (pathname, "/");
00406 strncat (pathname, ilog->filename, DRMS_MAXPATHLEN);
00407 analyze_log_file (pathname, start[2], lngth, &coverage, &pfirst, &plast);
00408 }
00409
00410 kstat = 0;
00411
00412 kstat += check_and_copy_key (orec, irec, "Ident");
00413 kstat += check_and_copy_key (orec, irec, "LonHG");
00414 kstat += check_and_copy_key (orec, irec, "LatHG");
00415 kstat += check_and_set_key_int (orec, "CarrRot", tmid_cr);
00416 kstat += check_and_set_key_float (orec, "CMLon", tmid_cl);
00417 lon_cm = drms_getkey_float (irec, "LonHG", &status); - tmid_cl;
00418 while (lon_cm < -180.0) lon_cm += 360.0;
00419 while (lon_cm > 180.0) lon_cm -= 360.0;
00420 kstat += check_and_set_key_float (orec, "LonCM", lon_cm);
00421 kstat += check_and_set_key_time (orec, "MidTime", tmid);
00422 kstat += check_and_set_key_time (orec, "T_START", tmid - 0.5 * lngth * tstep);
00423 kstat += check_and_set_key_time (orec, "T_STOP", tmid + 0.5 * lngth * tstep);
00424 kstat += check_and_set_key_float (orec, "Duration", lngth * tstep);
00425
00426 kstat += check_and_set_key_str (orec, "Module", module_ident);
00427 kstat += check_and_set_key_str (orec, "BLD_VERS", jsoc_version);
00428 kstat += check_and_set_key_time (orec, "Created", CURRENT_SYSTEM_TIME);
00429 kstat += check_and_set_key_str (orec, "Source", source);
00430
00431 kstat += check_and_copy_key (orec, irec, "CRPIX1");
00432 kstat += check_and_copy_key (orec, irec, "CRPIX2");
00433 kstat += check_and_set_key_float (orec, "CRPIX3", pmid);
00434 kstat += check_and_copy_key (orec, irec, "CRVAL1");
00435 kstat += check_and_copy_key (orec, irec, "CRVAL2");
00436 kstat += check_and_set_key_double (orec, "CRVAL3", tmid);
00437 kstat += check_and_copy_key (orec, irec, "CDELT1");
00438 kstat += check_and_copy_key (orec, irec, "CDELT2");
00439 kstat += check_and_copy_key (orec, irec, "CDELT3");
00440 kstat += check_and_copy_key (orec, irec, "CUNIT1");
00441 kstat += check_and_copy_key (orec, irec, "CUNIT2");
00442 kstat += check_and_copy_key (orec, irec, "CUNIT3");
00443 kstat += check_and_copy_key (orec, irec, "CTYPE1");
00444 kstat += check_and_copy_key (orec, irec, "CTYPE2");
00445 kstat += check_and_copy_key (orec, irec, "CTYPE3");
00446 kstat += check_and_copy_key (orec, irec, "WCSNAME");
00447 kstat += check_and_copy_key (orec, irec, "WCSAXES");
00448
00449 kstat += check_and_set_key_float (orec, "Coverage", coverage);
00450 kstat += check_and_copy_key (orec, irec, "Width");
00451 kstat += check_and_copy_key (orec, irec, "Height");
00452 kstat += check_and_copy_key (orec, irec, "Size");
00453 kstat += check_and_copy_key (orec, irec, "Backgrnd");
00454 kstat += check_and_copy_key (orec, irec, "RejectList");
00455 kstat += check_and_copy_key (orec, irec, "Cadence");
00456 kstat += check_and_copy_key (orec, irec, "MapScale");
00457 kstat += check_and_copy_key (orec, irec, "Map_PA");
00458 kstat += check_and_copy_key (orec, irec, "MapProj");
00459 kstat += check_and_copy_key (orec, irec, "Interp");
00460 kstat += check_and_copy_key (orec, irec, "RSunRef");
00461 kstat += check_and_copy_key (orec, irec, "ZonalTrk");
00462 kstat += check_and_copy_key (orec, irec, "ZonalVel");
00463 kstat += check_and_copy_key (orec, irec, "MeridTrk");
00464 kstat += check_and_copy_key (orec, irec, "MeridVel");
00465 merid_v = drms_getkey_float (irec, "MeridTrk", &status);
00466 kstat += check_and_set_key_float (orec, "LatDrift",
00467 merid_v * degrad * lngth * tstep);
00468 zonal_v = drms_getkey_float (irec, "ZonalTrk", &status);
00469 kstat += check_and_set_key_float (orec, "LonDrift",
00470 zonal_v * degrad * lngth * tstep);
00471 if (setmais && isfinite (mai[reci]))
00472 kstat += check_and_set_key_float (orec, "MAI", mai[reci]);
00473
00474 if (need_stats) kstat += set_stat_keys (orec, data);
00475
00476 if (kstat) {
00477 fprintf (stderr, "Error writing key value(s) to record in series %s\n",
00478 oser);
00479 fprintf (stderr, " series may not have appropriate structure\n");
00480 drms_close_record (orec, DRMS_FREE_RECORD);
00481 }
00482
00483 drms_close_record (orec, dispose);
00484 drms_free_array (data);
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 drms_close_records (drs, DRMS_FREE_RECORD);
00579 return 0;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590