28 #include "visir_recipe.h"
29 #include "visir_utils.h"
30 #include "irplib_framelist.h"
35 #include <sys/types.h>
44 #define RECIPE_STRING "visir_util_run_swarp"
45 #define DEFAULT_CONFIG VISIR_CONFIG_PATH "/visir_default.swarp"
46 #define SWARP_COADD_HEAD RECIPE_STRING "_coadd.head"
47 #define SWARP_DATA_FILES RECIPE_STRING "_data_files"
54 #define cpl_plugin_get_info visir_util_run_swarp_get_info
56 cpl_recipe_define(visir_util_run_swarp, VISIR_BINARY_VERSION,
57 "Julian Taylor", PACKAGE_BUGREPORT,
"2012",
58 "Run swarp program to coadd images.",
59 "WARNING: this recipe is intented to be run in a "
60 "temporary directory, it does not clean up behind itself\n"
61 "The files listed in the Set Of Frames (sof-file) "
63 "VISIR-chopnod-corrected-file.fits "VISIR_UTIL_CORRECTED
"\n"
64 "VISIR-error-map.fits "VISIR_UTIL_ERROR_MAP
65 "\nIt will produce the coaddition of each input frame "
66 "separately and of all frames together.\n"
67 "The single frame product(s) will have a FITS card\n"
68 "'HIERARCH ESO PRO CATG' with a value of: COADDED_IMAGE and "
69 "COADDED_WEIGHT\nThe total coaddition will have the tags "
70 "COADDED_IMAGE_COMBINED and COADDED_WEIGHT_COMBINED");
98 visir_util_run_swarp_fill_parameterlist(cpl_parameterlist *
self)
100 const char * context = PACKAGE
".visir_util_run_swarp";
102 skip_if(irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
103 "output-all", CPL_FALSE, NULL,
104 context,
"Output a coadded image "
105 "for each input file in addition "
106 "to the complete coaddition."));
108 skip_if(irplib_parameterlist_set_string(
self, PACKAGE, RECIPE_STRING,
109 "extra_config",
"NONE", NULL, context,
110 "Additional configuration parameters"));
112 skip_if(irplib_parameterlist_set_string(
self, PACKAGE, RECIPE_STRING,
113 "config_fname", DEFAULT_CONFIG, NULL,
114 context,
"Swarp configure file name."));
116 skip_if(irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
117 "nprocs", -1, NULL, context,
118 "Maximum number of swarp processes "
119 "that can be spawned simultaneously."));
122 return cpl_error_get_code();
126 static cpl_error_code
129 int ret = system(VISIR_SWARP_BIN
" -v > /dev/null 2>/dev/null");
130 if (WEXITSTATUS(ret) != 0) {
131 cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
132 "swarp not found in PATH");
133 return CPL_ERROR_UNSUPPORTED_MODE;
135 return CPL_ERROR_NONE;
140 sort_framelist(
const cpl_frameset * allframes,
const char * tag)
142 cx_list * frames = cx_list_new();
144 FOR_EACH_FRAMESET_C(frm, allframes) {
145 if (tag == NULL || strcmp(cpl_frame_get_tag(frm), tag) == 0)
146 cx_list_push_back(frames, frm);
149 cx_list_sort(frames, (cx_compare_func)visir_cmp_frm_fn);
155 static cpl_error_code
156 create_swarp_frames(cx_list * img_list, cx_list * err_list,
157 const cpl_frameset * frameset)
159 cx_list * imgframes = sort_framelist(frameset, VISIR_UTIL_CORRECTED);
160 cx_list * errframes = sort_framelist(frameset, VISIR_UTIL_ERROR_MAP);
163 FOR_EACH_T(cpl_frame * frm, imgframes) {
164 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
165 cx_list_push_back(img_list, cpl_frame_duplicate(frm));
168 FOR_EACH_T(cpl_frame * frm, errframes) {
169 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
170 cx_list_push_back(err_list, cpl_frame_duplicate(frm));
174 error_if(cx_list_size(err_list) != 0 &&
175 cx_list_size(img_list) != cx_list_size(err_list),
176 CPL_ERROR_UNSUPPORTED_MODE,
177 "Number of error frames does not match image frames");
181 cx_list_delete(imgframes);
182 cx_list_delete(errframes);
184 return cpl_error_get_code();
205 run_swarp(cpl_frame * imgfrm, cpl_frame * errfrm,
206 const cpl_parameterlist * parlist)
213 char coadd_weight[128];
214 const char * config =
215 irplib_parameterlist_get_string(parlist, PACKAGE,
216 RECIPE_STRING,
"config_fname");
218 irplib_parameterlist_get_string(parlist, PACKAGE,
219 RECIPE_STRING,
"extra_config");
220 if (strcasecmp(extra,
"NONE") == 0)
222 pid_t cpid = getpid();
223 sprintf(datafile,
"swarp_data_%d.list", (
int)cpid);
224 sprintf(errorfile,
"swarp_error_%d.list", (
int)cpid);
225 sprintf(coadd_img,
"tmp_coadd_%d.fits", (
int)cpid);
226 sprintf(coadd_weight,
"tmp_coadd_wgt_%d.fits", (
int)cpid);
228 FILE * data = fopen(datafile,
"w");
229 fprintf(data,
"%s\n", cpl_frame_get_filename(imgfrm));
232 FILE * error = fopen(errorfile,
"w");
233 fprintf(error,
"%s\n", cpl_frame_get_filename(errfrm));
238 char * cmd = cpl_sprintf(
"cp "SWARP_COADD_HEAD
" tmp_coadd_%d.head",
240 int status = system(cmd);
242 if (WEXITSTATUS(status) != 0) {
243 cpl_msg_info(cpl_func,
"copy of coaddition header failed");
244 _exit(WEXITSTATUS(status));
247 cmd = cpl_sprintf(VISIR_SWARP_BIN
" -c %s @%s -NTHREADS 1 "
248 "-BLANK_BADPIXELS Y "
250 "-WEIGHT_TYPE MAP_RMS %s "
252 "-WEIGHTOUT_NAME %s "
253 "> /dev/null 2>/dev/null",
254 config, datafile, errorfile, extra,
255 coadd_img, coadd_weight);
256 cpl_msg_debug(cpl_func,
"%s", cmd);
257 status = system(cmd);
259 cmd = cpl_sprintf(
"tmp_coadd_%d.head", (
int)cpid);
263 _exit(WEXITSTATUS(status));
271 static cpl_error_code
272 generate_coaddition_header(
const cx_list * imglist,
const char * config,
const char * extra)
276 FILE * data = fopen(SWARP_DATA_FILES,
"w");
277 char * cmd = cpl_sprintf(VISIR_SWARP_BIN
" -c %s @"SWARP_DATA_FILES
278 " -IMAGEOUT_NAME "SWARP_COADD_HEAD
279 " -HEADER_ONLY Y %s > /dev/null 2>/dev/null",
283 FOR_EACH_T(cpl_frame * frm, imglist) {
285 cpl_propertylist * plist =
286 cpl_propertylist_load(cpl_frame_get_filename(frm), 0);
287 int cd11ok = plist && cpl_propertylist_has(plist,
"CD1_1") &&
288 cpl_propertylist_get_double(plist,
"CD1_1") != 0.;
289 int cd22ok = plist && cpl_propertylist_has(plist,
"CD2_2") &&
290 cpl_propertylist_get_double(plist,
"CD2_2") != 0.;
291 cpl_propertylist_delete(plist);
292 error_if (!cd11ok, CPL_ERROR_ILLEGAL_INPUT,
293 "CD1_1 WCS key missing or zero");
294 error_if (!cd22ok, CPL_ERROR_ILLEGAL_INPUT,
295 "CD2_2 WCS key missing or zero");
297 cpl_msg_info(cpl_func,
"%s", cpl_frame_get_filename(frm));
298 ret = fprintf(data,
"%s\n", cpl_frame_get_filename(frm));
299 error_if(ret < 0, CPL_ERROR_FILE_IO,
"Failed writting swarp file list");
303 cpl_msg_info(cpl_func,
"Generating coaddition header");
304 cpl_msg_debug(cpl_func,
"%s", cmd);
305 status = system(cmd);
307 error_if(WEXITSTATUS(status) != 0, CPL_ERROR_FILE_IO,
"Swarp failed");
312 return cpl_error_get_code();
316 static cpl_error_code
317 coadd_images(pid_t * pids,
unsigned long * beamids,
float * imgwgts,
318 cpl_frameset * usedframes,
319 const cx_list * imglist,
const cx_list * errlist,
320 const int nmax_procs,
const cpl_parameterlist * parlist)
322 const int nfiles = cx_list_size(imglist);
323 int nprocs = CX_MIN(nfiles, visir_get_num_threads(CPL_FALSE));
327 nprocs = CX_MIN(nmax_procs, nprocs);
329 for(cx_list_iterator iit = cx_list_begin(imglist),
330 eit = cx_list_begin(errlist);
331 iit != cx_list_end(imglist);
332 iit = cx_list_next(imglist, iit),
333 eit = cx_list_next(errlist, eit)) {
335 cpl_frame * ifrm = cx_list_get(imglist, iit);
336 cpl_frame * efrm = cx_list_get(errlist, eit);
337 cpl_propertylist * plist =
338 cpl_propertylist_load(cpl_frame_get_filename(ifrm), 0);
341 beamid = cpl_propertylist_get_string(plist,
"ESO QC BEAMID");
342 beamids[i] = strtoul(beamid, NULL, 10);
344 cpl_propertylist_delete(plist);
348 cpl_frameset_insert(usedframes, cpl_frame_duplicate(ifrm));
349 cpl_frameset_insert(usedframes, cpl_frame_duplicate(efrm));
350 pids[i++] = run_swarp(ifrm, efrm, parlist);
351 cpl_msg_info(cpl_func,
"Coadding file (%d/%d)", i, nfiles);
352 if (i - done >= nprocs) {
354 pid_t r = waitpid(-1, &status, 0);
355 error_if(r == -1 || !WIFEXITED(status) || WEXITSTATUS(status),
356 CPL_ERROR_FILE_IO,
"Coaddition failed: %d %s",
357 WEXITSTATUS(status), r == -1 ? strerror(errno) :
"");
361 for (
int j = done; j < i; j++) {
363 pid_t r = waitpid(-1, &status, 0);
364 error_if(r == -1 || !WIFEXITED(status) || WEXITSTATUS(status),
365 CPL_ERROR_FILE_IO,
"Coaddition failed: %d, %s",
366 WEXITSTATUS(status), r == -1 ? strerror(errno) :
"");
371 return cpl_error_get_code();
375 static cpl_error_code
376 save_single_images(cpl_frameset * framelist,
const cpl_size nfiles,
377 const pid_t * pids,
const cpl_frameset * usedframes,
378 const cpl_parameterlist * parlist)
380 cpl_image * img = NULL;
381 cpl_image * wgt = NULL;
382 cpl_propertylist * plist = NULL;
384 for (cpl_size j = 0; j < nfiles; j++) {
388 sprintf(coadd_img,
"tmp_coadd_%d.fits", (
int)pids[j]);
389 sprintf(coadd_wgt,
"tmp_coadd_wgt_%d.fits", (
int)pids[j]);
391 cpl_image_delete(img);
392 cpl_image_delete(wgt);
393 img = cpl_image_load(coadd_img, CPL_TYPE_UNSPECIFIED, 0, 0);
394 wgt = cpl_image_load(coadd_wgt, CPL_TYPE_UNSPECIFIED, 0, 0);
397 cpl_propertylist_delete(plist);
398 plist = cpl_propertylist_load(coadd_img, 0);
401 sprintf(coadd_img,
"swarp_coadd_img_%03d.fits", (
int)j);
402 sprintf(coadd_wgt,
"swarp_coadd_wgt_%03d.fits", (
int)j);
405 img, CPL_BPP_IEEE_FLOAT,
406 RECIPE_STRING,
"COADDED_IMAGE",
407 plist, NULL, visir_pipe_id,
410 wgt, CPL_BPP_IEEE_FLOAT,
411 RECIPE_STRING,
"COADDED_WEIGHT",
412 plist, NULL, visir_pipe_id,
417 cpl_image_delete(img);
418 cpl_image_delete(wgt);
419 cpl_propertylist_delete(plist);
421 return cpl_error_get_code();
425 static cpl_propertylist *
426 generate_beam_averages(cpl_image ** av, cpl_image ** wav,
float * imgwgts,
427 const cpl_size nfiles,
428 const pid_t * pids,
const unsigned long * beamids)
431 cpl_image * img = NULL;
432 cpl_image * wgt = NULL;
433 cpl_propertylist * plist = NULL;
434 unsigned long max_beamid = 0;
435 float tmpwgts[nfiles];
437 cpl_ensure(nfiles > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
439 for (cpl_size j = 0; j < nfiles; j++) {
440 const unsigned long idx = beamids[j];
444 cpl_image_delete(img);
445 cpl_image_delete(wgt);
446 sprintf(coadd_img,
"tmp_coadd_%d.fits", (
int)pids[j]);
447 sprintf(coadd_wgt,
"tmp_coadd_wgt_%d.fits", (
int)pids[j]);
448 img = cpl_image_load(coadd_img, CPL_TYPE_UNSPECIFIED, 0, 0);
449 wgt = cpl_image_load(coadd_wgt, CPL_TYPE_UNSPECIFIED, 0, 0);
454 plist = cpl_propertylist_load(coadd_img, 0);
460 if (strcmp(cpl_propertylist_get_string(plist,
"CTYPE1"),
462 cpl_propertylist_set_string(plist,
"CTYPE1",
"RA---TAN");
463 cpl_propertylist_set_string(plist,
"CTYPE2",
"DEC--TAN");
464 cpl_propertylist_set_string(plist,
"CUNIT1",
"deg");
465 cpl_propertylist_set_string(plist,
"CUNIT2",
"deg");
470 cpl_image_multiply(img, wgt);
471 if (av[idx] == NULL) {
472 av[idx] = cpl_image_duplicate(img);
473 wav[idx] = cpl_image_duplicate(wgt);
476 skip_if(cpl_image_add(av[idx], img));
477 skip_if(cpl_image_add(wav[idx], wgt));
479 max_beamid = CX_MAX(max_beamid, idx);
481 tmpwgts[idx] = imgwgts[j];
484 for (
unsigned long i = 0; i < max_beamid + 1; i++) {
485 cpl_image_divide(av[i], wav[i]);
486 imgwgts[i] = tmpwgts[i];
491 cpl_image_delete(img);
492 cpl_image_delete(wgt);
513 static cpl_error_code
514 generate_combined_image(cpl_image ** avg, cpl_image ** wgt,
515 const float * imgwgts,
const unsigned long n,
516 cpl_image ** oimg, cpl_image ** owgt,
517 cpl_image ** octr, visir_comb_type ctype)
520 cpl_image * cimg = cpl_image_new(cpl_image_get_size_x(avg[0]),
521 cpl_image_get_size_y(avg[0]),
523 cpl_image * cwgt = cpl_image_new(cpl_image_get_size_x(wgt[0]),
524 cpl_image_get_size_y(wgt[0]),
526 cpl_image * contrib = cpl_image_new(cpl_image_get_size_x(wgt[0]),
527 cpl_image_get_size_y(wgt[0]),
534 for (
unsigned long i = 0; i < n; i++) {
535 cpl_mask * m = cpl_mask_threshold_image_create(wgt[i], -1, FLT_EPSILON);
536 cpl_image * bad = cpl_image_new_from_mask(m);
537 cpl_image_reject_from_mask(avg[i], m);
541 cpl_image_subtract_scalar(avg[i], cpl_image_get_median(avg[i]));
542 cpl_image_fill_rejected(avg[i], 0);
546 cpl_image_power(wgt[i], -1);
547 cpl_image_accept_all(wgt[i]);
549 cpl_image_multiply_scalar(bad, imgwgts[i]);
550 cpl_image_subtract(contrib, bad);
551 cpl_image_delete(bad);
555 cpl_image_add(cimg, avg[i]);
556 cpl_image_add(cwgt, wgt[i]);
558 wgtsum += imgwgts[i];
561 cpl_image_add_scalar(contrib, wgtsum);
562 if (ctype == VISIR_AVG_COMB) {
563 cpl_image_divide(cimg, contrib);
565 cpl_image_divide(cwgt, contrib);
566 cpl_image_divide(cwgt, contrib);
568 cpl_image_power(cwgt, -1);
576 return cpl_error_get_code();
593 static cpl_error_code
594 cut_bad_edges(cpl_image ** img, cpl_image ** wgt, cpl_image ** ctr,
595 cpl_propertylist * plist)
597 const cpl_size nx = cpl_image_get_size_x(*ctr);
598 const cpl_size ny = cpl_image_get_size_y(*ctr);
599 const cpl_size max_contrib = cpl_image_get_max(*ctr);
600 const double ctr_cutoff = max_contrib == 2 ? 0.4 : 0.7;
605 for (cpl_size i = 0; i < ny / 2; i++) {
606 cpl_vector * row = cpl_vector_new_from_image_row(*ctr, i + 1);
607 double sum = cpl_vector_get_sum(row);
608 cpl_vector_delete(row);
609 if (sum >= max_contrib * nx * ctr_cutoff) {
614 for (cpl_size i = ny - 1; i >= ny / 2; i--) {
615 cpl_vector * row = cpl_vector_new_from_image_row(*ctr, i + 1);
616 double sum = cpl_vector_get_sum(row);
617 cpl_vector_delete(row);
618 if (sum >= max_contrib * nx * ctr_cutoff) {
623 for (cpl_size i = 0; i < nx / 2; i++) {
624 cpl_vector * col = cpl_vector_new_from_image_column(*ctr, i + 1);
625 double sum = cpl_vector_get_sum(col);
626 cpl_vector_delete(col);
627 if (sum >= max_contrib * ny * ctr_cutoff) {
632 for (cpl_size i = nx - 1; i >= nx / 2; i--) {
633 cpl_vector * col = cpl_vector_new_from_image_column(*ctr, i + 1);
634 double sum = cpl_vector_get_sum(col);
635 cpl_vector_delete(col);
636 if (sum >= max_contrib * ny * ctr_cutoff) {
645 cpl_msg_info(cpl_func,
"Cutting low contribution edges "
646 "llx: %lld, lly: %lld, urx: %lld, ury: %lld",
647 cutlx, cutly, cutux, cutuy);
650 cpl_image * nimg, * nwgt, * nctr;
651 if (cutlx < cutux && cutly < cutuy) {
652 cpl_propertylist_set_double(plist,
"CRPIX1",
653 cpl_propertylist_get_double(plist,
"CRPIX1") - cutlx);
654 cpl_propertylist_set_double(plist,
"CRPIX2",
655 cpl_propertylist_get_double(plist,
"CRPIX2") - cutly);
656 nimg = cpl_image_extract(*img, cutlx, cutly, cutux, cutuy);
657 nwgt = cpl_image_extract(*wgt, cutlx, cutly, cutux, cutuy);
658 nctr = cpl_image_extract(*ctr, cutlx, cutly, cutux, cutuy);
661 nimg = cpl_image_duplicate(*img);
662 nwgt = cpl_image_duplicate(*wgt);
663 nctr = cpl_image_duplicate(*ctr);
665 cpl_image_delete(*img);
666 cpl_image_delete(*wgt);
667 cpl_image_delete(*ctr);
672 return cpl_error_get_code();
676 static cpl_error_code
677 check_inputs(
const cpl_frameset * framelist,
const char * config)
681 VISIR_UTIL_CORRECTED);
686 "Unequal number of data and error frames");
690 error_if(access(config, R_OK) != 0, CPL_ERROR_FILE_NOT_FOUND,
691 "Swarp configuration not found: %s", config);
697 return cpl_error_get_code();
709 static int visir_util_run_swarp(cpl_frameset * framelist,
710 const cpl_parameterlist * parlist)
712 cpl_frameset * usedframes = cpl_frameset_new();
713 cpl_propertylist * plist = NULL;
714 cx_list * imglist = cx_list_new();
715 cx_list * errlist = cx_list_new();
717 skip_if(check_swarp());
719 const cpl_boolean output_all =
720 irplib_parameterlist_get_bool(parlist, PACKAGE,
721 RECIPE_STRING,
"output-all");
722 const char * config =
723 irplib_parameterlist_get_string(parlist, PACKAGE,
724 RECIPE_STRING,
"config_fname");
726 irplib_parameterlist_get_string(parlist, PACKAGE,
727 RECIPE_STRING,
"extra_config");
728 const int nmax_procs =
729 irplib_parameterlist_get_int(parlist, PACKAGE,
730 RECIPE_STRING,
"nprocs");
731 if (visir_str_par_is_empty(extra))
734 error_if(visir_str_par_is_empty(config), CPL_ERROR_FILE_NOT_FOUND,
735 "A swarp configuration file is required. "
736 "You can create a default configuration with: swarp -d");
738 skip_if(check_inputs(framelist, config));
740 unlink(SWARP_DATA_FILES);
741 unlink(SWARP_COADD_HEAD);
745 create_swarp_frames(imglist, errlist, framelist);
746 error_if(cx_list_size(imglist) == 0 || cx_list_size(errlist) == 0,
747 CPL_ERROR_ILLEGAL_INPUT,
"No frames tagged "
748 VISIR_UTIL_CORRECTED
" and "VISIR_UTIL_ERROR_MAP
" found");
750 skip_if(generate_coaddition_header(imglist, config, extra));
753 const cpl_size nfiles = cx_list_size(imglist);
755 unsigned long beamids[nfiles];
756 float imgwgts[nfiles];
757 unsigned long nmax_beamid = 0;
758 cpl_image * av[nfiles];
759 cpl_image * wav[nfiles];
760 cpl_image * cimg = NULL;
761 cpl_image * cwgt = NULL;
762 cpl_image * cctr = NULL;
764 for (cpl_size j = 0; j < nfiles; j++)
765 av[j] = wav[j] = NULL;
767 skip_if(coadd_images(pids, beamids, imgwgts, usedframes,
768 imglist, errlist, nmax_procs, parlist));
770 for (cpl_size i = 0; i < nfiles; i++)
771 nmax_beamid = CX_MAX(nmax_beamid, beamids[i] + 1);
773 error_if((cpl_size)nmax_beamid - 1 > nfiles,
774 CPL_ERROR_UNSUPPORTED_MODE,
775 "Only consecutive BEAMID's supported");
777 if (output_all && nfiles > 1)
778 save_single_images(framelist, nfiles, pids, usedframes, parlist);
782 plist = generate_beam_averages(av, wav, imgwgts, nfiles, pids, beamids);
783 skip_if(plist == NULL);
785 generate_combined_image(av, wav, imgwgts, nmax_beamid, &cimg, &cwgt,
786 &cctr, VISIR_AVG_COMB);
787 for (cpl_size i = 0; i < nfiles; i++) {
788 cpl_image_delete(av[i]);
789 cpl_image_delete(wav[i]);
792 cut_bad_edges(&cimg, &cwgt, &cctr, plist);
795 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
796 "COADDED_IMAGE_COMBINED", plist, NULL,
797 visir_pipe_id,
"swarp_coadd_img_all.fits");
799 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
800 "COADDED_WEIGHT_COMBINED", plist, NULL,
801 visir_pipe_id,
"swarp_coadd_wgt_all.fits");
803 CPL_TYPE_INT, RECIPE_STRING,
804 "COADDED_CONTRIBUTION_COMBINED", plist, NULL,
805 visir_pipe_id,
"swarp_coadd_ctr_all.fits");
806 cpl_image_delete(cimg);
807 cpl_image_delete(cwgt);
808 cpl_image_delete(cctr);
814 unlink(SWARP_DATA_FILES);
815 unlink(SWARP_COADD_HEAD);
816 cx_list_destroy(imglist, (cx_free_func)cpl_frame_delete);
817 cx_list_destroy(errlist, (cx_free_func)cpl_frame_delete);
818 cpl_frameset_delete(usedframes);
819 cpl_propertylist_delete(plist);
820 return cpl_error_get_code();
cpl_error_code irplib_dfs_save_image(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_image *image, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
double visir_pfits_get_img_weight(const cpl_propertylist *self)
The relative weight of the image compared to the other images.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
cpl_error_code irplib_framelist_contains(const irplib_framelist *self, const char *key, cpl_type type, cpl_boolean is_equal, double fp_tol)
Verify that a property is present for all frames.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.