00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <jsoc_main.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <math.h>
00028 #include "cartography.c"
00029
00030
00031
00032 #ifndef MIN
00033 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
00034 #endif
00035 #ifndef MAX
00036 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
00037 #endif
00038
00039 #define SHOW(msg) {printf("%s", msg); fflush(stdout);}
00040 #define DIE(msg) {fflush(stdout); fprintf(stderr,"%s (status=%d)\n", msg, status); return(status);}
00041
00042 #define FREE_ARR(arr) {if (arr) {free(arr);}}
00043 #define DRMS_FREE_ARR(arr) {if (arr) {drms_free_array(arr);}}
00044
00045 #define EPSL (1.0E-5)
00046 #define RAD2DEG (180. / M_PI)
00047 #define RAD2ARCSEC (648000. / M_PI)
00048
00049
00050 #define APOD (0.995)
00051
00052
00053 #define BRTHRESH (120.)
00054
00055
00056
00057
00058
00059
00060 struct ephemeris {
00061 double rsun_obs;
00062 double asd;
00063 double xc, yc;
00064 double cdelt;
00065 double p0, b0;
00066 double rsun;
00067 double da;
00068 };
00069
00070 struct fwt {
00071 double fluxn[2];
00072 double fluxs[2];
00073 double latn[2];
00074 double lats[2];
00075 };
00076
00077
00078
00079
00080
00081 double getwalltime(void)
00082 {
00083 struct timeval tv;
00084 gettimeofday(&tv, NULL);
00085 return tv.tv_sec * 1000.0 + tv.tv_usec/1000.0;
00086 }
00087
00088 double getcputime(double *utime, double *stime)
00089 {
00090
00091 struct rusage ru;
00092 getrusage(RUSAGE_SELF, &ru);
00093 *utime = ru.ru_utime.tv_sec * 1000.0 + ru.ru_utime.tv_usec/1000.0;
00094 *stime = ru.ru_stime.tv_sec * 1000.0 + ru.ru_stime.tv_usec/1000.0;
00095 return *utime + *stime;
00096 }
00097
00098
00099
00100 int get_ephemeris(DRMS_Record_t *inRec, struct ephemeris *ephem);
00101
00102
00103 void get_lonlat(struct ephemeris *ephem, int *dims, double *lon, double *lat, double *wght);
00104
00105
00106 void los2radial(struct ephemeris *ephem, int *dims, double *bl, double *br, double *wght);
00107
00108
00109 void compute_mf(int *dims, double *br, double *bl, double *lon, double *lat,
00110 double *wght, int *outDims, double *mf);
00111
00112
00113 void compute_fwtlat(int *dims, double *br, double *lon, double *lat, double *wght, struct fwt *fwtlat);
00114
00115
00116 void set_mf_keys(DRMS_Record_t *outRec, int *outDims, double *mf, struct fwt *fwtlat);
00117
00118
00119
00120
00121
00122
00123 char *module_name = "meanpf";
00124
00125 ModuleArgs_t module_args[] =
00126 {
00127 {ARG_STRING, "in", "", "Input query"},
00128 {ARG_STRING, "out", "hmi.meanpf_720s", "Output query"},
00129 {ARG_END}
00130 };
00131
00132 int DoIt(void)
00133 {
00134
00135 int status = DRMS_SUCCESS;
00136
00137
00138
00139 double wt0, wt1, wt;
00140 double ut0, ut1, ut;
00141 double st0, st1, st;
00142 double ct0, ct1, ct;
00143 wt0 = getwalltime();
00144 ct0 = getcputime(&ut0, &st0);
00145
00146
00147
00148
00149
00150 char *inQuery = (char *)params_get_str(&cmdparams, "in");
00151 char *outQuery = (char *)params_get_str(&cmdparams, "out");
00152
00153
00154
00155
00156
00157 DRMS_RecordSet_t *inRS = NULL;
00158 inRS = drms_open_records(drms_env, inQuery, &status);
00159 if (status || inRS->n == 0) DIE("Input records error.");
00160
00161 int nrecs = inRS->n;
00162
00163
00164
00165
00166
00167 DRMS_RecordSet_t *outRS = drms_create_records(drms_env, nrecs, outQuery, DRMS_PERMANENT, &status);
00168 if (status) DIE("Output records not created.");
00169
00170
00171
00172
00173
00174 printf("Start, %d records in total\n", nrecs);
00175
00176 for (int irec = 0; irec < nrecs; irec++) {
00177
00178
00179
00180 wt = getwalltime();
00181 ct = getcputime(&ut, &st);
00182 printf("Record %d of %d done, %.2f ms wall time, %.2f ms cpu time\n",
00183 irec + 1, nrecs, wt - wt1, ct - ct1);
00184
00185
00186
00187 wt1 = getwalltime();
00188 ct1 = getcputime(&ut1, &st1);
00189
00190
00191
00192 DRMS_Record_t *inRec = inRS->records[irec];
00193 TIME t_rec = drms_getkey_time(inRec, "T_REC", &status);
00194
00195 char t_rec_str[100];
00196 sprint_time(t_rec_str, t_rec, "TAI", 0);
00197 printf("==============\nRecord #%d, [%s]\n", irec, t_rec_str);
00198
00199 struct ephemeris ephem;
00200 status = get_ephemeris(inRec, &ephem);
00201 if (status) {
00202 SHOW("Input record ephemeris error, record skipped.\n");
00203 }
00204
00205 DRMS_Segment_t *inSeg = drms_segment_lookupnum(inRec, 0);
00206 DRMS_Array_t *inArray = NULL;
00207 inArray = drms_segment_read(inSeg, DRMS_TYPE_DOUBLE, &status);
00208 if (status) {
00209 SHOW("Input array read error, record skipped.\n");
00210 if (inArray) drms_free_array(inArray);
00211 continue;
00212 }
00213
00214 int nx = inArray->axis[0], ny = inArray->axis[1];
00215 int nxny = nx * ny;
00216 int dims[2] = {nx, ny};
00217
00218
00219
00220 SHOW("Get lon/lat...\n");
00221
00222 double *lon = NULL, *lat = NULL, *wght = NULL;
00223 lon = (double *) (calloc(sizeof(double), nxny));
00224 lat = (double *) (calloc(sizeof(double), nxny));
00225 wght = (double *) (calloc(sizeof(double), nxny));
00226
00227 get_lonlat(&ephem, dims, lon, lat, wght);
00228
00229
00230
00231 double *bl = NULL, *br = NULL;
00232 bl = (double *) (inArray->data);
00233 br = (double *) (calloc(sizeof(double), nxny));
00234
00235 SHOW("Convert bl to br...\n");
00236 los2radial(&ephem, dims, bl, br, wght);
00237
00238
00239
00240 SHOW("Compute mf...\n");
00241
00242 int nlat = 180;
00243 int outDims_mf[2] = {nlat,4};
00244 double *mf = (double *) (calloc(sizeof(double), outDims_mf[0]*outDims_mf[1]));
00245
00246
00247
00248
00249
00250
00251
00252 compute_mf(dims, br, bl, lon, lat, wght, outDims_mf, mf);
00253
00254
00255
00256 struct fwt fwtlat;
00257 compute_fwtlat(dims, br, lon, lat, wght, &fwtlat);
00258
00259 fwtlat.fluxn[0] *= ephem.da;
00260 fwtlat.fluxn[1] *= ephem.da;
00261 fwtlat.fluxs[0] *= ephem.da;
00262 fwtlat.fluxs[1] *= ephem.da;
00263
00264
00265
00266 double *mf_br = (double *) (malloc(nlat * sizeof(double)));
00267 double *mf_bl = (double *) (malloc(nlat * sizeof(double)));
00268 double *w = (double *) (malloc(nlat * sizeof(double)));
00269 double *num = (double *) (malloc(nlat * sizeof(double)));
00270 for (int i = 0; i < nlat; i++) {
00271 mf_br[i] = mf[i];
00272 mf_bl[i] = mf[nlat + i];
00273 w[i] = mf[nlat * 2 + i];
00274 num[i] = mf[nlat * 3 + i];
00275 }
00276
00277
00278
00279 drms_free_array(inArray);
00280 FREE_ARR(br); FREE_ARR(wght); FREE_ARR(lon); FREE_ARR(lat);
00281
00282
00283
00284 SHOW("Output...\n");
00285
00286 int outDims[1] = {nlat};
00287 DRMS_Record_t *outRec = outRS->records[irec];
00288 DRMS_Segment_t *outSeg_br = drms_segment_lookup(outRec, "mf_br");
00289 DRMS_Array_t *outArray_br = drms_array_create(DRMS_TYPE_DOUBLE, 1, outDims, mf_br, &status);
00290 status = drms_segment_write(outSeg_br, outArray_br, 0);
00291
00292 DRMS_Segment_t *outSeg_bl = drms_segment_lookup(outRec, "mf_bl");
00293 DRMS_Array_t *outArray_bl = drms_array_create(DRMS_TYPE_DOUBLE, 1, outDims, mf_bl, &status);
00294 status = drms_segment_write(outSeg_bl, outArray_bl, 0);
00295
00296 DRMS_Segment_t *outSeg_w = drms_segment_lookup(outRec, "w");
00297 DRMS_Array_t *outArray_w = drms_array_create(DRMS_TYPE_DOUBLE, 1, outDims, w, &status);
00298 status = drms_segment_write(outSeg_w, outArray_w, 0);
00299
00300 DRMS_Segment_t *outSeg_num = drms_segment_lookup(outRec, "num");
00301 DRMS_Array_t *outArray_num = drms_array_create(DRMS_TYPE_DOUBLE, 1, outDims, num, &status);
00302 status = drms_segment_write(outSeg_num, outArray_num, 0);
00303
00304
00305
00306 SHOW("Set keywords...\n");
00307
00308 drms_copykey(outRec, inRec, "T_REC");
00309
00310 char timebuf[1024];
00311 double UNIX_epoch = -220924792.0;
00312 sprint_time(timebuf, (double)time(NULL) + UNIX_epoch, "ISO", 0);
00313 drms_setkey_string(outRec, "DATE", timebuf);
00314
00315 drms_setkey_double(outRec, "THRESH", BRTHRESH);
00316 drms_setkey_double(outRec, "DA", ephem.da);
00317
00318 drms_copykey(outRec, inRec, "QUALITY");
00319 drms_copykey(outRec, inRec, "CRLT_OBS");
00320 drms_copykey(outRec, inRec, "CRLN_OBS");
00321 drms_copykey(outRec, inRec, "CAR_ROT");
00322 drms_copykey(outRec, inRec, "OBS_VR");
00323 drms_copykey(outRec, inRec, "INTERVAL");
00324
00325
00326
00327 set_mf_keys(outRec, outDims_mf, mf, &fwtlat);
00328
00329
00330
00331 DRMS_FREE_ARR(outArray_br); DRMS_FREE_ARR(outArray_bl);
00332 DRMS_FREE_ARR(outArray_w); DRMS_FREE_ARR(outArray_num);
00333 FREE_ARR(mf);
00334
00335
00336
00337 wt = getwalltime();
00338 ct = getcputime(&ut, &st);
00339 printf("Record %d of %d done, %.2f ms wall time, %.2f ms cpu time\n",
00340 irec + 1, nrecs, wt - wt1, ct - ct1);
00341
00342 }
00343
00344
00345
00346 drms_close_records(inRS, DRMS_FREE_RECORD);
00347 drms_close_records(outRS, DRMS_INSERT_RECORD);
00348
00349 wt = getwalltime();
00350 ct = getcputime(&ut, &st);
00351 printf("==============\nTotal time spent: %.2f ms wall time, %.2f ms cpu time\n",
00352 wt - wt0, ct - ct0);
00353
00354 return DRMS_SUCCESS;
00355
00356 }
00357
00358
00359
00360
00361
00362 int get_ephemeris(DRMS_Record_t *inRec, struct ephemeris *ephem)
00363 {
00364
00365 int status = 0;
00366
00367 ephem->rsun_obs = drms_getkey_double(inRec, "RSUN_OBS", &status);
00368 if (status) return status;
00369 ephem->asd = ephem->rsun_obs / RAD2ARCSEC;
00370
00371 ephem->xc = drms_getkey_double(inRec, "CRPIX1", &status) - 1.;
00372 if (status) return status;
00373 ephem->yc = drms_getkey_double(inRec, "CRPIX2", &status) - 1.;
00374 if (status) return status;
00375
00376 double cdelt1 = drms_getkey_double(inRec, "CDELT1", &status);
00377 if (status) return status;
00378 double cdelt2 = drms_getkey_double(inRec, "CDELT2", &status);
00379 if (status) return status;
00380 if (fabs(cdelt1 - cdelt2) > EPSL) return 1;
00381 ephem->cdelt = cdelt1;
00382
00383 ephem->rsun = ephem->rsun_obs / ephem->cdelt;
00384
00385 ephem->p0 = drms_getkey_double(inRec, "CROTA2", &status) / RAD2DEG * (-1.);
00386 if (status) return status;
00387
00388 ephem->b0 = drms_getkey_double(inRec, "CRLT_OBS", &status) / RAD2DEG;
00389 if (status) return status;
00390
00391 double dsun_obs = drms_getkey_double(inRec, "DSUN_OBS", &status) / 1.e6;
00392 double dx = cdelt1 * ((dsun_obs - 696.) / RAD2ARCSEC);
00393 ephem->da = dx * dx;
00394
00395 return 0;
00396
00397 }
00398
00399
00400
00401 void get_lonlat(struct ephemeris *ephem, int *dims, double *lon, double *lat, double *wght)
00402 {
00403
00404 int ncol = dims[0], nrow = dims[1];
00405 int idx;
00406 int status = 0;
00407
00408 double x, y, r;
00409 double rho, sinlat, coslat, sig, mu, chi;
00410 double lat0, lon0;
00411
00412 for (int row = 0; row < nrow; row++) {
00413 y = (row - ephem->yc) / ephem->rsun;
00414 for (int col = 0; col < ncol; col++) {
00415 x = (col - ephem->xc) / ephem->rsun;
00416 r = hypot(x, y);
00417 idx = row * ncol + col;
00418 if (r <= APOD) {
00419 status = img2sphere(x, y, ephem->asd, ephem->b0, 0.0, ephem->p0,
00420 &rho, &lat0, &lon0, &sinlat, &coslat, &sig, &mu, &chi);
00421 if (status) {
00422 lon[idx] = lat[idx] = wght[idx] = DRMS_MISSING_DOUBLE;
00423 } else {
00424 lon[idx] = ((lon0 > M_PI) ? (lon0 - M_PI * 2) : lon0) * RAD2DEG;
00425 lat[idx] = lat0 * RAD2DEG;
00426 wght[idx] = 1.0 / mu;
00427 }
00428 } else {
00429 lon[idx] = lat[idx] = wght[idx] = DRMS_MISSING_DOUBLE;
00430 }
00431 }
00432 }
00433
00434 }
00435
00436
00437
00438 void los2radial(struct ephemeris *ephem, int *dims, double *bl, double *br, double *wght)
00439 {
00440
00441 int nxny = dims[0] * dims[1];
00442 int idx;
00443
00444 double x, y, r;
00445 double crho;
00446
00447 for (int idx = 0; idx < nxny; idx++) {
00448 if (isnan(wght[idx])) {
00449 br[idx] = bl[idx] = DRMS_MISSING_DOUBLE;
00450 } else {
00451 br[idx] = bl[idx] * wght[idx];
00452 }
00453 }
00454
00455 }
00456
00457
00458
00459 void compute_mf(int *dims, double *br, double *bl, double *lon, double *lat,
00460 double *wght, int *outDims, double *mf)
00461 {
00462
00463 int row_offset = outDims[0];
00464
00465 double *mf_br = mf;
00466 double *mf_bl = mf + row_offset;
00467 double *w = mf + row_offset * 2;
00468 double *num = mf + row_offset * 3;
00469
00470 int nx = dims[0], ny = dims[1];
00471 int nxny = nx * ny;
00472
00473 int ngood = 0;
00474 int ilat;
00475 double s, v1, v2;
00476
00477
00478 for (int idx = 0; idx < nxny; idx++) {
00479 if (isnan(lon[idx])) continue;
00480 ngood++;
00481
00482 if (fabs(lon[idx]) > 45.) continue;
00483
00484 ilat = floor(lat[idx] + 90.);
00485 if (ilat >= 180 || ilat < 0) continue;
00486
00487 mf_br[ilat] += (br[idx] * wght[idx]);
00488 mf_bl[ilat] += (bl[idx]);
00489 w[ilat] += wght[idx];
00490 num[ilat] ++;
00491 }
00492
00493
00494 for (ilat = 0; ilat < 180; ilat ++) {
00495 num[ilat] = fabs(num[ilat]);
00496 if (num[ilat] < EPSL) {
00497 mf_br[ilat] = DRMS_MISSING_DOUBLE;
00498 mf_bl[ilat] = DRMS_MISSING_DOUBLE;
00499 continue;
00500 }
00501 mf_br[ilat] /= (w[ilat]);
00502 mf_bl[ilat] /= (num[ilat]);
00503 }
00504
00505 }
00506
00507
00508
00509 void compute_fwtlat(int *dims, double *br, double *lon, double *lat, double *wght, struct fwt *fwtlat)
00510 {
00511
00512 int nx = dims[0], ny = dims[1];
00513 int nxny = nx * ny;
00514
00515 double fln[2] = {0, 0}, fls[2] = {0, 0};
00516 double f, fl;
00517
00518 for (int idx = 0; idx < nxny; idx++) {
00519
00520 if (fabs(lon[idx]) > 45. || fabs(lat[idx]) > 40. || fabs(br[idx]) < BRTHRESH) continue;
00521
00522 f = fabs(br[idx] * wght[idx]);
00523 fl = f * lat[idx];
00524
00525 if (lat[idx] >= 0 && br[idx] >= 0) {
00526 fwtlat->fluxn[0] += f; fln[0] += fl;
00527 }
00528
00529 if (lat[idx] >= 0 && br[idx] < 0) {
00530 fwtlat->fluxn[1] += f; fln[1] += fl;
00531 }
00532
00533 if (lat[idx] < 0 && br[idx] >= 0) {
00534 fwtlat->fluxs[0] += f; fls[0] += fl;
00535 }
00536
00537 if (lat[idx] < 0 && br[idx] < 0) {
00538 fwtlat->fluxs[1] += f; fls[1] += fl;
00539 }
00540 }
00541
00542 fwtlat->latn[0] = fln[0] / fwtlat->fluxn[0];
00543 fwtlat->latn[1] = fln[1] / fwtlat->fluxn[1];
00544 fwtlat->lats[0] = fls[0] / fwtlat->fluxs[0];
00545 fwtlat->lats[1] = fls[1] / fwtlat->fluxs[1];
00546
00547 fwtlat->fluxn[0] *= (1.e-4);
00548 fwtlat->fluxn[1] *= (-1.e-4);
00549 fwtlat->fluxs[0] *= (1.e-4);
00550 fwtlat->fluxs[1] *= (-1.e-4);
00551
00552 }
00553
00554
00555
00556 void set_mf_keys(DRMS_Record_t *outRec, int *outDims, double *mf, struct fwt *fwtlat)
00557 {
00558
00559 int row_offset = outDims[0];
00560
00561 double *mf_br = mf;
00562 double *mf_bl = mf + row_offset;
00563 double *w = mf + row_offset * 2;
00564 double *num = mf + row_offset * 3;
00565
00566 int idxn, idxs;
00567
00568
00569
00570 double bn3 = 0, bs3 = 0, wn3 = 0, ws3 = 0, numn3 = 0, nums3 = 0;
00571 for (int i = 0; i < 20; i++) {
00572 idxn = 179 - i;
00573 if (num[idxn] > EPSL) {
00574 bn3 += mf_br[idxn] * w[idxn];
00575 wn3 += w[idxn];
00576 numn3 += num[idxn];
00577 }
00578
00579 idxs = i;
00580 if (num[idxs] > EPSL) {
00581 bs3 += mf_br[idxs] * w[idxs];
00582 ws3 += w[idxs];
00583 nums3 += num[idxs];
00584 }
00585 }
00586
00587
00588
00589 double bn2 = 0, bs2 = 0, wn2 = 0, ws2 = 0, numn2 = 0, nums2 = 0;
00590 double bn1 = 0, bs1 = 0, wn1 = 0, ws1 = 0, numn1 = 0, nums1 = 0;
00591 for (int i = 0; i < 10; i++) {
00592 idxn = 159 - i;
00593 bn2 += mf_br[idxn] * w[idxn];
00594 wn2 += w[idxn];
00595 numn2 += num[idxn];
00596
00597 idxn = 149 - i;
00598 bn1 += mf_br[idxn] * w[idxn];
00599 wn1 += w[idxn];
00600 numn1 += num[idxn];
00601
00602 idxs = i + 20;
00603 bs2 += mf_br[idxs] * w[idxs];
00604 ws2 += w[idxs];
00605 nums2 += num[idxs];
00606
00607 idxs = i + 30;
00608 bs1 += mf_br[idxs] * w[idxs];
00609 ws1 += w[idxs];
00610 nums1 += num[idxs];
00611 }
00612
00613
00614
00615 drms_setkey_double(outRec, "BANDN3", bn3 / wn3);
00616 drms_setkey_double(outRec, "BANDS3", bs3 / ws3);
00617
00618 drms_setkey_double(outRec, "BANDN2", bn2 / wn2);
00619 drms_setkey_double(outRec, "BANDS2", bs2 / ws2);
00620
00621 drms_setkey_double(outRec, "BANDN1", bn1 / wn1);
00622 drms_setkey_double(outRec, "BANDS1", bs1 / ws1);
00623
00624 drms_setkey_double(outRec, "CAPN2", (bn2 + bn3) / (wn2 + wn3));
00625 drms_setkey_double(outRec, "CAPS2", (bs2 + bs3) / (ws2 + ws3));
00626
00627 drms_setkey_double(outRec, "CAPN1", (bn1 + bn2 + bn3) / (wn1 + wn2 + wn3));
00628 drms_setkey_double(outRec, "CAPS1", (bs1 + bs2 + bs3) / (ws1 + ws2 + ws3));
00629
00630 drms_setkey_double(outRec, "NUMN3", numn3);
00631 drms_setkey_double(outRec, "NUMS3", nums3);
00632
00633 drms_setkey_double(outRec, "NUMN2", numn2);
00634 drms_setkey_double(outRec, "NUMS2", nums2);
00635
00636 drms_setkey_double(outRec, "NUMN1", numn1);
00637 drms_setkey_double(outRec, "NUMS1", nums1);
00638
00639 drms_setkey_double(outRec, "WN3", wn3);
00640 drms_setkey_double(outRec, "WS3", ws3);
00641
00642 drms_setkey_double(outRec, "WN2", wn2);
00643 drms_setkey_double(outRec, "WS2", ws2);
00644
00645 drms_setkey_double(outRec, "WN1", wn1);
00646 drms_setkey_double(outRec, "WS1", ws1);
00647
00648
00649
00650 drms_setkey_double(outRec, "FLUXN_P", fwtlat->fluxn[0]);
00651 drms_setkey_double(outRec, "FLUXN_N", fwtlat->fluxn[1]);
00652 drms_setkey_double(outRec, "FLUXS_P", fwtlat->fluxs[0]);
00653 drms_setkey_double(outRec, "FLUXS_N", fwtlat->fluxs[1]);
00654
00655 drms_setkey_double(outRec, "FLATN_P", fwtlat->latn[0]);
00656 drms_setkey_double(outRec, "FLATN_N", fwtlat->latn[1]);
00657 drms_setkey_double(outRec, "FLATS_P", fwtlat->lats[0]);
00658 drms_setkey_double(outRec, "FLATS_N", fwtlat->lats[1]);
00659
00660 }