ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/util/apps/hmib2ptr.c
Revision: 1.4
Committed: Thu Oct 27 19:03:54 2016 UTC (6 years, 10 months ago) by arta
Content type: text/plain
Branch: MAIN
CVS Tags: Ver_9-41, Ver_8-12, Ver_9-4, Ver_9-3, Ver_9-2, Ver_9-1, Ver_9-0
Changes since 1.3: +101 -2 lines
Log Message:
Add some checks for NULL segments, records, etc.

File Contents

# Content
1 /*
2 * hmib2ptr.c
3 *
4 * This module takes hmi.B_720s and convert into three field components (Bp, Bt, Br)
5 * and optionally Stony Hurst longitude, latitude
6 * and three error images (Bp_err, Bt_err, Br_err)
7 * Potentially to be used in export system
8 *
9 * Author:
10 * Xudong Sun
11 *
12 * Version:
13 * v0.0 Aug 28 2015
14 *
15 * Notes:
16 * v0.0
17 * Need to check externally that the input is hmi.B_720s
18 *
19 * Example Calls:
20 * hmib2ptr "in=hmi.B_720s[2011.02.15_00:00]" "out=hmi_test.Bptr_720s" "requestid=test" -e -l
21 *
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <time.h>
27 #include <sys/time.h>
28 #include <math.h>
29 #include <string.h>
30 #include "jsoc_main.h"
31 #include "astro.h"
32 #include "fstats.h"
33 //#include "cartography.c"
34 //#include "img2helioVector.c"
35 //#include "vecErrProp.c" // new version of errorprop
36
37 #define PI (M_PI)
38 #define TWOPI (2*M_PI)
39 #define RADSINDEG (PI/180.)
40 #define RAD2ARCSEC (648000./M_PI)
41 #define SECINDAY (86400.)
42 #define FOURK (4096)
43 #define FOURK2 (16777216)
44
45 #define ARRLENGTH(ARR) (sizeof(ARR) / sizeof(ARR[0]))
46
47 // Some other things
48 #ifndef MIN
49 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
50 #endif
51 #ifndef MAX
52 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
53 #endif
54
55 #define DIE(msg) {fflush(stdout); fprintf(stderr,"%s, status=%d\n", msg, status); return(status);}
56 #define SHOW(msg) {printf("%s", msg); fflush(stdout);}
57
58 #define FREE_ARR(arr) {if (arr) {free(arr);}}
59 #define DRMS_FREE_ARR(arr) {if (arr && (arr->data)) {drms_free_array(arr);}}
60
61 #define kNotSpecified "Not Specified"
62
63 // Macros for WCS transformations. assume crpix1, crpix2 = CRPIX1, CRPIX2, sina,cosa = sin and cos of CROTA2 resp.
64 // and crvalx and crvaly are CRVAL1 and CRVAL2, cdelt = CDELT1 == CDELT2, then
65 // PIX_X and PIX_Y are CCD pixel addresses, WX and WY are arc-sec W and N on the Sun from disk center.
66 #define PIX_X(wx,wy) ((((wx-crvalx)*cosa + (wy-crvaly)*sina)/cdelt)+crpix1)
67 #define PIX_Y(wx,wy) ((((wy-crvaly)*cosa - (wx-crvalx)*sina)/cdelt)+crpix2)
68 #define WX(pix_x,pix_y) (((pix_x-crpix1)*cosa - (pix_y-crpix2)*sina)*cdelt+crvalx)
69 #define WY(pix_x,pix_y) (((pix_y-crpix2)*cosa + (pix_x-crpix1)*sina)*cdelt+crvaly)
70
71 // Ephemeris information
72 struct ephemeris {
73 double disk_lonc, disk_latc;
74 double disk_xc, disk_yc;
75 double rSun, asd, pa;
76 };
77
78 //=================================================================================================
79
80 /* Get ephemeris information */
81 int getEphemeris(DRMS_Record_t *inRec, struct ephemeris *ephem);
82
83 /* Convert field vector, calls img2helioVector */
84 void get_bptr(struct ephemeris *ephem, int *dims, float *fld, float *inc, float *azi,
85 float *bp, float *bt, float *br, float *lon, float *lat);
86
87 /* Compute error, calls errprop_rad */
88 void get_bptr_err(struct ephemeris *ephem, int *dims, float *fld, float *inc, float *azi,
89 float *lon, float *lat,
90 float *err_fld, float *err_inc, float *err_azi, float *cc_fi, float *cc_fa, float *cc_ia,
91 float *err_bp, float *err_bt, float *err_br);
92
93 /* Vector transformation */
94 int img2helioVector (double bxImg, double byImg, double bzImg, double *bxHelio,
95 double *byHelio, double *bzHelio, double lon, double lat,
96 double lonc, double latc, double pAng);
97
98 /* Error propagation */
99 void vecErrProp(float fld, float inc, float azi,
100 float var_fld, float var_inc, float var_azi, float cov_fi, float cov_fa, float cov_ia,
101 double lon, double lat, double lonc, double latc, double pa,
102 double *var_bp, double *var_bt, double *var_br);
103
104 /* From Cartography.c */
105 int img2sphere (double x, double y, double ang_r, double latc, double lonc,
106 double pa, double *rho, double *lat, double *lon, double *sinlat,
107 double *coslat, double *sig, double *mu, double *chi);
108
109 //=================================================================================================
110
111 char *module_name = "sharp";
112
113 ModuleArgs_t module_args[] =
114 {
115 {ARG_STRING, "in", kNotSpecified, "Input B series."},
116 {ARG_STRING, "out", kNotSpecified, "Input Bptr series."},
117 {ARG_STRING, "requestid", kNotSpecified, "Request ID."},
118 {ARG_INT, "ambweak", "2", "Disambiguation method. 0: potential acute, 1: random, 2: radial acute"},
119 {ARG_FLAG, "l", "0", "Flag for lat/lon output."},
120 {ARG_FLAG, "e", "0", "Flag for error output."},
121 {ARG_END}
122 };
123
124 int DoIt(void)
125 {
126
127 int status = DRMS_SUCCESS;
128
129 /* Get parameters */
130
131 char *inQuery = (char *) params_get_str(&cmdparams, "in");
132 char *outQuery = (char *) params_get_str(&cmdparams, "out");
133 char *requestid = (char *) params_get_str(&cmdparams, "requestid");
134 int ambweak = params_get_int(&cmdparams, "ambweak");
135 int do_lonlat = params_isflagset(&cmdparams, "l");
136 int do_error = params_isflagset(&cmdparams, "e");
137
138 if (ambweak < 0 || ambweak > 2) ambweak = 2;
139
140 /* Input and output data */
141
142 DRMS_RecordSet_t *inRS = drms_open_records(drms_env, inQuery, &status);
143
144 if (!inRS)
145 {
146 DIE("No records specified by record-set specification.\n");
147 }
148
149 int nrecs = inRS->n;
150 if (status || nrecs == 0) DIE("Input records error.");
151
152 DRMS_RecordSet_t *outRS = drms_create_records(drms_env, nrecs, outQuery, DRMS_PERMANENT, &status);
153 if (status) {
154 drms_close_records(inRS, DRMS_FREE_RECORD);
155 DIE("Output records not created.");
156 }
157
158 /* Work */
159
160 printf("Processing %d records:\n", nrecs);
161
162 for (int irec = 0; irec < nrecs; irec++) {
163
164 // Input record
165 DRMS_Record_t *inRec = inRS->records[irec];
166
167 if (!inRec)
168 {
169 fprintf(stderr, "No record with index %d in record set.\n", irec);
170 continue;
171 }
172
173 TIME t_rec = drms_getkey_time(inRec, "T_REC", &status);
174
175 if (status != DRMS_SUCCESS)
176 {
177 fprintf(stderr, "Unable to obtain keyword value for T_REC.\n");
178 continue;
179 }
180
181 char t_rec_str[100];
182 sprint_time(t_rec_str, t_rec, "TAI", 0);
183 printf("Processing record #%d, T_REC=%s\n", irec, t_rec_str);
184
185 // Ephemeris
186
187 struct ephemeris ephem;
188 status = getEphemeris(inRec, &ephem); // can never return anything but 'success'.
189
190 // Input images
191
192 DRMS_Segment_t *inSeg_fld = drms_segment_lookup(inRec, "field");
193 if (!inSeg_fld)
194 {
195 fprintf(stderr, "Missing required segment 'field'.\n");
196 continue;
197 }
198
199 DRMS_Segment_t *inSeg_inc = drms_segment_lookup(inRec, "inclination");
200 if (!inSeg_inc)
201 {
202 fprintf(stderr, "Missing required segment 'inclination'.\n");
203 continue;
204 }
205
206 DRMS_Segment_t *inSeg_azi = drms_segment_lookup(inRec, "azimuth");
207 if (!inSeg_azi)
208 {
209 fprintf(stderr, "Missing required segment 'azimuth'.\n");
210 continue;
211 }
212
213 DRMS_Segment_t *inSeg_amb = drms_segment_lookup(inRec, "disambig");
214 if (!inSeg_amb)
215 {
216 fprintf(stderr, "Missing required segment 'disambig'.\n");
217 continue;
218 }
219
220 int status_fld = 0, status_inc = 0, status_azi = 0, status_amb = 0;
221 DRMS_Array_t *inArray_fld = NULL, *inArray_inc = NULL, *inArray_azi = NULL, *inArray_amb = NULL;
222 inArray_fld = drms_segment_read(inSeg_fld, DRMS_TYPE_FLOAT, &status_fld);
223 inArray_inc = drms_segment_read(inSeg_inc, DRMS_TYPE_FLOAT, &status_inc);
224 inArray_azi = drms_segment_read(inSeg_azi, DRMS_TYPE_FLOAT, &status_azi);
225 inArray_amb = drms_segment_read(inSeg_amb, DRMS_TYPE_CHAR, &status_amb);
226 if (status_fld || status_inc || status_azi || status_amb) {
227 printf("Reading input arrays error, record skipped\n");
228 DRMS_FREE_ARR(inArray_fld); DRMS_FREE_ARR(inArray_inc);
229 DRMS_FREE_ARR(inArray_azi); DRMS_FREE_ARR(inArray_amb);
230 continue;
231 }
232
233 // Input error images if needed
234
235 DRMS_Array_t *inArray_err_fld = NULL, *inArray_err_inc = NULL, *inArray_err_azi = NULL;
236 DRMS_Array_t *inArray_cc_fi = NULL, *inArray_cc_fa = NULL, *inArray_cc_ia = NULL;
237 if (do_error) {
238 DRMS_Segment_t *inSeg_err_fld = drms_segment_lookup(inRec, "field_err");
239 DRMS_Segment_t *inSeg_err_inc = drms_segment_lookup(inRec, "inclination_err");
240 DRMS_Segment_t *inSeg_err_azi = drms_segment_lookup(inRec, "azimuth_err");
241 DRMS_Segment_t *inSeg_cc_fi = drms_segment_lookup(inRec, "field_inclination_err");
242 DRMS_Segment_t *inSeg_cc_fa = drms_segment_lookup(inRec, "field_az_err");
243 DRMS_Segment_t *inSeg_cc_ia = drms_segment_lookup(inRec, "inclin_azimuth_err");
244
245 if (!inSeg_err_fld || !inSeg_err_inc || !inSeg_err_azi || !inSeg_cc_fi || !inSeg_cc_fa || !inSeg_cc_ia)
246 {
247 fprintf(stderr, "Missing one or more required error segments.\n");
248 continue;
249 }
250
251 int status_err_fld = 0, status_err_inc = 0, status_err_azi = 0;
252 int status_cc_fi = 0, status_cc_fa = 0, status_cc_ia = 0;
253
254 inArray_err_fld = drms_segment_read(inSeg_err_fld, DRMS_TYPE_FLOAT, &status_err_fld);
255 inArray_err_inc = drms_segment_read(inSeg_err_inc, DRMS_TYPE_FLOAT, &status_err_inc);
256 inArray_err_azi = drms_segment_read(inSeg_err_azi, DRMS_TYPE_FLOAT, &status_err_azi);
257 inArray_cc_fi = drms_segment_read(inSeg_cc_fi, DRMS_TYPE_FLOAT, &status_cc_fi);
258 inArray_cc_fa = drms_segment_read(inSeg_cc_fa, DRMS_TYPE_FLOAT, &status_cc_fa);
259 inArray_cc_ia = drms_segment_read(inSeg_cc_ia, DRMS_TYPE_FLOAT, &status_cc_ia);
260 if (status_err_fld || status_err_inc || status_err_azi ||
261 status_cc_fi || status_cc_fa || status_cc_ia) {
262 printf("Reading input uncertainty arrays error, record skipped\n");
263 DRMS_FREE_ARR(inArray_err_fld); DRMS_FREE_ARR(inArray_err_inc); DRMS_FREE_ARR(inArray_err_azi);
264 DRMS_FREE_ARR(inArray_cc_fi); DRMS_FREE_ARR(inArray_cc_fa); DRMS_FREE_ARR(inArray_cc_ia);
265 DRMS_FREE_ARR(inArray_fld); DRMS_FREE_ARR(inArray_inc);
266 DRMS_FREE_ARR(inArray_azi); DRMS_FREE_ARR(inArray_amb);
267 continue;
268 }
269 }
270
271 // Some pre-processing
272
273 int ncols = inArray_fld->axis[0], nrows = inArray_fld->axis[1]; // FOURK
274 int npix = ncols * nrows;
275 int dims[2] = {ncols, nrows};
276
277 float *fld = (float *) (inArray_fld->data);
278 float *inc = (float *) (inArray_inc->data);
279 float *azi = (float *) (inArray_azi->data);
280 char *amb = (char *) (inArray_amb->data);
281 for (int ipix = 0; ipix < npix; ipix++) {
282 inc[ipix] *= RADSINDEG;
283 if (amb[ipix] >> ambweak) azi[ipix] += 180.; // bitwise operator
284 azi[ipix] *= RADSINDEG;
285 }
286
287 float *err_fld = NULL, *err_inc = NULL, *err_azi = NULL;
288 float *cc_fi = NULL, *cc_fa = NULL, *cc_ia = NULL;
289 if (do_error) {
290 err_fld = (float *) (inArray_err_fld->data);
291 err_inc = (float *) (inArray_err_inc->data);
292 err_azi = (float *) (inArray_err_azi->data);
293 cc_fi = (float *) (inArray_cc_fi->data);
294 cc_fa = (float *) (inArray_cc_fa->data);
295 cc_ia = (float *) (inArray_cc_ia->data);
296 for (int ipix = 0; ipix < npix; ipix++) {
297 err_inc[ipix] *= RADSINDEG;
298 err_azi[ipix] *= RADSINDEG; // conver to radian
299 }
300 }
301
302 // Bptr, also calculate lon/lat
303
304 float *bp = (float *) (malloc(npix * sizeof(float)));
305 float *bt = (float *) (malloc(npix * sizeof(float)));
306 float *br = (float *) (malloc(npix * sizeof(float)));
307 float *lon = (float *) (malloc(npix * sizeof(float))); // lon/lat in rad
308 float *lat = (float *) (malloc(npix * sizeof(float)));
309 get_bptr(&ephem, dims, fld, inc, azi, bp, bt, br, lon, lat); // working function
310
311 // Error if requested
312
313 float *err_bp = NULL, *err_bt = NULL, *err_br = NULL;
314 if (do_error) {
315 err_bp = (float *) (malloc(npix * sizeof(float)));
316 err_bt = (float *) (malloc(npix * sizeof(float)));
317 err_br = (float *) (malloc(npix * sizeof(float)));
318 get_bptr_err(&ephem, dims, fld, inc, azi, lon, lat,
319 err_fld, err_inc, err_azi, cc_fi, cc_fa, cc_ia,
320 err_bp, err_bt, err_br); // working function, all input in rad
321 }
322
323 // Convert lon/lat to deg if needed
324
325 if (do_lonlat) {
326 for (int ipix = 0; ipix < npix; ipix++) {
327 lon[ipix] /= RADSINDEG;
328 lat[ipix] /= RADSINDEG;
329 }
330 }
331
332 // Some clean up
333
334 DRMS_FREE_ARR(inArray_fld); DRMS_FREE_ARR(inArray_inc);
335 DRMS_FREE_ARR(inArray_azi); DRMS_FREE_ARR(inArray_amb);
336 if (do_error) {
337 DRMS_FREE_ARR(inArray_err_fld); DRMS_FREE_ARR(inArray_err_inc); DRMS_FREE_ARR(inArray_err_azi);
338 DRMS_FREE_ARR(inArray_cc_fi); DRMS_FREE_ARR(inArray_cc_fa); DRMS_FREE_ARR(inArray_cc_ia);
339 }
340 if (!do_lonlat) {
341 FREE_ARR(lon); FREE_ARR(lat);
342 }
343
344 // Output
345
346 DRMS_Record_t *outRec = outRS->records[irec];
347 if (!outRec)
348 {
349 fprintf(stderr, "No output record with index %d in record set.\n", irec);
350 continue;
351 }
352
353 DRMS_Segment_t *outSeg_bp = drms_segment_lookup(outRec, "Bp");
354 if (!outSeg_bp)
355 {
356 fprintf(stderr, "Missing required output segment 'Bp'.\n");
357 continue;
358 }
359
360 DRMS_Segment_t *outSeg_bt = drms_segment_lookup(outRec, "Bt");
361 if (!outSeg_bt)
362 {
363 fprintf(stderr, "Missing required output segment 'Bt'.\n");
364 continue;
365 }
366
367 DRMS_Segment_t *outSeg_br = drms_segment_lookup(outRec, "Br");
368 if (!outSeg_br)
369 {
370 fprintf(stderr, "Missing required output segment 'Br'.\n");
371 continue;
372 }
373
374 int status_bp = 0, status_bt = 0, status_br = 0;
375 DRMS_Array_t *outArray_bp = NULL, *outArray_bt = NULL, *outArray_br = NULL;
376 outArray_bp = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, bp, &status_bp);
377 outArray_bt = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, bt, &status_bt);
378 outArray_br = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, br, &status_br);
379 if (status_bp || status_bt || status_br) {
380 printf("Writing output arrays error, record skipped\n");
381 DRMS_FREE_ARR(outArray_bp); DRMS_FREE_ARR(outArray_bt); DRMS_FREE_ARR(outArray_br);
382 continue;
383 }
384 outArray_bp->israw = outArray_bt->israw = outArray_br->israw = 0; // always compressed
385 outArray_bp->bzero = outSeg_bp->bzero; outArray_bp->bscale = outSeg_bp->bscale;
386 outArray_bt->bzero = outSeg_bt->bzero; outArray_bt->bscale = outSeg_bt->bscale;
387 outArray_br->bzero = outSeg_br->bzero; outArray_br->bscale = outSeg_br->bscale;
388
389 status_bp = drms_segment_write(outSeg_bp, outArray_bp, 0);
390 status_bt = drms_segment_write(outSeg_bt, outArray_bt, 0);
391 status_br = drms_segment_write(outSeg_br, outArray_br, 0);
392 DRMS_FREE_ARR(outArray_bp); DRMS_FREE_ARR(outArray_bt); DRMS_FREE_ARR(outArray_br);
393
394 if (status_bp || status_bt || status_br) {
395 printf("Writing output arrays error, record skipped\n");
396 continue;
397 }
398
399 // Optional output
400
401 if (do_error) {
402 DRMS_Segment_t *outSeg_err_bp = drms_segment_lookup(outRec, "Bp_err");
403 if (!outSeg_err_bp)
404 {
405 fprintf(stderr, "Missing required output segment 'Bp_err'.\n");
406 continue;
407 }
408
409 DRMS_Segment_t *outSeg_err_bt = drms_segment_lookup(outRec, "Bt_err");
410 if (!outSeg_err_bt)
411 {
412 fprintf(stderr, "Missing required output segment 'Bt_err'.\n");
413 continue;
414 }
415
416 DRMS_Segment_t *outSeg_err_br = drms_segment_lookup(outRec, "Br_err");
417 if (!outSeg_err_br)
418 {
419 fprintf(stderr, "Missing required output segment 'Br_err'.\n");
420 continue;
421 }
422
423 int status_err_bp = 0, status_err_bt = 0, status_err_br = 0;
424 DRMS_Array_t *outArray_err_bp = NULL, *outArray_err_bt = NULL, *outArray_err_br = NULL;
425 outArray_err_bp = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, err_bp, &status_err_bp);
426 outArray_err_bt = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, err_bt, &status_err_bt);
427 outArray_err_br = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, err_br, &status_err_br);
428 if (status_err_bp || status_err_bt || status_err_br) {
429 printf("Writing error output arrays error, record skipped\n");
430 DRMS_FREE_ARR(outArray_err_bp); DRMS_FREE_ARR(outArray_err_bt); DRMS_FREE_ARR(outArray_err_br);
431 continue;
432 }
433 outArray_err_bp->israw = outArray_err_bt->israw = outArray_err_br->israw = 0; // always compressed, fixed Dec 23 2015
434 outArray_err_bp->bzero = outSeg_err_bp->bzero; outArray_err_bp->bscale = outSeg_err_bp->bscale;
435 outArray_err_bt->bzero = outSeg_err_bt->bzero; outArray_err_bt->bscale = outSeg_err_bt->bscale;
436 outArray_err_br->bzero = outSeg_err_br->bzero; outArray_err_br->bscale = outSeg_err_br->bscale;
437
438 status_err_bp = drms_segment_write(outSeg_err_bp, outArray_err_bp, 0);
439 status_err_bt = drms_segment_write(outSeg_err_bt, outArray_err_bt, 0);
440 status_err_br = drms_segment_write(outSeg_err_br, outArray_err_br, 0);
441 DRMS_FREE_ARR(outArray_err_bp); DRMS_FREE_ARR(outArray_err_bt); DRMS_FREE_ARR(outArray_err_br);
442
443 if (status_err_bp || status_err_bt || status_err_br) {
444 printf("Writing error output arrays error, record skipped\n");
445 continue;
446 }
447 }
448
449 if (do_lonlat) {
450 DRMS_Segment_t *outSeg_lon = drms_segment_lookup(outRec, "lon");
451 if (!outSeg_lon)
452 {
453 fprintf(stderr, "Missing required output segment 'lon'.\n");
454 continue;
455 }
456
457 DRMS_Segment_t *outSeg_lat = drms_segment_lookup(outRec, "lat");
458 if (!outSeg_lon)
459 {
460 fprintf(stderr, "Missing required output segment 'lat'.\n");
461 continue;
462 }
463
464 int status_lon = 0, status_lat = 0;
465 DRMS_Array_t *outArray_lon = NULL, *outArray_lat = NULL;
466 outArray_lon = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, lon, &status_lon);
467 outArray_lat = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, lat, &status_lat);
468 if (status_lon || status_lat) {
469 printf("Writing lon/lat arrays error, record skipped\n");
470 DRMS_FREE_ARR(outArray_lon); DRMS_FREE_ARR(outArray_lat);
471 continue;
472 }
473 outArray_lon->israw = outArray_lat->israw = 0; // always compressed
474 outArray_lon->bzero = outSeg_lon->bzero; outArray_lon->bscale = outSeg_lon->bscale;
475 outArray_lat->bzero = outSeg_lat->bzero; outArray_lat->bscale = outSeg_lat->bscale;
476
477 status_lon = drms_segment_write(outSeg_lon, outArray_lon, 0);
478 status_lat = drms_segment_write(outSeg_lat, outArray_lat, 0);
479 DRMS_FREE_ARR(outArray_lon); DRMS_FREE_ARR(outArray_lat);
480
481 if (status_lon || status_lat) {
482 printf("Writing lon/lat arrays error, record skipped\n");
483 continue;
484 }
485 }
486
487 // Keywords
488
489 drms_copykeys(outRec, inRec, 0, 0); // copy all keys
490
491 TIME val, trec, tnow, UNIX_epoch = -220924792.000; /* 1970.01.01_00:00:00_UTC */
492 tnow = (double)time(NULL);
493 tnow += UNIX_epoch;
494 drms_setkey_time(outRec, "DATE", tnow);
495 drms_setkey_int(outRec, "AMBWEAK", ambweak);
496 drms_setkey_string(outRec, "RequestID", requestid);
497 drms_setkey_string(outRec, "BUNIT_000", "Mx/cm^2");
498 drms_setkey_string(outRec, "BUNIT_001", "Mx/cm^2");
499 drms_setkey_string(outRec, "BUNIT_002", "Mx/cm^2");
500 drms_setkey_string(outRec, "BUNIT_003", "Mx/cm^2");
501 drms_setkey_string(outRec, "BUNIT_004", "Mx/cm^2");
502 drms_setkey_string(outRec, "BUNIT_005", "Mx/cm^2");
503 drms_setkey_string(outRec, "BUNIT_006", "degree");
504 drms_setkey_string(outRec, "BUNIT_007", "degree");
505
506 } // irec
507
508 drms_close_records(inRS, DRMS_FREE_RECORD);
509 drms_close_records(outRS, DRMS_INSERT_RECORD);
510
511 return 0;
512
513 } // DoIt
514
515
516 //=================================================================================================
517
518 /*
519 * Fetch ephemeris info from a DRMS record
520 * No error checking for now
521 *
522 */
523
524 int getEphemeris(DRMS_Record_t *inRec, struct ephemeris *ephem)
525 {
526
527 int status = 0;
528
529 float crota2 = drms_getkey_float(inRec, "CROTA2", &status); // rotation
530 double sina = sin(crota2 * RADSINDEG);
531 double cosa = cos(crota2 * RADSINDEG);
532
533 ephem->pa = - crota2 * RADSINDEG;
534 ephem->disk_latc = drms_getkey_float(inRec, "CRLT_OBS", &status) * RADSINDEG;
535 ephem->disk_lonc = drms_getkey_float(inRec, "CRLN_OBS", &status) * RADSINDEG;
536
537 float crvalx = 0.0;
538 float crvaly = 0.0;
539 float crpix1 = drms_getkey_float(inRec, "CRPIX1", &status);
540 float crpix2 = drms_getkey_float(inRec, "CRPIX2", &status);
541 float cdelt = drms_getkey_float(inRec, "CDELT1", &status); // in arcsec, assumimg dx=dy
542 ephem->disk_xc = PIX_X(0.0,0.0) - 1.0; // Center of disk in pixel, starting at 0
543 ephem->disk_yc = PIX_Y(0.0,0.0) - 1.0;
544
545 float dSun = drms_getkey_float(inRec, "DSUN_OBS", &status);
546 float rSun_ref = drms_getkey_float(inRec, "RSUN_REF", &status);
547 if (status) rSun_ref = 6.96e8;
548
549 ephem->asd = asin(rSun_ref/dSun);
550 ephem->rSun = asin(rSun_ref / dSun) * RAD2ARCSEC / cdelt; // in pixel
551
552 return 0;
553
554 }
555
556 /* Convert field vector, calls img2helioVector */
557 void get_bptr(struct ephemeris *ephem, int *dims, float *fld, float *inc, float *azi,
558 float *bp, float *bt, float *br, float *lon, float *lat)
559 {
560 int ncols = dims[0], nrows = dims[1];
561 int ipix = 0;
562
563 double lonc = 0., latc = ephem->disk_latc; // iput
564 double xc = ephem->disk_xc, yc = ephem->disk_yc;
565 double asd = ephem->asd, pa = ephem->pa, rSun = ephem->rSun;
566 double x, y, b_xi, b_eta, b_zeta;
567 double rho, lat_t, lon_t, sinlat_t, coslat_t, sig, mu, chi; // output
568 double bx_t, by_t, bz_t;
569 // printf("xc=%f, yc=%f, rSun=%f\n", xc, yc, rSun);
570
571 for (int row = 0; row < nrows; row++) {
572 for (int col = 0; col < ncols; col++) {
573 ipix = row * ncols + col;
574
575 // lon/lat
576 x = (col - xc) / rSun; y = (row - yc) / rSun;
577 if (img2sphere(x, y, asd, latc, lonc, pa,
578 &rho, &lat_t, &lon_t, &sinlat_t, &coslat_t,
579 &sig, &mu, &chi)) { // fail
580 lon[ipix] = lat[ipix] = DRMS_MISSING_FLOAT;
581 bp[ipix] = bt[ipix] = br[ipix] = DRMS_MISSING_FLOAT;
582 continue;
583 }
584 if (lon_t > PI) lon_t -= TWOPI;
585 lon[ipix] = lon_t; lat[ipix] = lat_t;
586
587 // Bvec
588 b_xi = - fld[ipix] * sin(inc[ipix]) * sin(azi[ipix]);
589 b_eta = fld[ipix] * sin(inc[ipix]) * cos(azi[ipix]);
590 b_zeta = fld[ipix] * cos(inc[ipix]);
591 img2helioVector(b_xi, b_eta, b_zeta, &bx_t, &by_t, &bz_t,
592 lon_t, lat_t, lonc, latc, pa);
593 bp[ipix] = bx_t;
594 bt[ipix] = by_t * (-1);
595 br[ipix] = bz_t;
596 }
597 }
598 }
599
600 /* Compute error, calls errprop_rad */
601 void get_bptr_err(struct ephemeris *ephem, int *dims, float *fld, float *inc, float *azi,
602 float *lon, float *lat,
603 float *err_fld, float *err_inc, float *err_azi, float *cc_fi, float *cc_fa, float *cc_ia,
604 float *err_bp, float *err_bt, float *err_br)
605 {
606 int ncols = dims[0], nrows = dims[1];
607 int npix = ncols * nrows;
608
609 double lonc = 0., latc = ephem->disk_latc, pa = ephem->pa; // Dec 23 2015, changed lonc from disc_lonc to 0.
610
611 float var_fld, var_inc, var_azi; // variance
612 float cov_fi, cov_fa, cov_ia; // covariance
613
614 double var_bp, var_bt, var_br;
615
616 for (int ipix = 0; ipix < npix; ipix++) {
617 if (isnan(lon[ipix])) {
618 err_bp[ipix] = err_bt[ipix] = err_br[ipix] = DRMS_MISSING_FLOAT;
619 continue;
620 }
621
622 // variance & covariance
623 var_fld = err_fld[ipix] * err_fld[ipix];
624 var_inc = err_inc[ipix] * err_inc[ipix];
625 var_azi = err_azi[ipix] * err_azi[ipix];
626 cov_fi = cc_fi[ipix] * err_fld[ipix] * err_inc[ipix];
627 cov_fa = cc_fa[ipix] * err_fld[ipix] * err_azi[ipix];
628 cov_ia = cc_ia[ipix] * err_inc[ipix] * err_azi[ipix];
629
630 // Do it
631 vecErrProp(fld[ipix], inc[ipix], azi[ipix], var_fld, var_inc, var_azi, cov_fi, cov_fa, cov_ia,
632 lon[ipix], lat[ipix], lonc, latc, pa, &var_bp, &var_bt, &var_br);
633 err_bp[ipix] = sqrt(var_bp);
634 err_bt[ipix] = sqrt(var_bt);
635 err_br[ipix] = sqrt(var_br);
636 }
637 }
638
639 // From img2helioVector.c
640 int img2helioVector (double bxImg, double byImg, double bzImg, double *bxHelio,
641 double *byHelio, double *bzHelio, double lon, double lat,
642 double lonc, double latc, double pAng) {
643 /*
644 * perform tramsformation of a vector from image location (lon, lat) to
645 * heliographic center. The formula is from Hagyard (1987), and further
646 * developed by Gary & Hagyard (1990).
647 *
648 * Arguments:
649 *
650 * bxImg, byImg, bzImg: three components of vector magnetic field on image
651 * coordinates.
652 * lon, lat: heliographic coordinates of the location where the vector field
653 * measured. They are in radians.
654 * lonc, latc: heliographic coordinates of the image disk center. They are in
655 * radians.
656 * pAng: position angle of the heliographic north pole, measured eastward
657 * from the north. It's in radians.
658 */
659
660 static double raddeg = M_PI / 180.;
661 double a11, a12, a13, a21, a22, a23, a31, a32, a33;
662
663 a11 = -sin(latc) * sin(pAng) * sin(lon - lonc) + cos(pAng) * cos(lon - lonc);
664 a12 = sin(latc) * cos(pAng) * sin(lon - lonc) + sin(pAng) * cos(lon - lonc);
665 a13 = -cos(latc) * sin(lon - lonc);
666 a21 = -sin(lat) * (sin(latc) * sin(pAng) * cos(lon - lonc) + cos(pAng) * sin(lon - lonc))
667 - cos(lat) * cos(latc) * sin(pAng);
668 a22 = sin(lat) * (sin(latc) * cos(pAng) * cos(lon - lonc) - sin(pAng) * sin(lon - lonc))
669 + cos(lat) * cos(latc) * cos(pAng);
670 a23 = -cos(latc) * sin(lat) * cos(lon - lonc) + sin(latc) * cos(lat);
671 a31 = cos(lat) * (sin(latc) * sin(pAng) * cos(lon - lonc) + cos(pAng) * sin(lon - lonc))
672 - sin(lat) * cos(latc) * sin(pAng);
673 a32 = -cos(lat) * (sin(latc) * cos(pAng) * cos(lon - lonc) - sin(pAng) * sin(lon - lonc))
674 + sin(lat) * cos(latc) * cos(pAng);
675 a33 = cos(lat) * cos(latc) * cos(lon - lonc) + sin(lat) * sin(latc);
676
677 *bxHelio = a11 * bxImg + a12 * byImg + a13 * bzImg;
678 *byHelio = a21 * bxImg + a22 * byImg + a23 * bzImg;
679 *bzHelio = a31 * bxImg + a32 * byImg + a33 * bzImg;
680
681 return 0;
682 }
683
684
685 // Error propagation for vector field
686 // Adapted from Yang's errorprop.c
687 // All angles in radian
688 // By or Bt=-By doesn't matter (all terms are squared)
689
690 void vecErrProp(float fld, float inc, float azi,
691 float var_fld, float var_inc, float var_azi, float cov_fi, float cov_fa, float cov_ia,
692 double lon, double lat, double lonc, double latc, double pa,
693 double *var_bp, double *var_bt, double *var_br)
694
695 {
696
697 // Coefficients
698
699 double a11, a12, a13, a21, a22, a23, a31, a32, a33;
700 a11 = - sin(latc) * sin(pa) * sin(lon - lonc) + cos(pa) * cos(lon - lonc);
701 a12 = sin(latc) * cos(pa) * sin(lon - lonc) + sin(pa) * cos(lon - lonc);
702 a13 = - cos(latc) * sin(lon - lonc);
703 a21 = - sin(lat) * (sin(latc) * sin(pa) * cos(lon - lonc) + cos(pa) * sin(lon - lonc))
704 - cos(lat) * cos(latc) * sin(pa);
705 a22 = sin(lat) * (sin(latc) * cos(pa) * cos(lon - lonc) - sin(pa) * sin(lon - lonc))
706 + cos(lat) * cos(latc) * cos(pa);
707 a23 = - cos(latc) * sin(lat) * cos(lon - lonc) + sin(latc) * cos(lat);
708 a31 = cos(lat) * (sin(latc) * sin(pa) * cos(lon - lonc) + cos(pa) * sin(lon - lonc))
709 - sin(lat) * cos(latc) * sin(pa);
710 a32 = - cos(lat) * (sin(latc) * cos(pa) * cos(lon - lonc) - sin(pa) * sin(lon - lonc))
711 + sin(lat) * cos(latc) * cos(pa);
712 a33 = cos(lat) * cos(latc) * cos(lon - lonc) + sin(lat) * sin(latc);
713
714 // Derivative
715
716 double dBpdfld, dBpdinc, dBpdazi;
717 double dBtdfld, dBtdinc, dBtdazi;
718 double dBrdfld, dBrdinc, dBrdazi;
719
720 dBpdfld = (- a11 * sin(inc) * sin(azi) + a12 * sin(inc) * cos(azi) + a13 * cos(inc));
721 dBpdinc = fld * (- a11 * cos(inc) * sin(azi) + a12 * cos(inc) * cos(azi) - a13 * sin(inc));
722 dBpdazi = fld * (- a11 * sin(inc) * cos(azi) - a12 * sin(inc) * sin(azi));
723
724 dBtdfld = (- a21 * sin(inc) * sin(azi) + a22 * sin(inc) * cos(azi) + a23 * cos(inc));
725 dBtdinc = fld * (- a21 * cos(inc) * sin(azi) + a22 * cos(inc) * cos(azi) - a23 * sin(inc));
726 dBtdazi = fld * (- a21 * sin(inc) * cos(azi) - a22 * sin(inc) * sin(azi));
727
728 dBrdfld = (- a31 * sin(inc) * sin(azi) + a32 * sin(inc) * cos(azi) + a33 * cos(inc));
729 dBrdinc = fld * (- a31 * cos(inc) * sin(azi) + a32 * cos(inc) * cos(azi) - a33 * sin(inc));
730 dBrdazi = fld * (- a31 * sin(inc) * cos(azi) - a32 * sin(inc) * sin(azi));
731
732 // Sum
733
734 *var_bp = dBpdfld * dBpdfld * var_fld + dBpdinc * dBpdinc * var_inc + dBpdazi * dBpdazi * var_azi +
735 2.0 * dBpdfld * dBpdinc * cov_fi + 2.0 * dBpdfld * dBpdazi * cov_fa + 2.0 * dBpdinc * dBpdazi * cov_ia;
736
737 *var_bt = dBtdfld * dBtdfld * var_fld + dBtdinc * dBtdinc * var_inc + dBtdazi * dBtdazi * var_azi +
738 2.0 * dBtdfld * dBtdinc * cov_fi + 2.0 * dBtdfld * dBtdazi * cov_fa + 2.0 * dBtdinc * dBtdazi * cov_ia;
739
740 *var_br = dBrdfld * dBrdfld * var_fld + dBrdinc * dBrdinc * var_inc + dBrdazi * dBrdazi * var_azi +
741 2.0 * dBrdfld * dBrdinc * cov_fi + 2.0 * dBrdfld * dBrdazi * cov_fa + 2.0 * dBrdinc * dBrdazi * cov_ia;
742
743 }
744
745 // from Cartography.c
746 int img2sphere (double x, double y, double ang_r, double latc, double lonc,
747 double pa, double *rho, double *lat, double *lon, double *sinlat,
748 double *coslat, double *sig, double *mu, double *chi) {
749 /*
750 * Map projected coordinates (x, y) to (lon, lat) and (rho | sig, chi)
751 *
752 * Arguments:
753 * x } Plate locations, in units of the image radius, relative
754 * y } to the image center
755 * ang_r Apparent semi-diameter of sun (angular radius of sun at
756 * the observer's tangent line)
757 * latc Latitude of disc center, uncorrected for light travel time
758 * lonc Longitude of disc center
759 * pa Position angle of solar north on image, measured eastward
760 * from north (sky coordinates)
761 * Return values:
762 * rho Angle point:sun_center:observer
763 * lon Heliographic longitude
764 * lat Heliographic latitude
765 * sinlat sine of heliographic latitude
766 * coslat cosine of heliographic latitude
767 * sig Angle point:observer:sun_center
768 * mu cosine of angle between the point:observer line and the
769 * local normal
770 * chi Position angle on image measured westward from solar
771 * north
772 *
773 * All angles are in radians.
774 * Return value is 1 if point is outside solar radius (in which case the
775 * heliographic coordinates and mu are meaningless), 0 otherwise.
776 * It is assumed that the image is direct; the x or y coordinates require a
777 * sign change if the image is inverted.
778 *
779 */
780 static double ang_r0 = 0.0, sinang_r = 0.0, tanang_r = 0.0;
781 static double latc0 = 0.0, coslatc = 1.0, sinlatc = 0.0;
782 double cosr, sinr, sinlon, sinsig;
783
784 if (ang_r != ang_r0) {
785 sinang_r = sin (ang_r);
786 tanang_r = tan (ang_r);
787 ang_r0 = ang_r;
788 }
789 if (latc != latc0) {
790 sinlatc = sin (latc);
791 coslatc = cos (latc);
792 latc0 = latc;
793 }
794 *chi = atan2 (x, y) + pa;
795 while (*chi > 2 * M_PI) *chi -= 2 * M_PI;
796 while (*chi < 0.0) *chi += 2 * M_PI;
797 /* Camera curvature correction, no small angle approximations */
798 *sig = atan (hypot (x, y) * tanang_r);
799 sinsig = sin (*sig);
800 *rho = asin (sinsig / sinang_r) - *sig;
801 if (*sig > ang_r) return (-1);
802 *mu = cos (*rho + *sig);
803 sinr = sin (*rho);
804 cosr = cos (*rho);
805
806 *sinlat = sinlatc * cos (*rho) + coslatc * sinr * cos (*chi);
807 *coslat = sqrt (1.0 - *sinlat * *sinlat);
808 *lat = asin (*sinlat);
809 sinlon = sinr * sin (*chi) / *coslat;
810 *lon = asin (sinlon);
811 if (cosr < (*sinlat * sinlatc)) *lon = M_PI - *lon;
812 *lon += lonc;
813 while (*lon < 0.0) *lon += 2 * M_PI;
814 while (*lon >= 2 * M_PI) *lon -= 2 * M_PI;
815 return (0);
816 }