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 #include <jsoc_main.h>
00081 #include "fstats.h"
00082
00083 #define RECTANGULAR (0)
00084 #define CASSINI (1)
00085 #define MERCATOR (2)
00086 #define CYLEQA (3)
00087 #define SINEQA (4)
00088 #define GNOMONIC (5)
00089 #define POSTEL (6)
00090 #define STEREOGRAPHIC (7)
00091 #define ORTHOGRAPHIC (8)
00092 #define LAMBERT (9)
00093
00094 #define RSUNM (6.96e8)
00095 #define INTERP_NEAREST_NEIGHBOR (1)
00096 #define INTERP_BILINEAR (2)
00097
00098 char *module_name = "maproj";
00099 char *module_desc = "mapping from solar images";
00100 char *version_id = "0.9";
00101
00102 ModuleArgs_t module_args[] = {
00103 {ARG_DATASET, "in", "", "input data set"},
00104 {ARG_DATASERIES, "out", "", "output data series"},
00105 {ARG_DOUBLE, "clat", "0.0", "heliographic latitude of map center [deg]"},
00106 {ARG_DOUBLE, "clon", "0.0", "Carrington longitude of map center [deg]"},
00107 {ARG_DOUBLE, "scale", "Not specified", "map scale at center [deg/pxl]"},
00108 {ARG_NUME, "map", "orthographic", "map projection",
00109 "carree, Cassini, Mercator, cyleqa, sineqa, gnomonic, Postel, stereographic, orthographic, Lambert"},
00110 {ARG_NUME, "interp", "cubiconv", "interpolation option",
00111 "cubiconv, nearest, bilinear"},
00112 {ARG_FLOAT, "grid", "Not Specified",
00113 "if specified, spacing of grid overlay [deg]"},
00114 {ARG_INT, "cols", "0", "columns in output map"},
00115 {ARG_INT, "rows", "0", "rows in output map"},
00116 {ARG_FLOAT, "map_pa", "0.0", "position angle of north on output map [deg]"},
00117 {ARG_FLOAT, "bscale", "0.0", "output scaling factor"},
00118 {ARG_FLOAT, "bzero", "Default", "output offset"},
00119 {ARG_STRING, "clon_key", "CRLN_OBS", "keyname for image central longitude"},
00120 {ARG_STRING, "clat_key", "CRLT_OBS", "keyname for image central latitude"},
00121 {ARG_STRING, "rsun_key", "R_SUN", "keyname for image semi-diameter (pixel)"},
00122 {ARG_STRING, "apsd_key", "RSUN_OBS", "keyname for apparent solar semi-diameter (arcsec)"},
00123 {ARG_STRING, "dsun_key", "DSUN_OBS", "keyname for observer distance"},
00124 {ARG_STRING, "requestid", "none", "RequestID for jsoc export management"},
00125 {ARG_FLAG, "A", NULL, "Generate output for all input segments"},
00126 {ARG_FLAG, "c", "", "center map at center of image"},
00127 {ARG_FLAG, "s", "", "clon is Stonyhurst longitude"},
00128 {ARG_FLAG, "v", "", "verbose mode"},
00129 {ARG_FLAG, "x", "", "write full headers, for export purposes."},
00130 {}
00131 };
00132
00133
00134 float missing_val;
00135
00136
00137 static double arc_distance (double lat, double lon, double latc, double lonc)
00138 {
00139 double cosa = sin (lat) * sin (latc) + cos (lat) * cos (latc) * cos (lon - lonc);
00140 return acos (cosa);
00141 }
00142
00143 static int plane2sphere (double x, double y, double latc, double lonc, double *lat, double *lon, int projection)
00144 {
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 static double latc0 = 0.0, sinlatc = 0.0, coslatc = 1.0 ;
00202 double r, rm, test;
00203 double cosr, sinr, cosp, sinp, coslat, sinlat, sinlon;
00204 double sinphi, cosphi, phicom;
00205 int status = 0;
00206
00207 if (latc != latc0) {
00208 coslatc = cos (latc);
00209 sinlatc = sin (latc);
00210 }
00211 latc0 = latc;
00212
00213 switch (projection) {
00214 case (RECTANGULAR):
00215 *lon = lonc + x;
00216 *lat = latc + y;
00217 if (arc_distance (*lat, *lon, latc, lonc) > M_PI_2) status = 1;
00218 if (fabs (x) > M_PI || fabs (y) > M_PI_2) status = -1;
00219 return status;
00220 case (CASSINI): {
00221 double sinx = sin (x);
00222 double cosy = cos (y + latc);
00223 double siny = sin (y + latc);
00224 *lat = acos (sqrt (cosy * cosy + siny * siny * sinx * sinx));
00225 if (y < -latc) *lat *= -1;
00226 *lon = (fabs (*lat) < M_PI_2) ? lonc + asin (sinx / cos (*lat)) : lonc;
00227 if (y > (M_PI_2 - latc) || y < (-M_PI_2 - latc))
00228 *lon = 2 * lonc + M_PI - *lon;
00229 if (*lon < -M_PI) *lon += 2* M_PI;
00230 if (*lon > M_PI) *lon -= 2 * M_PI;
00231 if (arc_distance (*lat, *lon, latc, lonc) > M_PI_2) status = 1;
00232 if (fabs (x) > M_PI || fabs (y) > M_PI_2) status = -1;
00233 return status;
00234 }
00235 case (CYLEQA):
00236 if (fabs (y) > 1.0) {
00237 y = copysign (1.0, y);
00238 status = -1;
00239 }
00240 cosphi = sqrt (1.0 - y*y);
00241 *lat = asin ((y * coslatc) + (cosphi * cos (x) * sinlatc));
00242 test = (cos (*lat) == 0.0) ? 0.0 : cosphi * sin (x) / cos (*lat);
00243 *lon = asin (test) + lonc;
00244 if (fabs (x) > M_PI_2) {
00245 status = 1;
00246 while (x > M_PI_2) {
00247 *lon = M_PI - *lon;
00248 x -= M_PI;
00249 }
00250 while (x < -M_PI_2) {
00251 *lon = -M_PI - *lon;
00252 x += M_PI;
00253 }
00254 }
00255 if (arc_distance (*lat, *lon, latc, lonc) > M_PI_2) status = 1;
00256 return status;
00257 case (SINEQA):
00258 cosphi = cos (y);
00259 if (cosphi <= 0.0) {
00260 *lat = y;
00261 *lon = lonc;
00262 if (cosphi < 0.0) status = -1;
00263 return status;
00264 }
00265 *lat = asin ((sin (y) * coslatc) + (cosphi * cos (x/cosphi) * sinlatc));
00266 coslat = cos (*lat);
00267 if (coslat <= 0.0) {
00268 *lon = lonc;
00269 if (coslat < 0.0) status = 1;
00270 return status;
00271 }
00272 test = cosphi * sin (x/cosphi) / coslat;
00273 *lon = asin (test) + lonc;
00274 if (fabs (x) > M_PI * cosphi) return (-1);
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 if (fabs (x) > M_PI_2 * cosphi) {
00288 status = 1;
00289 while (x > M_PI_2 * cosphi) {
00290 *lon = M_PI - *lon;
00291 x -= M_PI * cosphi;
00292 }
00293 while (x < -M_PI_2 * cosphi) {
00294 *lon = -M_PI - *lon;
00295 x += M_PI * cosphi;
00296 }
00297 }
00298
00299
00300
00301 return status;
00302 case (MERCATOR):
00303 phicom = 2.0 * atan (exp (y));
00304 sinphi = -cos (phicom);
00305 cosphi = sin (phicom);
00306 *lat = asin ((sinphi * coslatc) + (cosphi * cos (x) * sinlatc));
00307 *lon = asin (cosphi * sin (x) / cos (*lat)) + lonc;
00308 if (arc_distance (*lat, *lon, latc, lonc) > M_PI_2) status = 1;
00309 if (fabs (x) > M_PI_2) status = -1;
00310 return status;
00311 }
00312
00313 r = hypot (x, y);
00314 cosp = (r == 0.0) ? 1.0 : x / r;
00315 sinp = (r == 0.0) ? 0.0 : y / r;
00316
00317 switch (projection) {
00318 case (POSTEL):
00319 rm = r;
00320 if (rm > M_PI_2) status = 1;
00321 break;
00322 case (GNOMONIC):
00323 rm = atan (r);
00324 break;
00325 case (STEREOGRAPHIC):
00326 rm = 2 * atan (0.5 * r);
00327 if (rm > M_PI_2) status = 1;
00328 break;
00329 case (ORTHOGRAPHIC):
00330 if ( r > 1.0 ) {
00331 r = 1.0;
00332 status = -1;
00333 }
00334 rm = asin (r);
00335 break;
00336 case (LAMBERT):
00337 if ( r > 2.0 ) {
00338 r = 2.0;
00339 status = -1;
00340 }
00341 rm = 2 * asin (0.5 * r);
00342 if (rm > M_PI_2 && status == 0) status = 1;
00343 break;
00344 }
00345 cosr = cos (rm);
00346 sinr = sin (rm);
00347
00348 sinlat = sinlatc * cosr + coslatc * sinr * sinp;
00349 *lat = asin (sinlat);
00350 coslat = cos (*lat);
00351 sinlon = (coslat == 0.0) ? 0.0 : sinr * cosp / coslat;
00352
00353
00354
00355
00356
00357
00358 *lon = asin (sinlon);
00359
00360 if (cosr < (sinlat * sinlatc)) *lon = M_PI - *lon;
00361 *lon += lonc;
00362 return status;
00363 }
00364
00365
00366 #define NO_SEMIDIAMETER (0x0002)
00367 #define NO_XSCALE (0x0004)
00368 #define NO_YSCALE (0x0008)
00369 #define NO_XCENTERLOC (0x0010)
00370 #define NO_YCENTERLOC (0x0020)
00371 #define NO_HELIO_LATC (0x0040)
00372 #define NO_HELIO_LONC (0x0080)
00373 #define NO_HELIO_PA (0x0100)
00374 #define NO_XUNITS (0x0200)
00375 #define NO_YUNITS (0x0400)
00376 #define NO_OBSERVER_LAT (0x0002)
00377 #define NO_OBSERVER_LON (0x0004)
00378
00379 #define KEYSCOPE_VARIABLE (0x80000000)
00380
00381 typedef struct paramdef {
00382 double scale;
00383 double offset;
00384 double defval;
00385 unsigned int statusbit;
00386 char name[32];
00387 } ParamDef;
00388
00389
00390 static double lookup (DRMS_Record_t *rec, ParamDef key, int *status) {
00391 double value = key.defval;
00392 int lookupstat = 0;
00393
00394 value = drms_getkey_double (rec, key.name, &lookupstat);
00395 value = value * key.scale + key.offset;
00396 if (lookupstat) *status |= key.statusbit;
00397 if (isnan (value)) *status |= key.statusbit;
00398 return value;
00399 }
00400
00401 static char *lookup_str (DRMS_Record_t *rec, ParamDef key, int *status) {
00402 DRMS_Keyword_t *keywd;
00403 int lstat;
00404 char *value;
00405
00406 value = drms_getkey_string (rec, key.name, &lstat);
00407 if (lstat) *status |= key.statusbit;
00408
00409 if ((keywd = drms_keyword_lookup (rec, key.name, 1))) {
00410 if (keywd->info->recscope != 1) *status |= KEYSCOPE_VARIABLE;
00411 } else *status |= key.statusbit;
00412 return value;
00413 }
00414
00415 static int solar_image_info (DRMS_Record_t *img, double *xscl, double *yscl,
00416 double *ctrx, double *ctry, double *apsd, const char *rsun_key,
00417 const char *apsd_key, double *pang, double *ellipse_e, double *ellipse_pa,
00418 int *x_invrt, int *y_invrt, int *need_ephem, int AIPS_convention) {
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 enum param {
00452 XSCL, YSCL, XUNI, YUNI, LATC, LONC, CTRX, CTRY, PANG, APSD, RSUN,
00453 ESMA, ESMI, EECC, EANG, XASP, YASP, PCT
00454 };
00455 enum known_plat {
00456 UNKNOWN
00457 };
00458 static ParamDef param[PCT];
00459 static double raddeg = M_PI / 180.0;
00460 static double degrad = 180.0 / M_PI;
00461 double ella, ellb;
00462 int n, status = 0;
00463 static int scale_avail, xinv_type, yinv_type;
00464 static int hdrtype = UNKNOWN, lasthdr = UNKNOWN - 1;
00465 char *strval;
00466
00467
00468
00469 if (lasthdr != hdrtype) {
00470 if (lasthdr >= UNKNOWN)
00471 fprintf (stderr,
00472 "Warning from solar_image_info(): record keywords may change\n");
00473 for (n = 0; n < PCT; n++) {
00474 sprintf (param[n].name, "No Keyword");
00475 param[n].scale = 1.0;
00476 param[n].offset = 0.0;
00477 param[n].defval = NAN;
00478 param[n].statusbit = 0;
00479 }
00480 param[RSUN].statusbit = NO_SEMIDIAMETER;
00481 param[APSD].statusbit = NO_SEMIDIAMETER;
00482 param[XSCL].statusbit = NO_XSCALE;
00483 param[YSCL].statusbit = NO_YSCALE;
00484 param[XUNI].statusbit = NO_XUNITS;
00485 param[YUNI].statusbit = NO_YUNITS;
00486 param[CTRX].statusbit = NO_XCENTERLOC;
00487 param[CTRY].statusbit = NO_YCENTERLOC;
00488 param[CTRX].statusbit = NO_XCENTERLOC;
00489 param[CTRY].statusbit = NO_YCENTERLOC;
00490 param[LATC].statusbit = NO_HELIO_LATC;
00491 param[LONC].statusbit = NO_HELIO_LONC;
00492 param[PANG].statusbit = NO_HELIO_PA;
00493 param[EECC].defval = 0.0;
00494 param[EANG].defval = 0.0;
00495 param[XASP].defval = 1.0;
00496 param[YASP].defval = 1.0;
00497
00498 switch (hdrtype) {
00499 default:
00500
00501 scale_avail = 1;
00502 xinv_type = yinv_type = 0;
00503 sprintf (param[XUNI].name, "CUNIT1");
00504 sprintf (param[YUNI].name, "CUNIT2");
00505 sprintf (param[XSCL].name, "CDELT1");
00506 sprintf (param[YSCL].name, "CDELT2");
00507 sprintf (param[CTRX].name, "CRPIX1");
00508 param[CTRX].offset = -1.0;
00509 sprintf (param[CTRY].name, "CRPIX2");
00510 param[CTRY].offset = -1.0;
00511 *need_ephem = 0;
00512 strval = lookup_str (img, param[XUNI], &status);
00513 if (!(status & NO_XUNITS)) {
00514 if (!strcmp (strval, "arcsec")) param[XSCL].scale = 1.0;
00515 else if (!strcmp (strval, "arcmin")) param[XSCL].scale = 1.0 / 60.0;
00516 else if (!strcmp (strval, "deg")) param[XSCL].scale = 1.0 / 3600.0;
00517 else if (!strcmp (strval, "mas")) param[XSCL].scale = 1000.0;
00518 else if (!strcmp (strval, "rad")) param[XSCL].scale = degrad * 3600.0;
00519
00520
00521
00522 }
00523 if (strval) free (strval);
00524 strval = lookup_str (img, param[YUNI], &status);
00525 if (!(status & NO_YUNITS)) {
00526 if (!strcmp (strval, "arcsec")) param[YSCL].scale = 1.0;
00527 else if (!strcmp (strval, "arcmin")) param[YSCL].scale = 1.0 / 60.0;
00528 else if (!strcmp (strval, "deg")) param[YSCL].scale = 1.0 / 3600.0;
00529 else if (!strcmp (strval, "mas")) param[YSCL].scale = 1000.0;
00530 else if (!strcmp (strval, "rad")) param[YSCL].scale = degrad * 3600.0;
00531
00532
00533
00534 }
00535 if (strval) free (strval);
00536
00537
00538
00539
00540
00541 strncpy (param[RSUN].name, rsun_key, 31);
00542 strncpy (param[APSD].name, apsd_key, 31);
00543 sprintf (param[PANG].name, "CROTA2");
00544 param[PANG].scale = -raddeg;
00545 if (AIPS_convention) param[PANG].scale *= -1;
00546 sprintf (param[ESMA].name, "S_MAJOR");
00547 sprintf (param[ESMI].name, "S_MINOR");
00548 sprintf (param[EANG].name, "S_ANGLE");
00549 param[EANG].scale = -raddeg;
00550 if (AIPS_convention) param[EANG].scale *= -1;
00551 }
00552 }
00553 lasthdr = hdrtype;
00554
00555 *apsd = lookup (img, param[RSUN], &status);
00556 if (scale_avail) {
00557 *xscl = lookup (img, param[XSCL], &status);
00558 *yscl = lookup (img, param[YSCL], &status);
00559 if (status & NO_SEMIDIAMETER) {
00560 status &= ~NO_SEMIDIAMETER;
00561 *apsd = lookup (img, param[APSD], &status);
00562 if (status & NO_SEMIDIAMETER) {
00563 *need_ephem = 1;
00564 } else {
00565 if (!(status & (NO_XSCALE | NO_YSCALE))) {
00566 *apsd /= (*xscl <= *yscl) ? *xscl : *yscl;
00567 status &= ~NO_SEMIDIAMETER;
00568 }
00569 }
00570 }
00571 }
00572 ella = lookup (img, param[ESMA], &status);
00573 ellb = lookup (img, param[ESMI], &status);
00574 *ellipse_e = sqrt ((ella - ellb) * (ella + ellb)) / ella;
00575 *ellipse_pa = lookup (img, param[EANG], &status);
00576
00577 *ctrx = lookup (img, param[CTRX], &status);
00578 *ctry = lookup (img, param[CTRY], &status);
00579
00580 *pang = lookup (img, param[PANG], &status);
00581
00582 *x_invrt = xinv_type;
00583 *y_invrt = yinv_type;
00584
00585 return status;
00586 }
00587
00588
00589 #define MDI_IMG_ACPA (1.01e-3)
00590 #define MDI_IMG_ASPA (-1.49e-3)
00591
00592 static void mtrack_MDI_correct_imgctr (double *xc, double *yc, double rsun) {
00593 double rs2;
00594
00595 rs2 = rsun * rsun / 512.0;
00596 *xc -= MDI_IMG_ASPA * rs2;
00597 *yc -= MDI_IMG_ACPA * rs2;
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 #define MDI_IMG_SPA (-0.8290)
00620 #define MDI_IMG_CPA (0.5592)
00621 #define MDI_IMG_AEP (1.80e-3)
00622 #define MDI_IMG_BCPA (2.90e-4)
00623 #define MDI_IMG_BSPA (-4.30e-4)
00624
00625 static void mtrack_MDI_image_tip (double *x, double *y, int n, int direct) {
00626 double x0, y0, s, t;
00627
00628 while (n--) {
00629 x0 = *x;
00630 y0 = *y;
00631 t = direct * (MDI_IMG_SPA * x0 + MDI_IMG_CPA * y0);
00632 s = direct * (MDI_IMG_CPA * x0 - MDI_IMG_SPA * y0);
00633 *x += MDI_IMG_BSPA * t;
00634 *y += MDI_IMG_BCPA * t;
00635 *x -= MDI_IMG_BCPA * s;
00636 *y += MDI_IMG_BSPA * s;
00637 t *= MDI_IMG_AEP;
00638 *x++ += t * x0;
00639 *y++ += t * y0;
00640 }
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 #define MDI_IMG_STRETCH (1.83e-3)
00671
00672 static void mtrack_MDI_image_stretch (double *x, double *y, int n, int direct) {
00673 double f, r2, s;
00674
00675 s = direct * MDI_IMG_STRETCH;
00676 while (n--) {
00677 r2 = *x * *x + *y * *y;
00678 f = 1.0 + s * r2;
00679 *x++ *= f;
00680 *y++ *= f;
00681 }
00682 }
00683
00684 #define MDI_IMG_SOHO_PA (-0.2)
00685
00686 static void mtrack_MDI_correct_pa (double *pa) {
00687 *pa += MDI_IMG_SOHO_PA * M_PI / 180.0;
00688 }
00689
00690
00691
00692
00693
00694
00695 void ccker (double *u, double s) {
00696 double s2, s3;
00697
00698 s2= s * s;
00699 s3= s2 * s;
00700 u[0] = s2 - 0.5 * (s3 + s);
00701 u[1] = 1.5*s3 - 2.5*s2 + 1.0;
00702 u[2] = -1.5*s3 + 2.0*s2 + 0.5*s;
00703 u[3] = 0.5 * (s3 - s2);
00704 }
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 float ccint2 (float *f, int nx, int ny, double x, double y) {
00715 double ux[4], uy[4];
00716 double sum;
00717 int ix, iy, ix1, iy1, i, j;
00718
00719 if (x < 1.0 || x >= (float)(nx-2) || y < 1.0 || y >= (float)(ny-2))
00720 return missing_val;
00721
00722 ix = (int)x;
00723 ccker (ux, x - (double)ix);
00724 iy = (int)y;
00725 ccker (uy, y - (double)iy);
00726
00727 ix1 = ix - 1;
00728 iy1 = iy - 1;
00729 sum = 0.;
00730 for (i = 0; i < 4; i++)
00731 for (j = 0; j < 4; j++)
00732 sum = sum + f[(iy1+i) * nx + ix1 + j] * uy[i] * ux[j];
00733 return (float)sum;
00734 }
00735
00736 float linint2 (float *f, int cols, int rows, double x, double y) {
00737 double p, q, val;
00738 int col = (int)x, row = (int)y;
00739 int onerow = cols * row;
00740 int colp1 = col + 1, onerowp1 = onerow + cols;
00741
00742 if (x < 0.0 || x > cols || y < 0.0 || y >= rows)
00743 return missing_val;
00744 p = x - col;
00745 q = y - row;
00746 val = (1 - p) * (1 - q) * f[col + onerow]
00747 + p * (1 - q) * f[colp1 + onerow]
00748 + (1 - p) * q * f[col + onerowp1]
00749 + p * q * f[colp1 + onerowp1];
00750 return val;
00751 }
00752
00753 float nearest_val (float *f, int cols, int rows, double x, double y) {
00754 int col, row;
00755 if (x < -0.5 || x >= (cols - 0.5) || y < -0.5 || y >= (rows - 0.5))
00756 return missing_val;
00757 col = x + 0.5;
00758 row = y + 0.5;
00759 return f[col + row * cols];
00760 }
00761
00762 float array_imaginterp (DRMS_Array_t *img, double x, double y,
00763 int schema) {
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 double xs, ys;
00789 int cols, rows, mdim;
00790
00791 cols = img->axis[0];
00792 rows = img->axis[1];
00793 mdim = (cols > rows) ? cols : rows;
00794 xs = 0.5 * (x + 1.0) * mdim - 0.5;
00795 ys = 0.5 * (y + 1.0) * mdim - 0.5;
00796 if (schema == INTERP_NEAREST_NEIGHBOR)
00797 return nearest_val (img->data, cols, rows, xs, ys);
00798 else if (schema == INTERP_BILINEAR)
00799 return linint2 (img->data, cols, rows, xs, ys);
00800 else return ccint2 (img->data, cols, rows, xs, ys);
00801 }
00802
00803 static void perform_mapping (DRMS_Array_t *img, float *map,
00804 double *maplat, double *maplon, double *map_coslat, double *map_sinlat,
00805 int pixct, unsigned char *offsun, double latc, double lonc,
00806 double xc, double yc, double radius, double pa, double ellipse_e,
00807 double ellipse_pa, int x_invrt, int y_invrt, int interpolator,
00808 int MDI_correct_distort) {
00809
00810
00811
00812
00813
00814 static double sin_asd = 0.004660, cos_asd = 0.99998914;
00815
00816 double r, cos_cang, xr, yr;
00817 double cos_lat, sin_lat, lon, cos_lat_lon;
00818 double xx, yy;
00819 float interpval;
00820 int n;
00821
00822 double cos_pa = cos (pa);
00823 double sin_pa = sin (pa);
00824 double cos_latc = cos (latc);
00825 double sin_latc = sin (latc);
00826 int plate_cols = img->axis[0];
00827 int plate_rows = img->axis[1];
00828 double plate_width = (plate_cols > plate_rows) ? plate_cols : plate_rows;
00829
00830 xc *= 2.0 / plate_width;
00831 yc *= 2.0 / plate_width;
00832 radius *= 2.0 / plate_width;
00833
00834 for (n = 0; n < pixct; n++) {
00835
00836 if (offsun[n]) {
00837 map[n] = missing_val;
00838 continue;
00839 }
00840 sin_lat = map_sinlat[n];
00841 cos_lat = map_coslat[n];
00842 lon = maplon[n];
00843 cos_lat_lon = cos_lat * cos (lon - lonc);
00844 cos_cang = sin_lat * sin_latc + cos_latc * cos_lat_lon;
00845 if (cos_cang < 0.0) {
00846 map[n] = missing_val;
00847 continue;
00848 }
00849 r = radius * cos_asd / (1.0 - cos_cang * sin_asd);
00850 xr = r * cos_lat * sin (lon - lonc);
00851 yr = r * (sin_lat * cos_latc - sin_latc * cos_lat_lon);
00852 xx = xr * cos_pa - yr * sin_pa;
00853 yy = xr * sin_pa + yr * cos_pa;
00854 yy += yc;
00855 xx += xc;
00856
00857 if (plate_cols > plate_rows) yy -= 1.0 - plate_rows / plate_width;
00858 if (plate_rows > plate_cols) xx -= 1.0 - plate_cols / plate_width;
00859 interpval = array_imaginterp (img, xx, yy, interpolator);
00860
00861
00862 if (MDI_correct_distort) {
00863 mtrack_MDI_image_tip (&xx, &yy, 1, 1);
00864 mtrack_MDI_image_stretch (&xx, &yy, 1, 1);
00865 }
00866 map[n] = (isnan (interpval)) ? missing_val : interpval;
00867 }
00868 }
00869
00870 int near_grid_line (double lon, double lat, double grid, double near) {
00871
00872
00873
00874
00875 static double degrad = 180.0 / M_PI;
00876 double g2 = 0.5 * grid;
00877
00878 lon *= degrad;
00879 lat *= degrad;
00880
00881 while (lon < 0.0) lon += grid;
00882 while (lon > g2) lon -= grid;
00883 if (fabs (lon) < near) return 1;
00884 while (lat < 0.0) lat += grid;
00885 while (lat > g2) lat -= grid;
00886 if (fabs (lat) < near) return 1;
00887 return 0;
00888 }
00889
00890
00891
00892
00893
00894
00895 static int check_and_set_key_str(DRMS_Record_t *outRec, const char *key, const char *val)
00896 {
00897 DRMS_Keyword_t *keywd = NULL;
00898 char *vreq;
00899 int status;
00900 int errOut;
00901
00902 errOut = 0;
00903
00904 if (!(keywd = drms_keyword_lookup(outRec, key, 0))) return 1;
00905
00906 if (!drms_keyword_isconstant(keywd))
00907 {
00908
00909 return (drms_setkey_string(outRec, key, val) != DRMS_SUCCESS);
00910 }
00911
00912 vreq = drms_getkey_string(outRec, key, &status);
00913 if (status || !vreq)
00914 {
00915 fprintf (stderr, "Error retrieving value for constant keyword %s\n", key);
00916 errOut = 1;
00917 }
00918
00919 if (strcmp(vreq, val))
00920 {
00921 char format[256];
00922
00923 snprintf (format, sizeof(format), "Error: new value \"%s\" for constant keyword %%s\n differs from the existing value \"%s\"\n", keywd->info->format, keywd->info->format);
00924 fprintf(stderr, format, val, key, vreq);
00925 errOut = 1;
00926 }
00927
00928 if (vreq)
00929 {
00930
00931 free(vreq);
00932 vreq = NULL;
00933 }
00934
00935 if (errOut)
00936 {
00937 return 1;
00938 }
00939
00940 return 0;
00941 }
00942
00943 static int check_and_set_key_time(DRMS_Record_t *outRec, const char *key, TIME tval)
00944 {
00945 DRMS_Keyword_t *keywd = NULL;
00946 TIME treq;
00947 int status;
00948 char sreq[64], sval[64];
00949
00950 if (!(keywd = drms_keyword_lookup(outRec, key, 0))) return 1;
00951
00952 if (!drms_keyword_isconstant(keywd))
00953 {
00954
00955 return (drms_setkey_time(outRec, key, tval) != DRMS_SUCCESS);
00956 }
00957
00958 treq = drms_getkey_time(outRec, key, &status);
00959 if (status)
00960 {
00961 fprintf(stderr, "Error retrieving value for constant keyword %s\n", key);
00962 return 1;
00963 }
00964
00965 sprint_time(sreq, treq, keywd->info->unit, atoi(keywd->info->format));
00966 sprint_time(sval, tval, keywd->info->unit, atoi(keywd->info->format));
00967
00968 if (strcmp(sval, sreq))
00969 {
00970 fprintf (stderr, "Error: value %s for constant keyword %s\n", sval, key);
00971 fprintf (stderr, " differs from existing value %s\n", sreq);
00972 return 1;
00973 }
00974
00975 return 0;
00976 }
00977
00978 static int check_and_set_key_int(DRMS_Record_t *outRec, const char *key, int val)
00979 {
00980 DRMS_Keyword_t *keywd = NULL;
00981 int vreq;
00982 int status;
00983
00984 if (!(keywd = drms_keyword_lookup(outRec, key, 0))) return 1;
00985
00986 if (!drms_keyword_isconstant(keywd))
00987 {
00988
00989 return (drms_setkey_int(outRec, key, val) != DRMS_SUCCESS);
00990 }
00991
00992 vreq = drms_getkey_int(outRec, key, &status);
00993 if (status)
00994 {
00995 fprintf (stderr, "Error retrieving value for constant keyword %s\n", key);
00996 return 1;
00997 }
00998
00999 if (vreq != val)
01000 {
01001 char format[256];
01002
01003 snprintf (format, sizeof(format), "Error: new value \"%s\" for constant keyword %%s\n differs from the existing value \"%s\"\n", keywd->info->format, keywd->info->format);
01004 fprintf(stderr, format, val, key, vreq);
01005 return 1;
01006 }
01007
01008 return 0;
01009 }
01010
01011 static int check_and_set_key_float(DRMS_Record_t *outRec, const char *key, float val)
01012 {
01013 DRMS_Keyword_t *keywd = NULL;
01014 float vreq;
01015 int status;
01016 char sreq[128], sval[128];
01017
01018 if (!(keywd = drms_keyword_lookup(outRec, key, 0))) return 1;
01019
01020 if (!drms_keyword_isconstant(keywd))
01021 {
01022
01023 return (drms_setkey_float(outRec, key, val) != DRMS_SUCCESS);
01024 }
01025
01026 vreq = drms_getkey_float(outRec, key, &status);
01027
01028 if (status)
01029 {
01030 fprintf (stderr, "Error retrieving value for constant keyword %s\n", key);
01031 return 1;
01032 }
01033
01034 sprintf(sreq, keywd->info->format, vreq);
01035 sprintf(sval, keywd->info->format, val);
01036
01037 if (strcmp(sreq, sval))
01038 {
01039 char format[256];
01040
01041 snprintf(format, sizeof(format), "Error: parameter value %s for keyword %%s\n differs from required value %s\n", keywd->info->format, keywd->info->format);
01042 fprintf(stderr, format, val, key, vreq);
01043 return 1;
01044 }
01045
01046 return 0;
01047 }
01048
01049 int DoIt (void) {
01050 CmdParams_t *params = &cmdparams;
01051 DRMS_RecordSet_t *ids, *ods;
01052 DRMS_Record_t *inrec, *orec;
01053 DRMS_Segment_t *inseg = NULL;
01054 DRMS_Segment_t *oseg = NULL;
01055 DRMS_Array_t *image = NULL, *map = NULL;
01056 int irec;
01057 double *maplat, *maplon, *map_coslat, *map_sinlat;
01058 double x, y, x0, y0, xstp, ystp, xrot, yrot;
01059 double lat, lon, cos_phi, sin_phi;
01060 double img_lat, img_lon;
01061 double img_xscl, img_yscl, img_xc, img_yc, img_radius, img_pa;
01062 double grid_width;
01063 double ellipse_e, ellipse_pa;
01064 float *data;
01065 int axes[2];
01066 int pixct;
01067 int recCount;
01068 int kstat, status;
01069 int need_ephem;
01070 int x_invrt, y_invrt;
01071 int n, col, row;
01072 int MDI_correct, MDI_correct_distort;
01073 unsigned char *offsun, *ongrid;
01074 char source[DRMS_MAXQUERYLEN], recid[DRMS_MAXQUERYLEN];
01075 char module_ident[64], key[64];
01076
01077 double raddeg = M_PI / 180.0;
01078 double degrad = 1.0 / raddeg;
01079 int scaling_override = 0;
01080 char *mapname[] = {"PlateCarree", "Cassini-Soldner", "Mercator",
01081 "LambertCylindrical", "Sanson-Flamsteed", "gnomonic", "Postel",
01082 "stereographic", "orthographic", "LambertAzimuthal"};
01083 char *interpname[] = {"Cubic Convolution", "Nearest Neighbor", "Bilinear"};
01084 char *wcscode[] = {"CAR", "CAS", "MER", "CEA", "GLS", "TAN", "ARC", "STG",
01085 "SIN", "ZEA"};
01086 missing_val = 0.0 / 0.0;
01087 float bblank = -1.0 / 0.0;
01088 float wblank = 1.0 / 0.0;
01089
01090 const char *inset = params_get_str (params, "in");
01091 char *outser = strdup (params_get_str (params, "out"));
01092 double clat = params_get_double (params, "clat") * raddeg;
01093 double clon = params_get_double (params, "clon") * raddeg;
01094 double map_scale = params_get_double (params, "scale");
01095 double map_pa = params_get_double (params, "map_pa") * raddeg;
01096 float bscaleIn = params_get_float (params, "bscale");
01097 float bzeroIn = params_get_float (params, "bzero");
01098 float grid_spacing = params_get_float (params, "grid");
01099 int map_cols = params_get_int (params, "cols");
01100 int map_rows = params_get_int (params, "rows");
01101 int proj = params_get_int (params, "map");
01102 int intrpopt = params_get_int (params, "interp");
01103 char *RequestID = strdup (params_get_str (params, "requestid"));
01104 char *clon_key = strdup (params_get_str (params, "clon_key"));
01105 char *clat_key = strdup (params_get_str (params, "clat_key"));
01106 char *rsun_key = strdup (params_get_str (params, "rsun_key"));
01107 char *apsd_key = strdup (params_get_str (params, "apsd_key"));
01108 char *dsun_key = strdup (params_get_str (params, "dsun_key"));
01109 int center = params_isflagset (params, "c");
01110 int stonyhurst = params_isflagset (params, "s");
01111 int verbose = params_isflagset (params, "v");
01112
01113 int want_headers = params_isflagset (params, "x");
01114 int overlay = (isfinite (grid_spacing));
01115 int MDI_proc = params_isflagset (params, "M");
01116
01117 int hasSegList = 0;
01118 int doingAllSegs = params_isflagset(params, "A");
01119 float bscale;
01120 float bzero;
01121
01122 snprintf (module_ident, sizeof(module_ident), "%s v %s", module_name, version_id);
01123 if (verbose) printf ("%s: JSOC version %s\n", module_ident, jsoc_version);
01124
01125 if (map_cols < 1) map_cols = map_rows;
01126 if (map_rows < 1) map_rows = map_cols;
01127 if (map_rows < 1) {
01128 fprintf (stderr, "Error: at least one of \"cols\" or \"rows\" must be set\n");
01129 return 1;
01130 }
01131 if (isnan (map_scale) || map_scale == 0.0) {
01132 fprintf (stderr,
01133 "Error: auto scaling from image resolution not implemented;\n");
01134 fprintf (stderr, " scale parameter must be set.\n");
01135 return 1;
01136 }
01137 MDI_correct = MDI_correct_distort = MDI_proc;
01138 cos_phi = cos (map_pa);
01139 sin_phi = sin (map_pa);
01140 xstp = ystp = map_scale * raddeg;
01141 x0 = 0.5 * (1.0 - map_cols) * xstp;
01142 y0 = 0.5 * (1.0 - map_rows) * ystp;
01143 grid_width = 0.01 * grid_spacing;
01144
01145 char *testSegList = NULL;
01146 char *pCh = NULL;
01147
01148 testSegList = rindex(inset, '}');
01149 if (testSegList)
01150 {
01151 for (pCh = testSegList + 1, hasSegList = 1; *pCh; pCh++)
01152 {
01153 if (!isspace(*pCh))
01154 {
01155
01156 hasSegList = 0;
01157 break;
01158 }
01159 }
01160 }
01161
01162
01163 if (!(ids = drms_open_records(drms_env, inset, &status)))
01164 {
01165 fprintf (stderr, "Error: (%s) unable to open input data set \"%s\"\n", module_ident, inset);
01166 fprintf (stderr, " status = %d\n", status);
01167 return 1;
01168 }
01169
01170 recCount = ids->n;
01171
01172 if (recCount < 1)
01173 {
01174 fprintf(stderr, "Error: (%s) no records in selected input set\n", module_ident);
01175 fprintf(stderr, " %s\n", inset);
01176 drms_close_records(ids, DRMS_FREE_RECORD);
01177 return 1;
01178 }
01179
01180
01181 if (verbose) printf ("creating %d records in series %s\n", recCount, outser);
01182 ods = drms_create_records(drms_env, recCount, outser, DRMS_PERMANENT, &status);
01183 if (!ods || status != DRMS_SUCCESS)
01184 {
01185 fprintf (stderr, "Error: unable to create %d records in series %s\n", recCount, outser);
01186 fprintf (stderr, " drms_create_records() returned status %d\n", status);
01187 return 1;
01188 }
01189
01190
01191
01192 char *runderscore = rindex(outser, '_');
01193 int running_as_export = (runderscore && strcmp(runderscore, "_mod")==0);
01194
01195
01196 axes[0] = map_cols;
01197 axes[1] = map_rows;
01198 map = drms_array_create (DRMS_TYPE_FLOAT, 2, axes, NULL, &status);
01199 if (status) {
01200 fprintf (stderr, "Error: couldn't create output array\n");
01201 return 1;
01202 }
01203 pixct = map_cols * map_rows;
01204 maplat = (double *)malloc (pixct * sizeof (double));
01205 maplon = (double *)malloc (pixct * sizeof (double));
01206 map_coslat = (double *)malloc (pixct * sizeof (double));
01207 map_sinlat = (double *)malloc (pixct * sizeof (double));
01208 offsun = (unsigned char *)malloc (pixct * sizeof (char));
01209 if (overlay) ongrid = (unsigned char *)malloc (pixct * sizeof (char));
01210
01211
01212
01213
01214 for (n=0, row=0, y=y0; row < map_rows; row++, y += ystp)
01215 {
01216 for (col=0, x=x0; col < map_cols; col++, x += xstp, n++)
01217 {
01218 xrot = x * cos_phi - y * sin_phi;
01219 yrot = y * cos_phi + x * sin_phi;
01220 offsun[n] = plane2sphere (xrot, yrot, clat, clon, &lat, &lon, proj);
01221 maplat[n] = lat;
01222 maplon[n] = lon;
01223 map_coslat[n] = cos (lat);
01224 map_sinlat[n] = sin (lat);
01225 if (overlay) ongrid[n] = near_grid_line (maplon[n], maplat[n], grid_spacing, grid_width);
01226 }
01227 }
01228
01229 data = (float *)map->data;
01230
01231
01232
01233
01234
01235
01236
01237
01238 for (irec = 0; irec < recCount; irec++)
01239 {
01240
01241 inrec = ids->records[irec];
01242 drms_sprint_rec_query(source, inrec);
01243
01244 if (drms_record_numsegments(inrec) < 1)
01245 {
01246 fprintf(stderr, "Error: no data segments in input record-set %s\n", inset);
01247 drms_close_records(ids, DRMS_FREE_RECORD);
01248 return 1;
01249 }
01250
01251 fprintf(stderr, "Maproj reading rec %d\n", irec);
01252
01253
01254 DRMS_Segment_t *firstSeg = NULL;
01255 HIterator_t *segIter = NULL;
01256 DRMS_Segment_t *orig = NULL;
01257 int validSegsCount;
01258
01259 validSegsCount = 0;
01260 while ((inseg = drms_record_nextseg2(inrec, &segIter, 1, &orig)) != NULL)
01261 {
01262 if (!firstSeg)
01263 {
01264 firstSeg = inseg;
01265 }
01266 else
01267 {
01268 if (!hasSegList && !doingAllSegs)
01269 {
01270
01271 break;
01272 }
01273 }
01274
01275
01276 if (drms_segment_getnaxis(inseg) == 2)
01277 {
01278 ++validSegsCount;
01279 }
01280 else
01281 {
01282 continue;
01283 }
01284
01285 if (validSegsCount == 0)
01286 {
01287 fprintf (stderr, "Error: no data segment of dimension 2 in input series %s\n", inset);
01288 drms_close_records(ids, DRMS_FREE_RECORD);
01289 drms_close_records(ods, DRMS_FREE_RECORD);
01290 return 1;
01291 }
01292
01293 image = drms_segment_read(inseg, DRMS_TYPE_FLOAT, &status);
01294
01295
01296
01297 if (!image || status != DRMS_SUCCESS)
01298 {
01299 fprintf(stderr, "Unable to read input segment (%s).\n", inseg->info->name);
01300 drms_close_records(ids, DRMS_FREE_RECORD);
01301 drms_close_records(ods, DRMS_FREE_RECORD);
01302 return 1;
01303 }
01304
01305 img_lon = drms_getkey_double(inrec, clon_key, &status);
01306 img_lat = drms_getkey_double(inrec, clat_key, &status);
01307
01308 status = solar_image_info(inrec, &img_xscl, &img_yscl, &img_xc, &img_yc, &img_radius, rsun_key, apsd_key, &img_pa, &ellipse_e, &ellipse_pa, &x_invrt, &y_invrt, &need_ephem, 0);
01309 if (status & NO_SEMIDIAMETER)
01310 {
01311 int keystat = 0;
01312 double dsun_obs = drms_getkey_double(inrec, dsun_key, &keystat);
01313
01314 if (keystat)
01315 {
01316 fprintf (stderr, "Error: one or more essential keywords or values missing, needed %s; skipped\n",dsun_key);
01317 fprintf (stderr, "solar_image_info() returned %08x\n", status);
01318 continue;
01319 }
01320
01321 img_radius = asin (RSUNM / dsun_obs);
01322 img_radius *= 3600.0 * degrad;
01323 img_radius /= (img_xscl <= img_yscl) ? img_xscl : img_yscl;
01324 status &= ~NO_SEMIDIAMETER;
01325 }
01326
01327 if (status == KEYSCOPE_VARIABLE)
01328 {
01329 fprintf(stderr, "Warning: one or more keywords expected constant are variable\n");
01330 }
01331 else if (status)
01332 {
01333 fprintf(stderr, "Warning: one or more essential keywords or values missing, 2nd message; skipped\n");
01334 fprintf(stderr, "solar_image_info() returned %08x\n", status);
01335 continue;
01336 }
01337
01338 if (MDI_correct)
01339 {
01340 mtrack_MDI_correct_imgctr(&img_xc, &img_yc, img_radius);
01341 mtrack_MDI_correct_pa(&img_pa);
01342 }
01343
01344 img_xc -= 0.5 * (image->axis[0] - 1);
01345 img_yc -= 0.5 * (image->axis[1] - 1);
01346
01347 img_lon *= raddeg;
01348 img_lat *= raddeg;
01349
01350
01351 orec = ods->records[irec];
01352 oseg = drms_segment_lookupnum(orec, orig->info->segnum);
01353
01354
01355
01356
01357
01358 scaling_override = 0;
01359 bscale = bscaleIn;
01360 if (bscaleIn == 0.0)
01361 {
01362 bscale = oseg->bscale;
01363 if (verbose) printf ("bscale set to output default: %g\n", bscale);
01364 }
01365 else
01366 {
01367 scaling_override = 1;
01368 }
01369
01370 bzero = bzeroIn;
01371 if (isnan (bzero))
01372 {
01373 bzero = oseg->bzero;
01374 if (verbose) printf ("bzero set to output default: %g\n", bzero);
01375 }
01376 else
01377 {
01378 scaling_override = 1;
01379 }
01380
01381 map->bscale = bscale;
01382 map->bzero = bzero;
01383
01384
01385
01386 perform_mapping(image, data, maplat, maplon, map_coslat, map_sinlat, pixct, offsun, img_lat, img_lon, img_xc, img_yc, img_radius, img_pa, ellipse_e, ellipse_pa, x_invrt, y_invrt, intrpopt, MDI_correct_distort);
01387
01388
01389 drms_free_array(image);
01390
01391 if (overlay)
01392 {
01393 for (n = 0; n < pixct; n++)
01394 {
01395 if (ongrid[n]) data[n] = (isfinite(data[n])) ? bblank : wblank;
01396 }
01397 }
01398
01399
01400
01401
01402
01403 drms_copykeys(orec, inrec, 0, kDRMS_KeyClass_Explicit);
01404 drms_setkey_string(orec, "requestid", RequestID);
01405 set_statistics(oseg, map, 1);
01406
01407 kstat = 0;
01408 kstat += check_and_set_key_str (orec, "WCSNAME", "Carrington Heliographic");
01409 kstat += check_and_set_key_int (orec, "WCSAXES", 2);
01410 snprintf (key, sizeof(key), "CRLN-%s", wcscode[proj]);
01411 kstat += check_and_set_key_str (orec, "CTYPE1", key);
01412 snprintf (key, sizeof(key), "CRLT-%s", wcscode[proj]);
01413 kstat += check_and_set_key_str (orec, "CTYPE2", key);
01414 kstat += check_and_set_key_str (orec, "CUNIT1", "deg");
01415 kstat += check_and_set_key_str (orec, "CUNIT2", "deg");
01416 kstat += check_and_set_key_float (orec, "CRPIX1", 0.5 * map_cols + 0.5);
01417 kstat += check_and_set_key_float (orec, "CRPIX2", 0.5 * map_rows + 0.5);
01418 kstat += check_and_set_key_float (orec, "CRVAL1", clon * degrad);
01419 kstat += check_and_set_key_float (orec, "CRVAL2", clat * degrad);
01420 kstat += check_and_set_key_float (orec, "CDELT1", map_scale);
01421 kstat += check_and_set_key_float (orec, "CDELT2", map_scale);
01422
01423 kstat += check_and_set_key_float (orec, "CROTA2", map_pa * degrad);
01424 if (map_pa != 0.0) {
01425 kstat += check_and_set_key_float (orec, "PC1_1", cos (map_pa));
01426
01427 kstat += check_and_set_key_float (orec, "PC1_2", sin (map_pa));
01428
01429 kstat += check_and_set_key_float (orec, "PC2_1", sin (map_pa));
01430 kstat += check_and_set_key_float (orec, "PC2_2", cos (map_pa));
01431 }
01432
01433 kstat += check_and_set_key_float (orec, "LonHG", clon * degrad);
01434 kstat += check_and_set_key_float (orec, "LatHG", clat * degrad);
01435 kstat += check_and_set_key_str (orec, "MapProj", mapname[proj]);
01436 kstat += check_and_set_key_float (orec, "MapScale", map_scale);
01437 kstat += check_and_set_key_float (orec, "Width", map_cols * map_scale);
01438 kstat += check_and_set_key_float (orec, "Height", map_rows * map_scale);
01439 kstat += check_and_set_key_float (orec, "Size", sqrt (map_rows * map_cols) * map_scale);
01440 kstat += check_and_set_key_float (orec, "Map_PA", map_pa / raddeg);
01441 kstat += check_and_set_key_float (orec, "RSunRef", 1.0e-6 * RSUNM);
01442 kstat += check_and_set_key_str (orec, "Interp", interpname[intrpopt]);
01443
01444 kstat += check_and_set_key_str (orec, "Module", module_ident);
01445 kstat += check_and_set_key_str (orec, "BLD_VERS", jsoc_version);
01446 kstat += check_and_set_key_time (orec, "Created", CURRENT_SYSTEM_TIME);
01447 kstat += check_and_set_key_str (orec, "Source", source);
01448 kstat += check_and_set_key_str (orec, "Input", inset);
01449
01450
01451
01452 if (running_as_export)
01453 {
01454 char buf[1024];
01455
01456 drms_appendhistory(orec, "MapProj=", 1); drms_appendhistory(orec, mapname[proj], 0);
01457 sprintf(buf, "LonHG=%f, LatHG=%f", clon * degrad, clat * degrad);
01458 drms_appendhistory(orec, buf, 1);
01459 drms_appendhistory(orec, "Interp=", 1); drms_appendhistory(orec, interpname[intrpopt], 0);
01460 if (overlay)
01461 {
01462 sprintf(buf, "%f", grid_spacing);
01463 drms_appendhistory(orec, "GridSpacing=", 1); drms_appendhistory(orec, buf, 0);
01464 }
01465 drms_setkey_time(orec, "DATE", CURRENT_SYSTEM_TIME);
01466 drms_appendhistory(orec, "Source=", 1); drms_appendhistory(orec, source, 0);
01467 }
01468 else if (kstat)
01469 {
01470 fprintf (stderr, "Error writing key value(s) to record %d in series %s\n", irec, outser);
01471 fprintf (stderr, " series may not have appropriate structure\n");
01472 drms_close_records(ids, DRMS_FREE_RECORD);
01473 drms_close_records(ods, DRMS_FREE_RECORD);
01474 return 1;
01475 }
01476
01477
01478 if (!scaling_override)
01479 {
01480 map->bscale = inseg->bscale;
01481 if (verbose) printf("bscale set to input record value: %g\n", bscale);
01482 map->bzero = inseg->bzero;
01483 if (verbose) printf("bzero set to input record value: %g\n", bzero);
01484 }
01485
01486
01487
01488 if (want_headers)
01489 {
01490 status = drms_segment_writewithkeys(oseg, map, 0);
01491 }
01492 else
01493 {
01494 status = drms_segment_write(oseg, map, 0);
01495 }
01496
01497 if (status)
01498 {
01499 drms_sprint_rec_query (recid, orec);
01500 fprintf (stderr, "Error writing data to record %s\n", recid);
01501 fprintf (stderr, " series may not have appropriate structure\n");
01502 drms_close_records(ids, DRMS_FREE_RECORD);
01503 drms_close_records(ods, DRMS_FREE_RECORD);
01504 return 1;
01505 }
01506 }
01507
01508 if (segIter)
01509 {
01510 hiter_destroy(&segIter);
01511 }
01512
01513 if (!firstSeg)
01514 {
01515
01516 fprintf(stderr, "Error: no data segment of dimension 2 in input record-set %s\n", inset);
01517 drms_close_records(ids, DRMS_FREE_RECORD);
01518 drms_close_records(ods, DRMS_FREE_RECORD);
01519 return 1;
01520 }
01521 }
01522
01523 drms_close_records(ods, DRMS_INSERT_RECORD);
01524 drms_free_array(map);
01525 return 0;
01526 }