ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/sharp/apps/sharp.c
Revision: 1.39
Committed: Mon May 24 22:17:37 2021 UTC (2 years, 4 months ago) by mbobra
Content type: text/plain
Branch: MAIN
CVS Tags: Ver_LATEST, Ver_9-5, HEAD
Changes since 1.38: +25 -2 lines
Log Message:
Now calculates USFLUXL, MEANGBL, and CMASKL

File Contents

# Content
1 /*
2 * sharp.c
3 *
4 * This module creates the pipeline Space Weather Active Region Patches (SHARPs).
5 * It is a hard-coded strip-down version of bmap.c.
6 * It takes the Mharp and Bharp series and create the following quantities:
7 *
8 * Series 1: Sharp_CEA
9 * CEA remapped magnetogram, bitmap, continuum, doppler (same size in map coordinate, need manual spec?)
10 * CEA remapped vector field (Br, Bt, Bp) (same as above)
11 * Space weather indices based on vector cutouts (step 2)
12 *
13 * Series 2: Sharp_cutout:
14 * cutouts of magnetogram, bitmap, continuum, doppler (HARP defined, various sizes in CCD pixels)
15 * cutouts of all vector data segments (same as above)
16 *
17 * Author:
18 * Xudong Sun; Monica Bobra
19 *
20 * Version:
21 * v0.0 Jul 02 2012
22 * v0.1 Jul 23 2012
23 * v0.2 Sep 04 2012
24 * v0.3 Dec 18 2012
25 * v0.4 Jan 02 2013
26 * v0.5 Jan 23 2013
27 * v0.6 Aug 12 2013
28 * v0.7 Jan 02 2014
29 * v0.8 Feb 12 2014
30 * v0.9 Mar 04 2014
31 *
32 * Notes:
33 * v0.0
34 * Mharp & Bharp must be fully specified; other input are series names only
35 * All input records need to match, otherwise quit
36 * Mapping parameters depend on keywords of each record only, not necessarily consistent for now
37 * Cutout doesn't work for char segments yet (drms_segment_readslice bug)
38 * SW indices require ephemeris info which is not passed properly as of now
39 * v0.1
40 * Fixed char I/O thanks to Art
41 * SW indices fixed
42 * Added doppler and continuum
43 * Added other keywords: HEADER (populated by cvs build version), DATE_B
44 * v0.3
45 * Fixed memory leakage of 0.15G per rec; denoted with "Dec 18"
46 * v0.4
47 * Took out convert_inplace(). Was causing all the images to be int
48 * v0.5
49 * Corrected ephemeris keywords, added argument mInfo for setKeys()
50 * v0.6
51 * Changes in remapping of bitmap and conf_disambig, now near neighbor without anti-aliasing
52 * v0.7
53 * Added full disk as "b"
54 * Global flag fullDisk is set if "b" is set
55 * Utilize BharpRS and BharpRec all around
56 * Pass mharpRec to set_keys() too in case of full disk
57 * Fixed Bunit (removed from copy_me_keys(), added loops for Bunits in set_keys() here)
58 * Error for CEA still does account for disambiguation yet
59 * v0.8
60 * Added disambig to azimuth during error propagation
61 * Changed usage for disambig: bit 2 (radial acute) for full disk, bit 0 for patch
62 * Fixed disambig cutout for patch: 0 for even, 7 for odd
63 * v0.9
64 * Fixed unit
65 * Check whether in PATCH of FD mode, so the error propagation uses disambiguated azimuth or not
66 *
67 *
68 * Example Calls:
69 * [I] B (full disk disambiguation)
70 * > sharp "mharp=hmi.Mharp_720s[1832][2012.07.12_15:24]" "b=hmi_test.B_720s[2012.07.12_15:24]" "dop=hmi.V_720s[2012.07.12_15:24]" "cont=hmi.Ic_720s[2012.07.12_15:24]" "sharp_cea=su_xudong.sharp_cea_720s" "sharp_cut=su_xudong.sharp_720s"
71 * [II] BHARP (patch disambiguation)
72 * > sharp "mharp=hmi.Mharp_720s[1832][2012.07.12_15:24]" "bharp=hmi.Bharp_720s[1832][2012.07.12_15:24]" "dop=hmi.V_720s[2012.07.12_15:24]" "cont=hmi.Ic_720s[2012.07.12_15:24]" "sharp_cea=su_xudong.sharp_cea_720s" "sharp_cut=su_xudong.sharp_720s"
73 *
74 *
75 */
76
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <time.h>
80 #include <sys/time.h>
81 #include <math.h>
82 #include <string.h>
83 #include "jsoc_main.h"
84 #include "astro.h"
85 #include "fstats.h"
86 #include "cartography.c"
87 #include "fresize.h"
88 #include "finterpolate.h"
89 #include "img2helioVector.c"
90 #include "copy_me_keys.c"
91 #include "errorprop.c"
92 #include "sw_functions.c"
93
94 //#include <mkl.h> // Comment out mkl.h, which can only run on solar3
95 #include <mkl_blas.h>
96 #include <mkl_service.h>
97 #include <mkl_lapack.h>
98 #include <mkl_vml_functions.h>
99 #include <omp.h>
100
101 #define PI (M_PI)
102 #define RADSINDEG (PI/180.)
103 #define RAD2ARCSEC (648000./M_PI)
104 #define SECINDAY (86400.)
105 #define FOURK (4096)
106 #define FOURK2 (16777216)
107
108 #define ARRLENGTH(ARR) (sizeof(ARR) / sizeof(ARR[0]))
109
110 // Nyqvist rate at disk center is 0.03 degree. Oversample above 0.015 degree
111 #define NYQVIST (0.015)
112
113 // Maximum variation of LONDTMAX-LONDTMIN
114 #define MAXLONDIFF (1.2e-4)
115
116 // Some other things
117 #ifndef MIN
118 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
119 #endif
120 #ifndef MAX
121 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
122 #endif
123
124 #define DIE(msg) {fflush(stdout); fprintf(stderr,"%s, status=%d\n", msg, status); return(status);}
125 #define SHOW(msg) {printf("%s", msg); fflush(stdout);}
126
127 #define kNotSpecified "Not Specified"
128
129 // Macros for WCS transformations. assume crpix1, crpix2 = CRPIX1, CRPIX2, sina,cosa = sin and cos of CROTA2 resp.
130 // and crvalx and crvaly are CRVAL1 and CRVAL2, cdelt = CDELT1 == CDELT2, then
131 // PIX_X and PIX_Y are CCD pixel addresses, WX and WY are arc-sec W and N on the Sun from disk center.
132 #define PIX_X(wx,wy) ((((wx-crvalx)*cosa + (wy-crvaly)*sina)/cdelt)+crpix1)
133 #define PIX_Y(wx,wy) ((((wy-crvaly)*cosa - (wx-crvalx)*sina)/cdelt)+crpix2)
134 #define WX(pix_x,pix_y) (((pix_x-crpix1)*cosa - (pix_y-crpix2)*sina)*cdelt+crvalx)
135 #define WY(pix_x,pix_y) (((pix_y-crpix2)*cosa + (pix_x-crpix1)*sina)*cdelt+crvaly)
136
137 #define DISAMB_AZI 1
138 #define XSCALE 0.03
139 #define YSCALE 0.03
140 #define NBIN 3
141 #define INTERP 0
142 #define dpath "/home/jsoc/cvs/Development/JSOC"
143
144
145 /* ========================================================================================================== */
146
147 // Space weather keywords
148 struct swIndex {
149 float mean_vf;
150 float mean_vf_los;
151 float count_mask;
152 float count_mask_los;
153 float absFlux;
154 float absFlux_los;
155 float mean_hf;
156 float mean_gamma;
157 float mean_derivative_btotal;
158 float mean_derivative_bh;
159 float mean_derivative_bz;
160 float mean_derivative_los;
161 float mean_jz;
162 float us_i;
163 float mean_alpha;
164 float mean_ih;
165 float total_us_ih;
166 float total_abs_ih;
167 float totaljz;
168 float totpot;
169 float meanpot;
170 float area_w_shear_gt_45;
171 float meanshear_angle;
172 float area_w_shear_gt_45h;
173 float meanshear_angleh;
174 float mean_derivative_btotal_err;
175 float mean_vf_err;
176 float mean_gamma_err;
177 float mean_derivative_bh_err;
178 float mean_derivative_bz_err;
179 float mean_jz_err;
180 float us_i_err;
181 float mean_alpha_err;
182 float mean_ih_err;
183 float total_us_ih_err;
184 float total_abs_ih_err;
185 float totaljz_err;
186 float meanpot_err;
187 float totpot_err;
188 float meanshear_angle_err;
189 float Rparam;
190 float totfx;
191 float totfy;
192 float totfz;
193 float totbsq;
194 float epsx;
195 float epsy;
196 float epsz;
197 };
198
199 // Mapping method
200 enum projection {
201 carree,
202 cassini,
203 mercator,
204 cyleqa,
205 sineqa,
206 gnomonic,
207 postel,
208 stereographic,
209 orthographic,
210 lambert
211 };
212
213 // WSC code
214 char *wcsCode[] = {"CAR", "CAS", "MER", "CEA", "GLS", "TAN", "ARC", "STG",
215 "SIN", "ZEA"};
216
217 // Ephemeris information
218 struct ephemeris {
219 double disk_lonc, disk_latc;
220 double disk_xc, disk_yc;
221 double rSun, asd, pa;
222 };
223
224 // Mapping information
225 struct mapInfo {
226 float xc, yc; // reference point: center
227 int nrow, ncol; // size
228 float xscale, yscale; // scale
229 int nbin;
230 enum projection proj; // projection method
231 struct ephemeris ephem; // ephemeris info
232 float *xi_out, *zeta_out; // coordinate on full disk image to sample at
233 };
234
235 /* ========================================================================================================== */
236
237 /* Get all input data series */
238 int getInputRS(DRMS_RecordSet_t **mharpRS_ptr, DRMS_RecordSet_t **bharpRS_ptr,
239 char *mharpQuery, char *bharpQuery);
240
241 /* Check if Mharp and Bharp match */
242 int compareHarp(DRMS_RecordSet_t *mharpRS, DRMS_RecordSet_t *bharpRS);
243
244 /* Get other data series */
245 int getInputRS_aux(DRMS_RecordSet_t **inRS_ptr, char *inQuery, DRMS_RecordSet_t *harpRS);
246
247 /* Find record from record set with given T_rec */
248 int getInputRec_aux(DRMS_Record_t **inRec_ptr, DRMS_RecordSet_t *inRS, TIME trec);
249
250 /* Create CEA record */
251 int createCeaRecord(DRMS_Record_t *mharpRec, DRMS_Record_t *bharpRec,
252 DRMS_Record_t *dopRec, DRMS_Record_t *contRec,
253 DRMS_Record_t *sharpRec, struct swIndex *swKeys_ptr);
254
255 /* Mapping single segment, wrapper */
256 int mapScaler(DRMS_Record_t *sharpRec, DRMS_Record_t *inRec, DRMS_Record_t *harpRec,
257 struct mapInfo *mInfo, char *segName);
258
259 /* Mapping vector magnetogram, wrapper */
260 int mapVectorB(DRMS_Record_t *sharpRec, DRMS_Record_t *bharpRec, struct mapInfo *mInfo);
261
262 /* Mapping errors of vector magnetogram, wraper */
263 int mapVectorBErr(DRMS_Record_t *sharpRec, DRMS_Record_t *bharpRec, struct mapInfo *mInfo);
264
265 /* Determine reference point coordinate and patch size according to input */
266 int findPosition(DRMS_Record_t *inRec, struct mapInfo *mInfo);
267
268 /* Get ephemeris information */
269 int getEphemeris(DRMS_Record_t *inRec, struct ephemeris *ephem);
270
271 /* Compute the coordinates at which the full disk image is sampled */
272 void findCoord(struct mapInfo *mInfo);
273
274 /* Mapping function */
275 int performSampling(float *outData, float *inData, struct mapInfo *mInfo, int interpOpt);
276
277 /* Performing local vector transformation */
278 void vectorTransform(float *bx_map, float *by_map, float *bz_map, struct mapInfo *mInfo);
279
280 /* Map and propogate errors */
281 int getBErr(float *bx_err, float *by_err, float *bz_err,
282 DRMS_Record_t *inRec, struct mapInfo *mInfo);
283
284 /* Read full disk vector magnetogram */
285 int readVectorB(DRMS_Record_t *inRec, float *bx_img, float *by_img, float *bz_img);
286
287 /* Read variances and covariances of vector magnetograms */
288 int readVectorBErr(DRMS_Record_t *bharpRec,
289 float *bT, float *bI, float *bA,
290 float *errbT, float *errbI, float *errbA,
291 float *errbTbI, float *errbTbA, float *errbIbA);
292
293 // ===================
294
295 /* Create Cutout record */
296 int createCutRecord(DRMS_Record_t *mharpRec, DRMS_Record_t *bharpRec,
297 DRMS_Record_t *dopRec, DRMS_Record_t *contRec,
298 DRMS_Record_t *sharpRec, struct swIndex *swKeys_ptr);
299
300 /* Get cutout and write segment */
301 int writeCutout(DRMS_Record_t *outRec, DRMS_Record_t *inRec, DRMS_Record_t *harpRec, char *SegName);
302
303 // ===================
304
305 /* Compute space weather indices, no error checking for now */
306 void computeSWIndex(struct swIndex *swKeys_ptr, DRMS_Record_t *inRec, struct mapInfo *mInfo);
307
308 /* Set space weather indices, no error checking for now */
309 void setSWIndex(DRMS_Record_t *outRec, struct swIndex *swKeys_ptr);
310
311 /* Set all keywords, no error checking for now */
312 // Changed Dec 30 XS
313 void setKeys(DRMS_Record_t *outRec, DRMS_Record_t *mharpRec, DRMS_Record_t *bharpRec, struct mapInfo *mInfo);
314
315 // ===================
316
317 /* Nearest neighbor interpolation */
318 float nnb (float *f, int nx, int ny, double x, double y);
319
320 /* Wrapper for Jesper's rebin code */
321 void frebin (float *image_in, float *image_out, int nx, int ny, int nbin, int gauss);
322
323 /* ========================================================================================================== */
324
325 /* Remap segment names */
326 #define BR_SEG_CEA "Br"
327 #define BT_SEG_CEA "Bt"
328 #define BP_SEG_CEA "Bp"
329 #define BR_ERR_SEG_CEA "Br_err"
330 #define BT_ERR_SEG_CEA "Bt_err"
331 #define BP_ERR_SEG_CEA "Bp_err"
332
333 /* Cutout segment names, input identical to output */
334 char *MharpSegs[] = {"magnetogram", "bitmap"};
335 char *BharpSegs[] = {"inclination", "azimuth", "field", "vlos_mag", "dop_width", "eta_0",
336 "damping", "src_continuum", "src_grad", "alpha_mag", "chisq",
337 "conv_flag", // fixed
338 "info_map", "confid_map",
339 "inclination_err", "azimuth_err", "field_err", "vlos_err", "alpha_err",
340 "field_inclination_err", "field_az_err", "inclin_azimuth_err",
341 "field_alpha_err","inclination_alpha_err", "azimuth_alpha_err",
342 "disambig", "conf_disambig"};
343 // For stats
344 char *CutSegs[] = {"magnetogram", "bitmap", "Dopplergram", "continuum",
345 "inclination", "azimuth", "field", "vlos_mag", "dop_width", "eta_0",
346 "damping", "src_continuum", "src_grad", "alpha_mag", "chisq",
347 "conv_flag", // fixed
348 "info_map", "confid_map",
349 "inclination_err", "azimuth_err", "field_err", "vlos_err", "alpha_err",
350 "field_inclination_err", "field_az_err", "inclin_azimuth_err",
351 "field_alpha_err","inclination_alpha_err", "azimuth_alpha_err",
352 "disambig", "conf_disambig"};
353 char *CEASegs[] = {"magnetogram", "bitmap", "Dopplergram", "continuum",
354 BR_SEG_CEA, BT_SEG_CEA, BP_SEG_CEA, BR_ERR_SEG_CEA, BT_ERR_SEG_CEA, BP_ERR_SEG_CEA, "conf_disambig"};
355 // For Bunits, added Dec 30 XS
356 char *CutBunits[] = {"Mx/cm^2", " ", "cm/s", "DN/s",
357 "degree", "degree", "Mx/cm^2", "cm/s", "mA", " ",
358 "length units", "DN/s", "DN/s", " ", " ",
359 " ",
360 " ", " ",
361 "degree", "degree", "Mx/cm^2", "cm/s", " ",
362 " ", " ", " ",
363 " ", " ", " ",
364 " ", " "};
365 char *CEABunits[] = {"Mx/cm^2", " ", "cm/s", "DN/s",
366 "Mx/cm^2", "Mx/cm^2", "Mx/cm^2", "Mx/cm^2", "Mx/cm^2", "Mx/cm^2", " "}; // Mar 4 2014 XS
367
368 /* ========================================================================================================== */
369
370 char *module_name = "sharp";
371 int seed;
372
373 int fullDisk; // full disk mode
374 int amb4err; // Use azimuth disambiguation for error propagation, default is 0 for patch and 1 for FD
375
376 ModuleArgs_t module_args[] =
377 {
378 {ARG_STRING, "mharp", kNotSpecified, "Input Mharp series."},
379 {ARG_STRING, "bharp", kNotSpecified, "Input Bharp series."},
380 {ARG_STRING, "b", kNotSpecified, "Input B series, if set, overrides bharp."},
381 {ARG_STRING, "dop", kNotSpecified, "Input Doppler series."},
382 {ARG_STRING, "cont", kNotSpecified, "Input Continuum series."},
383 {ARG_STRING, "sharp_cea", kNotSpecified, "Output Sharp CEA series."},
384 {ARG_STRING, "sharp_cut", kNotSpecified, "Output Sharp cutout series."},
385 {ARG_INT, "seed", "987654", "Seed for the random number generator."},
386 {ARG_INT, "f_amb4err", "0", "Force using disambiguation in error propagation"}, // Mar 4 2014 XS
387 {ARG_END}
388 };
389
390 int DoIt(void)
391 {
392 int errbufstat = setvbuf(stderr, NULL, _IONBF, BUFSIZ);
393 int outbufstat = setvbuf(stdout, NULL, _IONBF, BUFSIZ);
394
395 int status = DRMS_SUCCESS;
396 int nrecs, irec;
397
398 char *mharpQuery, *bharpQuery, *bQuery;
399 char *dopQuery, *contQuery;
400 char *sharpCeaQuery, *sharpCutQuery;
401
402 DRMS_RecordSet_t *mharpRS = NULL, *bharpRS = NULL;
403 DRMS_RecordSet_t *dopRS = NULL, *contRS = NULL;
404
405 /* Get parameters */
406
407 mharpQuery = (char *) params_get_str(&cmdparams, "mharp");
408 bharpQuery = (char *) params_get_str(&cmdparams, "bharp");
409 bQuery = (char *) params_get_str(&cmdparams, "b");
410 dopQuery = (char *) params_get_str(&cmdparams, "dop");
411 contQuery = (char *) params_get_str(&cmdparams, "cont");
412 sharpCeaQuery = (char *) params_get_str(&cmdparams, "sharp_cea");
413 sharpCutQuery = (char *) params_get_str(&cmdparams, "sharp_cut");
414
415 seed = params_get_int(&cmdparams, "seed");
416 int f_amb4err = params_get_int(&cmdparams, "f_amb4err");
417
418 /* Get input data, check everything */
419
420 // Full disk mode if "b" is set
421 if (strcmp(bQuery, kNotSpecified)) {
422 fullDisk = 1;
423 bharpQuery = bQuery;
424 // SHOW(bharpQuery); SHOW("\n");
425 SHOW("Full disk mode\n");
426 } else {
427 fullDisk = 0;
428 SHOW("Harp mode\n");
429 }
430
431 // Mar 4 2014
432 if (f_amb4err == 0) { // no forcing, 0 for patch and 1 for FD
433 amb4err = fullDisk ? 1 : 0;
434 } else {
435 amb4err = 1;
436 }
437 printf("amb4err=%d\n", amb4err);
438
439 // Bharp point to B if full disk
440 if (getInputRS(&mharpRS, &bharpRS, mharpQuery, bharpQuery))
441 DIE("Input harp data error.");
442 nrecs = mharpRS->n;
443
444 if (getInputRS_aux(&dopRS, dopQuery, mharpRS))
445 DIE("Input doppler data error.");
446
447 if (getInputRS_aux(&contRS, contQuery, mharpRS))
448 DIE("Input continuum data error.");
449
450 /* Start */
451
452 printf("==============\nStart. %d image(s) in total.\n", nrecs);
453
454 for (irec = 0; irec < nrecs; irec++) {
455
456 /* Records in work */
457
458 DRMS_Record_t *mharpRec = NULL, *bharpRec = NULL;
459
460 mharpRec = mharpRS->records[irec];
461
462 TIME trec = drms_getkey_time(mharpRec, "T_REC", &status);
463
464 if (!fullDisk) {
465 bharpRec = bharpRS->records[irec];
466 } else {
467 if (getInputRec_aux(&bharpRec, bharpRS, trec)) { // Bharp point to full disk B
468 printf("Fetching B failed, image #%d skipped.\n", irec);
469 continue;
470 }
471 }
472
473 struct swIndex swKeys;
474
475 DRMS_Record_t *dopRec = NULL, *contRec = NULL;
476
477 if (getInputRec_aux(&dopRec, dopRS, trec)) {
478 printf("Fetching Doppler failed, image #%d skipped.\n", irec);
479 continue;
480 }
481 if (getInputRec_aux(&contRec, contRS, trec)) {
482 printf("Fetching continuum failed, image #%d skipped.\n", irec);
483 continue;
484 }
485
486 /* Create CEA record */
487
488 DRMS_Record_t *sharpCeaRec = drms_create_record(drms_env, sharpCeaQuery, DRMS_PERMANENT, &status);
489 if (status) { // if failed
490 printf("Creating CEA failed, image #%d skipped.\n", irec);
491 continue;
492 }
493
494 if (createCeaRecord(mharpRec, bharpRec, dopRec, contRec, sharpCeaRec, &swKeys)) { // do the work
495 printf("Creating CEA failed, image #%d skipped.\n", irec);
496 drms_close_record(sharpCeaRec, DRMS_FREE_RECORD);
497 continue;
498 } // swKeys updated here
499
500 drms_close_record(sharpCeaRec, DRMS_INSERT_RECORD);
501
502 /* Create Cutout record */
503
504 DRMS_Record_t *sharpCutRec = drms_create_record(drms_env, sharpCutQuery, DRMS_PERMANENT, &status);
505 if (status) { // if failed
506 printf("Creating cutout failed, image #%d skipped.\n", irec);
507 continue;
508 }
509
510 if (createCutRecord(mharpRec, bharpRec, dopRec, contRec, sharpCutRec, &swKeys)) { // do the work
511 printf("Creating cutout failed, image #%d skipped.\n", irec);
512 drms_close_record(sharpCutRec, DRMS_FREE_RECORD);
513 continue;
514 } // swKeys used here
515
516 drms_close_record(sharpCutRec, DRMS_INSERT_RECORD);
517
518 /* Done */
519
520 printf("Image #%d done.\n", irec);
521
522 } // irec
523
524
525 drms_close_records(mharpRS, DRMS_FREE_RECORD);
526 drms_close_records(bharpRS, DRMS_FREE_RECORD);
527 drms_close_records(dopRS, DRMS_FREE_RECORD); // Dec 18 2012
528 drms_close_records(contRS, DRMS_FREE_RECORD); // Dec 18 2012
529
530 return 0;
531
532 } // DoIt
533
534
535 // ===================================================================
536 // ===================================================================
537 // ===================================================================
538
539
540 /*
541 * Get input data series, including mHarp and bharp
542 * Need all records to match, otherwise quit
543 *
544 */
545
546 int getInputRS(DRMS_RecordSet_t **mharpRS_ptr, DRMS_RecordSet_t **bharpRS_ptr,
547 char *mharpQuery, char *bharpQuery)
548 {
549
550 int status = 0;
551
552 *mharpRS_ptr = drms_open_records(drms_env, mharpQuery, &status);
553 if (status || (*mharpRS_ptr)->n == 0) return 1;
554
555 if (fullDisk) {
556 if (getInputRS_aux(bharpRS_ptr, bharpQuery, *mharpRS_ptr)) return 1;
557 } else {
558 *bharpRS_ptr = drms_open_records(drms_env, bharpQuery, &status);
559 if (status || (*bharpRS_ptr)->n == 0) return 1;
560 if (compareHarp((*mharpRS_ptr), (*bharpRS_ptr))) return 1;
561 }
562
563 return 0;
564
565 }
566
567 /*
568 * Check if Mharp and Bharp match
569 *
570 */
571
572 int compareHarp(DRMS_RecordSet_t *mharpRS, DRMS_RecordSet_t *bharpRS)
573 {
574
575 int status = 0;
576 int nrecs = mharpRS->n;
577
578 DRMS_Record_t *mharpRec_t = NULL, *bharpRec_t = NULL; // temporary recs for utility
579
580 if (bharpRS->n != nrecs) {
581 return 1; // return 1 if different
582 }
583
584 for (int i = 0; i < nrecs; i++) {
585 mharpRec_t = mharpRS->records[i];
586 bharpRec_t = bharpRS->records[i];
587 if ((drms_getkey_int(mharpRec_t, "HARPNUM", &status) !=
588 drms_getkey_int(bharpRec_t, "HARPNUM", &status)) ||
589 (drms_getkey_time(mharpRec_t, "T_REC", &status) !=
590 drms_getkey_time(bharpRec_t, "T_REC", &status)))
591 {
592 return 1;
593 }
594 }
595
596 return 0;
597
598 }
599
600 /*
601 * Get other data series, check all T_REC are available
602 *
603 */
604
605 int getInputRS_aux(DRMS_RecordSet_t **inRS_ptr, char *inQuery, DRMS_RecordSet_t *harpRS)
606 {
607
608 int status = 0;
609
610 *inRS_ptr = drms_open_records(drms_env, inQuery, &status);
611 if (status || (*inRS_ptr)->n == 0) return status;
612
613 // Check if all T_rec are available, need to match both ways
614 int n = harpRS->n, n0 = (*inRS_ptr)->n;
615
616 for (int i0 = 0; i0 < n0; i0++) {
617 DRMS_Record_t *inRec = (*inRS_ptr)->records[i0];
618 TIME trec0 = drms_getkey_time(inRec, "T_REC", &status);
619 TIME trec = 0;
620 for (int i = 0; i < n; i++) {
621 DRMS_Record_t *harpRec = harpRS->records[i];
622 trec = drms_getkey_time(harpRec, "T_REC", &status);
623 if (fabs(trec0 - trec) < 10) break;
624 }
625 if (fabs(trec0 - trec) >= 10) return 1;
626 }
627
628 for (int i = 0; i < n; i++) {
629 DRMS_Record_t *harpRec = harpRS->records[i];
630 TIME trec = drms_getkey_time(harpRec, "T_REC", &status);
631 TIME trec0 = 0;
632 for (int i0 = 0; i0 < n0; i0++) {
633 DRMS_Record_t *inRec = (*inRS_ptr)->records[i0];
634 trec0 = drms_getkey_time(inRec, "T_REC", &status);
635 if (fabs(trec0 - trec) < 10) break;
636 }
637 if (fabs(trec0 - trec) >= 10) return 1;
638 }
639
640 return 0;
641
642 }
643
644 /*
645 * Find record from record set with given T_rec
646 *
647 */
648
649 int getInputRec_aux(DRMS_Record_t **inRec_ptr, DRMS_RecordSet_t *inRS, TIME trec)
650 {
651
652 int status = 0;
653
654 int n = inRS->n;
655 for (int i = 0; i < n; i++) {
656 *inRec_ptr = inRS->records[i];
657 TIME trec0 = drms_getkey_time((*inRec_ptr), "T_REC", &status);
658 if (fabs(trec0 - trec) < 10) return 0;
659 }
660
661 return 1;
662
663 }
664
665
666
667
668 /*
669 * Create CEA record: top level subroutine
670 * Also compute all the space weather keywords here
671 *
672 */
673
674 int createCeaRecord(DRMS_Record_t *mharpRec, DRMS_Record_t *bharpRec,
675 DRMS_Record_t *dopRec, DRMS_Record_t *contRec,
676 DRMS_Record_t *sharpRec, struct swIndex *swKeys_ptr)
677 {
678
679 int status = 0;
680 DRMS_Segment_t *inSeg;
681 DRMS_Array_t *inArray;
682
683 struct mapInfo mInfo;
684 mInfo.proj = (enum projection) cyleqa; // projection method
685 mInfo.xscale = XSCALE;
686 mInfo.yscale = YSCALE;
687
688 int ncol0, nrow0; // oversampled map size
689
690 // Get ephemeris
691
692 if (getEphemeris(mharpRec, &(mInfo.ephem))) {
693 SHOW("CEA: get ephemeris error\n");
694 return 1;
695 }
696
697 // Find position
698
699 if (findPosition(mharpRec, &mInfo)) {
700 SHOW("CEA: find position error\n");
701 return 1;
702 }
703
704 // ========================================
705 // Do this for all bitmaps, Aug 12 2013 XS
706 // ========================================
707
708 mInfo.nbin = 1; // for bitmaps. suppress anti-aliasing
709 ncol0 = mInfo.ncol;
710 nrow0 = mInfo.nrow;
711
712 mInfo.xi_out = (float *) (malloc(ncol0 * nrow0 * sizeof(float)));
713 mInfo.zeta_out = (float *) (malloc(ncol0 * nrow0 * sizeof(float)));
714
715 findCoord(&mInfo); // compute it here so it could be shared by the following 4 functions
716
717 if (mapScaler(sharpRec, mharpRec, mharpRec, &mInfo, "bitmap")) {
718 SHOW("CEA: mapping bitmap error\n");
719 return 1;
720 }
721 printf("Bitmap mapping done.\n");
722
723 if (mapScaler(sharpRec, bharpRec, mharpRec, &mInfo, "conf_disambig")) {
724 SHOW("CEA: mapping conf_disambig error\n");
725 return 1;
726 }
727 printf("Conf disambig mapping done.\n");
728
729 free(mInfo.xi_out);
730 free(mInfo.zeta_out);
731
732 // ========================================
733 // Do this again for floats, Aug 12 2013 XS
734 // ========================================
735 // Create xi_out, zeta_out array in mInfo:
736 // Coordinates to sample in original full disk image
737
738 mInfo.nbin = NBIN;
739 ncol0 = mInfo.ncol * mInfo.nbin + (mInfo.nbin / 2) * 2; // pad with nbin/2 on edge to avoid NAN
740 nrow0 = mInfo.nrow * mInfo.nbin + (mInfo.nbin / 2) * 2;
741
742 mInfo.xi_out = (float *) (malloc(ncol0 * nrow0 * sizeof(float)));
743 mInfo.zeta_out = (float *) (malloc(ncol0 * nrow0 * sizeof(float)));
744
745 findCoord(&mInfo); // compute it here so it could be shared by the following 4 functions
746
747 // Mapping single segment: Mharp, etc.
748
749 if (mapScaler(sharpRec, mharpRec, mharpRec, &mInfo, "magnetogram")) {
750 SHOW("CEA: mapping magnetogram error\n");
751 return 1;
752 }
753 printf("Magnetogram mapping done.\n");
754
755 if (mapScaler(sharpRec, dopRec, mharpRec, &mInfo, "Dopplergram")) {
756 SHOW("CEA: mapping dopplergram error\n");
757 return 1;
758 }
759 printf("Dopplergram mapping done.\n");
760
761 if (mapScaler(sharpRec, contRec, mharpRec, &mInfo, "continuum")) {
762 SHOW("CEA: mapping continuum error\n");
763 return 1;
764 }
765 printf("Intensitygram mapping done.\n");
766
767 // Mapping vector B
768
769 if (mapVectorB(sharpRec, bharpRec, &mInfo)) {
770 SHOW("CEA: mapping vector B error\n");
771 return 1;
772 }
773 printf("Vector B mapping done.\n");
774
775 // Mapping vector B errors
776
777 if (mapVectorBErr(sharpRec, bharpRec, &mInfo)) {
778 SHOW("CEA: mapping vector B uncertainty error\n");
779 return 1;
780 }
781 printf("Vector B error done.\n");
782
783 // Keywords & Links
784
785 drms_copykey(sharpRec, mharpRec, "T_REC");
786 drms_copykey(sharpRec, mharpRec, "HARPNUM");
787
788 if (fullDisk) {
789 DRMS_Link_t *bLink = hcon_lookup_lower(&sharpRec->links, "B");
790 if (bLink) drms_link_set("B", sharpRec, bharpRec);
791 } else {
792 DRMS_Link_t *bHarpLink = hcon_lookup_lower(&sharpRec->links, "BHARP");
793 if (bHarpLink) drms_link_set("BHARP", sharpRec, bharpRec);
794 }
795 DRMS_Link_t *mHarpLink = hcon_lookup_lower(&sharpRec->links, "MHARP");
796 if (mHarpLink) drms_link_set("MHARP", sharpRec, mharpRec);
797
798 setKeys(sharpRec, mharpRec, bharpRec, &mInfo); // Set all other keywords
799 drms_copykey(sharpRec, mharpRec, "QUALITY"); // copied from los records
800
801 // Space weather
802
803 computeSWIndex(swKeys_ptr, sharpRec, &mInfo); // compute it!
804 printf("Space weather indices done.\n");
805
806 setSWIndex(sharpRec, swKeys_ptr); // Set space weather indices
807
808 // Stats
809
810 int nCEASegs = ARRLENGTH(CEASegs);
811 for (int iSeg = 0; iSeg < nCEASegs; iSeg++) {
812 DRMS_Segment_t *outSeg = drms_segment_lookupnum(sharpRec, iSeg);
813 DRMS_Array_t *outArray = drms_segment_read(outSeg, DRMS_TYPE_FLOAT, &status);
814 int stat = set_statistics(outSeg, outArray, 1);
815 // printf("%d => %d\n", iSeg, stat);
816 drms_free_array(outArray);
817 }
818
819 free(mInfo.xi_out);
820 free(mInfo.zeta_out);
821 return 0;
822
823 }
824
825
826 /*
827 * Mapping a single segment
828 * Read in full disk image, utilize mapImage for mapping
829 * then write the segment out, segName same in in/out Rec
830 *
831 */
832
833 int mapScaler(DRMS_Record_t *sharpRec, DRMS_Record_t *inRec, DRMS_Record_t *harpRec,
834 struct mapInfo *mInfo, char *segName)
835 {
836
837 int status = 0;
838 int nx = mInfo->ncol, ny = mInfo->nrow, nxny = nx * ny;
839 int dims[2] = {nx, ny};
840 int interpOpt = INTERP; // Aug 12 XS, default, overridden below for bitmaps and conf_disambig
841
842 // Input full disk array
843
844 DRMS_Segment_t *inSeg = NULL;
845 inSeg = drms_segment_lookup(inRec, segName);
846 if (!inSeg) return 1;
847
848 DRMS_Array_t *inArray = NULL;
849 inArray = drms_segment_read(inSeg, DRMS_TYPE_FLOAT, &status);
850 if (!inArray) return 1;
851
852 if (!strcmp(segName, "conf_disambig") || !strcmp(segName, "bitmap")) {
853 // Moved out so it works for FD conf_disambig as well
854 // Jan 2 2014 XS
855 interpOpt = 3; // Aug 12 XS, near neighbor
856 }
857
858 float *inData;
859 int xsz = inArray->axis[0], ysz = inArray->axis[1];
860 if ((xsz != FOURK) || (ysz != FOURK)) { // for bitmap, make tmp full disk
861 float *inData0 = (float *) inArray->data;
862 inData = (float *) (calloc(FOURK2, sizeof(float)));
863 int x0 = (int) drms_getkey_float(harpRec, "CRPIX1", &status) - 1;
864 int y0 = (int) drms_getkey_float(harpRec, "CRPIX2", &status) - 1;
865 int ind_map;
866 for (int row = 0; row < ysz; row++) {
867 for (int col = 0; col < xsz; col++) {
868 ind_map = (row + y0) * FOURK + (col + x0);
869 inData[ind_map] = inData0[row * xsz + col];
870 }
871 }
872 drms_free_array(inArray); inArray = NULL;
873 } else {
874 inData = (float *) inArray->data;
875 }
876
877 // Mapping
878
879 float *map = (float *) (malloc(nxny * sizeof(float)));
880 if (performSampling(map, inData, mInfo, interpOpt)) // Add interpOpt for different types, Aug 12 XS
881 {if (inArray) drms_free_array(inArray); free(map); return 1;}
882
883 // Write out
884
885 DRMS_Segment_t *outSeg = NULL;
886 outSeg = drms_segment_lookup(sharpRec, segName);
887 if (!outSeg) return 1;
888
889 // DRMS_Type_t arrayType = outSeg->info->type;
890 DRMS_Array_t *outArray = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, map, &status);
891 if (status) {if (inArray) drms_free_array(inArray); free(map); return 1;}
892
893 // convert to needed data type
894
895 // drms_array_convert_inplace(outSeg->info->type, 0, 1, outArray); // Jan 02 2013
896
897 outSeg->axis[0] = outArray->axis[0]; outSeg->axis[1] = outArray->axis[1];
898 // outArray->parent_segment = outSeg;
899 outArray->israw = 0; // always compressed
900 outArray->bzero = outSeg->bzero;
901 outArray->bscale = outSeg->bscale;
902
903 status = drms_segment_write(outSeg, outArray, 0);
904 if (status) return 0;
905
906 if (inArray) drms_free_array(inArray);
907 if ((xsz != FOURK) || (ysz != FOURK)) free(inData); // Dec 18 2012
908 if (outArray) drms_free_array(outArray);
909 return 0;
910
911 }
912
913
914 /*
915 * Mapping vector magnetogram
916 *
917 */
918
919 int mapVectorB(DRMS_Record_t *sharpRec, DRMS_Record_t *bharpRec, struct mapInfo *mInfo)
920 {
921
922 int status = 0;
923 int nx = mInfo->ncol, ny = mInfo->nrow, nxny = nx * ny;
924 int dims[2] = {nx, ny};
925
926 // Read in segments, filling factor assume to be 1
927
928 float *bx_img = (float *) (malloc(FOURK2 * sizeof(float)));
929 float *by_img = (float *) (malloc(FOURK2 * sizeof(float)));
930 float *bz_img = (float *) (malloc(FOURK2 * sizeof(float)));
931
932 if (readVectorB(bharpRec, bx_img, by_img, bz_img)) {
933 printf("Read full disk image error\n");
934 free(bx_img); free(by_img); free(bz_img);
935 return 1;
936 }
937
938 // Mapping
939
940 float *bx_map = NULL, *by_map = NULL, *bz_map = NULL; // intermediate maps, in CCD bxyz representation
941
942 bx_map = (float *) (malloc(nxny * sizeof(float)));
943 if (performSampling(bx_map, bx_img, mInfo, INTERP))
944 {free(bx_img); free(by_img); free(bz_img); free(bx_map); return 1;}
945
946 by_map = (float *) (malloc(nxny * sizeof(float)));
947 if (performSampling(by_map, by_img, mInfo, INTERP))
948 {free(bx_img); free(by_img); free(bz_img); free(bz_map); return 1;}
949
950 bz_map = (float *) (malloc(nxny * sizeof(float)));
951 if (performSampling(bz_map, bz_img, mInfo, INTERP))
952 {free(bx_img); free(by_img); free(bz_img); free(bz_map); return 1;}
953
954 free(bx_img); free(by_img); free(bz_img);
955
956 // Vector transform
957
958 vectorTransform(bx_map, by_map, bz_map, mInfo);
959
960 for (int i = 0; i < nxny; i++) by_map[i] *= -1; // positive theta pointing south
961
962 // Write out
963
964 DRMS_Segment_t *outSeg;
965 DRMS_Array_t *outArray;
966
967 float *data_prt[3] = {bx_map, by_map, bz_map};
968 char *segName[3] = {BP_SEG_CEA, BT_SEG_CEA, BR_SEG_CEA};
969
970 for (int iSeg = 0; iSeg < 3; iSeg++) {
971 outSeg = drms_segment_lookup(sharpRec, segName[iSeg]);
972 outArray = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, data_prt[iSeg], &status);
973 outSeg->axis[0] = outArray->axis[0]; outSeg->axis[1] = outArray->axis[1];
974 // outArray->parent_segment = outSeg;
975 outArray->israw = 0;
976 outArray->bzero = outSeg->bzero;
977 outArray->bscale = outSeg->bscale;
978 status = drms_segment_write(outSeg, outArray, 0);
979 if (status) return 1;
980 drms_free_array(outArray);
981 }
982
983 //
984
985 return 0;
986
987 }
988
989
990 /*
991 * Mapping vector magnetogram errors
992 *
993 */
994
995 int mapVectorBErr(DRMS_Record_t *sharpRec, DRMS_Record_t *bharpRec, struct mapInfo *mInfo)
996 {
997
998 int status = 0;
999
1000 int nx = mInfo->ncol, ny = mInfo->nrow, nxny = nx * ny;
1001 int dims[2] = {nx, ny};
1002
1003 // Compute propogated errors, using nearest neighbour interpolation
1004
1005 float *bx_err = (float *) (malloc(nxny * sizeof(float)));
1006 float *by_err = (float *) (malloc(nxny * sizeof(float)));
1007 float *bz_err = (float *) (malloc(nxny * sizeof(float)));
1008
1009 if (getBErr(bx_err, by_err, bz_err, bharpRec, mInfo)) {
1010 free(bx_err); free(by_err); free(bz_err);
1011 return 1;
1012 }
1013
1014 // Write out
1015
1016 DRMS_Segment_t *outSeg;
1017 DRMS_Array_t *outArray;
1018
1019 float *data_prt[3] = {bx_err, by_err, bz_err};
1020 char *segName[3] = {BP_ERR_SEG_CEA, BT_ERR_SEG_CEA, BR_ERR_SEG_CEA};
1021
1022 for (int iSeg = 0; iSeg < 3; iSeg++) {
1023 outSeg = drms_segment_lookup(sharpRec, segName[iSeg]);
1024 outArray = drms_array_create(DRMS_TYPE_FLOAT, 2, dims, data_prt[iSeg], &status);
1025 outSeg->axis[0] = outArray->axis[0]; outSeg->axis[1] = outArray->axis[1];
1026 // outArray->parent_segment = outSeg;
1027 outArray->israw = 0;
1028 outArray->bzero = outSeg->bzero;
1029 outArray->bscale = outSeg->bscale;
1030 status = drms_segment_write(outSeg, outArray, 0);
1031 if (status) return 1;
1032 drms_free_array(outArray);
1033 }
1034
1035 //
1036
1037 return 0;
1038
1039 }
1040
1041
1042
1043 /*
1044 * Determine reference point coordinate and patch size according to keywords
1045 * xc, yc are the coordinate of patch center, in degrees
1046 * ncol and nrow are the final size
1047 *
1048 */
1049
1050 int findPosition(DRMS_Record_t *inRec, struct mapInfo *mInfo)
1051 {
1052
1053 int status = 0;
1054 int harpnum = drms_getkey_int(inRec, "HARPNUM", &status);
1055 TIME trec = drms_getkey_time(inRec, "T_REC", &status);
1056 float disk_lonc = drms_getkey_float(inRec, "CRLN_OBS", &status);
1057
1058 /* Center coord */
1059 // Changed into double Jun 16 2014 XS
1060
1061 double minlon = drms_getkey_double(inRec, "LONDTMIN", &status); if (status) return 1; // Stonyhurst lon
1062 double maxlon = drms_getkey_double(inRec, "LONDTMAX", &status); if (status) return 1;
1063 double minlat = drms_getkey_double(inRec, "LATDTMIN", &status); if (status) return 1;
1064 double maxlat = drms_getkey_double(inRec, "LATDTMAX", &status); if (status) return 1;
1065
1066 // A bug fixer for HARP (per M. Turmon)
1067 // When AR is below threshold, "LONDTMIN", "LONDTMAX" will be wrong
1068 // Also keywords such as "SIZE" will be NaN
1069 // We compute minlon & minlat then by
1070 // LONDTMIN(t) = LONDTMIN(t0) + (t - t0) * OMEGA_DT
1071
1072 // float psize = drms_getkey_float(inRec, "SIZE", &status);
1073 // if (psize != psize) {
1074
1075 if (minlon != minlon || maxlon != maxlon) { // check lons instead of SIZE
1076 TIME t0 = drms_getkey_time(inRec, "T_FRST1", &status); if (status) return 1; // changed from T_FRST to T_FRST1, T_FRST may not exist
1077 double omega = drms_getkey_double(inRec, "OMEGA_DT", &status); if (status) return 1;
1078 char firstRecQuery[100], t0_str[100];
1079 sprint_time(t0_str, t0, "TAI", 0);
1080 snprintf(firstRecQuery, 100, "%s[%d][%s]", inRec->seriesinfo->seriesname, harpnum, t0_str);
1081 DRMS_RecordSet_t *tmpRS = drms_open_records(drms_env, firstRecQuery, &status);
1082 if (status || tmpRS->n != 1) return 1;
1083 DRMS_Record_t *tmpRec = tmpRS->records[0];
1084 double minlon0 = drms_getkey_double(tmpRec, "LONDTMIN", &status); if (status) return 1;
1085 double maxlon0 = drms_getkey_double(tmpRec, "LONDTMAX", &status); if (status) return 1;
1086 minlon = minlon0 + (trec - t0) * omega / SECINDAY;
1087 maxlon = maxlon0 + (trec - t0) * omega / SECINDAY;
1088 printf("%s, %f, %f\n", firstRecQuery, minlon, maxlon);
1089 }
1090
1091 mInfo->xc = (maxlon + minlon) / 2. + disk_lonc;
1092 mInfo->yc = (maxlat + minlat) / 2.;
1093
1094 /* Size */
1095 // Rounded to 1.d3 precision first. Jun 16 2014 XS
1096 // The previous fix does not work. LONDTMAX-LONDTMIN varies from frame to frame
1097 // Need to find out the maximum possible difference, MAXLONDIFF (1.2e-4)
1098 // Now, ncol = (maxlon-minlon)/xscale, if the decimal part is outside 0.5 \pm (MAXLONDIFF/xscale)
1099 // proceed as it is. else, all use floor on ncol
1100
1101 float dpix = (MAXLONDIFF / mInfo->xscale) * 1.5; // "danger zone"
1102 float ncol = (maxlon - minlon) / mInfo->xscale;
1103 float d_ncol = fabs(ncol - floor(ncol) - 0.5); // distance to 0.5
1104 if (d_ncol < dpix) {
1105 mInfo->ncol = floor(ncol);
1106 } else {
1107 mInfo->ncol = round(ncol);
1108 }
1109
1110 mInfo->nrow = round((maxlat - minlat) / mInfo->yscale);
1111
1112 printf("xcol=%f, ncol=%d, nrow=%d\n", ncol, mInfo->ncol, mInfo->nrow);
1113
1114 return 0;
1115
1116 }
1117
1118
1119 /*
1120 * Fetch ephemeris info from a DRMS record
1121 * No error checking for now
1122 *
1123 */
1124
1125 int getEphemeris(DRMS_Record_t *inRec, struct ephemeris *ephem)
1126 {
1127
1128 int status = 0;
1129
1130 float crota2 = drms_getkey_float(inRec, "CROTA2", &status); // rotation
1131 double sina = sin(crota2 * RADSINDEG);
1132 double cosa = cos(crota2 * RADSINDEG);
1133
1134 ephem->pa = - crota2 * RADSINDEG;
1135 ephem->disk_latc = drms_getkey_float(inRec, "CRLT_OBS", &status) * RADSINDEG;
1136 ephem->disk_lonc = drms_getkey_float(inRec, "CRLN_OBS", &status) * RADSINDEG;
1137
1138 float crvalx = 0.0;
1139 float crvaly = 0.0;
1140 float crpix1 = drms_getkey_float(inRec, "IMCRPIX1", &status);
1141 float crpix2 = drms_getkey_float(inRec, "IMCRPIX2", &status);
1142 float cdelt = drms_getkey_float(inRec, "CDELT1", &status); // in arcsec, assumimg dx=dy
1143 ephem->disk_xc = PIX_X(0.0,0.0) - 1.0; // Center of disk in pixel, starting at 0
1144 ephem->disk_yc = PIX_Y(0.0,0.0) - 1.0;
1145
1146 float dSun = drms_getkey_float(inRec, "DSUN_OBS", &status);
1147 float rSun_ref = drms_getkey_float(inRec, "RSUN_REF", &status);
1148 if (status) rSun_ref = 6.96e8;
1149
1150 ephem->asd = asin(rSun_ref/dSun);
1151 ephem->rSun = asin(rSun_ref / dSun) * RAD2ARCSEC / cdelt;
1152
1153 return 0;
1154
1155 }
1156
1157
1158 /*
1159 * Compute the coordinates to be sampled on full disk image
1160 * mInfo->xi_out & mInfo->zeta_out
1161 * This is oversampled, its size is ncol0 & nrow0 as shown below
1162 *
1163 *
1164 */
1165
1166 void findCoord(struct mapInfo *mInfo)
1167 {
1168
1169 int ncol0 = mInfo->ncol * mInfo->nbin + (mInfo->nbin / 2) * 2; // pad with nbin/2 on edge to avoid NAN
1170 int nrow0 = mInfo->nrow * mInfo->nbin + (mInfo->nbin / 2) * 2;
1171
1172 float xscale0 = mInfo->xscale / mInfo->nbin * RADSINDEG; // oversampling resolution
1173 float yscale0 = mInfo->yscale / mInfo->nbin * RADSINDEG; // in rad
1174
1175 double lonc = mInfo->xc * RADSINDEG; // in rad
1176 double latc = mInfo->yc * RADSINDEG;
1177
1178 double disk_lonc = (mInfo->ephem).disk_lonc;
1179 double disk_latc = (mInfo->ephem).disk_latc;
1180
1181 double rSun = (mInfo->ephem).rSun;
1182 double disk_xc = (mInfo->ephem).disk_xc / rSun;
1183 double disk_yc = (mInfo->ephem).disk_yc / rSun;
1184 double pa = (mInfo->ephem).pa;
1185
1186 // Temp pointers
1187
1188 float *xi_out = mInfo->xi_out;
1189 float *zeta_out = mInfo->zeta_out;
1190
1191 // start
1192
1193 double x, y; // map coord
1194 double lat, lon; // helio coord
1195 double xi, zeta; // image coord (for one point)
1196
1197 int ind_map;
1198
1199 for (int row0 = 0; row0 < nrow0; row0++) {
1200 for (int col0 = 0; col0 < ncol0; col0++) {
1201
1202 ind_map = row0 * ncol0 + col0;
1203
1204 x = (col0 + 0.5 - ncol0/2.) * xscale0; // in rad
1205 y = (row0 + 0.5 - nrow0/2.) * yscale0;
1206
1207 /* map grid [x, y] corresponds to the point [lon, lat] in the heliographic coordinates.
1208 * the [x, y] are in radians with respect of the center of the map [xcMap, ycMap].
1209 * projection methods could be Mercator, Lambert, and many others. [maplonc, mapLatc]
1210 * is the heliographic longitude and latitude of the map center. Both are in degree.
1211 */
1212
1213 if (plane2sphere (x, y, latc, lonc, &lat, &lon, (int) mInfo->proj)) {
1214 xi_out[ind_map] = -1;
1215 zeta_out[ind_map] = -1;
1216 continue;
1217 }
1218
1219 /* map the grid [lon, lat] in the heliographic coordinates to [xi, zeta], a point in the
1220 * image coordinates. The image properties, xCenter, yCenter, rSun, pa, ecc and chi are given.
1221 */
1222
1223 if (sphere2img (lat, lon, disk_latc, disk_lonc, &xi, &zeta,
1224 disk_xc, disk_yc, 1.0, pa, 0., 0., 0., 0.)) {
1225 xi_out[ind_map] = -1;
1226 zeta_out[ind_map] = -1;
1227 continue;
1228 }
1229
1230 xi_out[ind_map] = xi * rSun;
1231 zeta_out[ind_map] = zeta * rSun;
1232
1233 }
1234 }
1235
1236 }
1237
1238
1239 /*
1240 * Sampling function
1241 * oversampling by nbin, then binning using a Gaussian
1242 * save results in outData, always of float type
1243 *
1244 */
1245
1246 int performSampling(float *outData, float *inData, struct mapInfo *mInfo, int interpOpt)
1247 {
1248
1249 int status = 0;
1250 int ind_map;
1251
1252 int ncol0 = mInfo->ncol * mInfo->nbin + (mInfo->nbin / 2) * 2; // pad with nbin/2 on edge to avoid NAN
1253 int nrow0 = mInfo->nrow * mInfo->nbin + (mInfo->nbin / 2) * 2;
1254
1255 // Changed Aug 12 2013, XS, for bitmaps
1256 float *outData0;
1257 if (interpOpt == 3 && mInfo->nbin == 1) {
1258 outData0 = outData;
1259 } else {
1260 outData0 = (float *) (malloc(ncol0 * nrow0 * sizeof(float)));
1261 }
1262
1263 float *xi_out = mInfo->xi_out;
1264 float *zeta_out = mInfo->zeta_out;
1265
1266 // Interpolation
1267
1268 struct fint_struct pars;
1269 // Aug 12 2013, passed in as argument now
1270
1271 switch (interpOpt) {
1272 case 0: // Wiener, 6 order, 1 constraint
1273 init_finterpolate_wiener(&pars, 6, 1, 6, 2, 1, 1, NULL, dpath);
1274 break;
1275 case 1: // Cubic convolution
1276 init_finterpolate_cubic_conv(&pars, 1., 3.);
1277 break;
1278 case 2: // Bilinear
1279 init_finterpolate_linear(&pars, 1.);
1280 break;
1281 case 3: // Near neighbor
1282 break;
1283 default:
1284 return 1;
1285 }
1286
1287 printf("interpOpt = %d, nbin = %d ", interpOpt, mInfo->nbin);
1288 if (interpOpt == 3) { // Aug 6 2013, Xudong
1289 for (int row0 = 0; row0 < nrow0; row0++) {
1290 for (int col0 = 0; col0 < ncol0; col0++) {
1291 ind_map = row0 * ncol0 + col0;
1292 outData0[ind_map] = nnb(inData, FOURK, FOURK, xi_out[ind_map], zeta_out[ind_map]);
1293 }
1294 }
1295 } else {
1296 finterpolate(&pars, inData, xi_out, zeta_out, outData0,
1297 FOURK, FOURK, FOURK, ncol0, nrow0, ncol0, DRMS_MISSING_FLOAT);
1298 }
1299
1300 // Rebinning, smoothing
1301
1302 if (interpOpt == 3 && mInfo->nbin == 1) {
1303 return 0;
1304 } else {
1305 frebin(outData0, outData, ncol0, nrow0, mInfo->nbin, 1); // Gaussian
1306 free(outData0); // Dec 18 2012
1307 }
1308
1309 //
1310
1311 return 0;
1312
1313 }
1314
1315
1316 /*
1317 * Performing local vector transformation
1318 * xyz: z refers to vertical (radial) component, x EW (phi), y NS
1319 *
1320 */
1321
1322 void vectorTransform(float *bx_map, float *by_map, float *bz_map, struct mapInfo *mInfo)
1323 {
1324
1325 int ncol = mInfo->ncol;
1326 int nrow = mInfo->nrow;
1327
1328 float xscale = mInfo->xscale * RADSINDEG; // in rad
1329 float yscale = mInfo->yscale * RADSINDEG;
1330
1331 double lonc = mInfo->xc * RADSINDEG; // in rad
1332 double latc = mInfo->yc * RADSINDEG;
1333
1334 double disk_lonc = (mInfo->ephem).disk_lonc;
1335 double disk_latc = (mInfo->ephem).disk_latc;
1336
1337 double rSun = (mInfo->ephem).rSun;
1338 double disk_xc = (mInfo->ephem).disk_xc / rSun;
1339 double disk_yc = (mInfo->ephem).disk_yc / rSun;
1340 double pa = (mInfo->ephem).pa;
1341
1342 int ind_map;
1343 double x, y;
1344 double lat, lon; // lat / lon for current point
1345
1346 double bx_tmp, by_tmp, bz_tmp;
1347
1348 //
1349
1350 for (int row = 0; row < mInfo->nrow; row++) {
1351 for (int col = 0; col < mInfo->ncol; col++) {
1352
1353 ind_map = row * mInfo->ncol + col;
1354
1355 x = (col + 0.5 - ncol / 2.) * xscale;
1356 y = (row + 0.5 - nrow / 2.) * yscale;
1357
1358 if (plane2sphere (x, y, latc, lonc, &lat, &lon, (int) mInfo->proj)) {
1359 bx_map[ind_map] = DRMS_MISSING_FLOAT;
1360 by_map[ind_map] = DRMS_MISSING_FLOAT;
1361 bz_map[ind_map] = DRMS_MISSING_FLOAT;
1362 continue;
1363 }
1364
1365 bx_tmp = by_tmp = bz_tmp = 0;
1366
1367 img2helioVector (bx_map[ind_map], by_map[ind_map], bz_map[ind_map],
1368 &bx_tmp, &by_tmp, &bz_tmp,
1369 lon, lat, disk_lonc, disk_latc, pa);
1370
1371 bx_map[ind_map] = bx_tmp;
1372 by_map[ind_map] = by_tmp;
1373 bz_map[ind_map] = bz_tmp;
1374
1375 }
1376 }
1377
1378 }
1379
1380
1381
1382 /*
1383 * Map and propogate vector field errors
1384 *
1385 */
1386
1387 int getBErr(float *bx_err, float *by_err, float *bz_err,
1388 DRMS_Record_t *inRec, struct mapInfo *mInfo)
1389 {
1390
1391 int status = 0;
1392
1393 // Get variances and covariances, filling factor assume to be 1
1394
1395 float *bT = (float *) (malloc(FOURK2 * sizeof(float))); // field
1396 float *bI = (float *) (malloc(FOURK2 * sizeof(float))); // inclination
1397 float *bA = (float *) (malloc(FOURK2 * sizeof(float))); // azimuth
1398
1399 float *errbT = (float *) (malloc(FOURK2 * sizeof(float)));
1400 float *errbI = (float *) (malloc(FOURK2 * sizeof(float)));
1401 float *errbA = (float *) (malloc(FOURK2 * sizeof(float)));
1402
1403 float *errbTbI = (float *) (malloc(FOURK2 * sizeof(float)));
1404 float *errbTbA = (float *) (malloc(FOURK2 * sizeof(float)));
1405 float *errbIbA = (float *) (malloc(FOURK2 * sizeof(float)));
1406
1407 if (readVectorBErr(inRec,
1408 bT, bI, bA,
1409 errbT, errbI, errbA,
1410 errbTbI, errbTbA, errbIbA)) {
1411 printf("Read full disk variances & covariances error\n");
1412 free(bT); free(bI); free(bA);
1413 free(errbT); free(errbI); free(errbA);
1414 free(errbTbI); free(errbTbA); free(errbIbA);
1415 return 1;
1416 }
1417
1418 // Size
1419
1420 int ncol = mInfo->ncol;
1421 int nrow = mInfo->nrow;
1422
1423 float xscale = mInfo->xscale * RADSINDEG; // in rad
1424 float yscale = mInfo->yscale * RADSINDEG;
1425
1426 double lonc = mInfo->xc * RADSINDEG; // in rad
1427 double latc = mInfo->yc * RADSINDEG;
1428
1429 double disk_lonc = (mInfo->ephem).disk_lonc;
1430 double disk_latc = (mInfo->ephem).disk_latc;
1431
1432 double rSun = (mInfo->ephem).rSun;
1433 double disk_xc = (mInfo->ephem).disk_xc / rSun;
1434 double disk_yc = (mInfo->ephem).disk_yc / rSun;
1435 double pa = (mInfo->ephem).pa;
1436
1437 // Start
1438
1439 double x, y; // map coord
1440 double lat, lon; // spherical coord
1441 double xi, zeta; // image coord, round to full pixel
1442
1443 int ind_map, ind_img;
1444
1445 double bpSigma2, btSigma2, brSigma2; // variances after prop
1446
1447 for (int row = 0; row < mInfo->nrow; row++) {
1448 for (int col = 0; col < mInfo->ncol; col++) {
1449
1450 ind_map = row * mInfo->ncol + col;
1451
1452 x = (col + 0.5 - ncol / 2.) * xscale;
1453 y = (row + 0.5 - nrow / 2.) * yscale;
1454
1455 if (plane2sphere (x, y, latc, lonc, &lat, &lon, (int) mInfo->proj)) {
1456 bx_err[ind_map] = DRMS_MISSING_FLOAT;
1457 by_err[ind_map] = DRMS_MISSING_FLOAT;
1458 bz_err[ind_map] = DRMS_MISSING_FLOAT;
1459 continue;
1460 }
1461
1462 if (sphere2img (lat, lon, disk_latc, disk_lonc, &xi, &zeta,
1463 disk_xc, disk_yc, 1.0, pa, 0., 0., 0., 0.)) {
1464 bx_err[ind_map] = DRMS_MISSING_FLOAT;
1465 by_err[ind_map] = DRMS_MISSING_FLOAT;
1466 bz_err[ind_map] = DRMS_MISSING_FLOAT; // Mar 7
1467 continue;
1468 }
1469
1470 xi *= rSun; xi = round(xi);
1471 zeta *= rSun; zeta = round(zeta); // nearest neighbor
1472
1473 ind_img = round(zeta * FOURK + xi);
1474
1475 if (errorprop(bT, bA, bI,
1476 errbT, errbA, errbI, errbTbA, errbTbI, errbIbA,
1477 lon, lat, disk_lonc, disk_latc, pa, FOURK, FOURK, xi, zeta,
1478 &btSigma2, &bpSigma2, &brSigma2)) {
1479 bx_err[ind_map] = DRMS_MISSING_FLOAT;
1480 by_err[ind_map] = DRMS_MISSING_FLOAT;
1481 bz_err[ind_map] = DRMS_MISSING_FLOAT;
1482 continue;
1483 }
1484
1485 bx_err[ind_map] = sqrt(bpSigma2);
1486 by_err[ind_map] = sqrt(btSigma2);
1487 bz_err[ind_map] = sqrt(brSigma2);
1488
1489 }
1490 }
1491
1492 //
1493
1494 free(bT); free(bI); free(bA);
1495 free(errbT); free(errbI); free(errbA);
1496 free(errbTbI); free(errbTbA); free(errbIbA);
1497 return 0;
1498
1499 }
1500
1501
1502
1503 /*
1504 * Read full disk vector magnetograms
1505 * Fill factor is 1, use default disambiguity resolution
1506 *
1507 */
1508
1509 int readVectorB(DRMS_Record_t *inRec, float *bx_img, float *by_img, float *bz_img)
1510 {
1511
1512 int status = 0;
1513
1514 DRMS_Segment_t *inSeg;
1515 DRMS_Array_t *inArray_ambig;
1516 DRMS_Array_t *inArray_bTotal, *inArray_bAzim, *inArray_bIncl;
1517
1518 char *ambig;
1519 float *bTotal, *bAzim, *bIncl;
1520
1521 inSeg = drms_segment_lookup(inRec, "disambig");
1522 inArray_ambig = drms_segment_read(inSeg, DRMS_TYPE_CHAR, &status);
1523 if (status) return 1;
1524 ambig = (char *)inArray_ambig->data;
1525
1526 inSeg = drms_segment_lookup(inRec, "field");
1527 inArray_bTotal = drms_segment_read(inSeg, DRMS_TYPE_FLOAT, &status);
1528 if (status) return 1;
1529 bTotal = (float *)inArray_bTotal->data;
1530
1531 inSeg = drms_segment_lookup(inRec, "azimuth");
1532 inArray_bAzim = drms_segment_read(inSeg, DRMS_TYPE_FLOAT, &status);
1533 if (status) return 1;
1534 bAzim = (float *)inArray_bAzim->data;
1535
1536 inSeg = drms_segment_lookup(inRec, "inclination");
1537 inArray_bIncl = drms_segment_read(inSeg, DRMS_TYPE_FLOAT, &status);
1538 if (status) return 1;
1539 bIncl = (float *)inArray_bIncl->data;
1540
1541 // Convert CCD xyz
1542
1543 int llx, lly; // lower-left corner
1544 int bmx, bmy; // bitmap size
1545
1546 if (fullDisk) {
1547 llx = lly = 0;
1548 bmx = bmy = FOURK;
1549 } else {
1550 llx = (int)(drms_getkey_float(inRec, "CRPIX1", &status)) - 1;
1551 lly = (int)(drms_getkey_float(inRec, "CRPIX2", &status)) - 1;
1552 bmx = inArray_ambig->axis[0];
1553 bmy = inArray_ambig->axis[1];
1554 }
1555
1556 int kx, ky, kOff;
1557 int ix = 0, jy = 0, yOff = 0, iData = 0;
1558 int xDim = FOURK, yDim = FOURK;
1559 int amb = 0;
1560
1561 for (jy = 0; jy < yDim; jy++)
1562 {
1563 ix = 0;
1564 yOff = jy * xDim;
1565 ky = jy - lly;
1566 for (ix = 0; ix < xDim; ix++)
1567 {
1568 iData = yOff + ix;
1569 kx = ix - llx;
1570
1571 // zero azi pointing up, zero incl pointing out from sun
1572 bx_img[iData] = - bTotal[iData] * sin(bIncl[iData] * RADSINDEG) * sin(bAzim[iData] * RADSINDEG);
1573 by_img[iData] = bTotal[iData] * sin(bIncl[iData] * RADSINDEG) * cos(bAzim[iData] * RADSINDEG);
1574 bz_img[iData] = bTotal[iData] * cos(bIncl[iData] * RADSINDEG);
1575
1576 // Disambiguation
1577
1578 if (kx < 0 || kx >= bmx || ky < 0 || ky >= bmy) {
1579 continue;
1580 } else {
1581 kOff = ky * bmx + kx;
1582 // if (ambig[kOff] % 2) { // 180
1583 // Feb 12 2014, use bit #2 for full disk, lowest bit for patch
1584 if (fullDisk) { amb = (ambig[kOff] / 4) % 2; } else { amb = ambig[kOff] % 2; }
1585 if (amb) { // Feb 12 2014, use bit #2
1586 bx_img[iData] *= -1.; by_img[iData] *= -1.;
1587 }
1588 }
1589 }
1590 }
1591
1592 // Clean up
1593
1594 drms_free_array(inArray_ambig);
1595 drms_free_array(inArray_bTotal);
1596 drms_free_array(inArray_bAzim);
1597 drms_free_array(inArray_bIncl);
1598
1599 return 0;
1600
1601 }
1602
1603
1604 /*
1605 * Read variances and covariances of vector magnetograms
1606 *
1607 */
1608
1609 int readVectorBErr(DRMS_Record_t *inRec,
1610 float *bT, float *bI, float *bA,
1611 float *errbT, float *errbI, float *errbA,
1612 float *errbTbI, float *errbTbA, float *errbIbA)
1613 {
1614
1615 int status = 0;
1616
1617 float *data_ptr[9];
1618 char *segName[9] = {"field", "inclination", "azimuth",
1619 "field_err", "inclination_err", "azimuth_err",
1620 "field_inclination_err", "field_az_err", "inclin_azimuth_err"};
1621 DRMS_Segment_t *inSegs[9];
1622 DRMS_Array_t *inArrays[9];
1623
1624 // Read full disk images
1625 // Do we need disambig? Dec 30 XS
1626
1627 for (int iSeg = 0; iSeg < 9; iSeg++) {
1628
1629 inSegs[iSeg] = drms_segment_lookup(inRec, segName[iSeg]);
1630 inArrays[iSeg] = drms_segment_read(inSegs[iSeg], DRMS_TYPE_FLOAT, &status);
1631 data_ptr[iSeg] = (float *) inArrays[iSeg]->data;
1632
1633 }
1634
1635 float *bT0 = data_ptr[0], *bI0 = data_ptr[1], *bA0 = data_ptr[2];
1636 float *errbT0 = data_ptr[3], *errbI0 = data_ptr[4], *errbA0 = data_ptr[5];
1637 float *errbTbI0 = data_ptr[6], *errbTbA0 = data_ptr[7], *errbIbA0 = data_ptr[8];
1638
1639 // Add disambig, Feb 12 2014
1640
1641 DRMS_Segment_t *inSeg;
1642 DRMS_Array_t *inArray_ambig;
1643
1644 if (amb4err) { // Mar 4 2014
1645
1646 inSeg = drms_segment_lookup(inRec, "disambig");
1647 inArray_ambig = drms_segment_read(inSeg, DRMS_TYPE_CHAR, &status);
1648 if (status) return 1;
1649 char *ambig = (char *)inArray_ambig->data;
1650
1651 int llx, lly; // lower-left corner
1652 int bmx, bmy; // bitmap size
1653
1654 if (fullDisk) {
1655 llx = lly = 0;
1656 bmx = bmy = FOURK;
1657 } else {
1658 llx = (int)(drms_getkey_float(inRec, "CRPIX1", &status)) - 1;
1659 lly = (int)(drms_getkey_float(inRec, "CRPIX2", &status)) - 1;
1660 bmx = inArray_ambig->axis[0];
1661 bmy = inArray_ambig->axis[1];
1662 }
1663
1664 int idx, idx_a;
1665 int amb;
1666
1667 for (int j = 0; j < bmy; j++) {
1668 for (int i = 0; i < bmx; i++) {
1669 idx_a = j * bmx + i;
1670 idx = (j + lly) * FOURK + (i + llx);
1671 // Feb 12 2014, use bit #2 for full disk, lowest bit for patch
1672 if (fullDisk) { amb = (ambig[idx_a] / 4) % 2; } else { amb = ambig[idx_a] % 2; }
1673 if (amb) { bA0[idx] += 180.; }
1674 }
1675 }
1676
1677 }
1678
1679 // Convert errors to variances, correlation coefficients to covariances
1680
1681 for (int i = 0; i < FOURK2; i++) {
1682
1683 if (fabs(errbI0[i]) > 180.) errbI0[i] = 180.;
1684 if (fabs(errbA0[i]) > 180.) errbA0[i] = 180.;
1685
1686 bT[i] = bT0[i];
1687 bI[i] = bI0[i]; // in deg, coverted in errorprop
1688 bA[i] = bA0[i];
1689
1690 errbT[i] = errbT0[i] * errbT0[i];
1691 errbI[i] = errbI0[i] * errbI0[i] * RADSINDEG * RADSINDEG;
1692 errbA[i] = errbA0[i] * errbA0[i] * RADSINDEG * RADSINDEG;
1693
1694 errbTbI[i] = errbTbI0[i] * errbT0[i] * errbI0[i] * RADSINDEG;
1695 errbTbA[i] = errbTbA0[i] * errbT0[i] * errbA0[i] * RADSINDEG;
1696 errbIbA[i] = errbIbA0[i] * errbI0[i] * errbA0[i] * RADSINDEG * RADSINDEG;
1697
1698 }
1699
1700 //
1701
1702 for (int iSeg = 0; iSeg < 9; iSeg++) drms_free_array(inArrays[iSeg]);
1703 if (amb4err) drms_free_array(inArray_ambig); // Feb 12; Mar 04 2014
1704
1705 return 0;
1706
1707 }
1708
1709
1710 /*
1711 * Create Cutout record: top level subroutine
1712 * Do the loops on segments and set the keywords here
1713 * Work is done in writeCutout routine below
1714 *
1715 */
1716
1717 int createCutRecord(DRMS_Record_t *mharpRec, DRMS_Record_t *bharpRec,
1718 DRMS_Record_t *dopRec, DRMS_Record_t *contRec,
1719 DRMS_Record_t *sharpRec, struct swIndex *swKeys_ptr)
1720 {
1721
1722 int status = 0;
1723
1724 int iHarpSeg;
1725 int nMharpSegs = ARRLENGTH(MharpSegs), nBharpSegs = ARRLENGTH(BharpSegs);
1726
1727 // Cutout Mharp
1728
1729 for (iHarpSeg = 0; iHarpSeg < nMharpSegs; iHarpSeg++) {
1730 if (writeCutout(sharpRec, mharpRec, mharpRec, MharpSegs[iHarpSeg])) {
1731 printf("Mharp cutout fails for %s\n", MharpSegs[iHarpSeg]);
1732 break;
1733 }
1734 }
1735 if (iHarpSeg != nMharpSegs) {
1736 SHOW("Cutout: segment number unmatch\n");
1737 return 1; // if failed
1738 }
1739 printf("Magnetogram cutout done.\n");
1740
1741 // Cutout Doppler
1742
1743 if (writeCutout(sharpRec, dopRec, mharpRec, "Dopplergram")) {
1744 printf("Doppler cutout failed\n");
1745 return 1;
1746 }
1747 printf("Dopplergram cutout done.\n");
1748
1749 // Cutout Continuum
1750
1751 if (writeCutout(sharpRec, contRec, mharpRec, "continuum")) {
1752 printf("Continuum cutout failed\n");
1753 return 1;
1754 }
1755 printf("Intensitygram cutout done.\n");
1756
1757 // Coutout Bharp
1758
1759 for (iHarpSeg = 0; iHarpSeg < nBharpSegs; iHarpSeg++) {
1760 if (writeCutout(sharpRec, bharpRec, mharpRec, BharpSegs[iHarpSeg])) {
1761 printf("Bharp cutout fails for %s\n", BharpSegs[iHarpSeg]);
1762 break;
1763 }
1764 }
1765 if (iHarpSeg != nBharpSegs) return 1; // if failed
1766 printf("Vector B cutout done.\n");
1767
1768 // Keywords & Links
1769
1770 drms_copykey(sharpRec, mharpRec, "T_REC");
1771 drms_copykey(sharpRec, mharpRec, "HARPNUM");
1772
1773 DRMS_Link_t *mHarpLink = hcon_lookup_lower(&sharpRec->links, "MHARP");
1774 if (mHarpLink) drms_link_set("MHARP", sharpRec, mharpRec);
1775 DRMS_Link_t *bHarpLink = hcon_lookup_lower(&sharpRec->links, "BHARP");
1776 if (bHarpLink) drms_link_set("BHARP", sharpRec, bharpRec);
1777
1778 setSWIndex(sharpRec, swKeys_ptr); // Set space weather indices
1779 setKeys(sharpRec, mharpRec, bharpRec, NULL); // Set all other keywords, NULL specifies cutout
1780
1781 // Stats
1782
1783 int nCutSegs = ARRLENGTH(CutSegs);
1784 for (int iSeg = 0; iSeg < nCutSegs; iSeg++) {
1785 DRMS_Segment_t *outSeg = drms_segment_lookupnum(sharpRec, iSeg);
1786 DRMS_Array_t *outArray = drms_segment_read(outSeg, DRMS_TYPE_FLOAT, &status);
1787 set_statistics(outSeg, outArray, 1);
1788 drms_free_array(outArray);
1789 }
1790
1791 return 0;
1792
1793 }
1794
1795
1796 /*
1797 * Get cutout and write segment
1798 * Change DISAMB_AZI to apply disambiguation to azimuth
1799 *
1800 */
1801
1802 int writeCutout(DRMS_Record_t *outRec, DRMS_Record_t *inRec, DRMS_Record_t *harpRec, char *SegName)
1803 {
1804
1805 int status = 0;
1806
1807 DRMS_Segment_t *inSeg = NULL, *outSeg = NULL;
1808 DRMS_Array_t *cutoutArray = NULL;
1809 // DRMS_Type_t arrayType;
1810
1811 int ll[2], ur[2], nx, ny, nxny; // lower-left and upper right coords
1812
1813 /* Info */
1814
1815 inSeg = drms_segment_lookup(inRec, SegName);
1816 if (!inSeg) return 1;
1817
1818 nx = (int) drms_getkey_float(harpRec, "CRSIZE1", &status);
1819 ny = (int) drms_getkey_float(harpRec, "CRSIZE2", &status);
1820 nxny = nx * ny;
1821 ll[0] = (int) drms_getkey_float(harpRec, "CRPIX1", &status) - 1; if (status) return 1;
1822 ll[1] = (int) drms_getkey_float(harpRec, "CRPIX2", &status) - 1; if (status) return 1;
1823 ur[0] = ll[0] + nx - 1; if (status) return 1;
1824 ur[1] = ll[1] + ny - 1; if (status) return 1;
1825
1826 if (inSeg->axis[0] == nx && inSeg->axis[1] == ny) { // for bitmaps, infomaps, etc.
1827 cutoutArray = drms_segment_read(inSeg, DRMS_TYPE_DOUBLE, &status);
1828 if (status) return 1;
1829 } else if (inSeg->axis[0] == FOURK && inSeg->axis[1] == FOURK) { // for full disk ones
1830 cutoutArray = drms_segment_readslice(inSeg, DRMS_TYPE_DOUBLE, ll, ur, &status);
1831 if (status) return 1;
1832 } else {
1833 return 1;
1834 }
1835
1836 // Feb 12 2014, fool-proof, for patch, change everything to 0 or 7!!!
1837 // This is a fix for disambiguation before Aug 2013
1838
1839 if (!strcmp(SegName, "disambig") && !fullDisk) {
1840 double *disamb = (double *) (cutoutArray->data);
1841 for (int i = 0; i < nxny; i++) {
1842 if (((int)disamb[i]) % 2) { disamb[i] = 7; } else { disamb[i] = 0; }
1843 }
1844 }
1845
1846 /* Adding disambiguation resolution to cutout azimuth? */
1847
1848 #if DISAMB_AZI
1849 int amb;
1850 if (!strcmp(SegName, "azimuth")) {
1851 DRMS_Segment_t *disambSeg = NULL;
1852 disambSeg = drms_segment_lookup(inRec, "disambig");
1853 if (!disambSeg) {drms_free_array(cutoutArray); return 1;}
1854 DRMS_Array_t *disambArray;
1855 if (fullDisk) { // Jan 2 2014 XS
1856 disambArray = drms_segment_readslice(disambSeg, DRMS_TYPE_CHAR, ll, ur, &status);
1857 if (status) return 1;
1858 } else {
1859 if (disambSeg->axis[0] == nx && disambSeg->axis[1] == ny) {
1860 disambArray = drms_segment_read(disambSeg, DRMS_TYPE_CHAR, &status);
1861 if (status) {drms_free_array(cutoutArray); return 1;}
1862 } else {
1863 drms_free_array(cutoutArray);
1864 return 1;
1865 }
1866 }
1867 double *azimuth = (double *) cutoutArray->data;
1868 char *disamb = (char *) disambArray->data;
1869 for (int n = 0; n < nxny; n++) {
1870 // if (disamb[n] % 2) azimuth[n] += 180.; // Nov 12 2013 Fixed!!!
1871 // Feb 12 2014, use bit #2 for full disk, lowest bit for patch
1872 if (fullDisk) { amb = (disamb[n] / 4) % 2; } else { amb = disamb[n] % 2; }
1873 if (amb) azimuth[n] += 180.;
1874 }
1875 drms_free_array(disambArray);
1876 }
1877 #endif
1878
1879 /* Write out */
1880
1881 outSeg = drms_segment_lookup(outRec, SegName);
1882 if (!outSeg) return 1;
1883 // drms_array_convert_inplace(outSeg->info->type, 0, 1, cutoutArray); // Jan 02 2013
1884 outSeg->axis[0] = cutoutArray->axis[0];
1885 outSeg->axis[1] = cutoutArray->axis[1];
1886 // cutoutArray->parent_segment = outSeg;
1887 cutoutArray->israw = 0; // always compressed
1888 cutoutArray->bzero = outSeg->bzero;
1889 cutoutArray->bscale = outSeg->bscale; // Same as inArray's
1890 status = drms_segment_write(outSeg, cutoutArray, 0);
1891 drms_free_array(cutoutArray);
1892 if (status) return 1;
1893
1894 return 0;
1895
1896 }
1897
1898
1899 /*
1900 * Compute space weather indices, no error checking for now
1901 * Based on M. Bobra's swharp_vectorB.c
1902 * No error checking for now
1903 *
1904 */
1905
1906 void computeSWIndex(struct swIndex *swKeys_ptr, DRMS_Record_t *inRec, struct mapInfo *mInfo)
1907 {
1908
1909 int status = 0;
1910 int nx = mInfo->ncol, ny = mInfo->nrow;
1911 int nxny = nx * ny;
1912 int dims[2] = {nx, ny};
1913
1914 // Get bx, by, bz, mask
1915
1916 // Use HARP (Turmon) bitmap as a threshold on spaceweather quantities
1917 DRMS_Segment_t *bitmaskSeg = drms_segment_lookup(inRec, "bitmap");
1918 DRMS_Array_t *bitmaskArray = drms_segment_read(bitmaskSeg, DRMS_TYPE_INT, &status);
1919 int *bitmask = (int *) bitmaskArray->data; // get the previously made mask array
1920
1921 //Use conf_disambig map as a threshold on spaceweather quantities
1922 DRMS_Segment_t *maskSeg = drms_segment_lookup(inRec, "conf_disambig");
1923 DRMS_Array_t *maskArray = drms_segment_read(maskSeg, DRMS_TYPE_INT, &status);
1924 int *mask = (int *) maskArray->data; // get the previously made mask array
1925
1926 DRMS_Segment_t *bxSeg = drms_segment_lookup(inRec, BP_SEG_CEA);
1927 DRMS_Array_t *bxArray = drms_segment_read(bxSeg, DRMS_TYPE_FLOAT, &status);
1928 float *bx = (float *) bxArray->data; // bx
1929
1930 DRMS_Segment_t *bySeg = drms_segment_lookup(inRec, BT_SEG_CEA);
1931 DRMS_Array_t *byArray = drms_segment_read(bySeg, DRMS_TYPE_FLOAT, &status);
1932 float *by = (float *) byArray->data; // by
1933 for (int i = 0; i < nxny; i++) by[i] *= -1;
1934
1935 DRMS_Segment_t *bzSeg = drms_segment_lookup(inRec, BR_SEG_CEA);
1936 DRMS_Array_t *bzArray = drms_segment_read(bzSeg, DRMS_TYPE_FLOAT, &status);
1937 float *bz = (float *) bzArray->data; // bz
1938
1939 //Use magnetogram map to compute R
1940 DRMS_Segment_t *losSeg = drms_segment_lookup(inRec, "magnetogram");
1941 DRMS_Array_t *losArray = drms_segment_read(losSeg, DRMS_TYPE_FLOAT, &status);
1942 float *los = (float *) losArray->data; // los
1943
1944 DRMS_Segment_t *bz_errSeg = drms_segment_lookup(inRec, BR_ERR_SEG_CEA);
1945 DRMS_Array_t *bz_errArray = drms_segment_read(bz_errSeg, DRMS_TYPE_FLOAT, &status);
1946 float *bz_err = (float *) bz_errArray->data; // bz_err
1947
1948 DRMS_Segment_t *by_errSeg = drms_segment_lookup(inRec, BT_ERR_SEG_CEA);
1949 DRMS_Array_t *by_errArray = drms_segment_read(by_errSeg, DRMS_TYPE_FLOAT, &status);
1950 float *by_err = (float *) by_errArray->data; // by_err
1951 //for (int i = 0; i < nxny; i++) by_err[i] *= -1;
1952
1953 DRMS_Segment_t *bx_errSeg = drms_segment_lookup(inRec, BP_ERR_SEG_CEA);
1954 DRMS_Array_t *bx_errArray = drms_segment_read(bx_errSeg, DRMS_TYPE_FLOAT, &status);
1955 float *bx_err = (float *) bx_errArray->data; // bx_err
1956
1957 // Get emphemeris
1958 float cdelt1_orig = drms_getkey_float(inRec, "CDELT1", &status);
1959 float dsun_obs = drms_getkey_float(inRec, "DSUN_OBS", &status);
1960 double rsun_ref = drms_getkey_double(inRec, "RSUN_REF", &status);
1961 double rsun_obs = drms_getkey_double(inRec, "RSUN_OBS", &status);
1962 float imcrpix1 = drms_getkey_float(inRec, "IMCRPIX1", &status);
1963 float imcrpix2 = drms_getkey_float(inRec, "IMCRPIX2", &status);
1964 float crpix1 = drms_getkey_float(inRec, "CRPIX1", &status);
1965 float crpix2 = drms_getkey_float(inRec, "CRPIX2", &status);
1966
1967 // convert cdelt1_orig from degrees to arcsec
1968 float cdelt1 = (atan((rsun_ref*cdelt1_orig*RADSINDEG)/(dsun_obs)))*(1/RADSINDEG)*(3600.);
1969
1970 //if (nx1 > floor((nx-1)/scale + 1) )
1971 // DIE("X-dimension of output array in fsample() is too large.");
1972 //if (ny1 > floor((ny-1)/scale + 1) )
1973 // DIE("Y-dimension of output array in fsample() is too large.");
1974
1975 // Temp arrays
1976 float *bh = (float *) (malloc(nxny * sizeof(float)));
1977 float *bt = (float *) (malloc(nxny * sizeof(float)));
1978 float *jz = (float *) (malloc(nxny * sizeof(float)));
1979 float *jz_smooth = (float *) (malloc(nxny * sizeof(float)));
1980 float *bpx = (float *) (malloc(nxny * sizeof(float)));
1981 float *bpy = (float *) (malloc(nxny * sizeof(float)));
1982 float *bpz = (float *) (malloc(nxny * sizeof(float)));
1983 float *derx = (float *) (malloc(nxny * sizeof(float)));
1984 float *dery = (float *) (malloc(nxny * sizeof(float)));
1985 float *derx_los = (float *) (malloc(nxny * sizeof(float)));
1986 float *dery_los = (float *) (malloc(nxny * sizeof(float)));
1987 float *derx_bt = (float *) (malloc(nxny * sizeof(float)));
1988 float *dery_bt = (float *) (malloc(nxny * sizeof(float)));
1989 float *derx_bh = (float *) (malloc(nxny * sizeof(float)));
1990 float *dery_bh = (float *) (malloc(nxny * sizeof(float)));
1991 float *derx_bz = (float *) (malloc(nxny * sizeof(float)));
1992 float *dery_bz = (float *) (malloc(nxny * sizeof(float)));
1993 float *bt_err = (float *) (malloc(nxny * sizeof(float)));
1994 float *bh_err = (float *) (malloc(nxny * sizeof(float)));
1995 float *jz_err = (float *) (malloc(nxny * sizeof(float)));
1996 float *jz_err_squared = (float *) (malloc(nxny * sizeof(float)));
1997 float *jz_err_squared_smooth = (float *) (malloc(nxny * sizeof(float)));
1998 float *jz_rms_err = (float *) (malloc(nxny * sizeof(float)));
1999 float *err_term1 = (float *) (calloc(nxny, sizeof(float)));
2000 float *err_term2 = (float *) (calloc(nxny, sizeof(float)));
2001 float *err_termA = (float *) (calloc(nxny, sizeof(float)));
2002 float *err_termB = (float *) (calloc(nxny, sizeof(float)));
2003 float *err_termAt = (float *) (calloc(nxny, sizeof(float)));
2004 float *err_termBt = (float *) (calloc(nxny, sizeof(float)));
2005 float *err_termAh = (float *) (calloc(nxny, sizeof(float)));
2006 float *err_termBh = (float *) (calloc(nxny, sizeof(float)));
2007
2008 // define some values for the R calculation
2009 int scale = round(2.0/cdelt1);
2010 int nx1 = nx/scale;
2011 int ny1 = ny/scale;
2012 int nxp = nx1+40;
2013 int nyp = ny1+40;
2014 float *rim = (float *)malloc(nx1*ny1*sizeof(float));
2015 float *p1p0 = (float *)malloc(nx1*ny1*sizeof(float));
2016 float *p1n0 = (float *)malloc(nx1*ny1*sizeof(float));
2017 float *p1p = (float *)malloc(nx1*ny1*sizeof(float));
2018 float *p1n = (float *)malloc(nx1*ny1*sizeof(float));
2019 float *p1 = (float *)malloc(nx1*ny1*sizeof(float));
2020 float *pmap = (float *)malloc(nxp*nyp*sizeof(float));
2021 float *p1pad = (float *)malloc(nxp*nyp*sizeof(float));
2022 float *pmapn = (float *)malloc(nx1*ny1*sizeof(float));
2023
2024 // define some arrays for the lorentz force calculation
2025 float *fx = (float *) (malloc(nxny * sizeof(float)));
2026 float *fy = (float *) (malloc(nxny * sizeof(float)));
2027 float *fz = (float *) (malloc(nxny * sizeof(float)));
2028
2029
2030 //spaceweather quantities computed
2031 if (computeAbsFlux(bz_err, bz , dims, &(swKeys_ptr->absFlux), &(swKeys_ptr->mean_vf), &(swKeys_ptr->mean_vf_err),
2032 &(swKeys_ptr->count_mask), mask, bitmask, cdelt1, rsun_ref, rsun_obs))
2033 {
2034 swKeys_ptr->absFlux = DRMS_MISSING_FLOAT; // If fail, fill in NaN
2035 swKeys_ptr->mean_vf = DRMS_MISSING_FLOAT;
2036 swKeys_ptr->mean_vf_err = DRMS_MISSING_FLOAT;
2037 swKeys_ptr->count_mask = DRMS_MISSING_INT;
2038 }
2039
2040 if (computeAbsFlux_los(los, dims, &(swKeys_ptr->absFlux_los), &(swKeys_ptr->mean_vf_los),
2041 &(swKeys_ptr->count_mask_los), bitmask, cdelt1, rsun_ref, rsun_obs))
2042 {
2043 swKeys_ptr->absFlux_los = DRMS_MISSING_FLOAT; // If fail, fill in NaN
2044 swKeys_ptr->mean_vf_los = DRMS_MISSING_FLOAT;
2045 swKeys_ptr->count_mask_los = DRMS_MISSING_INT;
2046 }
2047
2048 for (int i = 0; i < nxny; i++) bpz[i] = bz[i];
2049 greenpot(bpx, bpy, bpz, nx, ny);
2050
2051 computeBh(bx_err, by_err, bh_err, bx, by, bz, bh, dims, &(swKeys_ptr->mean_hf), mask, bitmask);
2052
2053 if (computeGamma(bz_err, bh_err, bx, by, bz, bh, dims, &(swKeys_ptr->mean_gamma), &(swKeys_ptr->mean_gamma_err),mask, bitmask))
2054 {
2055 swKeys_ptr->mean_gamma = DRMS_MISSING_FLOAT;
2056 swKeys_ptr->mean_gamma_err = DRMS_MISSING_FLOAT;
2057 }
2058
2059 computeB_total(bx_err, by_err, bz_err, bt_err, bx, by, bz, bt, dims, mask, bitmask);
2060
2061 if (computeBtotalderivative(bt, dims, &(swKeys_ptr->mean_derivative_btotal), mask, bitmask, derx_bt,
2062 dery_bt, bt_err, &(swKeys_ptr->mean_derivative_btotal_err), err_termAt, err_termBt))
2063 {
2064 swKeys_ptr->mean_derivative_btotal = DRMS_MISSING_FLOAT;
2065 swKeys_ptr->mean_derivative_btotal_err = DRMS_MISSING_FLOAT;
2066 }
2067
2068 if (computeBhderivative(bh, bh_err, dims, &(swKeys_ptr->mean_derivative_bh),
2069 &(swKeys_ptr->mean_derivative_bh_err), mask, bitmask, derx_bh, dery_bh, err_termAh, err_termBh))
2070 {
2071 swKeys_ptr->mean_derivative_bh = DRMS_MISSING_FLOAT;
2072 swKeys_ptr->mean_derivative_bh_err = DRMS_MISSING_FLOAT;
2073 }
2074
2075 if (computeBzderivative(bz, bz_err, dims, &(swKeys_ptr->mean_derivative_bz), &(swKeys_ptr->mean_derivative_bz_err),
2076 mask, bitmask, derx_bz, dery_bz, err_termA, err_termB))
2077 {
2078 swKeys_ptr->mean_derivative_bz = DRMS_MISSING_FLOAT; // If fail, fill in NaN
2079 swKeys_ptr->mean_derivative_bz_err = DRMS_MISSING_FLOAT;
2080 }
2081
2082 if (computeLOSderivative(los, dims, &(swKeys_ptr->mean_derivative_los), bitmask, derx_los, dery_los))
2083 {
2084 swKeys_ptr->mean_derivative_los = DRMS_MISSING_FLOAT; // If fail, fill in NaN
2085 }
2086
2087 computeJz(bx_err, by_err, bx, by, dims, jz, jz_err, jz_err_squared, mask, bitmask, cdelt1, rsun_ref, rsun_obs,
2088 derx, dery, err_term1, err_term2);
2089
2090
2091 if(computeJzsmooth(bx, by, dims, jz, jz_smooth, jz_err, jz_rms_err, jz_err_squared_smooth, &(swKeys_ptr->mean_jz),
2092 &(swKeys_ptr->mean_jz_err), &(swKeys_ptr->us_i), &(swKeys_ptr->us_i_err), mask, bitmask, cdelt1,
2093 rsun_ref, rsun_obs, derx, dery))
2094 {
2095 swKeys_ptr->mean_jz = DRMS_MISSING_FLOAT;
2096 swKeys_ptr->us_i = DRMS_MISSING_FLOAT;
2097 swKeys_ptr->mean_jz_err = DRMS_MISSING_FLOAT;
2098 swKeys_ptr->us_i_err = DRMS_MISSING_FLOAT;
2099 }
2100
2101 if (computeAlpha(jz_err, bz_err, bz, dims, jz, jz_smooth, &(swKeys_ptr->mean_alpha), &(swKeys_ptr->mean_alpha_err),
2102 mask, bitmask, cdelt1, rsun_ref, rsun_obs))
2103 {
2104 swKeys_ptr->mean_alpha = DRMS_MISSING_FLOAT;
2105 swKeys_ptr->mean_alpha_err = DRMS_MISSING_FLOAT;
2106 }
2107
2108 if (computeHelicity(jz_err, jz_rms_err, bz_err, bz, dims, jz, &(swKeys_ptr->mean_ih), &(swKeys_ptr->mean_ih_err),
2109 &(swKeys_ptr->total_us_ih), &(swKeys_ptr->total_abs_ih),
2110 &(swKeys_ptr->total_us_ih_err), &(swKeys_ptr->total_abs_ih_err), mask, bitmask, cdelt1, rsun_ref, rsun_obs))
2111 {
2112 swKeys_ptr->mean_ih = DRMS_MISSING_FLOAT;
2113 swKeys_ptr->total_us_ih = DRMS_MISSING_FLOAT;
2114 swKeys_ptr->total_abs_ih = DRMS_MISSING_FLOAT;
2115 swKeys_ptr->mean_ih_err = DRMS_MISSING_FLOAT;
2116 swKeys_ptr->total_us_ih_err = DRMS_MISSING_FLOAT;
2117 swKeys_ptr->total_abs_ih_err = DRMS_MISSING_FLOAT;
2118 }
2119
2120 if (computeSumAbsPerPolarity(jz_err, bz_err, bz, jz, dims, &(swKeys_ptr->totaljz), &(swKeys_ptr->totaljz_err),
2121 mask, bitmask, cdelt1, rsun_ref, rsun_obs))
2122 {
2123 swKeys_ptr->totaljz = DRMS_MISSING_FLOAT;
2124 swKeys_ptr->totaljz_err = DRMS_MISSING_FLOAT;
2125 }
2126
2127 if (computeFreeEnergy(bx_err, by_err, bx, by, bpx, bpy, dims,
2128 &(swKeys_ptr->meanpot), &(swKeys_ptr->meanpot_err), &(swKeys_ptr->totpot), &(swKeys_ptr->totpot_err),
2129 mask, bitmask, cdelt1, rsun_ref, rsun_obs))
2130 {
2131 swKeys_ptr->meanpot = DRMS_MISSING_FLOAT; // If fail, fill in NaN
2132 swKeys_ptr->totpot = DRMS_MISSING_FLOAT;
2133 swKeys_ptr->meanpot_err = DRMS_MISSING_FLOAT;
2134 swKeys_ptr->totpot_err = DRMS_MISSING_FLOAT;
2135 }
2136
2137
2138 if (computeShearAngle(bx_err, by_err, bz_err, bx, by, bz, bpx, bpy, bpz, dims,
2139 &(swKeys_ptr->meanshear_angle), &(swKeys_ptr->meanshear_angle_err), &(swKeys_ptr->area_w_shear_gt_45),
2140 mask, bitmask))
2141 {
2142 swKeys_ptr->meanshear_angle = DRMS_MISSING_FLOAT; // If fail, fill in NaN
2143 swKeys_ptr->area_w_shear_gt_45 = DRMS_MISSING_FLOAT;
2144 swKeys_ptr->meanshear_angle_err= DRMS_MISSING_FLOAT;
2145 }
2146
2147 if (computeR(bz_err, los , dims, &(swKeys_ptr->Rparam), cdelt1, rim, p1p0, p1n0,
2148 p1p, p1n, p1, pmap, nx1, ny1, scale, p1pad, nxp, nyp, pmapn))
2149 {
2150 swKeys_ptr->Rparam = DRMS_MISSING_FLOAT; // If fail, fill in NaN
2151 }
2152
2153
2154 if (computeLorentz(bx, by, bz, fx, fy, fz, dims, &(swKeys_ptr->totfx), &(swKeys_ptr->totfy), &(swKeys_ptr->totfz), &(swKeys_ptr->totbsq),
2155 &(swKeys_ptr->epsx), &(swKeys_ptr->epsy), &(swKeys_ptr->epsz), mask, bitmask, cdelt1, rsun_ref, rsun_obs))
2156 {
2157 swKeys_ptr->totfx = DRMS_MISSING_FLOAT;
2158 swKeys_ptr->totfy = DRMS_MISSING_FLOAT;
2159 swKeys_ptr->totfz = DRMS_MISSING_FLOAT;
2160 swKeys_ptr->totbsq = DRMS_MISSING_FLOAT;
2161 swKeys_ptr->epsx = DRMS_MISSING_FLOAT;
2162 swKeys_ptr->epsy = DRMS_MISSING_FLOAT;
2163 swKeys_ptr->epsz = DRMS_MISSING_FLOAT;
2164
2165 }
2166
2167 // Clean up the arrays
2168
2169 drms_free_array(bitmaskArray); // Dec 18 2012 Xudong
2170 drms_free_array(maskArray);
2171 drms_free_array(bxArray);
2172 drms_free_array(byArray);
2173 drms_free_array(bzArray);
2174 drms_free_array(losArray); // Mar 7
2175 drms_free_array(bx_errArray);
2176 drms_free_array(by_errArray);
2177 drms_free_array(bz_errArray);
2178
2179 free(bh); free(bt); free(jz); free(jz_smooth);
2180 free(bpx); free(bpy); free(bpz);
2181 free(derx); free(dery);
2182 free(derx_bt); free(dery_bt);
2183 free(derx_bz); free(dery_bz);
2184 free(derx_bh); free(dery_bh);
2185 free(derx_los); free(dery_los);
2186 free(bt_err); free(bh_err); free(jz_err);
2187 free(jz_err_squared); free(jz_rms_err);
2188 free(jz_err_squared_smooth);
2189
2190 // free the arrays that are related to the numerical derivatives
2191 free(err_term2);
2192 free(err_term1);
2193 free(err_termB);
2194 free(err_termA);
2195 free(err_termBt);
2196 free(err_termAt);
2197 free(err_termBh);
2198 free(err_termAh);
2199
2200 // free the arrays that are related to the r calculation
2201 free(rim);
2202 free(p1p0);
2203 free(p1n0);
2204 free(p1p);
2205 free(p1n);
2206 free(p1);
2207 free(pmap);
2208 free(p1pad);
2209 free(pmapn);
2210
2211 // free the arrays that are related to the lorentz calculation
2212 free(fx); free(fy); free(fz);
2213 }
2214
2215 /*
2216 * Set space weather indices, no error checking for now
2217 *
2218 */
2219
2220 void setSWIndex(DRMS_Record_t *outRec, struct swIndex *swKeys_ptr)
2221 {
2222 drms_setkey_float(outRec, "USFLUX", swKeys_ptr->mean_vf);
2223 drms_setkey_float(outRec, "USFLUXL", swKeys_ptr->mean_vf_los);
2224 drms_setkey_float(outRec, "MEANGAM", swKeys_ptr->mean_gamma);
2225 drms_setkey_float(outRec, "MEANGBT", swKeys_ptr->mean_derivative_btotal);
2226 drms_setkey_float(outRec, "MEANGBH", swKeys_ptr->mean_derivative_bh);
2227 drms_setkey_float(outRec, "MEANGBZ", swKeys_ptr->mean_derivative_bz);
2228 drms_setkey_float(outRec, "MEANGBL", swKeys_ptr->mean_derivative_los);
2229 drms_setkey_float(outRec, "MEANJZD", swKeys_ptr->mean_jz);
2230 drms_setkey_float(outRec, "TOTUSJZ", swKeys_ptr->us_i);
2231 drms_setkey_float(outRec, "MEANALP", swKeys_ptr->mean_alpha);
2232 drms_setkey_float(outRec, "MEANJZH", swKeys_ptr->mean_ih);
2233 drms_setkey_float(outRec, "TOTUSJH", swKeys_ptr->total_us_ih);
2234 drms_setkey_float(outRec, "ABSNJZH", swKeys_ptr->total_abs_ih);
2235 drms_setkey_float(outRec, "SAVNCPP", swKeys_ptr->totaljz);
2236 drms_setkey_float(outRec, "MEANPOT", swKeys_ptr->meanpot);
2237 drms_setkey_float(outRec, "TOTPOT", swKeys_ptr->totpot);
2238 drms_setkey_float(outRec, "MEANSHR", swKeys_ptr->meanshear_angle);
2239 drms_setkey_float(outRec, "SHRGT45", swKeys_ptr->area_w_shear_gt_45);
2240 drms_setkey_float(outRec, "CMASK", swKeys_ptr->count_mask);
2241 drms_setkey_float(outRec, "CMASKL", swKeys_ptr->count_mask_los);
2242 drms_setkey_float(outRec, "ERRBT", swKeys_ptr->mean_derivative_btotal_err);
2243 drms_setkey_float(outRec, "ERRVF", swKeys_ptr->mean_vf_err);
2244 drms_setkey_float(outRec, "ERRGAM", swKeys_ptr->mean_gamma_err);
2245 drms_setkey_float(outRec, "ERRBH", swKeys_ptr->mean_derivative_bh_err);
2246 drms_setkey_float(outRec, "ERRBZ", swKeys_ptr->mean_derivative_bz_err);
2247 drms_setkey_float(outRec, "ERRJZ", swKeys_ptr->mean_jz_err);
2248 drms_setkey_float(outRec, "ERRUSI", swKeys_ptr->us_i_err);
2249 drms_setkey_float(outRec, "ERRALP", swKeys_ptr->mean_alpha_err);
2250 drms_setkey_float(outRec, "ERRMIH", swKeys_ptr->mean_ih_err);
2251 drms_setkey_float(outRec, "ERRTUI", swKeys_ptr->total_us_ih_err);
2252 drms_setkey_float(outRec, "ERRTAI", swKeys_ptr->total_abs_ih_err);
2253 drms_setkey_float(outRec, "ERRJHT", swKeys_ptr->totaljz_err);
2254 drms_setkey_float(outRec, "ERRMPOT", swKeys_ptr->meanpot_err);
2255 drms_setkey_float(outRec, "ERRTPOT", swKeys_ptr->totpot_err);
2256 drms_setkey_float(outRec, "ERRMSHA", swKeys_ptr->meanshear_angle_err);
2257 drms_setkey_float(outRec, "R_VALUE", swKeys_ptr->Rparam);
2258 drms_setkey_float(outRec, "TOTFX", swKeys_ptr->totfx);
2259 drms_setkey_float(outRec, "TOTFY", swKeys_ptr->totfy);
2260 drms_setkey_float(outRec, "TOTFZ", swKeys_ptr->totfz);
2261 drms_setkey_float(outRec, "TOTBSQ", swKeys_ptr->totbsq);
2262 drms_setkey_float(outRec, "EPSX", swKeys_ptr->epsx);
2263 drms_setkey_float(outRec, "EPSY", swKeys_ptr->epsy);
2264 drms_setkey_float(outRec, "EPSZ", swKeys_ptr->epsz);
2265 };
2266
2267 /*
2268 * Set all keywords, no error checking for now
2269 *
2270 */
2271
2272 void setKeys(DRMS_Record_t *outRec, DRMS_Record_t *mharpRec, DRMS_Record_t *bharpRec, struct mapInfo *mInfo)
2273 {
2274
2275 copy_me_keys(bharpRec, outRec);
2276 copy_patch_keys(mharpRec, outRec); // Dec 30
2277 copy_geo_keys(mharpRec, outRec); // Dec 30
2278 copy_ambig_keys(bharpRec, outRec);
2279
2280 int status = 0;
2281
2282 // Change a few geometry keywords for CEA & cutout records
2283 if (mInfo != NULL) { // CEA
2284
2285 drms_setkey_float(outRec, "CRPIX1", mInfo->ncol/2. + 0.5);
2286 drms_setkey_float(outRec, "CRPIX2", mInfo->nrow/2. + 0.5);
2287
2288 drms_setkey_float(outRec, "CRVAL1", mInfo->xc);
2289 drms_setkey_float(outRec, "CRVAL2", mInfo->yc);
2290 drms_setkey_float(outRec, "CDELT1", mInfo->xscale);
2291 drms_setkey_float(outRec, "CDELT2", mInfo->yscale);
2292 drms_setkey_string(outRec, "CUNIT1", "degree");
2293 drms_setkey_string(outRec, "CUNIT2", "degree");
2294
2295 char key[64];
2296 snprintf (key, 64, "CRLN-%s", wcsCode[(int) mInfo->proj]);
2297 drms_setkey_string(outRec, "CTYPE1", key);
2298 snprintf (key, 64, "CRLT-%s", wcsCode[(int) mInfo->proj]);
2299 drms_setkey_string(outRec, "CTYPE2", key);
2300 drms_setkey_float(outRec, "CROTA2", 0.0);
2301
2302 // Jan 2 2014 XS
2303 int nSeg = ARRLENGTH(CEASegs);
2304 for (int iSeg = 0; iSeg < nSeg; iSeg++) {
2305 DRMS_Segment_t *outSeg = NULL;
2306 outSeg = drms_segment_lookup(outRec, CEASegs[iSeg]);
2307 if (!outSeg) continue;
2308 // Set Bunit
2309 char bunit_xxx[20];
2310 sprintf(bunit_xxx, "BUNIT_%03d", iSeg);
2311 //printf("%s, %s\n", bunit_xxx, CEABunits[iSeg]);
2312 drms_setkey_string(outRec, bunit_xxx, CEABunits[iSeg]);
2313 }
2314
2315 } else { // Cutout
2316
2317 float disk_xc, disk_yc;
2318 if (fullDisk) {
2319 disk_xc = drms_getkey_float(bharpRec, "CRPIX1", &status);
2320 disk_yc = drms_getkey_float(bharpRec, "CRPIX2", &status);
2321 } else {
2322 disk_xc = drms_getkey_float(mharpRec, "IMCRPIX1", &status);
2323 disk_yc = drms_getkey_float(mharpRec, "IMCRPIX2", &status);
2324 }
2325 float x_ll = drms_getkey_float(mharpRec, "CRPIX1", &status);
2326 float y_ll = drms_getkey_float(mharpRec, "CRPIX2", &status);
2327 // Defined as disk center's pixel address wrt lower-left of cutout
2328 drms_setkey_float(outRec, "CRPIX1", disk_xc - x_ll + 1.);
2329 drms_setkey_float(outRec, "CRPIX2", disk_yc - y_ll + 1.);
2330 // Always 0.
2331 drms_setkey_float(outRec, "CRVAL1", 0);
2332 drms_setkey_float(outRec, "CRVAL2", 0);
2333
2334 // Jan 2 2014 XS
2335 int nSeg = ARRLENGTH(CutSegs);
2336 for (int iSeg = 0; iSeg < nSeg; iSeg++) {
2337 DRMS_Segment_t *outSeg = NULL;
2338 outSeg = drms_segment_lookup(outRec, CutSegs[iSeg]);
2339 if (!outSeg) continue;
2340 // Set Bunit
2341 char bunit_xxx[20];
2342 sprintf(bunit_xxx, "BUNIT_%03d", iSeg);
2343 //printf("%s, %s\n", bunit_xxx, CutBunits[iSeg]);
2344 drms_setkey_string(outRec, bunit_xxx, CutBunits[iSeg]);
2345 }
2346
2347
2348 }
2349
2350 // Mar 19 XS
2351 if (fullDisk) {
2352 drms_setkey_int(outRec, "AMBPATCH", 0);
2353 drms_setkey_int(outRec, "AMBWEAK", 2);
2354 } else {
2355 drms_setkey_int(outRec, "AMBPATCH", 1);
2356 }
2357
2358 TIME val, trec, tnow, UNIX_epoch = -220924792.000; /* 1970.01.01_00:00:00_UTC */
2359 tnow = (double)time(NULL);
2360 tnow += UNIX_epoch;
2361
2362 val = drms_getkey_time(bharpRec, "DATE", &status);
2363 drms_setkey_time(outRec, "DATE_B", val);
2364 drms_setkey_time(outRec, "DATE", tnow);
2365
2366 // set cvs commit version into keyword HEADER
2367 char *cvsinfo = strdup("$Id: sharp.c,v 1.38 2015/03/18 00:28:26 xudong Exp $");
2368 char *cvsinfo2 = sw_functions_version();
2369 char cvsinfoall[2048];
2370 strcat(cvsinfoall,cvsinfo);
2371 strcat(cvsinfoall,"\n");
2372 strcat(cvsinfoall,cvsinfo2);
2373 status = drms_setkey_string(outRec, "CODEVER7", cvsinfoall);
2374
2375 };
2376
2377
2378 /* ############# Nearest neighbour interpolation ############### */
2379
2380 float nnb (float *f, int nx, int ny, double x, double y)
2381 {
2382
2383 if (x <= -0.5 || y <= -0.5 || x > nx - 0.5 || y > ny - 0.5)
2384 return DRMS_MISSING_FLOAT;
2385 int ilow = floor (x);
2386 int jlow = floor (y);
2387 int i = ((x - ilow) > 0.5) ? ilow + 1 : ilow;
2388 int j = ((y - jlow) > 0.5) ? jlow + 1 : jlow;
2389 return f[j * nx + i];
2390
2391 }
2392
2393
2394 /* ################## Wrapper for Jesper's rebin code ################## */
2395
2396 void frebin (float *image_in, float *image_out, int nx, int ny, int nbin, int gauss)
2397 {
2398
2399 struct fresize_struct fresizes;
2400 int nxout, nyout, xoff, yoff;
2401 int nlead = nx;
2402
2403 nxout = nx / nbin; nyout = ny / nbin;
2404 if (gauss && nbin != 1)
2405 init_fresize_gaussian(&fresizes, (nbin / 2), (nbin / 2 * 2), nbin); // for nbin=3, sigma=1, half truncate width=2
2406 else
2407 init_fresize_bin(&fresizes, nbin);
2408 xoff = nbin / 2 + nbin / 2;
2409 yoff = nbin / 2 + nbin / 2;
2410 fresize(&fresizes, image_in, image_out, nx, ny, nlead, nxout, nyout, nxout, xoff, yoff, DRMS_MISSING_FLOAT);
2411
2412 }