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
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 #include "jsoc_main.h"
00142 #include "drms_types.h"
00143 #include <time.h>
00144 #include <math.h>
00145 #include <timeio.h>
00146 #include "fitsio.h"
00147
00148 #include "cartography.c"
00149
00150 #include "roi_stats_mag_defs.h"
00151
00152 #include "propagate_keys.c"
00153
00154
00155
00156 static int verbflag;
00157
00158 static FILE *LOGout = NULL;
00159 static FILE *LOGerr = NULL;
00160
00161
00162 #define STR_MAX 256
00163
00164 #define LIST_MAX 10
00165
00166
00167 #define FN_INGEST_STDLOG "ingest-latest.log"
00168 #define FN_INGEST_STDERR "ingest-latest.err"
00169
00170 #define FN_TRACK_PARAM "track-param.txt"
00171
00172 #define FN_TRACK_FRAME "track-frame.txt"
00173
00174 #define FN_TRACK_STATS "track-stats.txt"
00175
00176 #define FN_TRACK_STATUS "track-status.txt"
00177
00178 #define FN_TRACK_DIR "track-%06d"
00179
00180 #define FN_TRACK_FITS "patch-%06d.fits.gz"
00181
00182 #define kNOT_SPEC "Not Specified"
00183
00184 #define REC_EPS 10.0
00185
00186 #define SEC_PER_DAY (24.0*60.0*60.0)
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 void
00205 V_printf(int flag, char *preamble, char *format, ...) {
00206 va_list args;
00207 extern char *module_name;
00208 extern FILE *LOGout;
00209 extern FILE *LOGerr;
00210 FILE *fp = (flag > 0) ? stdout : stderr;
00211 FILE *lp = (flag > 0) ? LOGout : LOGerr;
00212
00213 if (flag != 0) {
00214
00215 va_start(args, format);
00216 if (preamble)
00217 fprintf(fp, "%s: %s", module_name, preamble);
00218 vfprintf(fp, format, args);
00219 fflush(fp);
00220 va_end(args);
00221
00222 if (lp) {
00223 va_start(args, format);
00224 if (preamble)
00225 fprintf(lp, "%s: %s", module_name, preamble);
00226 vfprintf(lp, format, args);
00227 fflush(lp);
00228 va_end(args);
00229 }
00230 } else {
00231 va_start(args, format);
00232
00233 va_end(args);
00234 }
00235 }
00236
00237
00238
00239 #define DIE(...) do { \
00240 fflush(stdout); \
00241 V_printf(-1, "", "FATAL: %s.\n", __VA_ARGS__); \
00242 if (LOGout) fclose(LOGout); \
00243 if (LOGerr) fclose(LOGerr); \
00244 return 1; \
00245 } while (0)
00246
00247
00248 #define WARN(...) do { \
00249 fflush(stdout); \
00250 V_printf(-1, "", "WARNING: %s. Continuing.\n", __VA_ARGS__); \
00251 } while (0)
00252
00253
00254 #define RADSINDEG (M_PI/180.0)
00255 #define RAD2ARCSEC (648000. / M_PI)
00256
00257
00258
00259
00260
00261
00262
00263 #define PIX_X(wx,wy) ((((wx-crvalx)*cosa + (wy-crvaly)*sina)/cdelt)+crpix1)
00264 #define PIX_Y(wx,wy) ((((wy-crvaly)*cosa - (wx-crvalx)*sina)/cdelt)+crpix2)
00265 #define WX(pix_x,pix_y) (((pix_x-crpix1)*cosa - (pix_y-crpix2)*sina)*cdelt+crvalx)
00266 #define WY(pix_x,pix_y) (((pix_y-crpix2)*cosa + (pix_x-crpix1)*sina)*cdelt+crvaly)
00267
00268
00269 #define WCS2LOCALS(wcs) crvalx=(wcs).crval1; \
00270 crvaly=(wcs).crval2; \
00271 crpix1=(wcs).crpix1; \
00272 crpix2=(wcs).crpix2; \
00273 cdelt =(wcs).cdelt1; \
00274 crota2=(wcs).crota2; \
00275 sina=sin(crota2 * RADSINDEG); \
00276 cosa=cos(crota2 * RADSINDEG)
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 typedef struct {
00288 int ok;
00289 char missing[32];
00290
00291 double rsun_ref;
00292 double dsun_obs;
00293 float cdelt1;
00294 float crval1;
00295 float crval2;
00296 float crpix1;
00297 float crpix2;
00298 float crota2;
00299 float crlt_obs;
00300 float crln_obs;
00301 } wcs_t;
00302
00303
00304
00305
00306 typedef enum {
00307 Patch_Invalid = 0,
00308 Patch_Normal,
00309 Patch_Padding,
00310
00311 } patch_status_t;
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 typedef enum {
00323
00324
00325 Patch_Tag_None = -99,
00326
00327 Patch_Tag_Faint = -1,
00328
00329 Patch_Tag_Harder = 0,
00330 Patch_Tag_Normal = 1,
00331 Patch_Tag_Merge = 2,
00332 } patch_tag_t;
00333
00334
00335
00336
00337 typedef enum {
00338 Patch_Ingest_Eligible = 0,
00339 Patch_Ingest_Invalid,
00340 Patch_Ingest_Gap,
00341 Patch_Ingest_Missing,
00342 Patch_Ingest_Omit,
00343 Patch_Ingest_TooShort,
00344 Patch_Ingest_NUM,
00345 } patch_ingest_t;
00346
00347 static const char* const
00348 Patch_Ingest_Names[Patch_Ingest_NUM] = {
00349 "eligible to ingest",
00350 "no patch for this harp at this t_rec [ok]",
00351 "data gap in mags [ok]",
00352 "data missing in masks [likely error]",
00353 "omitted ingesting due to supplied options [ok]",
00354 "too short, typ. cosmic ray [ok]",
00355 };
00356
00357
00358
00359
00360 typedef struct {
00361 patch_status_t valid;
00362 int num;
00363 patch_tag_t tag;
00364 patch_ingest_t ingest;
00365 int success;
00366 int x0, y0;
00367 int fits_nx, fits_ny;
00368 float lat0, lon0, lat1, lon1;
00369 float omega;
00370 float stats[RS_num_stats];
00371 char *patchName;
00372 char *image;
00373 int dims[2];
00374 int xmin, xmax, ymin, ymax;
00375 } patch_info_t;
00376
00377
00378
00379
00380
00381 #define HARP_INFO_MATCH_MAX 11
00382 typedef struct {
00383 int id;
00384 int rec0, rec1;
00385 int rec0p, rec1p;
00386 int n_missing;
00387 int n_patch;
00388 int n_patchp;
00389 int n_patch_eligible;
00390 int n_patch_ingested;
00391 int n_patch_err;
00392 int top_match;
00393 int n_match;
00394 int match[HARP_INFO_MATCH_MAX];
00395
00396 } harp_info_t;
00397
00398
00399
00400
00401 typedef enum {
00402 Trec_Data_Unknown = 0,
00403 Trec_Data_Gap,
00404 Trec_Data_Missing,
00405 Trec_Data_OK,
00406 Trec_Data_NUM,
00407 } trec_data_t;
00408
00409 static const char* const
00410 Trec_Data_Names[Trec_Data_NUM] = {
00411 "un-inspected [ok: data record not examined]",
00412 "no mag present [ok: data gap]",
00413 "mag present, but no mask [likely error: missing data]",
00414 "mag and mask both present [ok]",
00415 };
00416
00417 typedef struct {
00418 TIME t;
00419 char str[24];
00420 trec_data_t data;
00421 wcs_t wcs;
00422 int nharp;
00423 } trec_info_t;
00424
00425
00426
00427
00428 typedef struct {
00429 int try_ok;
00430 int try_err;
00431 int hist[Patch_Ingest_NUM];
00432 } patch_ingest_tab_t;
00433
00434 typedef struct {
00435 int trec_patch_err;
00436 int trec_patch_valid;
00437 int hist[Trec_Data_NUM];
00438 } trec_ingest_tab_t;
00439
00440
00441
00442
00443
00444 typedef struct {
00445 int n_par;
00446 char **par_names;
00447 char **par_vals;
00448 } run_info_t;
00449
00450
00451
00452
00453
00454
00455
00456 typedef struct {
00457 int id;
00458 int rec0, rec1;
00459 int top_match;
00460 int n_match;
00461 } marp_info_t;
00462
00463
00464
00465
00466 typedef struct {
00467 int id;
00468 int marp_index;
00469 double count;
00470 double size;
00471 } marp_sort_t;
00472
00473
00474
00475
00476 typedef struct {
00477 patch_status_t valid;
00478 int id;
00479 TIME t;
00480 float lat, lon;
00481 float lon_carr;
00482 float lon_wid;
00483 float area;
00484 int spot;
00485 char class_mag[32];
00486 char class_zur[4];
00487 } match_info_t;
00488
00489 static const char *tracker_run_info_keys[] = {
00490
00491 "TKP_KWID", "kwid",
00492 "TKP_KLAT", "klat",
00493 "TKP_TAU", "tau",
00494 "TKP_TAU2", "tau2",
00495 "TKP_ACTV", "active",
00496 "TKP_FNUM", "final_num",
00497 "TKP_FTIM", "final_time",
00498 "TKP_MAPR", "maprate",
00499
00500 "TKP_RUNN", "run_name",
00501
00502
00503 "TKP_RUNT", "run_time",
00504
00505 NULL, NULL,
00506 };
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 int load_tracker_params(const char *rootDir, run_info_t *ri);
00519
00520 int load_run_info(const char *rootDir, char **, double, int *nHarp, int *nRec_all,
00521 TIME *, TIME *);
00522
00523 int load_harp_ids(const char *rootDir, char **, harp_info_t *harpInfo);
00524
00525 int load_all_patch_info(const char *rootDir, const char *refHarp,
00526 patch_info_t *, harp_info_t *, trec_info_t *,
00527 int nHarp, int, int, double, int);
00528
00529 int load_frame(FILE *fp, patch_info_t *pInfo, TIME *t);
00530
00531 int load_stats(FILE *fp, float *stats);
00532
00533 int mark_ingested_harp(const char *, run_info_t *, harp_info_t *);
00534
00535 void patch_print(FILE *fp, char *s, trec_info_t *tI, patch_info_t *pI);
00536
00537 void set_trec_times(trec_info_t *tRec, TIME t0, int nRec_all, int nRec_pad, double cadence);
00538
00539 void set_trec_hasdata(trec_info_t *tRec, char *magQuery, char *maskQuery, int *npix, int nRec_all);
00540
00541 void mark_eligible_patches(patch_info_t *, harp_info_t *, trec_info_t *tRec,
00542 int nHarp, int nRec_all, int nRec_eat,
00543 int rec0cut, int rec1cut, int nRec_min);
00544
00545 int ingest_harp(patch_info_t *, harp_info_t *, trec_info_t *trec1, trec_info_t *trec,
00546 run_info_t *,
00547 marp_info_t *,
00548 DRMS_Record_t *magRec, DRMS_Record_t *maskRec,
00549 char *maskImg, int mask_stride, char *outQuery);
00550
00551 int ingest_record(patch_info_t *, harp_info_t *, trec_info_t *trec1, trec_info_t *trec,
00552 run_info_t *,
00553 marp_info_t *,
00554 DRMS_Record_t *magRec, DRMS_Record_t *maskRec, char *outQuery);
00555
00556 int tabulate_patches(patch_ingest_tab_t *, trec_ingest_tab_t *,
00557 patch_info_t *, harp_info_t *, trec_info_t *, int, int);
00558
00559 int update_bitmap(patch_info_t *pInfo, char *maskImg, int maskStride);
00560
00561 char *get_instrument_mode(DRMS_Record_t *);
00562 int set_keys_code_info(char *, DRMS_Record_t *);
00563 int set_keys_runinfo(DRMS_Record_t *rec, run_info_t *runInfo);
00564 int set_keys_stats(char *inst_mode, DRMS_Record_t *rec, DRMS_Record_t *magRec, DRMS_Record_t *maskRec,
00565 patch_info_t *, harp_info_t *, trec_info_t *);
00566 int set_keys_match(DRMS_Record_t *rec, harp_info_t *hInfo, marp_info_t *mInfo);
00567
00568 int time_to_recnum(TIME t, TIME t0, int rec0, int nRec, double);
00569
00570 int compute_boundary(patch_info_t *, int, wcs_t);
00571
00572 void distance2center(wcs_t wcs, double x, double y, double *xDist, double *yDist);
00573
00574 char *load_drms_rec_seg(DRMS_RecordSet_t **, DRMS_Record_t **, DRMS_Array_t **,
00575 wcs_t *, char *query, char *trec, char *segname, DRMS_Type_t);
00576
00577 int load_fits(char *filename, char **image, int *dims);
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 static double getwalltime(void)
00588 {
00589 struct timeval tv;
00590 gettimeofday(&tv, NULL);
00591 return tv.tv_sec * 1000.0 + tv.tv_usec/1000.0;
00592 }
00593
00594 static double getcputime(double *utime, double *stime)
00595 {
00596 struct rusage ru;
00597 getrusage(RUSAGE_SELF, &ru);
00598 *utime = ru.ru_utime.tv_sec * 1000.0 + ru.ru_utime.tv_usec / 1000.0;
00599 *stime = ru.ru_stime.tv_sec * 1000.0 + ru.ru_stime.tv_usec / 1000.0;
00600 return *utime + *stime;
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610 #include "mharp_match.c"
00611
00612
00613
00614
00615
00616
00617 static
00618 int
00619 match_harp_export(const char *rootDir,
00620 double *dist,
00621 match_info_t *matchInfo,
00622 marp_info_t *marpInfo,
00623 int nMarp,
00624 patch_info_t *patchInfo,
00625 harp_info_t *harpInfo,
00626 trec_info_t *tRec,
00627 int nRec_all,
00628 int nRec_min,
00629 int nHarp)
00630 {
00631 const int print_if_invalid = 1;
00632 FILE *fp, *fp2;
00633 const char *base = "Param";
00634 const char *extn = "dat";
00635 char fn[STR_MAX];
00636 char root[STR_MAX];
00637 int rv;
00638 int h, m;
00639 int i, inx, inx1;
00640
00641 if (!rootDir)
00642 return 0;
00643 snprintf(root, sizeof(root), "%s/%s", rootDir, "Match");
00644 if (mkdir(root, 0775) != 0) {
00645 if (errno == EEXIST) {
00646 V_printf(-1, "", "Match dump: `%s' already exists, skipping dump.\n", root);
00647 } else {
00648 V_printf(-1, "", "Match dump: could not create `%s'.\n", root);
00649 perror(root);
00650 return 1;
00651 }
00652 } else {
00653 V_printf(verbflag > 0, "", "Match dump: dumping to `%s'.\n", root);
00654 }
00655
00656
00657
00658
00659 snprintf(fn, sizeof(fn), "%s/%s-dist.%s", root, base, extn);
00660 if ((fp = fopen(fn, "w")) == NULL) return 1;
00661 for (h = 0; h < nHarp; h++) {
00662 for (m = 0; m < nMarp; m++)
00663 fprintf(fp, "%g ", dist[h*nMarp+m]);
00664 fprintf(fp, "\n");
00665 }
00666 fclose(fp);
00667
00668 snprintf(fn, sizeof(fn), "%s/%s-harp.%s", root, base, extn);
00669 if ((fp = fopen(fn, "w")) == NULL) return 1;
00670 for (h = 0; h < nHarp; h++) {
00671 fprintf(fp, "%d\n", harpInfo[h].id);
00672 }
00673 fclose(fp);
00674
00675 snprintf(fn, sizeof(fn), "%s/%s-marp.%s", root, base, extn);
00676 if ((fp = fopen(fn, "w")) == NULL) return 1;
00677 for (m = 0; m < nMarp; m++) {
00678 fprintf(fp, "%d\n", marpInfo[m].id);
00679 }
00680 fclose(fp);
00681
00682 snprintf(fn, sizeof(fn), "%s/%s-match.%s", root, base, extn);
00683 if ((fp = fopen(fn, "w")) == NULL) return 1;
00684 for (m = 0; m < nMarp; m++) {
00685 for (i = 0; i < nRec_all; i++) {
00686 inx = nRec_all * m + i;
00687 if (print_if_invalid || matchInfo[inx].valid == Patch_Normal)
00688 match_ar_print(fp, "", matchInfo+inx);
00689 }
00690 }
00691 fclose(fp);
00692
00693 snprintf(fn, sizeof(fn), "%s/%s-patch.%s", root, base, extn);
00694 if ((fp = fopen(fn, "w")) == NULL) return 1;
00695 for (h = 0; h < nHarp; h++) {
00696 for (i = 0; i < nRec_all; i++) {
00697 inx = nRec_all * h + i;
00698 if (print_if_invalid || patchInfo[inx].valid == Patch_Normal)
00699 patch_print(fp, "", tRec+i, patchInfo+inx);
00700 }
00701 }
00702
00703
00704
00705
00706 double degsec = 360.0/(27.2753*24*3600);
00707 double t0 = tRec[0].t;
00708 double d_lon;
00709 const int Harp_smpl = 1;
00710 const int Marp_smpl = 10;
00711
00712
00713 snprintf(fn, sizeof(fn), "%s/Patch-list.csv", root);
00714 if ((fp2 = fopen(fn, "w")) == NULL) return 1;
00715
00716 for (h = 0; h < nHarp; h++) {
00717
00718
00719 if ((harpInfo[h].rec1 - harpInfo[h].rec0 + 1) < nRec_min)
00720 continue;
00721 snprintf(fn, sizeof(fn), "%s/harp-%06d.csv", root, harpInfo[h].id);
00722 if ((fp = fopen(fn, "w")) == NULL) return 1;
00723 for (inx1 = -1, i = 0; i < nRec_all; i += Harp_smpl) {
00724 inx = nRec_all * h + i;
00725 if (patchInfo[inx].valid == Patch_Normal) {
00726 inx1 = inx;
00727 d_lon = (tRec[i].t - t0) * degsec;
00728 fprintf(fp, "%.2f,%.2f,%.16s\n",
00729
00730
00731 patchInfo[inx].stats[RS_ar_area_lat],
00732 patchInfo[inx].stats[RS_ar_area_lon] - d_lon,
00733 tRec[i].str);
00734 }
00735 }
00736 fclose(fp);
00737
00738 if (inx1 >= 0) {
00739 double lat_wid = patchInfo[inx1].lat1 - patchInfo[inx1].lat0;
00740 double lon_wid = patchInfo[inx1].lon1 - patchInfo[inx1].lon0;
00741 fprintf(fp2, "%06d,%s,%.2f,%.2f\n", harpInfo[h].id, "harp", lat_wid, lon_wid);
00742 }
00743 }
00744
00745 for (h = 0; h < nMarp; h++) {
00746 snprintf(fn, sizeof(fn), "%s/marp-%06d.csv", root, marpInfo[h].id);
00747 if ((fp = fopen(fn, "w")) == NULL) return 1;
00748 for (inx1 = -1, i = 0; i < nRec_all; i += Marp_smpl) {
00749 inx = nRec_all * h + i;
00750 if (matchInfo[inx].valid == Patch_Normal) {
00751 inx1 = inx;
00752 d_lon = (tRec[i].t - t0) * degsec;
00753 fprintf(fp, "%.2f,%.2f,%.16s\n",
00754 matchInfo[inx].lat,
00755 matchInfo[inx].lon - d_lon,
00756 tRec[i].str);
00757 }
00758 }
00759 fclose(fp);
00760
00761 if (inx1 >= 0) {
00762 double lat_wid = 0.0;
00763 double lon_wid = matchInfo[inx1].lon_wid;
00764 fprintf(fp2, "%06d,%s,%.2f,%.2f\n", marpInfo[h].id, "marp", lat_wid, lon_wid);
00765 }
00766 }
00767 fclose(fp2);
00768
00769
00770 V_printf(verbflag > 0, "", "Match dump: dump to `%s' complete.\n", root);
00771 return 0;
00772 }
00773
00774
00775
00776
00777
00778
00779 static
00780 int
00781 match_harp_marp_old(const char *rootDir,
00782 match_info_t *matchInfo,
00783 marp_info_t *marpInfo,
00784 int nMarp,
00785 patch_info_t *patchInfo,
00786 harp_info_t *harpInfo,
00787 trec_info_t *tRec,
00788 int nRec_all,
00789 int nRec_min,
00790 int nHarp)
00791 {
00792 int rec;
00793 int h, m;
00794 int Hinx, Minx;
00795 double d1, wt1, ct1;
00796 double diff, wt;
00797 double Hlat, Hlon, Mlat, Mlon;
00798 double *dist;
00799
00800
00801 if ((dist = calloc(nMarp*nHarp, sizeof(*dist))) == NULL) {
00802 V_printf(-1, "", "Could not allocate %d x %d match-dist matrix\n",
00803 nMarp, nHarp);
00804 return 1;
00805 }
00806 for (h = 0; h < nHarp; h++)
00807 for (m = 0; m < nMarp; m++) {
00808 d1 = 0;
00809 wt1 = 0;
00810 ct1 = 0;
00811 for (rec = 0; rec < nRec_all; rec++) {
00812 Hinx = h*nRec_all+rec;
00813 Minx = m*nRec_all+rec;
00814 if (patchInfo[Hinx].valid != Patch_Normal)
00815 continue;
00816 ct1++;
00817 if (matchInfo[Minx].valid != Patch_Normal)
00818 continue;
00819
00820 Hlat = patchInfo[Hinx].stats[RS_ar_area_lat];
00821 Hlon = patchInfo[Hinx].stats[RS_ar_area_lon];
00822 Mlat = matchInfo[Minx].lat;
00823 Mlon = matchInfo[Minx].lon;
00824 diff = sqrt(1.00 * (Hlat - Mlat)*(Hlat - Mlat) +
00825 0.25 * (Hlon - Mlon)*(Hlon - Mlon));
00826 wt = patchInfo[Hinx].stats[RS_rgn_size];
00827 d1 += diff * wt;
00828 wt1 += wt;
00829 }
00830
00831 dist[h*nMarp+m] = d1/wt1;
00832 }
00833
00834 if (match_harp_export(rootDir, dist,
00835 matchInfo, marpInfo, nMarp,
00836 patchInfo, harpInfo, tRec,
00837 nRec_all, nRec_min, nHarp) != 0) {
00838 V_printf(-1, "", "Failed to export (fopen problem?), continuing.\n");
00839 }
00840
00841 double d_best;
00842 const double d_best_enough = 5.0;
00843 int h_best = 0;
00844 for (m = 0; m < nMarp; m++) {
00845
00846 for (d_best = d_best_enough*1e6, h = 0; h < nHarp; h++) {
00847
00848 if (d_best > dist[h*nMarp+m]) {
00849 d_best = dist[h*nMarp+m];
00850 h_best = h;
00851 }
00852 }
00853 if (d_best < d_best_enough) {
00854
00855 V_printf(verbflag > 1, "\t", "Matching HARP %d to MARP %d (%.2f)\n",
00856 harpInfo[h_best].id, marpInfo[m].id, d_best);
00857
00858 harpInfo[h_best].match[harpInfo[h_best].n_match++] = m;
00859 } else {
00860 V_printf(verbflag > 1, "\t", "No match for MARP %d (%g)\n",
00861 marpInfo[m].id, d_best);
00862 }
00863 }
00864 free(dist);
00865 return 0;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 #define max(a,b) (((a)>(b))?(a):(b))
00882
00883 static
00884 void
00885 match_harp_marp_distance(match_info_t *matchI,
00886 patch_info_t *patchI,
00887 double *dist1,
00888 double *dist2)
00889 {
00890 double Mlat = matchI->lat;
00891 double Mlon = matchI->lon;
00892 double Hlat = patchI->stats[RS_ar_area_lat];
00893 double Hlon = patchI->stats[RS_ar_area_lon];
00894
00895 double Hlat0 = patchI->lat0;
00896 double Hlon0 = patchI->lon0;
00897 double Hlat1 = patchI->lat1;
00898 double Hlon1 = patchI->lon1;
00899
00900
00901
00902
00903
00904
00905 double Dlat0 = max(0, Hlat0 - Mlat);
00906 double Dlon0 = max(0, Hlon0 - Mlon);
00907 double Dlat1 = max(0, Mlat - Hlat1);
00908 double Dlon1 = max(0, Mlon - Hlon1);
00909 double Dlat = Dlat0 + Dlat1;
00910 double Dlon = Dlon0 + Dlon1;
00911
00912 *dist1 = sqrt(1.00 * Dlat*Dlat + 0.25 * Dlon*Dlon);
00913
00914 *dist2 = sqrt(1.00 * (Hlat - Mlat)*(Hlat - Mlat) +
00915 0.25 * (Hlon - Mlon)*(Hlon - Mlon));
00916 }
00917
00918
00919 #undef max
00920
00921
00922
00923
00924
00925 static int
00926 match_sort_cmp_size(const void *av, const void *bv) {
00927 const marp_sort_t *a = (const marp_sort_t *) av;
00928 const marp_sort_t *b = (const marp_sort_t *) bv;
00929 return b->size - a->size;
00930 }
00931
00932 static int
00933 match_sort_cmp_id(const void *av, const void *bv) {
00934 const marp_sort_t *a = (const marp_sort_t *) av;
00935 const marp_sort_t *b = (const marp_sort_t *) bv;
00936 return a->id - b->id;
00937 }
00938
00939 static
00940 int
00941 match_harp_marp(const char *rootDir,
00942 match_info_t *matchInfo,
00943 marp_info_t *marpInfo,
00944 int nMarp,
00945 patch_info_t *patchInfo,
00946 harp_info_t *harpInfo,
00947 trec_info_t *tRec,
00948 int nRec_all,
00949 int nRec_min,
00950 int nHarp)
00951 {
00952 int rec;
00953 int h, m, h_best, n_match;
00954 int Hinx, Minx;
00955 double d_box, d_box_best;
00956 double d_ctr, d_ctr_best;
00957 double ct_best;
00958
00959
00960
00961 const double d_best_enough = 0.5;
00962 double *HMct, *Msize;
00963 marp_sort_t match1, *match_list;
00964
00965 if ((HMct = calloc(nMarp*nHarp, sizeof(*HMct))) == NULL) {
00966 V_printf(-1, "", "Could not allocate %d x %d match-count matrix\n",
00967 nMarp, nHarp);
00968 return 1;
00969 }
00970 if ((Msize = calloc(nMarp, sizeof(*Msize))) == NULL) {
00971 V_printf(-1, "", "Could not allocate %d-length match-size vector\n",
00972 nMarp);
00973 return 1;
00974 }
00975 if ((match_list = calloc(nMarp, sizeof(*match_list))) == NULL) {
00976 V_printf(-1, "", "Could not allocate %d-length match-sort vector\n",
00977 nMarp);
00978 return 1;
00979 }
00980
00981 for (rec = 0; rec < nRec_all; rec++) {
00982 for (m = 0; m < nMarp; m++) {
00983
00984 Minx = m*nRec_all+rec;
00985 if (matchInfo[Minx].valid != Patch_Normal) continue;
00986 Msize[m] += (matchInfo[Minx].area > 0) ? matchInfo[Minx].area : 1;
00987
00988
00989 h_best = -1;
00990 for (h = 0; h < nHarp; h++) {
00991
00992 Hinx = h*nRec_all+rec;
00993 if (patchInfo[Hinx].valid != Patch_Normal) continue;
00994
00995 match_harp_marp_distance(matchInfo+Minx, patchInfo+Hinx, &d_box, &d_ctr);
00996
00997 if ((h_best < 0) || (d_box < d_box_best)) {
00998 d_box_best = d_box;
00999 d_ctr_best = d_ctr;
01000 h_best = h;
01001 } else if (( d_box == d_box_best) &&
01002 ((d_ctr < d_ctr_best) || isnan(d_ctr_best))) {
01003 d_ctr_best = d_ctr;
01004 h_best = h;
01005 }
01006 }
01007
01008 if ((h_best >= 0) &&
01009 (d_box_best < d_best_enough)) {
01010 HMct[h_best*nMarp + m]++;
01011 }
01012 }
01013 }
01014
01015
01016
01017
01018
01019
01020 for (m = 0; m < nMarp; m++) {
01021
01022
01023 h_best = -1;
01024 for (ct_best = 0, h = 0; h < nHarp; h++) {
01025 if (HMct[h*nMarp+m] > ct_best) {
01026 ct_best = HMct[h*nMarp+m];
01027 h_best = h;
01028 }
01029 }
01030 marpInfo[m].top_match = h_best;
01031
01032
01033 for (h = 0; h < nHarp; h++)
01034 if (HMct[h*nMarp+m] < ct_best*0.25)
01035 HMct[h*nMarp+m] = 0;
01036 }
01037
01038
01039
01040 if (match_harp_export(rootDir, HMct,
01041 matchInfo, marpInfo, nMarp,
01042 patchInfo, harpInfo, tRec,
01043 nRec_all, nRec_min, nHarp) != 0) {
01044 V_printf(-1, "", "Failed to export (fopen problem?), continuing.\n");
01045 }
01046
01047
01048
01049 for (h = 0; h < nHarp; h++) {
01050 for (n_match = m = 0; m < nMarp; m++) {
01051 if (HMct[h*nMarp+m] > 0) {
01052
01053 match1.marp_index = m;
01054 match1.id = marpInfo[m].id;
01055 match1.count = HMct[h*nMarp+m];
01056 match1.size = Msize[m];
01057
01058 match_list[n_match++] = match1;
01059
01060 marpInfo[m].n_match++;
01061 }
01062 }
01063
01064 qsort(match_list, n_match, sizeof(marp_sort_t), match_sort_cmp_size);
01065 if (n_match > 0)
01066 harpInfo[h].top_match = match_list[0].marp_index;
01067 else
01068 harpInfo[h].top_match = -1;
01069
01070 if (n_match > HARP_INFO_MATCH_MAX)
01071 n_match = HARP_INFO_MATCH_MAX;
01072
01073 qsort(match_list, n_match, sizeof(marp_sort_t), match_sort_cmp_id);
01074
01075 harpInfo[h].n_match = n_match;
01076 for (m = 0; m < n_match; m++) {
01077
01078 V_printf(verbflag > 1, "\t", "Matching HARP %d to MARP %d (ct=%.0f,siz=%f)\n",
01079 harpInfo[h].id,
01080 match_list[m].id,
01081 match_list[m].count,
01082 match_list[m].size);
01083
01084 harpInfo[h].match[m] = match_list[m].marp_index;
01085 }
01086 }
01087
01088 char matchStr[20];
01089 for (m = 0; m < nMarp; m++) {
01090
01091 snprintf(matchStr, sizeof(matchStr), "[best: %d]",
01092 (marpInfo[m].top_match >= 0) ? harpInfo[marpInfo[m].top_match].id : -1);
01093
01094 V_printf(verbflag > 0, "\t", "Matches found for MARP %d: %d %s\n",
01095 marpInfo[m].id, marpInfo[m].n_match,
01096 (marpInfo[m].n_match > 0) ? matchStr : "");
01097 }
01098 free(HMct);
01099 free(Msize);
01100 free(match_list);
01101 return 0;
01102 }
01103
01104
01105
01106
01107
01108
01109
01110 char *module_name = "ingest_mharp";
01111 char *hmi_mharp_version = "1.1";
01112
01113 ModuleArgs_t module_args[] = {
01114 {ARG_STRING, "root", kNOT_SPEC, "Input file directory"},
01115 {ARG_STRING, "lists", "track-new.txt", "File(s) listing HARP numbers (comma-separated)"},
01116 {ARG_INT, "match", "0", "Dump match-AR summary info? (<0 for post-dump exit)"},
01117 {ARG_STRING, "out", kNOT_SPEC, "Output HARP data series"},
01118 {ARG_STRING, "mag", "hmi.M_720s","Input magnetogram data series"},
01119 {ARG_STRING, "mask", kNOT_SPEC, "Input mask data series"},
01120 {ARG_STRING, "href", kNOT_SPEC, "Reference HARP bounding box source (default: none)"},
01121 {ARG_STRING, "t0cut", kNOT_SPEC, "Earliest time allowed to ingest (default: none)"},
01122 {ARG_STRING, "t1cut", kNOT_SPEC, "Latest time allowed to ingest (default: none)"},
01123 {ARG_INT, "trec", "0", "Number of T_RECs to ingest (0=all, 1=latest)"},
01124 {ARG_INT, "tpad", "120", "Temporal padding (in images, >=0, 120=1 day)"},
01125 {ARG_INT, "tmin", "1", "Minimum T_REC's needed to ingest a patch (1=all)"},
01126 {ARG_DOUBLE, "cadence","720.0", "Image cadence in seconds"},
01127 {ARG_INT, "readonly", "0", "Read-only with respect to rootdir (if ro=1, match=0)"},
01128 {ARG_INT, "verb", "1", "Verbosity: 0=errs only; 1, 2 = more"},
01129 {ARG_END}
01130 };
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146 int DoIt(void)
01147 {
01148
01149 const char *listNamesIn;
01150 const char *rootDir;
01151 int matchStatus;
01152 int readOnly;
01153 char *outQuery, *maskQuery, *magQuery;
01154 const char *refHarp;
01155 char *t0cutIn, *t1cutIn;
01156 char fn_log[STR_MAX], fn_err[STR_MAX];
01157
01158 DRMS_RecordSet_t *inRecSet, *magRecSet, *maskRecSet;
01159 DRMS_Record_t *inRec, *maskRec, *magRec;
01160 DRMS_Array_t *maskData;
01161 char *maskImg;
01162 int maskStride;
01163
01164 int listNum;
01165 char *listNames[LIST_MAX];
01166 char *listBuf;
01167
01168 patch_info_t *patchInfo = NULL;
01169 harp_info_t *harpInfo = NULL;
01170 trec_info_t *tRec = NULL;
01171 run_info_t runInfo;
01172
01173 int nMarp;
01174 match_info_t *matchInfo = NULL;
01175 marp_info_t *marpInfo = NULL;
01176
01177 TIME t0, t1;
01178 char t0_S[32], t1_S[32];
01179 TIME t0cut, t1cut;
01180 char t0cut_S[32], t1cut_S[32];
01181 int rec0cut, rec1cut;
01182 int nHarp;
01183 int nRec;
01184 int nRec_pad;
01185 int nRec_all;
01186 int nRec_eat;
01187 int nRec_min;
01188 double cadence;
01189 int npix_fulldisk;
01190 int Harp_try;
01191 int Harp_ok, Harp_err;
01192 int rec;
01193 int i;
01194 int rv, inx;
01195 char *err;
01196
01197 double wt0, wt;
01198 double ut0, ut;
01199 double st0, st;
01200 double ct0, ct;
01201
01202
01203 wt0 = getwalltime();
01204 ct0 = getcputime(&ut0, &st0);
01205
01206 rootDir = cmdparams_get_str(&cmdparams, "root", NULL);
01207 if (strcmp(rootDir, kNOT_SPEC) == 0) DIE("Root directory must be specified");
01208
01209 snprintf(fn_log, sizeof(fn_log), "%s/%s", rootDir, FN_INGEST_STDLOG);
01210 snprintf(fn_err, sizeof(fn_err), "%s/%s", rootDir, FN_INGEST_STDERR);
01211 if ((LOGout = fopen(fn_log, "w")) == NULL)
01212 DIE("Could not open regular log file `%s' for writing", fn_log);
01213 if ((LOGerr = fopen(fn_err, "w")) == NULL)
01214 DIE("Could not open error log file `%s' for writing", fn_err);
01215
01216 outQuery = (char *) cmdparams_get_str(&cmdparams, "out", NULL);
01217 if (strcmp(outQuery, kNOT_SPEC) == 0) DIE("Output HARP series must be specified");
01218 listNamesIn = cmdparams_get_str(&cmdparams, "lists", NULL);
01219 if (strcmp(listNamesIn, kNOT_SPEC) == 0) DIE("HARP list file(s) must be specified");
01220 matchStatus = cmdparams_get_int(&cmdparams, "match", NULL);
01221 readOnly = cmdparams_get_int(&cmdparams, "readonly", NULL);
01222 if (readOnly) matchStatus = 0;
01223 magQuery = (char *) cmdparams_get_str(&cmdparams, "mag", NULL);
01224 maskQuery = (char *) cmdparams_get_str(&cmdparams, "mask", NULL);
01225 if (strcmp(maskQuery, kNOT_SPEC) == 0) DIE("mask series must be specified");
01226 refHarp = cmdparams_get_str(&cmdparams, "href", NULL);
01227 if (strcmp(refHarp, kNOT_SPEC) == 0) refHarp = NULL;
01228 nRec_eat = cmdparams_get_int(&cmdparams, "trec", NULL);
01229 nRec_pad = cmdparams_get_int(&cmdparams, "tpad", NULL);
01230 nRec_min = cmdparams_get_int(&cmdparams, "tmin", NULL);
01231 cadence = cmdparams_get_double(&cmdparams, "cadence", NULL);
01232
01233 t0cutIn = (char *) cmdparams_get_str(&cmdparams, "t0cut", NULL);
01234 t1cutIn = (char *) cmdparams_get_str(&cmdparams, "t1cut", NULL);
01235 verbflag = cmdparams_get_int(&cmdparams, "verb", NULL);
01236
01237 if (nRec_min <= 0)
01238 DIE("tmin must be a positive integer");
01239 if (nRec_eat < 0)
01240 DIE("trec must be a nonnegative integer");
01241 if (nRec_pad < 0)
01242 DIE("tpad must be a nonnegative integer");
01243 if ((nRec_eat > 0) && (nRec_eat <= nRec_pad))
01244 DIE("number of trec to ingest (trec) must be larger than padding (tpad)");
01245
01246 if (strcmp(t0cutIn, kNOT_SPEC) == 0) {
01247 t0cut = NAN;
01248 strcpy(t0cut_S, "no cut-time before");
01249 } else {
01250 t0cut = sscan_time(t0cutIn);
01251 if (time_is_invalid(t0cut)) DIE("Could not parse given t0cut");
01252 sprint_time(t0cut_S, t0cut, "TAI", 0);
01253 }
01254 if (strcmp(t1cutIn, kNOT_SPEC) == 0) {
01255 t1cut = NAN;
01256 strcpy(t1cut_S, "no cut-time after");
01257 } else {
01258 t1cut = sscan_time(t1cutIn);
01259 if (time_is_invalid(t1cut)) DIE("Could not parse given t1cut");
01260 sprint_time(t1cut_S, t1cut, "TAI", 0);
01261 }
01262 if (t0cut > t1cut) DIE("Need t0cut <= t1cut");
01263 if (!isnan(t0cut) || !isnan(t1cut))
01264 V_printf(1, "", "Chosen T_REC cut interval: %s - %s\n", t0cut_S, t1cut_S);
01265
01266 listNum = 0;
01267 listBuf = strdup(listNamesIn);
01268 bzero(listNames, sizeof(listNames));
01269 for (char **listp = listNames; (*listp = strsep(&listBuf, ",")) != NULL; listNum++)
01270 if (**listp != '\0')
01271 if (++listp >= &listNames[LIST_MAX])
01272 break;
01273 if (listNum >= LIST_MAX || listNames[listNum] != NULL)
01274 DIE("Got too many list files, reduce or recompile");
01275
01276 V_printf(verbflag > 0, "", "Ingesting from `%s'\n", rootDir);
01277 V_printf(verbflag > 0, "", " Got %d list file%s from `%s'\n",
01278 listNum, listNum == 1 ? "" : "s", listNamesIn);
01279 V_printf(verbflag > 0, "", "Ingesting into `%s'\n", outQuery);
01280 V_printf(verbflag > 0, "", "Mask input series `%s'\n", maskQuery);
01281 if (refHarp)
01282 V_printf(verbflag > 0, "", "Reference harp series is `%s'\n", refHarp);
01283
01284
01285
01286
01287 if (load_run_info(rootDir, listNames, cadence, &nHarp, &nRec, &t0, &t1))
01288 DIE("Error finding basic run info (bad rootDir, listfile, or format?)");
01289 if (load_tracker_params(rootDir, &runInfo))
01290 WARN("Failed to load tracker parameter file. Some keys will not be set");
01291 if (nRec == 0) {
01292 V_printf(1, "", "Got nHarp = 0. Using nominal time range. Setting pad = 0.\n");
01293 nRec_pad = 0;
01294 }
01295 nRec_all = nRec + 2*nRec_pad;
01296
01297 sprint_time(t0_S, t0, "TAI", 0);
01298 sprint_time(t1_S, t1, "TAI", 0);
01299 V_printf(verbflag > 0, "", "nHarp = %d; nRec = %d; nRec_all = %d; pad = %d.\n",
01300 nHarp, nRec, nRec_all, nRec_pad);
01301 V_printf(verbflag > 0, "", "t0 = %s\n", t0_S);
01302 V_printf(verbflag > 0, "", "t1 = %s\n", t1_S);
01303
01304 if (nRec_eat == 0)
01305 nRec_eat = nRec_all;
01306 if (nRec_eat > nRec_all) {
01307 nRec_eat = nRec_all;
01308
01309 WARN("Specified trec to ingest was larger than total trecs + padding; capping it");
01310 }
01311
01312 if (t0cut < t0 || t0cut > t1) WARN("Specified t0cut outside [t0,t1].");
01313 if (t1cut < t0 || t1cut > t1) WARN("Specified t1cut outside [t0,t1].");
01314 rec0cut = time_to_recnum(t0cut, t0, nRec_pad, -1, cadence);
01315 rec1cut = time_to_recnum(t1cut, t0, nRec_pad, -1, cadence);
01316
01317 if (rec0cut > nRec_all) rec0cut = nRec_all;
01318
01319 if (rec0cut >= 0 || rec1cut >= 0)
01320
01321 V_printf(verbflag > 0, "", "Cut times: rec0cut = %d, rec1cut = %d\n", rec0cut, rec1cut);
01322 else
01323
01324 V_printf(verbflag > 0, "",
01325 "Compiling %d HARPs over %d distinct T_REC's among %d total T_REC's.\n",
01326 nHarp, nRec_eat, nRec_all);
01327
01328
01329
01330
01331
01332 patchInfo = calloc(nHarp * nRec_all, sizeof(*patchInfo));
01333 harpInfo = calloc(nHarp, sizeof(*harpInfo));
01334 tRec = calloc( nRec_all, sizeof(*tRec));
01335 if (!tRec || !harpInfo || !patchInfo)
01336 DIE("Memory allocation failure");
01337
01338 V_printf(verbflag > 0, "", "Setting T_REC times\n");
01339 set_trec_times(tRec, t0, nRec_all, nRec_pad, cadence);
01340
01341 V_printf(verbflag > 0, "", "Checking mag/mask availability and WCS across T_REC\n");
01342 set_trec_hasdata(tRec, magQuery, maskQuery, &npix_fulldisk, nRec_all);
01343
01344 V_printf(verbflag > 0, "", "Getting HARP id numbers\n");
01345 if (load_harp_ids(rootDir, listNames, harpInfo) != 0)
01346 DIE("Error creating HARP id list (bad listfile or format?)");
01347
01348 V_printf(verbflag > 0, "", "Getting detailed HARP info\n");
01349 if (load_all_patch_info(rootDir, refHarp,
01350 patchInfo, harpInfo,
01351 tRec, nHarp, nRec_all, nRec_pad, cadence, npix_fulldisk))
01352 DIE("Error fetching HARP info (bad listfiles/format)");
01353
01354 mark_eligible_patches(patchInfo, harpInfo, tRec, nHarp,
01355 nRec_all, nRec_eat, rec0cut, rec1cut, nRec_min);
01356
01357 wt = getwalltime();
01358 ct = getcputime(&ut, &st);
01359 V_printf(1, "", "elapsed time after indexing: %.3f s wall, %.3f s cpu\n",
01360 (wt - wt0)*1e-3, (ct - ct0)*1e-3);
01361
01362
01363
01364
01365 V_printf(verbflag > 0, "", "Loading match regions\n");
01366
01367 if (match_load_resample(nRec_all, tRec, &nMarp, &marpInfo, &matchInfo) != 0) {
01368 V_printf(-1, "", "Could not load and resample Match-AR metadata.\n");
01369 DIE("Unable to read MATCH AR information");
01370 }
01371 if (nMarp == 0)
01372 V_printf(1, "", "No match ARs supplied/found, continuing.\n");
01373 V_printf(verbflag > 0, "", "Matching %d HARPs to %d Match-regions\n", nHarp, nMarp);
01374
01375 match_harp_marp((matchStatus == 0) ? NULL : rootDir,
01376 matchInfo, marpInfo, nMarp,
01377 patchInfo, harpInfo, tRec,
01378 nRec_all, nRec_min, nHarp);
01379 free(matchInfo);
01380 matchInfo = NULL;
01381
01382 wt = getwalltime();
01383 ct = getcputime(&ut, &st);
01384 V_printf(1, "", "elapsed time after matching: %.3f s wall, %.3f s cpu\n",
01385 (wt - wt0)*1e-3, (ct - ct0)*1e-3);
01386
01387 if (matchStatus < 0) {
01388 V_printf(-1, "", "Early exit due to given match option (match = %d)\n", matchStatus);
01389
01390 if (LOGout) fclose(LOGout);
01391 if (LOGerr) fclose(LOGerr);
01392 return DRMS_SUCCESS;
01393 }
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403 for (rec = 0; rec < nRec_all; rec++) {
01404 if (tRec[rec].nharp == 0) {
01405 V_printf(verbflag > 0, "\t", "[%3d/%3d] %s: Nothing to ingest.\n",
01406 rec+1, nRec_all, tRec[rec].str);
01407 continue;
01408 }
01409 V_printf(verbflag > 1, "\t", "Ingesting at %s [%d/%d]\n", tRec[rec].str, rec+1, nRec_all);
01410
01411 V_printf(verbflag > 2, "\t\t", "Opening mag: %s[%s]\n", magQuery, tRec[rec].str);
01412 err = load_drms_rec_seg(&magRecSet, &magRec, NULL, NULL,
01413 magQuery, tRec[rec].str, NULL, DRMS_TYPE_RAW);
01414 if (err) {
01415 V_printf(-1, "", "%s (%s[%s]) -- skipping this T_REC.\n", err, magQuery, tRec[rec].str);
01416 continue;
01417 }
01418
01419 V_printf(verbflag > 2, "\t\t", "Opening mask: %s[%s]\n", maskQuery, tRec[rec].str);
01420 err = load_drms_rec_seg(&maskRecSet, &maskRec, &maskData, NULL,
01421 maskQuery, tRec[rec].str, "mask", DRMS_TYPE_CHAR);
01422 if (err) {
01423 V_printf(-1, "", "%s (%s[%s]) -- skipping this T_REC.\n", err, maskQuery, tRec[rec].str);
01424 drms_close_records(magRecSet, DRMS_FREE_RECORD); magRecSet = NULL;
01425 continue;
01426 }
01427 maskImg = (char *) maskData->data;
01428 maskStride = maskData->axis[0];
01429
01430 Harp_try = Harp_ok = Harp_err = 0;
01431 for (i = 0; i < nHarp; i++) {
01432 inx = i*nRec_all + rec;
01433 if (patchInfo[inx].valid == Patch_Invalid || patchInfo[inx].ingest != Patch_Ingest_Eligible)
01434 continue;
01435 V_printf(verbflag > 2, "\t\t", " HARP[%d][%s] begin\n", harpInfo[i].id, tRec[rec].str);
01436
01437 Harp_try++;
01438 rv = ingest_harp(patchInfo+inx, harpInfo+i, tRec+rec,
01439 tRec,
01440 &runInfo,
01441 marpInfo,
01442 magRec, maskRec,
01443 maskImg, maskStride,
01444 outQuery);
01445 if (rv != 0) {
01446 V_printf(-1, "", "Error ingesting HARP[%d][%s], skipped\n", harpInfo[i].id, tRec[rec].str);
01447 Harp_err++;
01448 continue;
01449 }
01450 Harp_ok++;
01451 patchInfo[inx].success = 1;
01452 V_printf(verbflag > 1, "\t", " HARP[%d][%s] done\n", harpInfo[i].id, tRec[rec].str);
01453 }
01454 V_printf(verbflag > 0, "\t", "[%3d/%3d] %s:\t%2d attempted = %2d OK + %2d errors%s\n",
01455 rec+1, nRec_all, tRec[rec].str, Harp_try, Harp_ok, Harp_err,
01456 Harp_err > 0 ? " ***" : "");
01457 drms_free_array(maskData);
01458 drms_close_records(magRecSet, DRMS_FREE_RECORD); magRecSet = NULL;
01459 drms_close_records(maskRecSet, DRMS_FREE_RECORD); maskRecSet = NULL;
01460 }
01461
01462
01463
01464
01465 for (i = 0; i < nHarp; i++) {
01466 if (mark_ingested_harp(readOnly ? NULL : rootDir, &runInfo, harpInfo+i) != 0)
01467 V_printf(-1, "", "HARP %d was ingested into JSOC but not noted in status file.\n",
01468 harpInfo[i].id);
01469 }
01470
01471
01472
01473
01474 trec_ingest_tab_t tRec_tab;
01475 patch_ingest_tab_t patch_tab;
01476 int clean_exit = 1;
01477
01478 tabulate_patches(&patch_tab, &tRec_tab, patchInfo, harpInfo, tRec, nHarp, nRec_all);
01479
01480
01481 rv = 0;
01482 V_printf(1, "", "Ingestion summary -- across HARPs:\n");
01483 for (i = 0; i < nHarp; i++) {
01484
01485 if (harpInfo[i].n_patch_eligible == 0) continue;
01486 rv = 1;
01487
01488 V_printf(1, "", " HARP[%d]: %4d T_RECs eligible = %4d ok + %d errs.\n",
01489 harpInfo[i].id, harpInfo[i].n_patch_eligible,
01490 harpInfo[i].n_patch_ingested, harpInfo[i].n_patch_err);
01491
01492 if (harpInfo[i].n_patch_err > 0)
01493 V_printf(-1, "", "WARNING: HARP[%d] had %d ingestion errors in %d eligible T_RECs\n",
01494 harpInfo[i].id, harpInfo[i].n_patch_err, harpInfo[i].n_patch_eligible);
01495 }
01496 if (rv == 0)
01497 V_printf(1, "", " (No HARPs ingested)\n");
01498
01499
01500 V_printf(1, "", "Ingestion summary -- across T_RECs:\n");
01501 V_printf(1, "", " Considered NT = %d T_RECs.\n", nRec_all);
01502 V_printf(1, "", " Ingested across %d T_RECs (< NT is OK).\n", tRec_tab.trec_patch_valid);
01503 V_printf(1, "", " Ingest error in %d T_RECs.\n", tRec_tab.trec_patch_err);
01504 for (i = 0; i < Trec_Data_NUM; i++) {
01505 V_printf(1, "", " Of NT, %d T_RECs were: %s\n", tRec_tab.hist[i], Trec_Data_Names[i]);
01506 }
01507 if (tRec_tab.hist[Trec_Data_Missing] > 0) {
01508 clean_exit = 0;
01509 for (i = -1; i <= 1; i += 2)
01510 V_printf(i, "", "WARNING: %d mask records were missing (not due to simple mag gap).\n",
01511 tRec_tab.hist[Trec_Data_Missing]);
01512 }
01513
01514
01515 V_printf(1, "", "Ingestion summary -- across all patches (HARP appearances):\n");
01516 V_printf(1, "", " Processed NP = %d patches over all HARPs and all T_RECs.\n",
01517 nRec_all*nHarp - patch_tab.hist[Patch_Ingest_Invalid]);
01518 for (i = 0; i < Patch_Ingest_NUM; i++) {
01519 if (i == (int) Patch_Ingest_Invalid) continue;
01520 V_printf(1, "", " Of NP, %d patches were: %s\n", patch_tab.hist[i], Patch_Ingest_Names[i]);
01521 }
01522 V_printf(1, "", " Attempted to ingest NP1 = %d patches over all T_RECs.\n",
01523 patch_tab.hist[Patch_Ingest_Eligible]);
01524 V_printf(1, "", " Of NP1, %d patches were ingested successfully.\n", patch_tab.try_ok);
01525 V_printf(1, "", " Of NP1, %d patches had ingestion errors.\n", patch_tab.try_err);
01526 if (patch_tab.try_err > 0) {
01527 clean_exit = 0;
01528 for (i = -1; i <= 1; i += 2)
01529 V_printf(i, "", "WARNING: %d patch ingestion errors were NOT due to missing mags.\n",
01530 patch_tab.try_err);
01531 }
01532
01533
01534 free(marpInfo);
01535 free(listBuf);
01536
01537
01538 for (i = 0; i < nHarp * nRec_all; i++)
01539 {
01540 if (patchInfo[i].patchName)
01541 {
01542 free(patchInfo[i].patchName);
01543 patchInfo[i].patchName = NULL;
01544 }
01545 }
01546
01547 free(patchInfo);
01548 free(tRec);
01549 free(harpInfo);
01550
01551
01552 wt = getwalltime();
01553 ct = getcputime(&ut, &st);
01554 V_printf(1, "", "total time used: %.3f s wall, %.3f s cpu\n",
01555 (wt - wt0)*1e-3, (ct - ct0)*1e-3);
01556 if (clean_exit) {
01557 V_printf(1, "", "Exiting OK.\n");
01558 } else {
01559 for (i = -1; i <= 1; i += 2)
01560 V_printf(i, "", "Exiting with some warnings.\n");
01561 }
01562
01563 if (LOGout) fclose(LOGout);
01564 if (LOGerr) fclose(LOGerr);
01565 return DRMS_SUCCESS;
01566 }
01567
01568
01569
01570
01571
01572
01573
01574 static
01575 int
01576 tabulate_patches(patch_ingest_tab_t *pTab,
01577 trec_ingest_tab_t *tTab,
01578 patch_info_t *patchInfo,
01579 harp_info_t *harpInfo,
01580 trec_info_t *tRec,
01581 int nHarp,
01582 int nRec_all)
01583
01584 {
01585 int rec, i, inx;
01586 int something_failed;
01587 patch_ingest_t p_code;
01588 trec_data_t d_code;
01589
01590
01591 pTab->try_ok = 0;
01592 pTab->try_err = 0;
01593 bzero(pTab->hist, sizeof(pTab->hist));
01594 tTab->trec_patch_err = 0;
01595 tTab->trec_patch_valid = 0;
01596 bzero(tTab->hist, sizeof(tTab->hist));
01597 for (i = 0; i < nHarp; i++)
01598 harpInfo[i].n_patch_eligible =
01599 harpInfo[i].n_patch_ingested =
01600 harpInfo[i].n_patch_err = 0;
01601
01602 for (rec = 0; rec < nRec_all; rec++) {
01603
01604
01605
01606 d_code = tRec[rec].data;
01607 if (d_code < 0 || d_code >= Trec_Data_NUM) {
01608 V_printf(-1, "",
01609 "Internal error: Bad trec code %d at %s in tabulate_patches.\n",
01610 d_code, tRec[rec].str);
01611 return 1;
01612 }
01613 tTab->hist[(int) d_code]++;
01614
01615
01616
01617 something_failed = 0;
01618 for (i = 0; i < nHarp; i++) {
01619 inx = i*nRec_all + rec;
01620 p_code = patchInfo[inx].ingest;
01621 if (p_code < 0 || p_code >= Patch_Ingest_NUM) {
01622 V_printf(-1, "",
01623 "Internal error: Bad patch code %d at %s, harp %d, in tabulate_patches.\n",
01624 p_code, tRec[rec].str, patchInfo[inx].num);
01625 return 1;
01626 }
01627
01628 pTab->hist[(int) p_code]++;
01629
01630 if (p_code == Patch_Ingest_Eligible) {
01631 harpInfo[i].n_patch_eligible++;
01632 if (patchInfo[inx].success) {
01633 harpInfo[i].n_patch_ingested++;
01634 pTab->try_ok++;
01635 } else {
01636 harpInfo[i].n_patch_err++;
01637 pTab->try_err++;
01638 something_failed = 1;
01639 }
01640 }
01641 }
01642
01643
01644
01645 if (something_failed)
01646 tTab->trec_patch_err++;
01647 if (tRec[rec].nharp > 0)
01648 tTab->trec_patch_valid++;
01649 }
01650 return 0;
01651 }
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668 static
01669 int
01670 time_to_recnum(TIME t, TIME t0, int rec0, int nRec, double cadence)
01671 {
01672 if (isnan(t)) return -1;
01673 double rec_diff = (t - t0) / cadence;
01674 int rec = rec0 + ((int) rint(rec_diff));
01675
01676 if (nRec >= 0) {
01677 if (rec < 0) rec = 0;
01678 if (rec >= nRec) rec = nRec-1;
01679 }
01680 return rec;
01681 }
01682
01683
01684
01685
01686
01687
01688
01689
01690 static
01691 int
01692 wcs_load(wcs_t *wcs, DRMS_Record_t *rec)
01693 {
01694 int status, retval;
01695 const size_t Nmiss = sizeof(wcs->missing);
01696
01697
01698 status = 0;
01699 wcs->rsun_ref = drms_getkey_double(rec, "RSUN_REF", &status);
01700 if (status) wcs->rsun_ref = 6.96e8;
01701 status = 0;
01702 wcs->dsun_obs = drms_getkey_double(rec, "DSUN_OBS", &status);
01703 wcs->cdelt1 = drms_getkey_float (rec, "CDELT1", &status);
01704 wcs->crval1 = drms_getkey_float (rec, "CRVAL1", &status);
01705 wcs->crval2 = drms_getkey_float (rec, "CRVAL2", &status);
01706 wcs->crpix1 = drms_getkey_float (rec, "CRPIX1", &status);
01707 wcs->crpix2 = drms_getkey_float (rec, "CRPIX2", &status);
01708 wcs->crota2 = drms_getkey_float (rec, "CROTA2", &status);
01709 wcs->crlt_obs = drms_getkey_float (rec, "CRLT_OBS", &status);
01710 wcs->crln_obs = drms_getkey_float (rec, "CRLN_OBS", &status);
01711
01712 strcpy(wcs->missing, "");
01713 retval = 0;
01714
01715 if (status != 0) {
01716 snprintf(wcs->missing, Nmiss, "Failed getkey()");
01717 retval = 1;
01718 } else {
01719 if (isnan(wcs->dsun_obs)) snprintf(wcs->missing, Nmiss, "NaN %s", "DSUN_OBS");
01720 if (isnan(wcs->cdelt1 )) snprintf(wcs->missing, Nmiss, "NaN %s", "CDELT1");
01721 if (isnan(wcs->crval1 )) snprintf(wcs->missing, Nmiss, "NaN %s", "CRVAL1");
01722 if (isnan(wcs->crval2 )) snprintf(wcs->missing, Nmiss, "NaN %s", "CRVAL2");
01723 if (isnan(wcs->crpix1 )) snprintf(wcs->missing, Nmiss, "NaN %s", "CRPIX1");
01724 if (isnan(wcs->crpix2 )) snprintf(wcs->missing, Nmiss, "NaN %s", "CRPIX2");
01725 if (isnan(wcs->crota2 )) snprintf(wcs->missing, Nmiss, "NaN %s", "CROTA2");
01726 if (isnan(wcs->crlt_obs)) snprintf(wcs->missing, Nmiss, "NaN %s", "CRLT_OBS");
01727 if (isnan(wcs->crln_obs)) snprintf(wcs->missing, Nmiss, "NaN %s", "CRLN_OBS");
01728
01729 if (strlen(wcs->missing) > 0)
01730 retval = 2;
01731 }
01732 if (retval) V_printf(1, "wcs_load: ", "WCS fail: %s\n", wcs->missing);
01733 return retval;
01734 }
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772 static
01773 char *
01774 load_drms_rec_seg(DRMS_RecordSet_t **recSetP,
01775 DRMS_Record_t **recP,
01776 DRMS_Array_t **dataP,
01777 wcs_t *wcs,
01778
01779 char *query,
01780 char *trec,
01781 char *segname,
01782 DRMS_Type_t d_typ)
01783 {
01784 char rec_query[STR_MAX];
01785 char tag[STR_MAX];
01786 int status, return_code;
01787 DRMS_RecordSet_t *the_recSet;
01788 DRMS_Record_t *the_rec;
01789 DRMS_Array_t *the_data;
01790 DRMS_Segment_t *the_seg;
01791
01792
01793 if (!query || !trec)
01794 return "Illegal argument to load_drms_rec_seg: need query and trec";
01795 if (!recSetP && (recP || dataP))
01796 return "Illegal argument to load_drms_rec_seg: recSet required here";
01797 if (!segname && dataP)
01798 return "Illegal argument to load_drms_rec_seg: segname required for data";
01799
01800 if (recSetP) *recSetP = NULL;
01801 if (recP) *recP = NULL;
01802 if (dataP) *dataP = NULL;
01803 if (wcs) {wcs->ok = 0; strcpy(wcs->missing, ""); }
01804
01805 snprintf(tag, sizeof(tag), "%s %s",
01806 segname ? "and segment" : "(no segment)",
01807 dataP ? "and array" : "");
01808
01809 snprintf(rec_query, sizeof(rec_query), "%s[%s]", query, trec);
01810 V_printf(verbflag > 2, "\t\t", "Opening record %s %s\n", rec_query, tag);
01811 status = 0;
01812 the_recSet = drms_open_records(drms_env, rec_query, &status);
01813 if (status != 0) {
01814
01815 return "Could not open record at this T_REC";
01816 }
01817
01818 if (the_recSet->n != 1) {
01819 drms_close_records(the_recSet, DRMS_FREE_RECORD);
01820 return "Could not open single record at this T_REC";
01821 }
01822 the_rec = the_recSet->records[0];
01823
01824 int quality = drms_getkey_int(the_rec, "QUALITY", &status);
01825 if (status != 0 || (quality & 0x80000000)) {
01826 drms_close_records(the_recSet, DRMS_FREE_RECORD);
01827 return "Missing data at this T_REC (quality)";
01828 }
01829
01830 if (wcs) {
01831 return_code = wcs_load(wcs, the_rec);
01832 if (return_code != 0) {
01833 drms_close_records(the_recSet, DRMS_FREE_RECORD);
01834 return "Missing WCS at this T_REC";
01835 }
01836 }
01837
01838 if (segname) {
01839 the_seg = drms_segment_lookup(the_rec, segname);
01840 if (the_seg == NULL) {
01841 drms_close_records(the_recSet, DRMS_FREE_RECORD);
01842 return "Failed data segment lookup at this T_REC";
01843 }
01844 }
01845
01846 if (segname && dataP) {
01847
01848 the_data = drms_segment_read(the_seg, d_typ, &status);
01849 if (the_data == NULL || status != 0) {
01850 drms_close_records(the_recSet, DRMS_FREE_RECORD);
01851 return "Failed data segment read at this T_REC";
01852 }
01853 }
01854
01855 if (recSetP) *recSetP = the_recSet;
01856 if (recP) *recP = the_rec;
01857 if (dataP) *dataP = the_data;
01858
01859
01860 if (!recSetP)
01861 drms_close_records(the_recSet, DRMS_FREE_RECORD);
01862 return NULL;
01863 }
01864
01865
01866
01867
01868
01869 static
01870 void
01871 set_trec_times(trec_info_t *tRec,
01872 TIME t0,
01873 int nRec_all, int nRec_pad,
01874 double cadence)
01875 {
01876 TIME t;
01877 int rec;
01878
01879 for (rec = 0; rec < nRec_all; rec++) {
01880 t = t0 + (rec - nRec_pad) * cadence;
01881
01882 tRec[rec].t = t;
01883 sprint_time(tRec[rec].str, t, "TAI", 0);
01884
01885 tRec[rec].data = Trec_Data_Unknown;
01886 tRec[rec].nharp = 0;
01887 }
01888 }
01889
01890
01891
01892
01893
01894
01895 static
01896 void
01897 mark_eligible_patches(patch_info_t *patchInfo,
01898 harp_info_t *harpInfo,
01899 trec_info_t *tRec,
01900 int nHarp,
01901 int nRec_all,
01902 int nRec_eat,
01903 int rec0cut,
01904 int rec1cut,
01905 int nRec_min)
01906
01907 {
01908 int rec, the_rec;
01909 int i, hits;
01910
01911 V_printf(verbflag > 0, "\t", "Patch scan: finding patches eligible for ingest.\n");
01912
01913 for (i = 0; i < nHarp; i++)
01914 for (rec = 0; rec < nRec_all; rec++)
01915 patchInfo[i*nRec_all + rec].ingest = Patch_Ingest_Eligible;
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926 if (nRec_eat < nRec_all)
01927 V_printf(verbflag > 0, "\t", " Implementing trec-to-ingest limitation (e.g., NRT mode)\n");
01928 for (i = 0; i < nHarp; i++)
01929 for (rec = 0; rec < nRec_all-nRec_eat; rec++)
01930 if (patchInfo[i*nRec_all + rec].ingest == Patch_Ingest_Eligible)
01931 patchInfo[i*nRec_all + rec].ingest = Patch_Ingest_Omit;
01932
01933
01934 if (rec0cut >= 0) {
01935 V_printf(verbflag > 0, "\t", " Implementing t0cut limitation\n");
01936
01937 for (i = 0; i < nHarp; i++) {
01938
01939
01940 if (harpInfo[i].rec0p <= rec0cut && harpInfo[i].rec0 > rec0cut)
01941 the_rec = harpInfo[i].rec0p;
01942 else {
01943 the_rec = rec0cut;
01944 if (the_rec > nRec_all) the_rec = nRec_all;
01945 }
01946 for (rec = 0; rec < the_rec; rec++)
01947 if (patchInfo[i*nRec_all + rec].ingest == Patch_Ingest_Eligible)
01948 patchInfo[i*nRec_all + rec].ingest = Patch_Ingest_Omit;
01949 }
01950 }
01951
01952 if (rec1cut >= 0) {
01953 V_printf(verbflag > 0, "\t", " Implementing t1cut limitation\n");
01954
01955 for (i = 0; i < nHarp; i++) {
01956
01957
01958 if (harpInfo[i].rec1p > rec1cut && harpInfo[i].rec1 <= rec1cut)
01959 the_rec = harpInfo[i].rec1p+1;
01960 else
01961 the_rec = rec1cut+1;
01962
01963 for (rec = the_rec; rec < nRec_all; rec++)
01964 if (patchInfo[i*nRec_all + rec].ingest == Patch_Ingest_Eligible)
01965 patchInfo[i*nRec_all + rec].ingest = Patch_Ingest_Omit;
01966 }
01967 }
01968
01969
01970
01971
01972
01973
01974
01975
01976 for (rec = 0; rec < nRec_all; rec++) {
01977 if (tRec[rec].data == Trec_Data_Gap) {
01978
01979 for (hits = i = 0; i < nHarp; i++) {
01980 if ((patchInfo[i*nRec_all + rec].ingest == Patch_Ingest_Eligible) &&
01981 ((rec >= harpInfo[i].rec0p) && (rec <= harpInfo[i].rec1p))) {
01982 patchInfo[i*nRec_all + rec].ingest = Patch_Ingest_Gap;
01983 hits++;
01984 }
01985 }
01986 if (hits > 0)
01987 V_printf(verbflag > 0, "\t", " Skipping %s (with %d HARP%s), no mag.\n",
01988 tRec[rec].str, hits, hits == 1 ? "" : "s");
01989 } else if (tRec[rec].data == Trec_Data_Missing) {
01990
01991 for (hits = i = 0; i < nHarp; i++) {
01992 if ((patchInfo[i*nRec_all + rec].ingest == Patch_Ingest_Eligible) &&
01993 ((rec >= harpInfo[i].rec0p) && (rec <= harpInfo[i].rec1p))) {
01994 patchInfo[i*nRec_all + rec].ingest = Patch_Ingest_Missing;
01995 hits++;
01996 }
01997 }
01998 if (hits > 0)
01999 V_printf(verbflag > 0, "\t", " Skipping %s (with %d HARP%s), no mask.\n",
02000 tRec[rec].str, hits, hits == 1 ? "" : "s");
02001 }
02002 }
02003
02004
02005
02006
02007 for (rec = 0; rec < nRec_all; rec++)
02008 for (i = 0; i < nHarp; i++)
02009 if ((patchInfo[i*nRec_all + rec].valid == Patch_Invalid) &&
02010 (patchInfo[i*nRec_all + rec].ingest == Patch_Ingest_Eligible))
02011 patchInfo[i*nRec_all + rec].ingest = Patch_Ingest_Invalid;
02012
02013 for (i = 0; i < nHarp; i++) {
02014
02015 if ((harpInfo[i].rec1 - harpInfo[i].rec0 + 1) < nRec_min) {
02016 V_printf(verbflag > 0, "\t", " Skipping HARP[%d], too short (CR)\n", harpInfo[i].id);
02017 for (rec = 0; rec < nRec_all; rec++)
02018 if (patchInfo[i*nRec_all + rec].ingest == Patch_Ingest_Eligible)
02019 patchInfo[i*nRec_all + rec].ingest = Patch_Ingest_TooShort;
02020 }
02021 }
02022
02023
02024 for (rec = 0; rec < nRec_all; rec++) {
02025 tRec[rec].nharp = 0;
02026 for (i = 0; i < nHarp; i++)
02027 if (patchInfo[i*nRec_all + rec].ingest == Patch_Ingest_Eligible) {
02028 tRec[rec].nharp++;
02029 }
02030 }
02031 V_printf(verbflag > 0, "\t", "Patch scan: done.\n");
02032 }
02033
02034
02035
02036
02037
02038
02039
02040 static
02041 void
02042 set_trec_hasdata(trec_info_t *tRec, char *magQuery, char *maskQuery, int *npix, int nRec_all)
02043 {
02044 int rec;
02045 wcs_t the_wcs;
02046 int Rec_valid, Rec_miss, Rec_err, Rec_ok;
02047 char *err;
02048 int npix_fulldisk = 0;
02049
02050 V_printf(verbflag > 0, "\t", "T_REC scan: scanning image series for missing data\n");
02051 Rec_valid = Rec_miss = Rec_err = Rec_ok = 0;
02052
02053
02054 for (rec = 0; rec < nRec_all; rec++) {
02055 Rec_valid++;
02056
02057 err = load_drms_rec_seg(NULL, NULL, NULL,
02058 &the_wcs,
02059 magQuery, tRec[rec].str,
02060 NULL, DRMS_TYPE_RAW);
02061 if (err) {
02062
02063 V_printf(1, "\t ", "%s%s (%s[%s]) -- skipping this T_REC.\n", err,
02064 (strlen(the_wcs.missing) > 0) ? the_wcs.missing : "",
02065 magQuery, tRec[rec].str);
02066 tRec[rec].data = Trec_Data_Gap;
02067 Rec_miss++;
02068 continue;
02069 }
02070
02071 err = load_drms_rec_seg(NULL, NULL, NULL,
02072 NULL,
02073 maskQuery, tRec[rec].str,
02074 "mask", DRMS_TYPE_RAW);
02075 if (err) {
02076
02077 V_printf( 1, "\t ", "%s (%s[%s]) -- skipping this T_REC.\n", err, maskQuery, tRec[rec].str);
02078 V_printf(-1, "", "%s (%s[%s]) -- skipping this T_REC.\n", err, maskQuery, tRec[rec].str);
02079 tRec[rec].data = Trec_Data_Missing;
02080 Rec_err++;
02081 continue;
02082 }
02083 if (npix_fulldisk == 0) {
02084
02085 DRMS_RecordSet_t *mRecSet;
02086 DRMS_Array_t *mArray = NULL;
02087 err = load_drms_rec_seg(&mRecSet, NULL,
02088 &mArray, NULL,
02089 maskQuery, tRec[rec].str,
02090 "mask", DRMS_TYPE_RAW);
02091
02092 if (!err) {
02093 npix_fulldisk = mArray->axis[0];
02094
02095 if (mArray)
02096 {
02097 drms_free_array(mArray);
02098 mArray = NULL;
02099 }
02100
02101 drms_close_records(mRecSet, DRMS_FREE_RECORD);
02102 }
02103 }
02104
02105 tRec[rec].data = Trec_Data_OK;
02106 tRec[rec].wcs = the_wcs;
02107 Rec_ok++;
02108 }
02109
02110 *npix = npix_fulldisk;
02111 V_printf(verbflag > 0, "\t", "T_REC scan: %d valid = %d OK + %d missing + %d errors\n",
02112 Rec_valid, Rec_ok, Rec_miss, Rec_err);
02113 V_printf(verbflag > 1, "\t\t", "T_REC scan found NAXIS1 = %d\n", npix_fulldisk);
02114
02115 if (Rec_err > 0)
02116 V_printf(-1, "", "Found missing masks in %s at %d T_REC(s). Continuing.\n", maskQuery, Rec_err);
02117 }
02118
02119
02120
02121
02122
02123
02124
02125 static
02126 void
02127 patch_print(FILE *fp, char *s, trec_info_t *tI, patch_info_t *pI)
02128 {
02129 const int human_friendly = 0;
02130 char trec_str[24];
02131
02132 if (human_friendly) {
02133 if (pI->valid != Patch_Normal) {
02134 fprintf(fp, "%sPatch not valid\n", s);
02135 } else {
02136 sprint_time(trec_str, tI->t, "TAI", 0);
02137 fprintf(fp,
02138 "%sID = %d (%s) @ (%.2f,%.2f) A = %.1f\n",
02139 s, pI->num, trec_str,
02140 pI->stats[RS_ar_area_lat],
02141 pI->stats[RS_ar_area_lon],
02142 pI->stats[RS_rgn_size]);
02143 }
02144 } else {
02145
02146
02147 fprintf(fp,
02148 "%d\t%d\t%.1f\t"
02149 "%.2f\t%.2f\t"
02150 "%.2f\t%.2f\t"
02151 "%.2f\t%.2f\t"
02152 "%.1f\n",
02153 pI->num, pI->valid, (double) tI->t,
02154 pI->stats[RS_ar_area_lat],
02155 pI->stats[RS_ar_area_lon],
02156 pI->lat0, pI->lon0,
02157 pI->lat1, pI->lon1,
02158 pI->stats[RS_rgn_size]);
02159 }
02160 }
02161
02162
02163
02164
02165 int
02166 load_tracker_params(const char *rootDir, run_info_t *ri)
02167 {
02168 FILE *fp;
02169 int p, np, llen;
02170 char fn[STR_MAX];
02171 char line[STR_MAX];
02172 char *val, *name_end;
02173
02174 snprintf(fn, sizeof(fn), "%s/%s", rootDir, FN_TRACK_PARAM);
02175 if ((fp = fopen(fn, "r")) == NULL) {
02176 V_printf(-1, "", "Failed to open `%s'.\n", fn);
02177 return 1;
02178 }
02179
02180 np = 0;
02181 while (fgets(line, sizeof(line), fp) != NULL) {
02182 llen = strlen(line);
02183
02184 if (line[llen-1] != '\n') {
02185 V_printf(-1, "", "Line: `%.20s ...' in param file `%s' is too long.\n", line, fn);
02186 return 1;
02187 }
02188 if (line[0] == '#' || line[0] == '\n') continue;
02189 np++;
02190 }
02191 ri->n_par = np;
02192 if (np == 0) {
02193 fclose(fp);
02194 return 0;
02195 }
02196
02197 ri->par_names = calloc(np, sizeof(*(ri->par_names)));
02198 ri->par_vals = calloc(np, sizeof(*(ri->par_vals )));
02199 if (ri->par_names == NULL || ri->par_vals == NULL) {
02200 V_printf(-1, "", "Calloc fail in load_tracker_params for np = %d\n", np);
02201 fclose(fp);
02202 return 1;
02203 }
02204
02205 rewind(fp);
02206 p = 0;
02207 while (fgets(line, sizeof(line), fp) != NULL) {
02208 llen = strlen(line);
02209 if (line[0] == '#' || line[0] == '\n') continue;
02210
02211 line[--llen] = '\0';
02212
02213 while (line[llen-1] == ' ' || line[llen-1] == '\t')
02214 line[--llen] = '\0';
02215
02216 val = strchr(line, (int) ':');
02217 if (val == NULL) {
02218 V_printf(-1, "", "load_tracker_params: no colon in line `%s' in file `%s'\n",
02219 line, fn);
02220 fclose(fp);
02221 return 1;
02222 }
02223
02224 for (name_end = val-1; *name_end == ' ' || *name_end == '\t'; name_end--)
02225 *name_end = '\0';
02226 *val++ = '\0';
02227
02228 while (*val == ' ' || *val == '\t')
02229 *val++ == '\0';
02230
02231 ri->par_names[p] = strdup(line);
02232 ri->par_vals [p] = strdup( val);
02233 p += 1;
02234 }
02235 fclose(fp);
02236 V_printf(verbflag > 0, "", "Got %d tracker params from `%s'\n", np, fn);
02237 return 0;
02238 }
02239
02240
02241
02242
02243 static
02244 int
02245 load_run_info(const char *rootDir, char **lists,
02246 double cadence,
02247 int *nHarp,
02248 int *nRec,
02249 TIME *p_t0,
02250 TIME *p_t1)
02251 {
02252 char *list1;
02253 char full_list[STR_MAX], currDir[STR_MAX], frameFile[STR_MAX];
02254 char line[STR_MAX];
02255 char *endptr;
02256 FILE *fp, *frameFp;
02257 int harp_id;
02258 int harp_count;
02259 int line_num;
02260 int rv, status;
02261 patch_info_t pInfo;
02262 TIME t, t0, t1;
02263 int *harp_ids;
02264 int nHarp_top = 1024;
02265 int dupe;
02266 int j;
02267
02268 harp_ids = calloc(nHarp_top, sizeof(*harp_ids));
02269 if (harp_ids == NULL) {
02270 V_printf(-1, "", "Error: Unable to allocate space for harp-id list\n");
02271 return 1;
02272 }
02273 harp_count = 0;
02274 t0 = sscan_time("2999.12.31_23:59:28Z");
02275 t1 = sscan_time("-4712.01.01_11:59:28Z");
02276 while ((list1 = *lists++) != NULL) {
02277
02278 if (*list1 == '/')
02279 snprintf(full_list, sizeof(full_list), "%s", list1);
02280 else
02281 snprintf(full_list, sizeof(full_list), "%s/%s", rootDir, list1);
02282 fp = fopen(full_list, "r");
02283 if (!fp) {
02284 V_printf(-1, "", "Error: Could not open HARP list file %s\n", full_list);
02285 return 1;
02286 }
02287 status = 0;
02288 while (fgets(line, sizeof(line), fp)) {
02289 if (*line == '#') continue;
02290 harp_id = strtol(line, &endptr, 10);
02291
02292 if (harp_id <= 0 || harp_id > INT_MAX) {
02293
02294 V_printf(-1, "", "Bad HARP number format in %s: %s\n", full_list, line);
02295 status = 1;
02296 break;
02297 }
02298
02299
02300 for (dupe = j = 0; !dupe && j < harp_count; j++)
02301 if (harp_ids[j] == (int) harp_id)
02302 dupe = 1;
02303
02304 if (!dupe)
02305 harp_ids[harp_count++] = (int) harp_id;
02306 else
02307 V_printf(verbflag > 1, " ", "ID count: Skipped dupe HARP #%d (this is ok).\n",
02308 (int) harp_id);
02309
02310 if (harp_count == nHarp_top) {
02311 nHarp_top *= 4;
02312 if ((harp_ids = realloc(harp_ids, nHarp_top*sizeof(*harp_ids))) == NULL) {
02313 V_printf(-1, "", "Failed realloc of harp ID buffer to size %d\n", nHarp_top);
02314 status = 1;
02315 break;
02316 }
02317 }
02318
02319
02320 snprintf(frameFile, sizeof(frameFile),
02321 "%s/" FN_TRACK_DIR "/%s", rootDir, harp_id, FN_TRACK_FRAME);
02322
02323 frameFp = fopen(frameFile, "r");
02324 if (!frameFp) {
02325 V_printf(-1, "", "Error: frame list file %s not found for HARP %06d (prescan).\n",
02326 frameFile, harp_id);
02327 status = 1;
02328 break;
02329 }
02330
02331 for (line_num = 1;
02332 (rv = load_frame(frameFp, &pInfo, &t)) == 0;
02333 line_num++) {
02334 if (t < t0) t0 = t;
02335 if (t > t1) t1 = t;
02336 }
02337 fclose(frameFp);
02338
02339 if (rv == 1) {
02340 V_printf(-1, "", "Error: Bad frame line %d in %s.\n", line_num, frameFile);
02341 status = 1;
02342 break;
02343 }
02344 }
02345 fclose(fp);
02346 if (status)
02347 return 1;
02348 }
02349 free(harp_ids);
02350
02351
02352
02353 if (harp_count > 0) {
02354 float nRec_check = ((t1 - t0) / cadence) + 1;
02355 *p_t0 = t0;
02356 *p_t1 = t1;
02357 *nHarp = harp_count;
02358 *nRec = (int) nRec_check;
02359 if (abs(nRec_check - *nRec) > REC_EPS/cadence) {
02360 V_printf(-1, "", "Error: cadence (%f) does not divide HARP TREC range (%f).\n",
02361 cadence, t1-t0);
02362 return 1;
02363 }
02364 } else {
02365 *nHarp = 0;
02366 *nRec = 0;
02367 *p_t0 = *p_t1 = sscan_time("2011.02.14_00:00:00_TAI");
02368 }
02369
02370 return 0;
02371 }
02372
02373
02374
02375
02376
02377 static
02378 int
02379 load_harp_ids(const char *rootDir, char **lists, harp_info_t *harpInfo)
02380 {
02381 char *list1;
02382 char full_list[STR_MAX];
02383 char line[STR_MAX];
02384 char *endptr;
02385 FILE *fp;
02386 long harp_id;
02387 int i, j;
02388 int dupe;
02389
02390 i = 0;
02391 while ((list1 = *lists++) != NULL) {
02392
02393 if (*list1 == '/')
02394 snprintf(full_list, sizeof(full_list), "%s", list1);
02395 else
02396 snprintf(full_list, sizeof(full_list), "%s/%s", rootDir, list1);
02397 fp = fopen(full_list, "r");
02398 if (!fp) {
02399 V_printf(-1, "", "Could not open HARP summary file %s\n", full_list);
02400 return 1;
02401 }
02402 while (fgets(line, sizeof(line), fp)) {
02403 if (*line == '#') continue;
02404
02405 harp_id = strtol(line, &endptr, 10);
02406 if (harp_id <= 0 || harp_id > INT_MAX) {
02407
02408 V_printf(-1, "", "Bad HARP ID format in %s: %s\n", full_list, line);
02409 fclose(fp);
02410 return 1;
02411 }
02412
02413
02414 for (dupe = j = 0; !dupe && j < i; j++)
02415 if (harpInfo[j].id == (int) harp_id)
02416 dupe = 1;
02417 if (!dupe)
02418 harpInfo[i++].id = (int) harp_id;
02419 else
02420 V_printf(verbflag > 2, " ", "ID load: Skipped dupe HARP #%d (this is ok)\n",
02421 (int) harp_id);
02422 }
02423 fclose(fp);
02424 }
02425 return 0;
02426 }
02427
02428
02429
02430
02431
02432
02433
02434
02435 static
02436 char *
02437 load_harp_reference(const char *refHarp, int harp_id, TIME *t0,
02438 double *lat0, double *lon0, double *lat1, double *lon1, double *omega)
02439 {
02440 char harpRecQuery[STR_MAX];
02441 DRMS_RecordSet_t *harpRecSet;
02442 DRMS_Record_t *harpRec;
02443 int status = 0;
02444
02445
02446 snprintf(harpRecQuery, sizeof(harpRecQuery), "%s[%d][%s]", refHarp, harp_id, "^");
02447 V_printf(verbflag > 2, "\t\t", "Opening HARP %s (box match)\n", harpRecQuery);
02448 harpRecSet = drms_open_records(drms_env, harpRecQuery, &status);
02449 if (status != 0)
02450 return "";
02451 if (harpRecSet->n != 1)
02452 return "Found more than one HARP record";
02453 harpRec = harpRecSet->records[0];
02454 *lat0 = drms_getkey_double(harpRec, "LATDTMIN", &status);
02455 *lon0 = drms_getkey_double(harpRec, "LONDTMIN", &status);
02456 *lat1 = drms_getkey_double(harpRec, "LATDTMAX", &status);
02457 *lon1 = drms_getkey_double(harpRec, "LONDTMAX", &status);
02458 *omega = drms_getkey_double(harpRec, "OMEGA_DT", &status);
02459 *t0 = drms_getkey_time (harpRec, "T_REC", &status);
02460 if (status != 0)
02461 return "Could not get HARP keys";
02462 if (isnan(*lat0) || isnan(*lon0) || isnan(*lat1) || isnan(*lon1) || isnan(*omega))
02463 return "HARP bbox was invalid/missing";
02464 if (time_is_invalid(*t0))
02465 return "HARP time was invalid/missing";
02466
02467 return NULL;
02468 }
02469
02470
02471
02472
02473
02474
02475 static
02476 void
02477 patch_set_to_harp_reference(patch_info_t *pI, TIME t, TIME t0,
02478 double lat0, double lon0, double lat1, double lon1, double omega)
02479 {
02480
02481 TIME dt = t - t0;
02482
02483 double omegaP = omega / SEC_PER_DAY;
02484
02485 pI->lat0 = lat0;
02486 pI->lon0 = lon0 + omegaP * dt;
02487 pI->lat1 = lat1;
02488 pI->lon1 = lon1 + omegaP * dt;
02489 pI->omega = omega;
02490 }
02491
02492
02493
02494
02495
02496
02497 static
02498 int
02499 load_harp_patches(int harp_id,
02500 const char *refHarp,
02501 char *currDir,
02502 char *frameFile,
02503 char *statFile,
02504 patch_info_t *patchInfo,
02505 harp_info_t *harpInfo,
02506 trec_info_t *tRec,
02507 int nRec_all,
02508 double cadence)
02509 {
02510
02511 double lat0, lon0, lat1, lon1, omega;
02512 TIME t0;
02513 char t0_S[32];
02514 int ref_ready;
02515
02516 FILE *frameFp, *statFp;
02517 int rec, rec0, rec1;
02518 TIME t, t_rec0, t_rec1;
02519 patch_info_t pInfo;
02520 int rv1, rv2, status;
02521 int line_num, nPatch;
02522 char the_patchName[STR_MAX];
02523
02524
02525 frameFp = fopen(frameFile, "r");
02526 if (!frameFp) {
02527 V_printf(-1, "", "Frame list file `%s' not found for HARP %06d (full scan).\n",
02528 frameFile, harp_id);
02529 return 1;
02530 }
02531 statFp = fopen(statFile, "r");
02532 if (!statFp) {
02533 fclose(frameFp);
02534 V_printf(-1, "", "Stat list file `%s' not found for HARP %06d\n",
02535 statFile, harp_id);
02536 return 1;
02537 }
02538
02539
02540 ref_ready = 0;
02541 if (refHarp) {
02542 char *msg;
02543 msg = load_harp_reference(refHarp, harp_id, &t0, &lat0, &lon0, &lat1, &lon1, &omega);
02544 if (msg == NULL) {
02545 ref_ready = 1;
02546 sprint_time(t0_S, t0, "TAI", 0);
02547 V_printf(verbflag > 2, "\t\t",
02548 "Reference box: %s[%d][%s]: (%.4f,%.4f) to (%.4f,%.4f)\n",
02549 refHarp, harp_id, t0_S, lat0, lon0, lat1, lon1);
02550 } else {
02551 strcpy(t0_S, "");
02552 if (*msg == '\0')
02553
02554 V_printf(verbflag > 2, "\t\t",
02555 "Could not open reference harp %s[%d] -- no such harp.\n",
02556 refHarp, harp_id);
02557 else
02558
02559 V_printf(verbflag > 1, "\t\t",
02560 "Error opening reference harp %s[%d] -- bad box (%s).\n",
02561 refHarp, harp_id, msg);
02562 }
02563 }
02564
02565
02566 for (status = 0, nPatch = 1, line_num = 1;
02567 status == 0 &&
02568 (rv1 = load_frame(frameFp, &pInfo, &t)) == 0 &&
02569 (rv2 = load_stats(statFp, pInfo.stats)) == 0;
02570 nPatch++, line_num++) {
02571
02572
02573 snprintf(the_patchName, sizeof(the_patchName),
02574 "%s/" FN_TRACK_FITS, currDir, nPatch);
02575 if ((pInfo.patchName = strdup(the_patchName)) == NULL) {
02576 V_printf(-1, "", "Error: failed strdup (%s), harp %d\n", the_patchName, harp_id);
02577 status = 1;
02578 continue;
02579 }
02580 double rec_check = (t - tRec[0].t) / cadence;
02581 rec = (int) rec_check;
02582
02583 if (rec < 0 || rec >= nRec_all) {
02584 V_printf(-1, "", "Error: time at line %d out-of-range\n", line_num);
02585 status = 1;
02586 continue;
02587 }
02588
02589 if (abs(rec - rec_check) > REC_EPS/cadence) {
02590 V_printf(-1, "", "Error: Mismatch between time at line %d, "
02591 "initial time, and cadence %f\n", line_num, cadence);
02592 status = 1;
02593 continue;
02594 }
02595
02596 if (ref_ready)
02597 patch_set_to_harp_reference(&pInfo, t, t0, lat0, lon0, lat1, lon1, omega);
02598
02599
02600
02601
02602 patchInfo[rec] = pInfo;
02603 }
02604 fclose(frameFp);
02605 fclose(statFp);
02606
02607 if (rv1 == 1) {
02608 V_printf(-1, "", "Error: Bad frame line %d in `%s'.\n", line_num, frameFile);
02609 status = 1;
02610 } else if (rv2 == 1) {
02611 V_printf(-1, "", "Error: Bad stats line %d in `%s'.\n", line_num, statFile);
02612 status = 1;
02613 } else if (status) {
02614 V_printf(-1, "", "Error: Bad line %d in `%s'.\n", line_num, frameFile);
02615 }
02616 return status;
02617 }
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627 static
02628 int
02629 set_patch_info_blanks(patch_info_t *patchInfo,
02630 harp_info_t *harpInfo,
02631 trec_info_t *tRec,
02632 int nRec_all,
02633 double cadence)
02634 {
02635 int rec, sn;
02636 const int rec0p = harpInfo->rec0p;
02637 const int rec0 = harpInfo->rec0;
02638 const int rec1 = harpInfo->rec1;
02639 const int rec1p = harpInfo->rec1p;
02640 const float omega =
02641 patchInfo[rec0].omega / SEC_PER_DAY * cadence;
02642
02643
02644
02645 for (rec = rec0; rec <= rec1; rec++) {
02646
02647 if (tRec[rec].data == Trec_Data_OK && patchInfo[rec].valid == Patch_Invalid) {
02648
02649 patchInfo[rec].valid = Patch_Padding;
02650 patchInfo[rec].tag = Patch_Tag_Faint;
02651 patchInfo[rec].num = patchInfo[rec0].num;
02652 patchInfo[rec].lat0 = patchInfo[rec0].lat0;
02653 patchInfo[rec].lat1 = patchInfo[rec0].lat1;
02654 patchInfo[rec].lon0 = patchInfo[rec0].lon0 + (rec - rec0)*omega;
02655 patchInfo[rec].lon1 = patchInfo[rec0].lon1 + (rec - rec0)*omega;
02656 patchInfo[rec].omega = patchInfo[rec0].omega;
02657
02658
02659 if (patchInfo[rec].patchName)
02660 {
02661 free(patchInfo[rec].patchName);
02662 patchInfo[rec].patchName = calloc(1, sizeof(char));
02663 }
02664
02665 for (sn = 0; sn < RS_num_stats; sn++)
02666 patchInfo[rec].stats[sn] = DRMS_MISSING_FLOAT;
02667 }
02668 }
02669
02670 for (rec = rec0p; rec < rec0; rec++) {
02671
02672 if (tRec[rec].data == Trec_Data_OK) {
02673 patchInfo[rec].valid = Patch_Padding;
02674 patchInfo[rec].tag = Patch_Tag_None;
02675 patchInfo[rec].num = patchInfo[rec0].num;
02676 patchInfo[rec].lat0 = patchInfo[rec0].lat0;
02677 patchInfo[rec].lat1 = patchInfo[rec0].lat1;
02678 patchInfo[rec].lon0 = patchInfo[rec0].lon0 + (rec - rec0)*omega;
02679 patchInfo[rec].lon1 = patchInfo[rec0].lon1 + (rec - rec0)*omega;
02680 patchInfo[rec].omega = patchInfo[rec0].omega;
02681
02682
02683 if (patchInfo[rec].patchName)
02684 {
02685 free(patchInfo[rec].patchName);
02686 patchInfo[rec].patchName = calloc(1, sizeof(char));
02687 }
02688
02689 for (sn = 0; sn < RS_num_stats; sn++)
02690 patchInfo[rec].stats[sn] = DRMS_MISSING_FLOAT;
02691 }
02692 }
02693
02694 for (rec = rec1p; rec > rec1; rec--) {
02695
02696 if (tRec[rec].data == Trec_Data_OK) {
02697 patchInfo[rec].valid = Patch_Padding;
02698 patchInfo[rec].tag = Patch_Tag_None;
02699 patchInfo[rec].num = patchInfo[rec1].num;
02700 patchInfo[rec].lat0 = patchInfo[rec1].lat0;
02701 patchInfo[rec].lat1 = patchInfo[rec1].lat1;
02702 patchInfo[rec].lon0 = patchInfo[rec1].lon0 + (rec - rec1)*omega;
02703 patchInfo[rec].lon1 = patchInfo[rec1].lon1 + (rec - rec1)*omega;
02704 patchInfo[rec].omega = patchInfo[rec1].omega;
02705
02706
02707
02708 if (patchInfo[rec].patchName)
02709 {
02710 free(patchInfo[rec].patchName);
02711 patchInfo[rec].patchName = calloc(1, sizeof(char));
02712 }
02713 for (sn = 0; sn < RS_num_stats; sn++)
02714 patchInfo[rec].stats[sn] = DRMS_MISSING_FLOAT;
02715 }
02716 }
02717 return 0;
02718 }
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730 static
02731 int
02732 set_harp_info_extent(patch_info_t *patchInfo,
02733 harp_info_t *hInfo,
02734 trec_info_t *tRec,
02735 int nRec_all,
02736 int nRec_pad)
02737 {
02738 int rec;
02739 int rec0, rec1;
02740 int rec0p, rec1p;
02741
02742
02743 rec0 = nRec_all - 1;
02744 rec1 = 0;
02745 for (rec = 0; rec < nRec_all; rec++) {
02746 if (patchInfo[rec].valid == Patch_Normal) {
02747 if (rec < rec0) rec0 = rec;
02748 if (rec > rec1) rec1 = rec;
02749 }
02750 }
02751
02752 if (rec0 > rec1) {
02753 V_printf(-1, "", "Error: No patches present in this HARP.\n");
02754 return 1;
02755 }
02756
02757 rec0p = rec0 - nRec_pad;
02758 if (rec0p < 0) rec0p = 0;
02759
02760 while (tRec[rec0p].data != Trec_Data_OK)
02761 rec0p++;
02762
02763 rec1p = rec1 + nRec_pad;
02764 if (rec1p >= nRec_all) rec1p = nRec_all-1;
02765
02766 while (tRec[rec1p].data != Trec_Data_OK)
02767 rec1p--;
02768
02769 V_printf(verbflag > 2, "\t\t",
02770 "HARP %d: recs = {%d..%d} recspad = {%d..%d}\n",
02771 hInfo->id, rec0, rec1, rec0p, rec1p);
02772 hInfo->rec0 = rec0;
02773 hInfo->rec1 = rec1;
02774 hInfo->rec0p = rec0p;
02775 hInfo->rec1p = rec1p;
02776 return 0;
02777 }
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789 static
02790 void
02791 set_patch_info_pixbox(patch_info_t *patchInfo,
02792 harp_info_t *hInfo,
02793 trec_info_t *tRec,
02794 int pix_max,
02795 int nRec_all)
02796 {
02797 int rec;
02798 const int rec0p = hInfo->rec0p;
02799 const int rec0 = hInfo->rec0;
02800 const int rec1 = hInfo->rec1;
02801 const int rec1p = hInfo->rec1p;
02802 int rv, farside, pad_lo, pad_hi;
02803
02804
02805 farside = 0;
02806 for (rec = rec0p; rec <= rec1p; rec++) {
02807
02808 if (patchInfo[rec].valid == Patch_Invalid)
02809 continue;
02810
02811
02812 V_printf(verbflag > 2, "\t\t", "HARP[%d][%s]: bbox update\n",
02813 hInfo->id, tRec[rec].str);
02814 rv = compute_boundary(&(patchInfo[rec]), pix_max, tRec[rec].wcs);
02815
02816 if (rv) {
02817
02818 farside++;
02819
02820
02821
02822 patchInfo[rec].valid = Patch_Invalid;
02823 }
02824 }
02825
02826
02827
02828
02829 pad_lo = 0;
02830 for (rec = rec0p; patchInfo[rec].valid == Patch_Invalid && rec < rec0; rec++)
02831 pad_lo++;
02832 hInfo->rec0p = rec;
02833
02834
02835
02836 pad_hi = 0;
02837 for (rec = rec1p; patchInfo[rec].valid == Patch_Invalid && rec > rec1; rec--)
02838 pad_hi++;
02839 hInfo->rec1p = rec;
02840
02841 if (pad_lo > 0 || pad_hi > 0)
02842 V_printf(verbflag > 2, "\t\t",
02843 "HARP %d: recspad shrinks to {%d..%d} after finding %d farside patches\n",
02844 hInfo->id, hInfo->rec0p, hInfo->rec1p, farside);
02845 }
02846
02847
02848
02849
02850
02851
02852
02853
02854 static
02855 int
02856 set_harp_info_miss(patch_info_t *patchInfo,
02857 harp_info_t *hInfo,
02858 trec_info_t *tRec,
02859 int nRec_all)
02860 {
02861 int rec;
02862 int n_missing;
02863 int n_patch, n_patchp;
02864 const int rec0p = hInfo->rec0p;
02865 const int rec0 = hInfo->rec0;
02866 const int rec1 = hInfo->rec1;
02867 const int rec1p = hInfo->rec1p;
02868
02869
02870 for (n_patch = n_missing = 0, rec = rec0; rec <= rec1; rec++) {
02871 if (tRec[rec].data == Trec_Data_OK && patchInfo[rec].valid != Patch_Invalid)
02872 n_patch++;
02873 if (tRec[rec].data != Trec_Data_OK || patchInfo[rec].valid == Patch_Invalid)
02874 n_missing++;
02875 }
02876
02877 for (n_patchp = 0, rec = rec0p; rec <= rec1p; rec++)
02878 if (tRec[rec].data == Trec_Data_OK && patchInfo[rec].valid != Patch_Invalid)
02879 n_patchp++;
02880 V_printf(verbflag > 2, "\t\t",
02881 "HARP %d: #patches-seen = %d, #missing = %d, #patches-with-padding = %d\n",
02882 hInfo->id, n_patch, n_missing, n_patchp);
02883 hInfo->n_missing = n_missing;
02884 hInfo->n_patch = n_patch;
02885 hInfo->n_patchp = n_patchp;
02886 return 0;
02887 }
02888
02889
02890
02891
02892 static
02893 int
02894 mark_ingested_harp(const char *rootDir,
02895 run_info_t *runInfo,
02896 harp_info_t *hInfo)
02897 {
02898 char statusFile[STR_MAX];
02899 FILE *statusFp;
02900 int harp_id;
02901 time_t tloc;
02902 char timestr[32];
02903 const char *run_key = "run_name";
02904 char *run_name;
02905 int p;
02906
02907 if (rootDir == NULL) return 1;
02908 harp_id = hInfo->id;
02909
02910 time(&tloc);
02911 strftime(timestr, sizeof(timestr), "%Y%m%dT%H%M%S", localtime(&tloc));
02912
02913 run_name = "unnamed_run";
02914 for (p = 0; p < runInfo->n_par; p++) {
02915 if (strcasecmp(run_key, runInfo->par_names[p]) == 0) {
02916 run_name = runInfo->par_vals[p];
02917 break;
02918 }
02919 }
02920
02921
02922 snprintf(statusFile, sizeof(statusFile),
02923 "%s/" FN_TRACK_DIR "/%s", rootDir, harp_id, FN_TRACK_STATUS);
02924
02925 statusFp = fopen(statusFile, "a");
02926 if (!statusFp) {
02927 V_printf(-1, "",
02928 "Warning: unable to append to status file %s for HARP %06d (post-ingest).\n",
02929 statusFile, harp_id);
02930 return 1;
02931 }
02932 fprintf(statusFp, "%s\t%s\t%s\n", "ingested", run_name, timestr);
02933 fclose(statusFp);
02934 return 0;
02935 }
02936
02937
02938
02939
02940
02941
02942
02943 static
02944 int
02945 load_all_patch_info(const char *rootDir,
02946 const char *refHarp,
02947 patch_info_t *patchInfo,
02948 harp_info_t *harpInfo,
02949 trec_info_t *tRec,
02950 int nHarp,
02951 int nRec_all, int nRec_pad,
02952 double cadence,
02953 int pix_max)
02954 {
02955
02956 char currDir[STR_MAX];
02957 char frameFile[STR_MAX], statFile[STR_MAX];
02958
02959 int i;
02960 int harp_id;
02961 int rec;
02962 patch_info_t pInfo;
02963 int status;
02964
02965 for (i = 0; i < nHarp; i++) {
02966
02967
02968
02969
02970 harp_id = harpInfo[i].id;
02971
02972 snprintf(currDir, sizeof(currDir), "%s/" FN_TRACK_DIR, rootDir, harp_id);
02973 snprintf(frameFile, sizeof(frameFile), "%s/%s", currDir, FN_TRACK_FRAME);
02974 snprintf(statFile, sizeof(statFile), "%s/%s", currDir, FN_TRACK_STATS);
02975
02976 status =
02977 load_harp_patches(harp_id,
02978 refHarp,
02979 currDir, frameFile, statFile,
02980 patchInfo + i*nRec_all,
02981 harpInfo + i,
02982 tRec,
02983 nRec_all, cadence);
02984 if (status != 0) {
02985 V_printf(-1, "", "Error: Could not load HARP %d (id = %06d).\n", i, harp_id);
02986 return status;
02987 }
02988
02989
02990 status = set_harp_info_extent(patchInfo+nRec_all*i, harpInfo+i, tRec, nRec_all, nRec_pad);
02991 if (status != 0) {
02992 V_printf(-1, "", "Error: Could not find boundaries: HARP %d (id = %06d).\n",
02993 i, harp_id);
02994 return status;
02995 }
02996
02997 set_patch_info_blanks(patchInfo+nRec_all*i, harpInfo+i, tRec, nRec_all, cadence);
02998
02999
03000
03001
03002
03003 set_patch_info_pixbox(patchInfo+nRec_all*i, harpInfo+i, tRec, pix_max, nRec_all);
03004
03005
03006 set_harp_info_miss(patchInfo+nRec_all*i, harpInfo+i, tRec, nRec_all);
03007 }
03008
03009 if (0)
03010 for (i = 0; i < 1 && i < nHarp; i++)
03011 for (rec = 0; rec < nRec_all; rec++) {
03012 if (patchInfo[i * nRec_all + rec].valid) {
03013 patch_info_t tmp = patchInfo[i * nRec_all + rec];
03014 if (tmp.valid != Patch_Normal) continue;
03015 printf("\trec# = %d, x0 = %d, y0 = %d\n", rec, tmp.x0, tmp.y0);
03016 printf("\ttrack stats: #pix=%.2f, area1=%.2f, area2=%.2f\n",
03017 tmp.stats[0], tmp.stats[1], tmp.stats[2]);
03018 fflush(stdout);
03019 break;
03020 }
03021 }
03022 return 0;
03023 }
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036 static
03037 int
03038 ingest_harp(patch_info_t *pInfo,
03039 harp_info_t *hInfo,
03040 trec_info_t *tRec1,
03041 trec_info_t *tRec,
03042 run_info_t *runInfo,
03043 marp_info_t *mInfo,
03044 DRMS_Record_t *magRec,
03045 DRMS_Record_t *maskRec,
03046 char *maskImg,
03047 int maskStride,
03048 char *outQuery)
03049 {
03050 int rv;
03051
03052 if (pInfo->valid == Patch_Invalid) return 0;
03053
03054 if (pInfo->valid == Patch_Normal) {
03055
03056 if (!pInfo->patchName) {
03057 V_printf(-1, "", "Internal error: Bad patchName during ingest %s.\n", outQuery);
03058 return 1;
03059 }
03060 if (load_fits(pInfo->patchName, &(pInfo->image), pInfo->dims) != 0) {
03061 V_printf(-1, "", "Patch read failed, could not ingest %s.\n", outQuery);
03062 return 1;
03063 }
03064
03065 if (pInfo->dims[0] != pInfo->fits_nx ||
03066 pInfo->dims[1] != pInfo->fits_ny) {
03067 free(pInfo->image);
03068 pInfo->image = NULL;
03069 V_printf(-1, "", "Patch dims mismatch: fits = (%d,%d) frame = (%d,%d).\n",
03070 pInfo->dims[0], pInfo->dims[1],
03071 pInfo->fits_nx, pInfo->fits_ny);
03072 V_printf(-1, "", "Patch read failed, could not ingest %s.\n", outQuery);
03073 return 1;
03074 }
03075 } else {
03076
03077 pInfo->image = NULL;
03078 }
03079
03080
03081 if (update_bitmap(pInfo, maskImg, maskStride) != 0) {
03082 V_printf(-1, "", "Could not compute full HARP mask at %s\n", outQuery);
03083 return 1;
03084 }
03085
03086
03087
03088
03089 rv = ingest_record(pInfo, hInfo, tRec1, tRec, runInfo,
03090 mInfo, magRec, maskRec, outQuery);
03091 if (rv == 2) {
03092 V_printf(-1, "", "Failed to insert %s\n", outQuery);
03093 return 1;
03094 } else if (rv == 1) {
03095
03096 V_printf(verbflag > 1, "", "Some nonfatal errors with %s\n", outQuery);
03097 }
03098
03099 return 0;
03100 }
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115 static
03116 int
03117 update_bitmap(patch_info_t *pInfo, char *maskImg, int maskStride)
03118 {
03119 char *patch_map = pInfo->image;
03120 char patch_val;
03121 int nx = pInfo->xmax - pInfo->xmin + 1;
03122 int ny = pInfo->ymax - pInfo->ymin + 1;
03123 int i, j, i0, j0;
03124
03125 if (pInfo->valid == Patch_Invalid)
03126 return 0;
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138 pInfo->image = calloc(nx*ny, sizeof(*(pInfo->image)));
03139 if (pInfo->image == NULL) {
03140 pInfo->image = patch_map;
03141 V_printf(-1, "", "Unable to allocate space for new patch bitmap\n");
03142 return 1;
03143 }
03144
03145
03146 for (j = 0; j < ny; j++)
03147 for (i = 0; i < nx; i++)
03148 pInfo->image[j*nx + i] = maskImg[(j + pInfo->ymin) * maskStride +
03149 (i + pInfo->xmin)];
03150 V_printf(verbflag > 2, "\t\t ", "shifting mask (nx,ny) = (%d, %d) -> (%d, %d)\n",
03151 pInfo->dims[0], pInfo->dims[1], nx, ny);
03152
03153
03154 if (patch_map) {
03155 for (j = 0; j < ny; j++) {
03156 for (i = 0; i < nx; i++) {
03157
03158
03159
03160 i0 = pInfo->xmin + i - pInfo->x0;
03161 j0 = pInfo->ymin + j - pInfo->y0;
03162
03163 if (i0 < 0 || i0 >= pInfo->dims[0]) continue;
03164 if (j0 < 0 || j0 >= pInfo->dims[1]) continue;
03165 patch_val = patch_map[j0 * (pInfo->dims[0]) + i0];
03166
03167
03168 if (patch_val != 0)
03169 pInfo->image[j*nx+i] = patch_val;
03170 }
03171 }
03172
03173 free(patch_map);
03174 }
03175
03176 pInfo->x0 = pInfo->xmin;
03177 pInfo->y0 = pInfo->ymin;
03178 pInfo->dims[0] = nx;
03179 pInfo->dims[1] = ny;
03180 return 0;
03181 }
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194 static
03195 int
03196 ingest_record(patch_info_t *pInfo,
03197 harp_info_t *hInfo,
03198 trec_info_t *tRec1,
03199 trec_info_t *tRec,
03200 run_info_t *runInfo,
03201 marp_info_t *mInfo,
03202 DRMS_Record_t *magRec,
03203 DRMS_Record_t *maskRec,
03204 char *outQuery)
03205 {
03206 DRMS_Record_t *outRec = NULL;
03207 DRMS_Segment_t *outSeg = NULL;
03208 DRMS_Array_t *outData = NULL;
03209 DRMS_Link_t *link;
03210 int datavals, totvals;
03211 double xDist, yDist;
03212 char *inst_mode;
03213 int status = 0;
03214 int rv;
03215 int ok, not_ok;
03216 int i;
03217
03218 rv = 0;
03219 outRec = drms_create_record(drms_env, outQuery, DRMS_PERMANENT, &rv);
03220 if (rv) {
03221 V_printf(-1, "", "Could not create record for patch bitmap.\n");
03222
03223 if (pInfo->image)
03224 {
03225 free(pInfo->image);
03226 pInfo->image = NULL;
03227 }
03228 return 2;
03229 }
03230 outSeg = drms_segment_lookup(outRec, "bitmap");
03231 if (!outSeg) {
03232 V_printf(-1, "", "Could not find bitmap segment in patch.\n");
03233 drms_close_record(outRec, DRMS_FREE_RECORD);
03234
03235 if (pInfo->image)
03236 {
03237 free(pInfo->image);
03238 pInfo->image = NULL;
03239 }
03240 return 2;
03241 }
03242
03243 outData = drms_array_create(DRMS_TYPE_CHAR, 2, pInfo->dims, pInfo->image, &rv);
03244 if (rv) {
03245 V_printf(-1, "", "Could not create array for patch bitmap segment.\n");
03246 if (outData)
03247 {
03248 drms_free_array(outData);
03249 pInfo->image = NULL;
03250 }
03251 return 2;
03252 }
03253
03254 outSeg->axis[0] = outData->axis[0];
03255 outSeg->axis[1] = outData->axis[1];
03256 outData->parent_segment = outSeg;
03257
03258
03259
03260
03261 inst_mode = get_instrument_mode(magRec);
03262
03263 not_ok = 0;
03264 ok = drms_setkey_int (outRec, "HARPNUM", pInfo->num);
03265 if (ok != DRMS_SUCCESS) not_ok++;
03266 ok = drms_setkey_time (outRec, "T_REC", tRec1->t);
03267 if (ok != DRMS_SUCCESS) not_ok++;
03268
03269 ok = drms_setkey_string(outRec, "BLD_VERS", jsoc_version);
03270 if (ok != DRMS_SUCCESS) not_ok++;
03271 ok = drms_setkey_time (outRec, "DATE", CURRENT_SYSTEM_TIME);
03272 if (ok != DRMS_SUCCESS) not_ok++;
03273
03274 not_ok += set_keys_code_info(inst_mode, outRec);
03275
03276
03277 not_ok += set_keys_runinfo(outRec, runInfo);
03278
03279 not_ok += set_keys_stats(inst_mode, outRec, magRec, maskRec, pInfo, hInfo, tRec);
03280
03281 not_ok += set_keys_match(outRec, hInfo, mInfo);
03282
03283 totvals = (pInfo->dims[0])*(pInfo->dims[1]);
03284 for (datavals = i = 0; i < totvals; i++)
03285 if (pInfo->image[i] != 0) datavals++;
03286 ok = drms_setkey_int(outRec, "TOTVALS", totvals);
03287 if (ok != DRMS_SUCCESS) not_ok++;
03288 ok = drms_setkey_int(outRec, "DATAVALS", datavals);
03289 if (ok != DRMS_SUCCESS) not_ok++;
03290 ok = drms_setkey_int(outRec, "MISSVALS", totvals-datavals);
03291 if (ok != DRMS_SUCCESS) not_ok++;
03292
03293 distance2center(tRec1->wcs, pInfo->x0, pInfo->y0, &xDist, &yDist);
03294 ok = drms_setkey_float(outRec, "CRVAL1", xDist);
03295 if (ok != DRMS_SUCCESS) not_ok++;
03296 ok = drms_setkey_float(outRec, "CRVAL2", yDist);
03297 if (ok != DRMS_SUCCESS) not_ok++;
03298
03299 if (not_ok > 0) {
03300 V_printf(-1, "\t\t", "Failed to set up %d patch keys: %s\n", not_ok, tRec1->str);
03301
03302
03303 }
03304
03305
03306 rv = drms_setlink_static(outRec, "MDATA", magRec->recnum);
03307 if (rv) {
03308 status = 1;
03309 V_printf(-1, "\t", "MDATA link failed\n");
03310 }
03311 rv = drms_setlink_static(outRec, "MASK", maskRec->recnum);
03312 if (rv) {
03313 status = 1;
03314 V_printf(-1, "\t", "MASK link failed\n");
03315 }
03316
03317 rv = drms_segment_write(outSeg, outData, 0);
03318 if (rv) {
03319 V_printf(-1, "", "Failed to write segment for patch.\n");
03320 drms_free_array(outData);
03321 return 2;
03322 }
03323 drms_free_array(outData);
03324 pInfo->image = NULL;
03325 drms_close_record(outRec, DRMS_INSERT_RECORD);
03326 return status;
03327 }
03328
03329
03330
03331
03332
03333
03334 static
03335 int
03336 tag_is_invalid(int tag)
03337 {
03338 if ((tag == (int) Patch_Tag_Faint ) ||
03339 (tag == (int) Patch_Tag_Harder) ||
03340 (tag == (int) Patch_Tag_Normal) ||
03341 (tag == (int) Patch_Tag_Merge ))
03342 return 0;
03343 else
03344 return 1;
03345 }
03346
03347
03348
03349
03350
03351 static
03352 int
03353 load_frame(FILE *fp, patch_info_t *pInfo, TIME *t)
03354 {
03355 const int rv_expect = 12;
03356 char t_rec[24];
03357 int tag;
03358 int rv;
03359
03360 pInfo->valid = Patch_Invalid;
03361
03362 rv = fscanf(fp, "%d %23s %d %d %d %d %d %f %f %f %f %f",
03363 &(pInfo->num),
03364 t_rec,
03365 &tag,
03366 &(pInfo->fits_nx),
03367 &(pInfo->fits_ny),
03368 &(pInfo->x0),
03369 &(pInfo->y0),
03370 &(pInfo->lat0),
03371 &(pInfo->lon0),
03372 &(pInfo->lat1),
03373 &(pInfo->lon1),
03374 &(pInfo->omega));
03375 if (rv == EOF) return -1;
03376 if (rv != rv_expect) {
03377 V_printf(-1, "", "Warning: could not read frame line, bad file?\n");
03378 return 1;
03379 }
03380 if (tag_is_invalid(tag)) {
03381 V_printf(-1, "", "Warning: could not read frame tag (%d), bad value?\n", tag);
03382 return 1;
03383 } else {
03384 pInfo->tag = (patch_tag_t) tag;
03385 }
03386
03387
03388 pInfo->x0 -= 1;
03389 pInfo->y0 -= 1;
03390
03391 *t = sscan_time(t_rec);
03392 if (time_is_invalid(*t)) {
03393 V_printf(-1, "", "Warning: could not read frame time (%s), bad file?\n", t_rec);
03394 return 1;
03395 }
03396 if (isnan(pInfo->lat0) || isnan(pInfo->lat1) ||
03397 isnan(pInfo->lon0) || isnan(pInfo->lon1) || isnan(pInfo->omega)) {
03398 V_printf(-1, "", "Warning: found a NaN in frame line, bad file?\n");
03399 return 1;
03400 }
03401
03402
03403 pInfo->valid = Patch_Normal;
03404 return 0;
03405 }
03406
03407
03408
03409
03410
03411 static
03412 int
03413 load_stats(FILE *fp, float *stats)
03414 {
03415 int i;
03416 int rv;
03417 float x;
03418
03419 for (i = 0; i < RS_num_stats; i++) {
03420 rv = fscanf(fp, "%f", &x);
03421 if (rv == EOF) return -1;
03422 if (rv != 1) {
03423 V_printf(-1, "", "Warning: load_stats could not read stat #%d, bad file?\n", i+1);
03424 return 1;
03425 }
03426 stats[i] = x;
03427
03428 }
03429 return 0;
03430 }
03431
03432
03433
03434
03435
03436
03437 static
03438 int
03439 load_fits(char *filename, char **image, int *dims)
03440 {
03441 char *data = NULL;
03442 fitsfile *fptr = NULL;
03443 int fstatus = 0;
03444 int mem_err = 0;
03445 int bitpix;
03446 int naxis;
03447 long datasize;
03448 long dims_long[2];
03449 long fpixel[2] = {1, 1};
03450
03451 fits_open_file(&fptr, filename, READONLY, &fstatus);
03452 if (fstatus != 0) goto done;
03453 fits_get_img_param(fptr, 2, &bitpix, &naxis, dims_long, &fstatus);
03454 if (fstatus != 0) goto done;
03455
03456 datasize = dims_long[0] * dims_long[1];
03457 if ((data = calloc(datasize, sizeof(*data))) == NULL) {
03458 mem_err = 1;
03459 goto done;
03460 }
03461
03462 fits_read_pix(fptr, TSBYTE, fpixel, datasize, NULL, data, NULL, &fstatus);
03463 if (fstatus != 0) goto done;
03464
03465 done:
03466 if (fptr)
03467 fits_close_file(fptr, &fstatus);
03468 if (fstatus || mem_err) {
03469
03470 char err_msg[FLEN_STATUS];
03471 if (mem_err)
03472 strncpy(err_msg, "failed calloc for image data", sizeof(err_msg));
03473 else
03474 fits_get_errstatus(fstatus, err_msg);
03475 V_printf(-1, "", "Error opening fits file `%s': %s\n", filename, err_msg);
03476
03477 free(data);
03478
03479 *image = NULL;
03480 dims[0] = dims[1] = 0;
03481 } else {
03482
03483 *image = data;
03484 dims[0] = dims_long[0];
03485 dims[1] = dims_long[1];
03486 }
03487 return (fstatus || mem_err) ? 1 : 0;
03488 }
03489
03490
03491
03492
03493
03494
03495
03496 static
03497 char *
03498 get_instrument_mode(DRMS_Record_t *xmRec)
03499 {
03500 char * const default_mode = "HMI";
03501 int status = 0;
03502 char *kw;
03503
03504 kw = drms_getkey_string(xmRec, "TELESCOP", &status);
03505 if (status == 0) {
03506
03507 if (strcasestr(kw, "SDO") || strcasestr(kw, "HMI"))
03508 return "HMI";
03509 else if (strcasestr(kw, "SOHO") || strcasestr(kw, "MDI"))
03510 return "MDI";
03511 else
03512 return default_mode;
03513 }
03514 return default_mode;
03515 }
03516
03517
03518
03519
03520 static int
03521 set_keys_code_info(char *inst_mode, DRMS_Record_t *outRec)
03522 {
03523 extern char *hmi_mharp_version;
03524 char *doc_url;
03525 char keystr[80];
03526 int ok;
03527 int not_ok = 0;
03528
03529
03530
03531 if (strcmp(inst_mode, "HMI") == 0)
03532 doc_url = "http://jsoc.stanford.edu/jsocwiki/HARPDataSeries";
03533 else if (strcmp(inst_mode, "MDI") == 0)
03534 doc_url = "http://jsoc.stanford.edu/jsocwiki/MTARPDataSeries";
03535 else
03536 doc_url = "No known documentation";
03537 ok = drms_setkey_string(outRec, "HRPDOCU", doc_url);
03538 if (ok != DRMS_SUCCESS) not_ok++;
03539
03540 snprintf(keystr, sizeof(keystr), "%s ver: %s", module_name, hmi_mharp_version);
03541 ok = drms_setkey_string(outRec, "HRPCODEV", keystr);
03542 if (ok != DRMS_SUCCESS) not_ok++;
03543 return not_ok;
03544 }
03545
03546
03547
03548
03549
03550 static
03551 int
03552 set_keys_runinfo(DRMS_Record_t *rec,
03553 run_info_t *runInfo)
03554 {
03555 const char **keys = tracker_run_info_keys;
03556 const char *drms_key;
03557 const char *tracker_key;
03558 int not_ok, iKey;
03559 int p, found, ok;
03560
03561 for (not_ok = iKey = 0; keys[iKey] != NULL; iKey += 2) {
03562
03563 drms_key = keys[iKey];
03564 tracker_key = keys[iKey+1];
03565
03566 for (found = p = 0; p < runInfo->n_par; p++) {
03567 if (strcasecmp(tracker_key, runInfo->par_names[p]) == 0) {
03568 found = 1;
03569 ok = drms_setkey_string(rec, drms_key, runInfo->par_vals[p]);
03570 if (ok != DRMS_SUCCESS) not_ok++;
03571 }
03572 }
03573 if (!found) not_ok++;
03574 }
03575 return not_ok;
03576 }
03577
03578
03579
03580
03581
03582 static
03583 int
03584 set_keys_match(DRMS_Record_t *rec,
03585 harp_info_t *hInfo,
03586 marp_info_t *mInfo)
03587 {
03588 int ok, status;
03589 int not_ok = 0;
03590 const int nMatch = hInfo->n_match;
03591 int best_match, m;
03592 char str[20];
03593 char all_match[STR_MAX];
03594
03595
03596 ok = drms_setkey_int(rec, "NOAA_NUM", nMatch);
03597 if (ok != DRMS_SUCCESS) not_ok++;
03598
03599 if (nMatch == 0)
03600 best_match = 0;
03601 else
03602 best_match = mInfo[hInfo->top_match].id;
03603 ok = drms_setkey_int(rec, "NOAA_AR", best_match);
03604 if (ok != DRMS_SUCCESS) not_ok++;
03605
03606 *all_match = '\0';
03607 for (m = 0; m < nMatch; m++) {
03608 snprintf(str, sizeof(str), "%s%d", (m == 0) ? "" : ",", mInfo[hInfo->match[m]].id);
03609 strncat(all_match, str, sizeof(all_match));
03610 }
03611 ok = drms_setkey_string(rec, "NOAA_ARS", all_match);
03612 if (ok != DRMS_SUCCESS) not_ok++;
03613 return not_ok;
03614 }
03615
03616
03617
03618
03619
03620
03621 static
03622 int
03623 set_keys_stats(char *inst_mode,
03624 DRMS_Record_t *rec,
03625 DRMS_Record_t *magRec,
03626 DRMS_Record_t *maskRec,
03627 patch_info_t *pInfo,
03628 harp_info_t *hInfo,
03629 trec_info_t *tRec)
03630 {
03631 float *stats = pInfo->stats;
03632 int ok, status;
03633 int not_ok = 0;
03634
03635 status = propagate_keys_harp(inst_mode, magRec, maskRec, rec);
03636 if (status == -1) {
03637
03638 V_printf(-1, "", "set_keys: propagate_keys failed (null record)\n");
03639 } else {
03640 not_ok += status;
03641 }
03642
03643
03644 ok = drms_setkey_float(rec, "CRPIX1", pInfo->x0);
03645 if (ok != DRMS_SUCCESS) not_ok++;
03646 ok = drms_setkey_float(rec, "CRPIX2", pInfo->y0);
03647 if (ok != DRMS_SUCCESS) not_ok++;
03648
03649 ok = drms_setkey_float(rec, "CRSIZE1", pInfo->dims[0]);
03650 if (ok != DRMS_SUCCESS) not_ok++;
03651 ok = drms_setkey_float(rec, "CRSIZE2", pInfo->dims[1]);
03652 if (ok != DRMS_SUCCESS) not_ok++;
03653
03654 ok = drms_setkey_time(rec, "T_FRST", tRec[hInfo->rec0p].t);
03655 if (ok != DRMS_SUCCESS) not_ok++;
03656 ok = drms_setkey_time(rec, "T_FRST1", tRec[hInfo->rec0 ].t);
03657 if (ok != DRMS_SUCCESS) not_ok++;
03658 ok = drms_setkey_time(rec, "T_LAST1", tRec[hInfo->rec1 ].t);
03659 if (ok != DRMS_SUCCESS) not_ok++;
03660 ok = drms_setkey_time(rec, "T_LAST", tRec[hInfo->rec1p].t);
03661 if (ok != DRMS_SUCCESS) not_ok++;
03662 ok = drms_setkey_int(rec, "N_PATCH", hInfo->n_patchp);
03663 if (ok != DRMS_SUCCESS) not_ok++;
03664 ok = drms_setkey_int(rec, "N_PATCH1", hInfo->n_patch);
03665 if (ok != DRMS_SUCCESS) not_ok++;
03666 ok = drms_setkey_int(rec, "N_PATCHM", hInfo->n_missing);
03667 if (ok != DRMS_SUCCESS) not_ok++;
03668
03669
03670 ok = drms_setkey_int(rec, "H_MERGE", (pInfo->tag == Patch_Tag_Merge ) ? 1 : 0);
03671 if (ok != DRMS_SUCCESS) not_ok++;
03672 ok = drms_setkey_int(rec, "H_FAINT",
03673 ((pInfo->tag == Patch_Tag_Harder) ||
03674 (pInfo->tag == Patch_Tag_Faint )) ? 1 : 0);
03675 if (ok != DRMS_SUCCESS) not_ok++;
03676
03677 ok = drms_setkey_float(rec, "LONDTMIN", pInfo->lon0);
03678 if (ok != DRMS_SUCCESS) not_ok++;
03679 ok = drms_setkey_float(rec, "LATDTMIN", pInfo->lat0);
03680 if (ok != DRMS_SUCCESS) not_ok++;
03681 ok = drms_setkey_float(rec, "LONDTMAX", pInfo->lon1);
03682 if (ok != DRMS_SUCCESS) not_ok++;
03683 ok = drms_setkey_float(rec, "LATDTMAX", pInfo->lat1);
03684 if (ok != DRMS_SUCCESS) not_ok++;
03685 ok = drms_setkey_float(rec, "OMEGA_DT", pInfo->omega);
03686 if (ok != DRMS_SUCCESS) not_ok++;
03687
03688 int sn;
03689 for (sn = 0; sn < RS_num_stats; sn++) {
03690 char *name1 = (char *) RS_index2keyname[sn];
03691
03692
03693 if (name1) {
03694 switch (*name1) {
03695 case 'i':
03696 ok = drms_setkey_int(rec, name1+1, (int) stats[sn]);
03697 break;
03698 case 'f':
03699 ok = drms_setkey_float(rec, name1+1, (float) stats[sn]);
03700 break;
03701 default:
03702
03703 V_printf(-1, "", "set_keys: Unknown key type (first char of keyname %s)\n", name1);
03704 ok = DRMS_SUCCESS + 1;
03705 break;
03706 }
03707 if (ok != DRMS_SUCCESS) not_ok++;
03708 V_printf(ok != DRMS_SUCCESS, "", "set_keys: failed to set %s -> %f\n", name1, stats[sn]);
03709 }
03710 }
03711 return not_ok;
03712 }
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733 #define UPDATE_RANGE do { \
03734 ondisk = 1; \
03735 if (x < xmin) xmin = x; \
03736 if (x > xmax) xmax = x; \
03737 if (y < ymin) ymin = y; \
03738 if (y > ymax) ymax = y; \
03739 } while (0)
03740
03741 static
03742 int
03743 compute_boundary(patch_info_t *pInfo, int pix_max, wcs_t wcs)
03744 {
03745 int farside, ondisk;
03746 double xmin, xmax, ymin, ymax;
03747 double x, y, lat, lon, lat0, lon0, lat1, lon1, dl;
03748
03749
03750
03751
03752 double crvalx, crvaly, crpix1, crpix2, cdelt, crota2, sina, cosa;
03753 WCS2LOCALS(wcs);
03754
03755 double xcen = PIX_X(0.0,0.0) - 1.0;
03756 double ycen = PIX_Y(0.0,0.0) - 1.0;
03757
03758 double latc = wcs.crlt_obs * RADSINDEG;
03759 double lonc = wcs.crln_obs * RADSINDEG;
03760 double peff = - wcs.crota2 * RADSINDEG;
03761 double ang_r = asin(wcs.rsun_ref / wcs.dsun_obs);
03762 double rsun = asin(wcs.rsun_ref / wcs.dsun_obs) * RAD2ARCSEC / wcs.cdelt1;
03763
03764 V_printf(verbflag > 2, "\t\t ", "cen = (%.2f, %.2f) R=%f latc=%.2f lonc=%.2f\n",
03765 pInfo->num, xcen, ycen, rsun, latc/RADSINDEG, lonc/RADSINDEG);
03766
03767
03768 lat0 = pInfo->lat0 * RADSINDEG;
03769 lat1 = pInfo->lat1 * RADSINDEG;
03770 lon0 = pInfo->lon0 * RADSINDEG + lonc;
03771 lon1 = pInfo->lon1 * RADSINDEG + lonc;
03772 dl = 0.03 * RADSINDEG;
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782 farside = 0;
03783
03784 ondisk = 0;
03785 xmin = ymin = HUGE_VAL;
03786 xmax = ymax = -HUGE_VAL;
03787
03788 for (lat = lat0; lat <= lat1; lat += dl) {
03789 if (!sphere2img(lat, lon0, latc, lonc, &x, &y, xcen, ycen,
03790 rsun, peff, 0., 0., 0., 0.))
03791 UPDATE_RANGE;
03792 else
03793 farside = 1;
03794 if (!sphere2img(lat, lon1, latc, lonc, &x, &y, xcen, ycen,
03795 rsun, peff, 0., 0., 0., 0.))
03796 UPDATE_RANGE;
03797 else
03798 farside = 1;
03799 }
03800
03801 for (lon = lon0; lon <= lon1; lon += dl) {
03802 if (!sphere2img(lat0, lon, latc, lonc, &x, &y, xcen, ycen,
03803 rsun, peff, 0., 0., 0., 0.))
03804 UPDATE_RANGE;
03805 else
03806 farside = 1;
03807 if (!sphere2img(lat1, lon, latc, lonc, &x, &y, xcen, ycen,
03808 rsun, peff, 0., 0., 0., 0.))
03809 UPDATE_RANGE;
03810 else
03811 farside = 1;
03812 }
03813 V_printf(verbflag > 2, "\t\t ",
03814 "BB : (%.3f, %.3f) X (%.3f, %.3f), %s, %s\n", xmin, xmax, ymin, ymax,
03815 ondisk ? "some on-disk pixels" : "no visible pixels",
03816 farside ? "some farside pixels" : "no farside pixels");
03817
03818 if (!ondisk)
03819 return 1;
03820
03821
03822
03823
03824 if (farside) {
03825 xmin -= 1.0;
03826 xmax += 1.0;
03827 ymin -= 1.0;
03828 ymax += 1.0;
03829 }
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839 double rho, sinlat, coslat, sig, mu, chi;
03840 int rv;
03841 for (double xpos = -1; xpos <= 1; xpos += 1)
03842 for (double ypos = -1; ypos <= 1; ypos += 1) {
03843 if (!(xpos == 0 || ypos == 0)) continue;
03844 if (xpos == 0 && ypos == 0) continue;
03845 rv = img2sphere(xpos, ypos,
03846 ang_r, latc, lonc, peff,
03847 &rho, &lat, &lon, &sinlat, &coslat, &sig, &mu, &chi);
03848 if (rv)
03849 V_printf(verbflag > 3, "\t\t\t", "(%f,%f) not on sphere\n", xpos, ypos);
03850 else
03851 V_printf(verbflag > 3, "\t\t\t",
03852 "(x,y) = (% .1f,% .1f) -> (lat,lon) = (% 6.1f,% 6.1f)\n",
03853 xpos, ypos, lat/RADSINDEG, lon/RADSINDEG);
03854
03855 while (lon < lon0) lon += 2*M_PI;
03856 while (lon > lon1) lon -= 2*M_PI;
03857 if (lat0 <= lat && lat <= lat1 && lon0 <= lon && lon <= lon1) {
03858
03859 V_printf(verbflag > 2, "\t\t ", "Note: Extremum found off the box boundary.\n");
03860
03861
03862 x = xcen + rsun*xpos;
03863 y = ycen + rsun*ypos;
03864 UPDATE_RANGE;
03865 }
03866 }
03867
03868
03869
03870 V_printf(verbflag > 2, "\t\t ", "BB pre : (%.3f, %.3f) X (%.3f, %.3f)\n",
03871 xmin, xmax, ymin, ymax);
03872 if (xmin < 0 ) xmin = 0;
03873 if (xmax >= pix_max) xmax = pix_max - 1;
03874 if (ymin < 0 ) ymin = 0;
03875 if (ymax >= pix_max) ymax = pix_max - 1;
03876 V_printf(verbflag > 2, "\t\t ", "BB clip: (%.3f, %.3f) X (%.3f, %.3f)\n",
03877 xmin, xmax, ymin, ymax);
03878
03879 pInfo->xmin = floor(xmin);
03880 pInfo->xmax = ceil(xmax);
03881 pInfo->ymin = floor(ymin);
03882 pInfo->ymax = ceil(ymax);
03883 V_printf(verbflag > 2, "\t\t ", "BB end : (%d, %d) X (%d, %d)\n",
03884 pInfo->xmin, pInfo->xmax, pInfo->ymin, pInfo->ymax);
03885
03886 return 0;
03887 }
03888
03889
03890 #undef UPDATE_RANGE
03891
03892
03893
03894
03895
03896
03897 static
03898 void
03899 distance2center(wcs_t wcs, double x, double y, double *xDist, double *yDist)
03900 {
03901
03902 double crvalx, crvaly, crpix1, crpix2, cdelt, crota2, sina, cosa;
03903 WCS2LOCALS(wcs);
03904
03905
03906 double pix_x = x + 1.0;
03907 double pix_y = y + 1.0;
03908
03909
03910 *xDist = WX(pix_x,pix_y);
03911 *yDist = WY(pix_x,pix_y);
03912
03913
03914 }