00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023
00024
00025
00026
00027
00028 #include "visir_recipe.h"
00029 #include "visir_utils.h"
00030 #include "irplib_framelist.h"
00031 #include <cxlist.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <strings.h>
00035 #include <sys/types.h>
00036 #include <sys/wait.h>
00037
00038 #include <unistd.h>
00039
00040 #include <fcntl.h>
00041 #include <semaphore.h>
00042
00043
00044
00045
00046
00047 #define RECIPE_STRING "visir_util_run_swarp"
00048 #define DEFAULT_CONFIG VISIR_CONFIG_PATH "/visir_default.swarp"
00049 #define SWARP_COADD_HEAD RECIPE_STRING "_coadd.head"
00050 #define SWARP_DATA_FILES RECIPE_STRING "_data_files"
00051
00052
00053
00054
00055
00056 #ifdef VISIR_CHAIN
00057 #define cpl_plugin_get_info visir_util_run_swarp_get_info
00058 #endif
00059 cpl_recipe_define(visir_util_run_swarp, VISIR_BINARY_VERSION,
00060 "Julian Taylor", PACKAGE_BUGREPORT, "2012",
00061 "Run swarp program to coadd images.",
00062 "WARNING: this recipe is intented to be run in a "
00063 "temporary directory, it does not clean up behind itself\n"
00064 "The files listed in the Set Of Frames (sof-file) "
00065 "must be tagged:\n"
00066 "VISIR-chopnod-corrected-file.fits "VISIR_UTIL_CORRECTED"\n"
00067 "VISIR-error-map.fits "VISIR_UTIL_ERROR_MAP
00068 "\nIt will produce the coaddition of each input frame "
00069 "separately and of all frames together.\n"
00070 "The single frame product(s) will have a FITS card\n"
00071 "'HIERARCH ESO PRO CATG' with a value of: COADDED_IMAGE and "
00072 "COADDED_WEIGHT\nThe total coaddition will have the tags "
00073 VISIR_IMG_COADDED_IMG" and "VISIR_IMG_COADDED_WGT);
00074
00075
00079
00080
00081
00082
00083
00084
00085 typedef enum {
00086 VISIR_AVG_COMB,
00087 VISIR_SUM_COMB
00088 } visir_comb_type;
00089
00090
00091
00099
00100 static cpl_error_code
00101 visir_util_run_swarp_fill_parameterlist(cpl_parameterlist * self)
00102 {
00103 const char * context = PACKAGE ".visir_util_run_swarp";
00104
00105 skip_if(irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00106 "output-all", CPL_FALSE, NULL,
00107 context, "Output a coadded image "
00108 "for each input file in addition "
00109 "to the complete coaddition."));
00110
00111 skip_if(irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00112 "extra_config", "NONE", NULL, context,
00113 "Additional configuration parameters"));
00114
00115 skip_if(irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00116 "config_fname", DEFAULT_CONFIG, NULL,
00117 context, "Swarp configure file name."));
00118
00119 skip_if(irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00120 "nprocs", -1, NULL, context,
00121 "Maximum number of swarp processes "
00122 "that can be spawned simultaneously."));
00123 end_skip;
00124
00125 return cpl_error_get_code();
00126 }
00127
00128
00129 static cpl_error_code
00130 check_swarp(void)
00131 {
00132 int ret = system(VISIR_SWARP_BIN " -v > /dev/null 2>/dev/null");
00133 if (WEXITSTATUS(ret) != 0) {
00134 cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
00135 "swarp not found in PATH");
00136 return CPL_ERROR_UNSUPPORTED_MODE;
00137 }
00138 return CPL_ERROR_NONE;
00139 }
00140
00141
00142 static cx_list *
00143 sort_framelist(const cpl_frameset * allframes, const char * tag)
00144 {
00145 cx_list * frames = cx_list_new();
00146
00147 FOR_EACH_FRAMESET_C(frm, allframes) {
00148 if (tag == NULL || strcmp(cpl_frame_get_tag(frm), tag) == 0)
00149 cx_list_push_back(frames, frm);
00150 }
00151
00152 cx_list_sort(frames, (cx_compare_func)visir_cmp_frm_fn);
00153
00154 return frames;
00155 }
00156
00157
00158 static cpl_error_code
00159 create_swarp_frames(cx_list * img_list, cx_list * err_list,
00160 const cpl_frameset * frameset)
00161 {
00162 cx_list * imgframes = sort_framelist(frameset, VISIR_UTIL_CORRECTED);
00163 cx_list * errframes = sort_framelist(frameset, VISIR_UTIL_ERROR_MAP);
00164 skip_if(0);
00165
00166 FOR_EACH_T(cpl_frame * frm, imgframes) {
00167 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
00168 cx_list_push_back(img_list, cpl_frame_duplicate(frm));
00169 }
00170
00171 FOR_EACH_T(cpl_frame * frm, errframes) {
00172 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
00173 cx_list_push_back(err_list, cpl_frame_duplicate(frm));
00174 }
00175
00176
00177 error_if(cx_list_size(err_list) != 0 &&
00178 cx_list_size(img_list) != cx_list_size(err_list),
00179 CPL_ERROR_UNSUPPORTED_MODE,
00180 "Number of error frames does not match image frames");
00181
00182 end_skip;
00183
00184 cx_list_delete(imgframes);
00185 cx_list_delete(errframes);
00186
00187 return cpl_error_get_code();
00188 }
00189
00190
00191
00206
00207 static pid_t
00208 run_swarp_resample(cpl_frame * imgfrm, cpl_frame * errfrm,
00209 const cpl_parameterlist * parlist,
00210 char * basedir,
00211 int ext_low, int ext_high,
00212 sem_t * sem_resamp)
00213 {
00214 cpl_msg_debug(cpl_func, "start swarp %s: %d %d", cpl_frame_get_filename(imgfrm), ext_low, ext_high);
00215 pid_t pid = fork();
00216 if (pid == 0) {
00217 char * cmd;
00218 char datafile[128];
00219 char errorfile[128];
00220 const char * config =
00221 irplib_parameterlist_get_string(parlist, PACKAGE,
00222 RECIPE_STRING, "config_fname");
00223 const char * extra =
00224 irplib_parameterlist_get_string(parlist, PACKAGE,
00225 RECIPE_STRING, "extra_config");
00226 if (strcasecmp(extra, "NONE") == 0)
00227 extra = "";
00228 pid_t cpid = getpid();
00229 sprintf(datafile, "swarp_data_%d.list", (int)cpid);
00230 sprintf(errorfile, "swarp_error_%d.list", (int)cpid);
00231
00232 FILE * data = fopen(datafile, "w");
00233 if (cpl_frame_get_filename(imgfrm)[0] != '/') {
00234 fprintf(data, "%s/%s[%d:%d]\n", basedir,
00235 cpl_frame_get_filename(imgfrm), ext_low, ext_high);
00236 }
00237 else {
00238 fprintf(data, "%s[%d:%d]\n", cpl_frame_get_filename(imgfrm),
00239 ext_low, ext_high);
00240 }
00241 fclose(data);
00242
00243 FILE * error = fopen(errorfile, "w");
00244 if (cpl_frame_get_filename(errfrm)[0] != '/') {
00245 fprintf(error, "%s/%s[%d:%d]\n", basedir,
00246 cpl_frame_get_filename(errfrm), ext_low, ext_high);
00247 }
00248 else {
00249 fprintf(error, "%s[%d:%d]\n", cpl_frame_get_filename(errfrm),
00250 ext_low, ext_high);
00251 }
00252 fclose(error);
00253
00254 cmd = cpl_sprintf(VISIR_SWARP_BIN " -c %s @%s -NTHREADS 1 "
00255 "-BLANK_BADPIXELS Y "
00256 "-WEIGHT_IMAGE @%s "
00257 "-WEIGHT_TYPE MAP_RMS %s "
00258 "-COMBINE N "
00259 "> \"%s/swarp-resamp_%d.log\" 2>&1",
00260 config, datafile, errorfile, extra, basedir, (int)cpid);
00261 cpl_msg_debug(cpl_func, "RESAMPLE: %s", cmd);
00262 int status = system(cmd);
00263 cpl_free(cmd);
00264
00265
00266 sem_post(sem_resamp);
00267
00268 sem_close(sem_resamp);
00269 _exit(WEXITSTATUS(status));
00270 }
00271 else {
00272 return pid;
00273 }
00274 }
00275
00276
00291
00292 static pid_t
00293 run_swarp_coadd(cpl_frame * imgfrm, cpl_frame * errfrm,
00294 const cpl_parameterlist * parlist,
00295 sem_t * sem_coadd, sem_t * sem_resamp)
00296 {
00297 pid_t pid = fork();
00298 if (pid == 0) {
00299
00300
00301 cpl_size next = cpl_frame_get_nextensions(imgfrm);
00302 cpl_size bs = 300;
00303 pid_t lpids[next / bs + ((next % bs) != 0)];
00304 int l = 0;
00305 char tmpdir[] = RECIPE_STRING"_XXXXXX";
00306 char * basedir = visir_get_cwd();
00307 if (basedir == NULL ||
00308 visir_get_tempdir(tmpdir) != CPL_TRUE || chdir(tmpdir) != 0) {
00309 cpl_msg_error(cpl_func, "Creating temporary directory failed");
00310
00311 sem_post(sem_coadd);
00312
00313 sem_close(sem_coadd);
00314 sem_close(sem_resamp);
00315 cpl_free(basedir);
00316 _exit(EXIT_FAILURE);
00317 }
00318
00319
00320
00321 char * cmd = cpl_sprintf("cp \"%s/"SWARP_COADD_HEAD"\" coadd.head", basedir);
00322 int status = system(cmd);
00323 cpl_free(cmd);
00324 if (WEXITSTATUS(status) != 0) {
00325 cpl_msg_error(cpl_func, "copy of coaddition header failed");
00326
00327 sem_post(sem_coadd);
00328
00329 sem_close(sem_coadd);
00330 sem_close(sem_resamp);
00331 cpl_free(basedir);
00332 _exit(EXIT_FAILURE);
00333 }
00334
00335 for (cpl_size b = 1; b < next + 1; b += bs) {
00336
00337 sem_wait(sem_resamp);
00338 pid_t resamp_pid = run_swarp_resample(imgfrm, errfrm, parlist,
00339 basedir, b,
00340 CX_MIN(b + bs, next + 1),
00341 sem_resamp);
00342 lpids[l++] = resamp_pid;
00343 }
00344
00345
00346 sem_post(sem_coadd);
00347
00348 sem_close(sem_coadd);
00349 sem_close(sem_resamp);
00350
00351 for (int k = 0; k < l; k++) {
00352 pid_t r = waitpid(lpids[k], &status, 0);
00353 if (r == -1 || !WIFEXITED(status) || WEXITSTATUS(status))
00354 _exit(WEXITSTATUS(status));
00355 cpl_msg_debug(cpl_func, "resamp %s %d done",
00356 cpl_frame_get_filename(imgfrm), k);
00357 }
00358
00359 const char * config =
00360 irplib_parameterlist_get_string(parlist, PACKAGE,
00361 RECIPE_STRING, "config_fname");
00362 const char * extra =
00363 irplib_parameterlist_get_string(parlist, PACKAGE,
00364 RECIPE_STRING, "extra_config");
00365 if (strcasecmp(extra, "NONE") == 0)
00366 extra = "";
00367 pid_t cpid = getpid();
00368 char * coadd_img = cpl_sprintf("%s/tmp_coadd_%d.fits",
00369 basedir, (int)cpid);
00370 char * coadd_weight = cpl_sprintf("%s/tmp_coadd_wgt_%d.fits",
00371 basedir, (int)cpid);
00372
00373
00374
00375 cmd = cpl_sprintf("cp \"%s/"SWARP_COADD_HEAD"\" \"%s/tmp_coadd_%d.head\"",
00376 basedir, basedir, (int)cpid);
00377 status = system(cmd);
00378 cpl_free(cmd);
00379 if (WEXITSTATUS(status) != 0) {
00380 cpl_msg_error(cpl_func, "copy of coaddition header failed");
00381 cpl_free(coadd_img);
00382 cpl_free(coadd_weight);
00383 cpl_free(basedir);
00384 _exit(WEXITSTATUS(status));
00385 }
00386
00387 cmd = cpl_sprintf(VISIR_SWARP_BIN" -c %s $(ls *resamp.fits) "
00388 "-NTHREADS 1 -BLANK_BADPIXELS Y "
00389 "-WEIGHT_TYPE MAP_WEIGHT %s "
00390 "-IMAGEOUT_NAME %s "
00391 "-WEIGHTOUT_NAME %s "
00392 "-RESAMPLE N -COMBINE Y "
00393 "> %s/swarp-coadd-%d.log 2>&1",
00394 config, extra,
00395 coadd_img, coadd_weight, basedir, (int)cpid);
00396 cpl_msg_debug(cpl_func, "COADD: %s", cmd);
00397 status = system(cmd);
00398 cpl_free(cmd);
00399 if (chdir(basedir) == 0) {
00400 cmd = cpl_sprintf("rm -rf \"%s\"", tmpdir);
00401 status = system(cmd);
00402 cpl_free(cmd);
00403 }
00404 cpl_free(coadd_img);
00405 cpl_free(coadd_weight);
00406
00407 _exit(WEXITSTATUS(status));
00408 }
00409 else {
00410 return pid;
00411 }
00412 }
00413
00414
00415 static cpl_error_code
00416 generate_coaddition_header(const cx_list * imglist, const char * config, const char * extra)
00417 {
00418
00419
00420 FILE * data = fopen(SWARP_DATA_FILES, "w");
00421 char * cmd = cpl_sprintf(VISIR_SWARP_BIN " -c %s @"SWARP_DATA_FILES
00422 " -IMAGEOUT_NAME "SWARP_COADD_HEAD
00423 " -HEADER_ONLY Y %s > /dev/null 2>/dev/null",
00424 config, extra);
00425 int status;
00426
00427 FOR_EACH_T(cpl_frame * frm, imglist) {
00428 int ret;
00429 cpl_propertylist * plist =
00430 cpl_propertylist_load(cpl_frame_get_filename(frm), 0);
00431 cpl_errorstate cleanstate = cpl_errorstate_get();
00432 cpl_boolean invalid =
00433 (cpl_propertylist_get_double(plist, "CD1_1") == 0. &&
00434 cpl_propertylist_get_double(plist, "CD1_2") == 0.) ||
00435 (cpl_propertylist_get_double(plist, "CD2_1") == 0. &&
00436 cpl_propertylist_get_double(plist, "CD2_2") == 0.);
00437 invalid = invalid || (cpl_error_get_code() != CPL_ERROR_NONE);
00438 cpl_errorstate_set(cleanstate);
00439 cpl_propertylist_delete(plist);
00440 error_if (invalid, CPL_ERROR_ILLEGAL_INPUT,
00441 "CDX_Y WCS key missing or zero");
00442
00443 cpl_msg_info(cpl_func, "%s", cpl_frame_get_filename(frm));
00444 ret = fprintf(data, "%s\n", cpl_frame_get_filename(frm));
00445 error_if(ret < 0, CPL_ERROR_FILE_IO, "Failed writting swarp file list");
00446 }
00447 fclose(data);
00448
00449 cpl_msg_info(cpl_func, "Generating coaddition header");
00450 status = system(cmd);
00451
00452 error_if(WEXITSTATUS(status) != 0, CPL_ERROR_FILE_IO, "Swarp failed");
00453
00454 end_skip;
00455 cpl_free(cmd);
00456
00457 return cpl_error_get_code();
00458 }
00459
00460
00461 static cpl_error_code
00462 coadd_images(pid_t * pids, unsigned long * beamids, float * imgwgts,
00463 cpl_frameset * usedframes,
00464 const cx_list * imglist, const cx_list * errlist,
00465 const int nprocs, const cpl_parameterlist * parlist)
00466 {
00467 const int nfiles = cx_list_size(imglist);
00468 int i = 0;
00469
00470
00471
00472
00473
00474
00475
00476
00477 char * sem_resamp_name = cpl_sprintf("/visir_swarp_resamp_%d_%d",
00478 getuid(), getpid());
00479 char * sem_coadd_name = cpl_sprintf("/visir_swarp_coadd_%d_%d",
00480 getuid(), getpid());
00481 sem_t * sem_resamp = sem_open(sem_resamp_name , O_CREAT, 0644, nprocs);
00482 sem_t * sem_coadd = sem_open(sem_coadd_name , O_CREAT, 0644, 1);
00483 sem_unlink(sem_coadd_name);
00484 sem_unlink(sem_resamp_name);
00485
00486 for(cx_list_iterator iit = cx_list_begin(imglist),
00487 eit = cx_list_begin(errlist);
00488 iit != cx_list_end(imglist);
00489 iit = cx_list_next(imglist, iit),
00490 eit = cx_list_next(errlist, eit)) {
00491 const char * beamid;
00492 cpl_frame * ifrm = cx_list_get(imglist, iit);
00493 cpl_frame * efrm = cx_list_get(errlist, eit);
00494 cpl_propertylist * plist =
00495 cpl_propertylist_load(cpl_frame_get_filename(ifrm), 0);
00496 skip_if(0);
00497
00498 beamid = cpl_propertylist_get_string(plist, "ESO QC BEAMID");
00499 beamids[i] = strtoul(beamid, NULL, 10);
00500 imgwgts[i] = visir_pfits_get_img_weight(plist);
00501 cpl_propertylist_delete(plist);
00502
00503 skip_if(0);
00504
00505 cpl_frameset_insert(usedframes, cpl_frame_duplicate(ifrm));
00506 cpl_frameset_insert(usedframes, cpl_frame_duplicate(efrm));
00507
00508
00509
00510 sem_wait(sem_coadd);
00511 pids[i++] = run_swarp_coadd(ifrm, efrm, parlist,
00512 sem_coadd, sem_resamp);
00513 cpl_msg_info(cpl_func, "Coadding file (%d/%d)", i, nfiles);
00514 }
00515 for (int j = 0; j < i; j++) {
00516 int status;
00517 pid_t r = waitpid(-1, &status, 0);
00518 error_if(r == -1 || !WIFEXITED(status) || WEXITSTATUS(status),
00519 CPL_ERROR_FILE_IO, "Coaddition failed: %d, %s",
00520 WEXITSTATUS(status), r == -1 ? strerror(errno) : "");
00521 }
00522
00523 end_skip;
00524 sem_close(sem_coadd);
00525 sem_close(sem_resamp);
00526 cpl_free(sem_resamp_name);
00527 cpl_free(sem_coadd_name);
00528
00529 return cpl_error_get_code();
00530 }
00531
00532
00533 static cpl_error_code
00534 save_single_images(cpl_frameset * framelist, const cpl_size nfiles,
00535 const pid_t * pids, const cpl_frameset * usedframes,
00536 const cpl_parameterlist * parlist)
00537 {
00538 cpl_image * img = NULL;
00539 cpl_image * wgt = NULL;
00540 cpl_propertylist * plist = NULL;
00541
00542 for (cpl_size j = 0; j < nfiles; j++) {
00543 char coadd_img[200];
00544 char coadd_wgt[200];
00545
00546 sprintf(coadd_img, "tmp_coadd_%d.fits", (int)pids[j]);
00547 sprintf(coadd_wgt, "tmp_coadd_wgt_%d.fits", (int)pids[j]);
00548
00549 cpl_image_delete(img);
00550 cpl_image_delete(wgt);
00551 img = cpl_image_load(coadd_img, CPL_TYPE_UNSPECIFIED, 0, 0);
00552 wgt = cpl_image_load(coadd_wgt, CPL_TYPE_UNSPECIFIED, 0, 0);
00553 skip_if(0);
00554
00555 cpl_propertylist_delete(plist);
00556 plist = cpl_propertylist_load(coadd_img, 0);
00557 skip_if(0);
00558
00559 sprintf(coadd_img, "swarp_coadd_img_%03d.fits", (int)j);
00560 sprintf(coadd_wgt, "swarp_coadd_wgt_%03d.fits", (int)j);
00561
00562 skip_if(irplib_dfs_save_image(framelist, parlist, usedframes,
00563 img, CPL_BPP_IEEE_FLOAT,
00564 RECIPE_STRING, "COADDED_IMAGE",
00565 plist, NULL, visir_pipe_id,
00566 coadd_img));
00567 skip_if(irplib_dfs_save_image(framelist, parlist, usedframes,
00568 wgt, CPL_BPP_IEEE_FLOAT,
00569 RECIPE_STRING, "COADDED_WEIGHT",
00570 plist, NULL, visir_pipe_id,
00571 coadd_wgt));
00572 }
00573
00574 end_skip;
00575 cpl_image_delete(img);
00576 cpl_image_delete(wgt);
00577 cpl_propertylist_delete(plist);
00578
00579 return cpl_error_get_code();
00580 }
00581
00582
00583 static cpl_propertylist *
00584 generate_beam_averages(cpl_image ** av, cpl_image ** wav, float * imgwgts,
00585 const cpl_size nfiles,
00586 const pid_t * pids, const unsigned long * beamids)
00587 {
00588
00589 cpl_image * img = NULL;
00590 cpl_image * wgt = NULL;
00591 cpl_propertylist * plist = NULL;
00592 unsigned long max_beamid = 0;
00593 float tmpwgts[nfiles];
00594
00595 cpl_ensure(nfiles > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
00596
00597 for (cpl_size j = 0; j < nfiles; j++) {
00598 const unsigned long idx = beamids[j];
00599 char coadd_img[200];
00600 char coadd_wgt[200];
00601
00602 cpl_image_delete(img);
00603 cpl_image_delete(wgt);
00604 sprintf(coadd_img, "tmp_coadd_%d.fits", (int)pids[j]);
00605 sprintf(coadd_wgt, "tmp_coadd_wgt_%d.fits", (int)pids[j]);
00606 img = cpl_image_load(coadd_img, CPL_TYPE_UNSPECIFIED, 0, 0);
00607 wgt = cpl_image_load(coadd_wgt, CPL_TYPE_UNSPECIFIED, 0, 0);
00608
00609 skip_if(0);
00610
00611 if (plist == NULL)
00612 plist = cpl_propertylist_load(coadd_img, 0);
00613
00614
00615
00616
00617
00618 if (strcmp(cpl_propertylist_get_string(plist, "CTYPE1"),
00619 "PIXEL") == 0) {
00620 cpl_propertylist_set_string(plist, "CTYPE1", "RA---TAN");
00621 cpl_propertylist_set_string(plist, "CTYPE2", "DEC--TAN");
00622 cpl_propertylist_set_string(plist, "CUNIT1", "deg");
00623 cpl_propertylist_set_string(plist, "CUNIT2", "deg");
00624 }
00625
00626 skip_if(0);
00627
00628 cpl_image_multiply(img, wgt);
00629 if (av[idx] == NULL) {
00630 av[idx] = cpl_image_duplicate(img);
00631 wav[idx] = cpl_image_duplicate(wgt);
00632 }
00633 else {
00634 skip_if(cpl_image_add(av[idx], img));
00635 skip_if(cpl_image_add(wav[idx], wgt));
00636 }
00637 max_beamid = CX_MAX(max_beamid, idx);
00638
00639 tmpwgts[idx] = imgwgts[j];
00640 }
00641
00642 for (unsigned long i = 0; i < max_beamid + 1; i++) {
00643 cpl_image_divide(av[i], wav[i]);
00644 imgwgts[i] = tmpwgts[i];
00645 }
00646
00647 end_skip;
00648
00649 cpl_image_delete(img);
00650 cpl_image_delete(wgt);
00651
00652 return plist;
00653 }
00654
00655
00656
00670
00671 static cpl_error_code
00672 generate_combined_image(cpl_image ** avg, cpl_image ** wgt,
00673 const float * imgwgts, const unsigned long n,
00674 cpl_image ** oimg, cpl_image ** owgt,
00675 cpl_image ** octr, visir_comb_type ctype)
00676 {
00677
00678 cpl_image * cimg = cpl_image_new(cpl_image_get_size_x(avg[0]),
00679 cpl_image_get_size_y(avg[0]),
00680 CPL_TYPE_FLOAT);
00681 cpl_image * cwgt = cpl_image_new(cpl_image_get_size_x(wgt[0]),
00682 cpl_image_get_size_y(wgt[0]),
00683 CPL_TYPE_FLOAT);
00684 cpl_image * contrib = cpl_image_new(cpl_image_get_size_x(wgt[0]),
00685 cpl_image_get_size_y(wgt[0]),
00686 CPL_TYPE_INT);
00687 int wgtsum = 0;
00688
00689 skip_if(0);
00690
00691
00692 for (unsigned long i = 0; i < n; i++) {
00693 cpl_mask * m = cpl_mask_threshold_image_create(wgt[i], -1, FLT_EPSILON);
00694 cpl_image * bad = cpl_image_new_from_mask(m);
00695 cpl_image_reject_from_mask(avg[i], m);
00696
00697
00698
00699 cpl_image_subtract_scalar(avg[i], cpl_image_get_median(avg[i]));
00700 cpl_image_fill_rejected(avg[i], 0);
00701 cpl_mask_delete(m);
00702
00703
00704 cpl_image_power(wgt[i], -1);
00705 cpl_image_accept_all(wgt[i]);
00706
00707 cpl_image_multiply_scalar(bad, imgwgts[i]);
00708 cpl_image_subtract(contrib, bad);
00709 cpl_image_delete(bad);
00710
00711 skip_if(0);
00712
00713 cpl_image_add(cimg, avg[i]);
00714 cpl_image_add(cwgt, wgt[i]);
00715
00716 wgtsum += imgwgts[i];
00717 }
00718
00719 cpl_image_add_scalar(contrib, wgtsum);
00720 if (ctype == VISIR_AVG_COMB) {
00721 cpl_image_divide(cimg, contrib);
00722
00723 cpl_image_divide(cwgt, contrib);
00724 cpl_image_divide(cwgt, contrib);
00725 }
00726 cpl_image_power(cwgt, -1);
00727
00728 *oimg = cimg;
00729 *owgt = cwgt;
00730 *octr = contrib;
00731
00732 end_skip;
00733
00734 return cpl_error_get_code();
00735 }
00736
00737
00738
00750
00751 static cpl_error_code
00752 cut_bad_edges(cpl_image ** img, cpl_image ** wgt, cpl_image ** ctr,
00753 cpl_propertylist * plist)
00754 {
00755 const cpl_size nx = cpl_image_get_size_x(*ctr);
00756 const cpl_size ny = cpl_image_get_size_y(*ctr);
00757 const cpl_size max_contrib = cpl_image_get_max(*ctr);
00758 const double ctr_cutoff = max_contrib == 2 ? 0.4 : 0.7;
00759 cpl_size cutly = 0;
00760 cpl_size cutuy = 0;
00761 cpl_size cutlx = 0;
00762 cpl_size cutux = 0;
00763 for (cpl_size i = 0; i < ny / 2; i++) {
00764 cpl_vector * row = cpl_vector_new_from_image_row(*ctr, i + 1);
00765 double sum = cpl_vector_get_sum(row);
00766 cpl_vector_delete(row);
00767 if (sum >= max_contrib * nx * ctr_cutoff) {
00768 break;
00769 }
00770 cutly = i + 1;
00771 }
00772 for (cpl_size i = ny - 1; i >= ny / 2; i--) {
00773 cpl_vector * row = cpl_vector_new_from_image_row(*ctr, i + 1);
00774 double sum = cpl_vector_get_sum(row);
00775 cpl_vector_delete(row);
00776 if (sum >= max_contrib * nx * ctr_cutoff) {
00777 break;
00778 }
00779 cutuy = i + 1;
00780 }
00781 for (cpl_size i = 0; i < nx / 2; i++) {
00782 cpl_vector * col = cpl_vector_new_from_image_column(*ctr, i + 1);
00783 double sum = cpl_vector_get_sum(col);
00784 cpl_vector_delete(col);
00785 if (sum >= max_contrib * ny * ctr_cutoff) {
00786 break;
00787 }
00788 cutlx = i + 1;
00789 }
00790 for (cpl_size i = nx - 1; i >= nx / 2; i--) {
00791 cpl_vector * col = cpl_vector_new_from_image_column(*ctr, i + 1);
00792 double sum = cpl_vector_get_sum(col);
00793 cpl_vector_delete(col);
00794 if (sum >= max_contrib * ny * ctr_cutoff) {
00795 break;
00796 }
00797 cutux = i + 1;
00798 }
00799 cutlx += 1;
00800 cutly += 1;
00801 cutux -= 1;
00802 cutuy -= 1;
00803 cpl_msg_info(cpl_func, "Cutting low contribution edges "
00804 "llx: %lld, lly: %lld, urx: %lld, ury: %lld",
00805 cutlx, cutly, cutux, cutuy);
00806
00807
00808 cpl_image * nimg, * nwgt, * nctr;
00809 if (cutlx < cutux && cutly < cutuy) {
00810 cpl_propertylist_set_double(plist, "CRPIX1",
00811 cpl_propertylist_get_double(plist, "CRPIX1") - cutlx);
00812 cpl_propertylist_set_double(plist, "CRPIX2",
00813 cpl_propertylist_get_double(plist, "CRPIX2") - cutly);
00814 nimg = cpl_image_extract(*img, cutlx, cutly, cutux, cutuy);
00815 nwgt = cpl_image_extract(*wgt, cutlx, cutly, cutux, cutuy);
00816 nctr = cpl_image_extract(*ctr, cutlx, cutly, cutux, cutuy);
00817 }
00818 else {
00819 nimg = cpl_image_duplicate(*img);
00820 nwgt = cpl_image_duplicate(*wgt);
00821 nctr = cpl_image_duplicate(*ctr);
00822 }
00823 cpl_image_delete(*img);
00824 cpl_image_delete(*wgt);
00825 cpl_image_delete(*ctr);
00826 *img = nimg;
00827 *wgt = nwgt;
00828 *ctr = nctr;
00829
00830 return cpl_error_get_code();
00831 }
00832
00833
00834 static cpl_error_code
00835 check_inputs(const cpl_frameset * framelist, const char * config)
00836 {
00837 irplib_framelist * alldata = irplib_framelist_cast(framelist);
00838 irplib_framelist * data = irplib_framelist_extract(alldata,
00839 VISIR_UTIL_CORRECTED);
00840 irplib_framelist * errors = irplib_framelist_extract(alldata, "ERROR_MAP");
00841 irplib_framelist_load_propertylist_all(data, 0, "ESO QC", CPL_FALSE);
00842 error_if(irplib_framelist_get_size(data) !=
00843 irplib_framelist_get_size(errors), CPL_ERROR_ILLEGAL_INPUT,
00844 "Unequal number of data and error frames");
00845 skip_if(irplib_framelist_contains(data, "ESO QC BEAMID", CPL_TYPE_STRING,
00846 CPL_FALSE, 0.0));
00847
00848 error_if(access(config, R_OK) != 0, CPL_ERROR_FILE_NOT_FOUND,
00849 "Swarp configuration not found: %s", config);
00850 end_skip;
00851
00852 irplib_framelist_delete(alldata);
00853 irplib_framelist_delete(data);
00854 irplib_framelist_delete(errors);
00855 return cpl_error_get_code();
00856 }
00857
00858
00859
00866
00867 static int visir_util_run_swarp(cpl_frameset * framelist,
00868 const cpl_parameterlist * parlist)
00869 {
00870 cpl_frameset * usedframes = cpl_frameset_new();
00871 cpl_propertylist * plist = NULL;
00872 cx_list * imglist = cx_list_new();
00873 cx_list * errlist = cx_list_new();
00874
00875 skip_if(check_swarp());
00876
00877 cpl_fits_set_mode(CPL_FITS_STOP_CACHING);
00878
00879 const cpl_boolean output_all =
00880 irplib_parameterlist_get_bool(parlist, PACKAGE,
00881 RECIPE_STRING, "output-all");
00882 const char * config =
00883 irplib_parameterlist_get_string(parlist, PACKAGE,
00884 RECIPE_STRING, "config_fname");
00885 const char * extra =
00886 irplib_parameterlist_get_string(parlist, PACKAGE,
00887 RECIPE_STRING, "extra_config");
00888 int nmax_procs =
00889 irplib_parameterlist_get_int(parlist, PACKAGE,
00890 RECIPE_STRING, "nprocs");
00891 if (visir_str_par_is_empty(extra))
00892 extra = "";
00893
00894 if (nmax_procs <= 0) {
00895 nmax_procs = visir_get_num_threads(CPL_TRUE);
00896 }
00897
00898 error_if(visir_str_par_is_empty(config), CPL_ERROR_FILE_NOT_FOUND,
00899 "A swarp configuration file is required. "
00900 "You can create a default configuration with: swarp -d");
00901
00902 skip_if(check_inputs(framelist, config));
00903
00904 unlink(SWARP_DATA_FILES);
00905 unlink(SWARP_COADD_HEAD);
00906
00907 skip_if(0);
00908
00909 create_swarp_frames(imglist, errlist, framelist);
00910 error_if(cx_list_size(imglist) == 0 || cx_list_size(errlist) == 0,
00911 CPL_ERROR_ILLEGAL_INPUT, "No frames tagged "
00912 VISIR_UTIL_CORRECTED" and "VISIR_UTIL_ERROR_MAP" found");
00913
00914 skip_if(generate_coaddition_header(imglist, config, extra));
00915
00916 {
00917 const cpl_size nfiles = cx_list_size(imglist);
00918 pid_t pids[nfiles];
00919 unsigned long beamids[nfiles];
00920 float imgwgts[nfiles];
00921 unsigned long nmax_beamid = 0;
00922 cpl_image * av[nfiles];
00923 cpl_image * wav[nfiles];
00924 cpl_image * cimg = NULL;
00925 cpl_image * cwgt = NULL;
00926 cpl_image * cctr = NULL;
00927
00928 for (cpl_size j = 0; j < nfiles; j++)
00929 av[j] = wav[j] = NULL;
00930
00931 skip_if(coadd_images(pids, beamids, imgwgts, usedframes,
00932 imglist, errlist, nmax_procs, parlist));
00933
00934 for (cpl_size i = 0; i < nfiles; i++)
00935 nmax_beamid = CX_MAX(nmax_beamid, beamids[i] + 1);
00936
00937 error_if((cpl_size)nmax_beamid - 1 > nfiles,
00938 CPL_ERROR_UNSUPPORTED_MODE,
00939 "Only consecutive BEAMID's supported");
00940
00941 if (output_all && nfiles > 1)
00942 save_single_images(framelist, nfiles, pids, usedframes, parlist);
00943
00944 skip_if(0);
00945
00946 plist = generate_beam_averages(av, wav, imgwgts, nfiles, pids, beamids);
00947 skip_if(plist == NULL);
00948
00949 generate_combined_image(av, wav, imgwgts, nmax_beamid, &cimg, &cwgt,
00950 &cctr, VISIR_AVG_COMB);
00951 for (cpl_size i = 0; i < nfiles; i++) {
00952 cpl_image_delete(av[i]);
00953 cpl_image_delete(wav[i]);
00954 }
00955
00956 cut_bad_edges(&cimg, &cwgt, &cctr, plist);
00957
00958 irplib_dfs_save_image(framelist, parlist, usedframes, cimg,
00959 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00960 VISIR_IMG_COADDED_IMG, plist, NULL,
00961 visir_pipe_id, "swarp_coadd_img_all.fits");
00962 irplib_dfs_save_image(framelist, parlist, usedframes, cwgt,
00963 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00964 VISIR_IMG_COADDED_WGT, plist, NULL,
00965 visir_pipe_id, "swarp_coadd_wgt_all.fits");
00966 irplib_dfs_save_image(framelist, parlist, usedframes, cctr,
00967 CPL_TYPE_INT, RECIPE_STRING,
00968 VISIR_IMG_COADDED_CTR, plist, NULL,
00969 visir_pipe_id, "swarp_coadd_ctr_all.fits");
00970 cpl_image_delete(cimg);
00971 cpl_image_delete(cwgt);
00972 cpl_image_delete(cctr);
00973 skip_if(0);
00974 }
00975
00976 end_skip;
00977
00978 unlink(SWARP_DATA_FILES);
00979 unlink(SWARP_COADD_HEAD);
00980 cx_list_destroy(imglist, (cx_free_func)cpl_frame_delete);
00981 cx_list_destroy(errlist, (cx_free_func)cpl_frame_delete);
00982 cpl_frameset_delete(usedframes);
00983 cpl_propertylist_delete(plist);
00984 return cpl_error_get_code();
00985 }