29 #include "visir_recipe.h"
30 #include "irplib_framelist.h"
31 #include "irplib_wcs.h"
44 #ifndef VISIR_UTIL_REPACK_CONAD
45 #define VISIR_UTIL_REPACK_CONAD 1.1
48 #define RECIPE_STRING "visir_util_repack"
50 #define VISIR_DRS_CONAD "ESO DET OUT1 CONAD"
57 VISIR_SUB_NOCORRECT = 0,
58 VISIR_SUB_CHOPCORRECT = 1,
59 VISIR_SUB_CHOPNODCORRECT = 2
76 cpl_boolean normalize;
80 const irplib_framelist * rawframes;
82 const cpl_parameterlist * parlist;
84 const cpl_propertylist * plist;
85 visir_data_type datatype;
90 const char * remregexp;
112 const char * procatgon;
113 const char * procatgoff;
116 cpl_image * mean_off;
117 cpl_size * nmean_off;
119 double time_obsstart;
120 double time_filewrite;
122 double time_min_obsstart;
123 double time_max_filewrite;
126 static cpl_error_code
129 cpl_frameset * products,
131 cpl_image * nonlinear,
133 const cpl_bivector * lintab);
135 static inline cpl_error_code
136 visir_util_repack_check(
const cpl_image *,
137 const cpl_imagelist *,
138 const cpl_imagelist *);
141 #define cpl_plugin_get_info visir_util_repack_get_info
143 cpl_recipe_define(visir_util_repack, VISIR_BINARY_VERSION,
144 "Lars Lundin", PACKAGE_BUGREPORT,
"2011",
145 "Conversion of raw CUBE2 or BURST images to on- and off-cubes",
146 "The files listed in the Set Of Frames (sof-file) "
148 "VISIR-CUBE2-raw-file.fits " VISIR_UTIL_REPACK_RAW
150 "VISIR-BURST-raw-file.fits " VISIR_IMG_BURST
"\n"
151 "VISIR-BURST-bpm-file.fits " VISIR_CALIB_STATIC_MASK
152 "\nFor BURST data it will remove planes where the chopper "
153 "switched from on <-> off based on the "
154 "timestamps in the header."
155 "\nThe product(s) will have a FITS card\n"
156 "'HIERARCH ESO PRO CATG' with a value of one of:\n"
157 VISIR_UTIL_REPACK_A_ON_PROCATG
" (NodPos: A, ChopPos: on)\n"
158 VISIR_UTIL_REPACK_A_OFF_PROCATG
" (NodPos: A, ChopPos: off)\n"
159 VISIR_UTIL_REPACK_B_ON_PROCATG
" (NodPos: B, ChopPos: on)\n"
160 VISIR_UTIL_REPACK_B_OFF_PROCATG
" (NodPos: B, ChopPos: off)\n"
173 "For CUBE2, the recipe will produce a static "
174 "bad-pixel map, it will have a FITS card\n"
175 "'HIERARCH ESO PRO CATG' with a value of:\n"
176 VISIR_CALIB_STATIC_MASK
"\n"
199 visir_imagelist_pop(cpl_imagelist * list)
201 if (cpl_imagelist_get_size(list) == 0)
203 return cpl_imagelist_unset(list, cpl_imagelist_get_size(list) - 1);
216 static cpl_type get_optimum_save_type(
const cpl_image * img)
218 cpl_type res = CPL_TYPE_UNSPECIFIED;
219 if (cpl_image_get_type(img) == CPL_TYPE_INT) {
220 cpl_stats * stats = cpl_stats_new_from_image(img, CPL_STATS_MIN |
222 if ((
int)cpl_stats_get_max(stats) <= CX_MAXSHORT &&
223 (
int)cpl_stats_get_min(stats) >= CX_MINSHORT)
224 res = CPL_TYPE_SHORT;
225 cpl_stats_delete(stats);
241 static cpl_error_code
242 visir_util_repack_fill_parameterlist(cpl_parameterlist *
self)
244 const char * context = PACKAGE
"." RECIPE_STRING;
247 cpl_ensure_code(
self, CPL_ERROR_NULL_INPUT);
252 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"planestart",
253 0, NULL, context,
"Plane number to "
254 "start repacking from, earlier planes "
256 cpl_ensure_code(!err, err);
259 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"ncycles",
260 -1, NULL, context,
"Number of full "
261 "on-off cycles to repack. <= 0 for all.");
262 cpl_ensure_code(!err, err);
265 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"trimlow",
266 0, NULL, context,
"Burst data only. "
267 "Number of additional planes to cut "
268 "from before each plane with chopper "
270 cpl_ensure_code(!err, err);
273 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"trimhigh",
274 0, NULL, context,
"Burst data only. "
275 "Number of additional planes to cut "
276 "from after each plane with chopper "
277 "movement.\n A value of -1 does not "
278 "skip the plane of the movement.");
279 cpl_ensure_code(!err, err);
282 err = irplib_parameterlist_set_string(
self, PACKAGE, RECIPE_STRING,
283 "bkgcorrect",
"none", NULL, context,
284 "Output background corrected planes by "
285 "subtracting chop (on/off) and nod (A/B) "
286 "planes\n Options:\n"
287 " none: no correction\n"
289 " chopnod: (Aon - Aoff) - (Bon - Boff)");
290 cpl_ensure_code(!err, err);
295 irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
"normalize",
296 CPL_TRUE, NULL, context,
297 "Normalize planes by DIT");
298 cpl_ensure_code(!err, err);
302 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
303 "compress", CPL_FALSE, NULL, context,
304 "Apply lossless compression on output"
305 "files. Can only be done for integer "
307 cpl_ensure_code(!err, err);
309 return CPL_ERROR_NONE;
326 repack_framestate_new(irplib_framelist * rawframes,
int iframe,
327 const cpl_parameterlist * parlist)
330 int ndit, ncycles, planes_per_cycle = 2;
332 const char * filename = cpl_frame_get_filename(frame);
334 state->time_max_filewrite = -1;
335 state->time_min_obsstart = 1e300;
337 state->rawframes = rawframes;
339 state->iframe = iframe;
341 state->tag = cpl_frame_get_tag(frame);
343 error_if(strcmp(state->tag, VISIR_CALIB_STATIC_MASK) == 0,
344 CPL_ERROR_UNSUPPORTED_MODE,
" ");
349 const cpl_size iext = 0;
353 state->parlist = parlist;
358 skip_if(visir_get_data_type(frame, state->plist, &state->datatype, &next));
360 if (state->datatype == VISIR_DATA_AQU_HCYCLE) {
362 state->naxis3 = next;
364 else if (state->datatype == VISIR_DATA_AQU_INT) {
373 const char * bkgc = irplib_parameterlist_get_string(parlist, PACKAGE,
376 if (visir_str_par_is_empty(bkgc) || !strcasecmp(bkgc,
"none"))
377 state->bkgcorrect = VISIR_SUB_NOCORRECT;
378 else if (!strcasecmp(bkgc,
"chopnod"))
379 state->bkgcorrect = VISIR_SUB_CHOPNODCORRECT;
380 else if (!strcasecmp(bkgc,
"chop"))
381 state->bkgcorrect = VISIR_SUB_CHOPCORRECT;
383 error_if(1, CPL_ERROR_ILLEGAL_INPUT,
384 "Unknown parameter to --bkgcorrect: %s", bkgc);
386 error_if(!state->chop_on && state->bkgcorrect == VISIR_SUB_CHOPCORRECT,
387 CPL_ERROR_ILLEGAL_INPUT,
"Requested chop correction on data "
388 "with "VISIR_PFITS_BOOL_CHOP_STATUS
" false");
391 error_if(state->datatype == VISIR_DATA_AQU_INT &&
392 state->bkgcorrect != VISIR_SUB_CHOPNODCORRECT,
393 CPL_ERROR_INCOMPATIBLE_INPUT,
394 "INT frame only data requires --bkgcorrect to be chopnod");
397 error_if(state->datatype == VISIR_DATA_CUBE1,
398 CPL_ERROR_INCOMPATIBLE_INPUT,
399 "CUBE1 data not supported please use the legacy recipes "
400 "visir_img_combine or visir_spc_obs");
402 state->normalize = irplib_parameterlist_get_bool(parlist, PACKAGE,
408 error_if(state->normalize && state->dit == 0, CPL_ERROR_ILLEGAL_INPUT,
409 "Cannot normalize by DIT = 0");
411 state->planestart = irplib_parameterlist_get_int(parlist, PACKAGE,
414 error_if(state->planestart >= state->naxis3, CPL_ERROR_ILLEGAL_INPUT,
415 "planestart %d equal or larger than number of planes %d.",
416 state->planestart, state->naxis3);
421 IRPLIB_DIAG_PRAGMA_PUSH_ERR(-Wswitch);
422 switch(state->datatype) {
423 case VISIR_DATA_CUBE1:
426 case VISIR_DATA_AQU_HCYCLE:
427 case VISIR_DATA_CUBE2:
428 planes_per_cycle = 2;
430 case VISIR_DATA_AQU_INT:
432 planes_per_cycle = 1;
434 case VISIR_DATA_BURST:
435 planes_per_cycle = ndit * 2;
437 case VISIR_DATA_AQU_BURST:
438 case VISIR_DATA_AQU_BURST_EXT:
440 planes_per_cycle = 1. / (state->dit * chop_freq);
443 IRPLIB_DIAG_PRAGMA_POP;
445 ncycles = irplib_parameterlist_get_int(parlist, PACKAGE,
446 RECIPE_STRING,
"ncycles");
448 ncycles = irplib_pfits_get_int(state->plist,
449 VISIR_PFITS_INT_CHOP_NCYCLES);
451 state->planeend = state->planestart + ncycles * planes_per_cycle;
454 if (state->planeend >= state->naxis3 || state->planeend <= 0) {
455 if (state->planestart % planes_per_cycle == 0)
456 state->planeend = state->naxis3;
458 state->planeend = state->naxis3 -
459 (planes_per_cycle - (state->planestart % planes_per_cycle));
464 if (state->normalize && (state->dit < 1e-6 ||
465 (
double)((int)(1. / state->dit)) != 1. / state->dit))
466 state->load_type = CPL_TYPE_FLOAT;
468 state->load_type = CPL_TYPE_UNSPECIFIED;
470 state->trimlow = irplib_parameterlist_get_int(parlist, PACKAGE,
473 state->trimhigh = irplib_parameterlist_get_int(parlist, PACKAGE,
477 state->compress = irplib_parameterlist_get_bool(parlist, PACKAGE,
481 if (state->compress && CPL_IO_COMPRESS_RICE == 0) {
482 cpl_msg_warning(cpl_func,
"CPL version too old for compression.");
483 state->compress = CPL_FALSE;
486 state->conad = VISIR_UTIL_REPACK_CONAD;
489 state->remregexp =
"^(" VISIR_PFITS_DOUBLE_CUMOFFSETX
490 "|" VISIR_PFITS_DOUBLE_CUMOFFSETY
")$";
499 state->comoffx = cpl_propertylist_get_comment
500 (state->plist, VISIR_PFITS_DOUBLE_CUMOFFSETX);
501 state->comoffy = cpl_propertylist_get_comment
502 (state->plist, VISIR_PFITS_DOUBLE_CUMOFFSETY);
505 state->jitterwidth = 0.;
506 if (cpl_propertylist_has(state->plist,
"ESO SEQ JITTER WIDTH")) {
508 cpl_propertylist_get_double(state->plist,
"ESO SEQ JITTER WIDTH");
509 state->jitterwidth /= state->pfov;
514 cpl_propertylist * extplist = cpl_propertylist_load(filename, 1);
515 skip_if(extplist == NULL);
517 cpl_propertylist_delete(extplist);
521 if (visir_data_is_burst(state->datatype)) {
522 visir_img_burst_find_delta_chop(state->plist,
527 state->bpmthresh = VISIR_HCYCLE_BPM_THRESHOLD;
529 if (state->bkgcorrect == VISIR_SUB_NOCORRECT) {
531 state->is_a = nodpos != NULL &&
532 (strstr(nodpos,
"A") || strstr(nodpos,
"a")) ? CPL_TRUE : CPL_FALSE;
533 state->procatgon = state->is_a ? VISIR_UTIL_REPACK_A_ON_PROCATG
534 : VISIR_UTIL_REPACK_B_ON_PROCATG;
535 state->procatgoff = state->is_a ? VISIR_UTIL_REPACK_A_OFF_PROCATG
536 : VISIR_UTIL_REPACK_B_OFF_PROCATG;
537 state->onname = cpl_sprintf(RECIPE_STRING
"_%s_on_%03d"
538 CPL_DFS_FITS, nodpos, 1+iframe);
539 state->offname = cpl_sprintf(RECIPE_STRING
"_%s_off_%03d"
540 CPL_DFS_FITS, nodpos, 1+iframe);
544 skip_if (nodpos == NULL);
545 skip_if (strstr(nodpos,
"B") == NULL && strstr(nodpos,
"b") == NULL);
547 }
else if (state->bkgcorrect == VISIR_SUB_CHOPCORRECT) {
549 state->is_a = nodpos != NULL &&
550 (strstr(nodpos,
"A") || strstr(nodpos,
"a")) ? CPL_TRUE : CPL_FALSE;
551 state->procatgon = state->is_a ?
"BKG_CORRECTED_A" :
"BKG_CORRECTED_B";
552 state->onname = cpl_sprintf(RECIPE_STRING
"_%s_bkgcor_%03d"
553 CPL_DFS_FITS, nodpos, 1+iframe);
556 state->is_a = nodpos != NULL &&
557 (strstr(nodpos,
"A") || strstr(nodpos,
"a")) ? CPL_TRUE : CPL_FALSE;
558 state->procatgon = VISIR_UTIL_CORRECTED;
559 state->onname = cpl_sprintf(RECIPE_STRING
"_bkgcor_%03d"
560 CPL_DFS_FITS, 1+iframe);
565 if (state->datatype == VISIR_DATA_AQU_HCYCLE ||
566 state->datatype == VISIR_DATA_AQU_INT ) {
567 cpl_propertylist * plist = cpl_propertylist_load(filename, 1);
570 cpl_propertylist_delete(plist);
578 state->mean_on = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
579 state->nmean_on = cpl_calloc(1,
sizeof(cpl_size));
580 state->mean_off = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
581 state->nmean_off = cpl_calloc(1,
sizeof(cpl_size));
598 repack_framestate_delete(
void * state_)
605 cpl_free(state->onname);
606 cpl_free(state->offname);
607 cpl_image_delete(state->mean_on);
608 cpl_image_delete(state->mean_off);
609 cpl_free(state->nmean_on);
610 cpl_free(state->nmean_off);
623 static cpl_error_code
624 store_means(
const visir_sub_type bkgcorrect,
const irplib_framelist * rawfr,
625 cpl_frameset * framelist,
const cpl_parameterlist * parlist,
626 cpl_image ** mean, cpl_size * nmean, visir_frame_type * frametype)
628 cpl_frameset * usedframes[] = {cpl_frameset_new(), cpl_frameset_new(),
629 cpl_frameset_new(), cpl_frameset_new()};
631 int normalize = irplib_parameterlist_get_bool(parlist, PACKAGE,
634 cpl_propertylist * plist = cpl_propertylist_new();
636 cpl_propertylist_append_string(plist,
"BUNIT",
"adu / s");
638 cpl_propertylist_append_string(plist,
"BUNIT",
"adu");
641 if (bkgcorrect == VISIR_SUB_CHOPNODCORRECT) {
642 for (
int i = 1; i < 4; i++) {
643 cpl_image_add(mean[0], mean[i]);
644 nmean[0] += nmean[i];
646 skip_if(cpl_image_divide_scalar(mean[0], nmean[0]));
650 cpl_frameset_insert(usedframes[0], frm);
653 mean[0], CPL_TYPE_UNSPECIFIED,
654 RECIPE_STRING,
"MEAN",
655 plist, NULL, visir_pipe_id,
656 "visir_util_repack_mean.fits"));
658 else if (bkgcorrect == VISIR_SUB_CHOPCORRECT) {
659 const char * procatg[] = {
"MEAN_A",
"MEAN_B"};
660 const char * fn[] ={
"visir_util_repack_mean_A.fits",
661 "visir_util_repack_mean_B.fits"};
662 for (
int i = 0; i < 2; i++) {
663 int idx = i == 0 ? 0 : 2;
664 cpl_image_add(mean[idx], mean[idx + 1]);
665 nmean[idx] += nmean[idx + 1];
666 skip_if(cpl_image_divide_scalar(mean[idx], nmean[idx]));
668 if ((i == 0 && frametype[j] == VISIR_FRAME_B) ||
669 (i == 1 && frametype[j] == VISIR_FRAME_A) ||
670 frametype[j] == VISIR_FRAME_STATIC)
674 cpl_frameset_insert(usedframes[i], frm);
677 mean[idx], CPL_TYPE_UNSPECIFIED,
678 RECIPE_STRING, procatg[i],
679 plist, NULL, visir_pipe_id, fn[i]));
683 const char * procatg[] = {
"MEAN_A_ON",
"MEAN_A_OFF",
684 "MEAN_B_ON",
"MEAN_B_OFF"};
685 const char * fn[] ={
"visir_util_repack_mean_Aoff.fits",
686 "visir_util_repack_mean_Aon.fits",
687 "visir_util_repack_mean_Boff.fits",
688 "visir_util_repack_mean_Bon.fits"};
689 for (
int i = 0; i < 4; i++) {
690 skip_if(cpl_image_divide_scalar(mean[i], nmean[i]));
692 if ((i < 2 && frametype[j] == VISIR_FRAME_A) ||
693 (i >= 2 && frametype[j] == VISIR_FRAME_B) ||
694 frametype[j] == VISIR_FRAME_STATIC)
698 cpl_frameset_insert(usedframes[i], frm);
701 mean[i], CPL_TYPE_UNSPECIFIED,
702 RECIPE_STRING, procatg[i],
703 plist, NULL, visir_pipe_id, fn[i]));
709 cpl_propertylist_delete(plist);
710 for (
size_t i = 0; i <
sizeof(usedframes)/
sizeof(usedframes[0]); i++)
711 cpl_frameset_delete(usedframes[i]);
713 return cpl_error_get_code();
725 static int visir_util_repack(cpl_frameset * framelist,
726 const cpl_parameterlist * parlist)
728 irplib_framelist * allframes = NULL;
729 irplib_framelist * rawframes = NULL;
731 cx_list * alist = cx_list_new();
732 cx_list * blist = cx_list_new();
733 cpl_image * bpm = NULL;
735 cpl_image * nonlinear = NULL;
736 cpl_bivector * lintable = NULL;
737 cpl_image * mean[] = {NULL, NULL, NULL, NULL};
738 cpl_size nmean[] = {0, 0, 0, 0};
739 visir_sub_type bkgcorrect = VISIR_SUB_NOCORRECT;
740 visir_frame_type * frametype = NULL;
741 double xjitter0, yjitter0;
745 cpl_fits_set_mode(CPL_FITS_START_CACHING);
749 skip_if(allframes == NULL);
752 "|" VISIR_SPC_OBS_ECH_RAW
753 "|" VISIR_SPC_PHOT_RAW
754 "|" VISIR_SPC_PHOT_ECH_RAW
755 "|" VISIR_IMG_PHOT_RAW
756 "|" VISIR_IMG_COMBINE_CN
757 "|" VISIR_IMG_COMBINE_CNJ
758 "|" VISIR_IMG_COMBINE_CJ
759 "|" VISIR_IMG_COMBINE_NJ
760 "|" VISIR_IMG_COMBINE_DJ
763 "|" VISIR_UTIL_REPACK_RAW
764 "|" VISIR_UTIL_INPUTS_RAW
768 skip_if (rawframes == NULL);
771 frametype = cpl_malloc(
sizeof(visir_frame_type) * n);
773 for (
int i = 0; i < n; i++) {
776 state = repack_framestate_new(rawframes, i, parlist);
778 frametype[i] = state->is_a ? VISIR_FRAME_A : VISIR_FRAME_B;
779 if (state->is_a == CPL_TRUE)
780 cx_list_push_back(alist, state);
782 cx_list_push_back(blist, state);
786 error_if(cx_list_size(alist) == 0, CPL_ERROR_ILLEGAL_INPUT,
787 "No frames with nodpos A");
788 error_if(cx_list_size(blist) == 0, CPL_ERROR_ILLEGAL_INPUT,
789 "No frames with nodpos B");
790 if (cx_list_size(alist) != cx_list_size(blist)) {
791 if (cx_list_size(alist) > cx_list_size(alist)) {
792 cpl_msg_warning(cpl_func,
793 "Expecting even number of files, ignoring the last Nod A frame");
794 repack_framestate_delete(cx_list_pop_back(alist));
796 if (cx_list_size(blist) > cx_list_size(alist)) {
797 cpl_msg_warning(cpl_func,
798 "Expecting even number of files, ignoring the last Nod B frame");
799 repack_framestate_delete(cx_list_pop_back(blist));
802 error_if(cx_list_size(alist) != cx_list_size(blist),
803 CPL_ERROR_ILLEGAL_INPUT,
804 "Unequal number of A and B frames. A: %d, B: %d",
805 (
int)cx_list_size(alist), (
int)cx_list_size(blist));
808 cpl_frame * frm = cpl_frameset_find(framelist, VISIR_CALIB_STATIC_MASK);
812 bpm = cpl_image_load(cpl_frame_get_filename(frm),
813 CPL_TYPE_UNSPECIFIED, 0, 0);
815 cpl_msg_warning(cpl_func,
"Loading of bad pixel map %s failed",
816 cpl_frame_get_filename(frm));
819 cpl_msg_info(cpl_func,
"Loaded bad pixel mask from %s",
820 cpl_frame_get_filename(frm));
821 if (visir_data_is_aqu(state->datatype)) {
827 cpl_size nx = cpl_image_get_size_x(bpm);
828 cpl_size ny = cpl_image_get_size_y(bpm);
829 cpl_size llx = 1, lly = 1, urx = nx, ury = ny;
830 if (win_nx > 0 && start_x > 0) {
832 urx = start_x + win_nx - 1;
834 if (win_ny > 0 && start_y > 0) {
836 ury = start_y + win_ny - 1;
838 if (llx != 1 || urx != nx || lly != 1 || ury != ny) {
839 cpl_image * tmp = cpl_image_extract(bpm, llx, lly, urx, ury);
840 cpl_image_delete(bpm);
845 nonlinear = cpl_image_new(cpl_image_get_size_x(bpm),
846 cpl_image_get_size_y(bpm), CPL_TYPE_INT);
855 const char * lextname = NULL;
856 if (visir_is_img(st->plist)) {
857 lextname =
"IMAGE_LIN";
859 else if (visir_is_spc(st->plist)) {
860 lextname =
"SPEC_LIN";
862 cpl_frame * frm = cpl_frameset_find(framelist, VISIR_CALIB_LIN);
863 if (lextname && frm && visir_data_is_aqu(st->datatype)) {
864 const char * fn = cpl_frame_get_filename(frm);
865 cpl_msg_info(cpl_func,
"Correcting linearity using %s extension "
866 "of %s", lextname, fn);
867 cpl_size iext = cpl_fits_find_extension(fn, lextname);
868 error_if(iext < 0, CPL_ERROR_ILLEGAL_INPUT,
869 "Linearity correction extension %s not found in %s",
872 cpl_table * tab = cpl_table_load(fn, iext, 0);
873 const size_t n = cpl_table_get_nrow(tab);
874 lintable = cpl_bivector_new(n);
875 memcpy(cpl_bivector_get_x_data(lintable),
876 cpl_table_get_data_double(tab,
"dc_level"),
878 memcpy(cpl_bivector_get_y_data(lintable),
879 cpl_table_get_data_double(tab,
"conv_gain"),
881 cpl_table_delete(tab);
884 cpl_vector_divide_scalar(cpl_bivector_get_y(lintable),
885 cpl_vector_get_mean(cpl_bivector_get_y(lintable)));
891 if (!cx_list_empty(alist))
893 if (!cx_list_empty(blist))
896 if (fstatea == NULL || fstateb == NULL)
900 fstatea->load_type = CPL_TYPE_FLOAT;
901 fstateb->load_type = CPL_TYPE_FLOAT;
905 if (cpl_propertylist_has(fstatea->plist,
"DATE-OBS") &&
906 cpl_propertylist_has(fstatea->plist,
"DATE") &&
907 cpl_propertylist_has(fstateb->plist,
"DATE-OBS") &&
908 cpl_propertylist_has(fstateb->plist,
"DATE")) {
910 cpl_propertylist_get_string(fstatea->plist,
"DATE-OBS");
911 irplib_wcs_mjd_from_string(&(fstatea->time_obsstart), str);
912 str = cpl_propertylist_get_string(fstatea->plist,
"DATE");
913 irplib_wcs_mjd_from_string(&(fstatea->time_filewrite), str);
915 str = cpl_propertylist_get_string(fstateb->plist,
"DATE-OBS");
916 irplib_wcs_mjd_from_string(&(fstateb->time_obsstart), str);
917 str = cpl_propertylist_get_string(fstateb->plist,
"DATE");
918 irplib_wcs_mjd_from_string(&(fstateb->time_filewrite), str);
921 fstatea->time_min_obsstart = CX_MIN(fstatea->time_obsstart,
922 fstateb->time_obsstart);
923 fstateb->time_min_obsstart = CX_MIN(fstatea->time_obsstart,
924 fstateb->time_obsstart);
925 fstatea->time_max_filewrite = CX_MAX(fstatea->time_filewrite,
926 fstateb->time_filewrite);
927 fstateb->time_max_filewrite = CX_MAX(fstatea->time_filewrite,
928 fstateb->time_filewrite);
931 OMP_PRAGMA(omp parallel num_threads(2))
932 OMP_PRAGMA(omp single)
934 visir_util_repack_two(fstatea, fstateb, framelist, &bpm, nonlinear,
935 xjitter0, yjitter0, lintable);
939 bkgcorrect = fstatea->bkgcorrect;
941 for (
int i = 0; i < 4; i++) {
942 cpl_image * stimg = i % 2 == 0 ? st[i]->mean_on : st[i]->mean_off;
943 cpl_size nst = i % 2 == 0 ? *st[i]->nmean_on : *st[i]->nmean_off;
945 mean[i] = cpl_image_duplicate(stimg);
947 cpl_image_add(mean[i], stimg);
951 repack_framestate_delete(fstatea);
952 repack_framestate_delete(fstateb);
953 cpl_fits_set_mode(CPL_FITS_RESTART_CACHING);
956 skip_if(store_means(bkgcorrect, rawframes, framelist, parlist,
957 mean, nmean, frametype));
962 cpl_image_get_size_x(bpm) == cpl_image_get_size_x(mean[0]) &&
963 cpl_image_get_size_y(bpm) == cpl_image_get_size_y(mean[0])) {
966 cpl_size total = nmean[0] + nmean[1] + nmean[2] + nmean[3];
967 cpl_mask * mnonlinear =
968 cpl_mask_threshold_image_create(nonlinear, total * 0.9, total * 2);
969 cpl_msg_info(cpl_func,
"%lld (%.3g%%) pixels non-linear in 90%% "
970 "of %lld frames", cpl_mask_count(mnonlinear),
971 (100. * cpl_mask_count(mnonlinear)) /
972 (cpl_mask_get_size_x(mnonlinear) *
973 cpl_mask_get_size_y(mnonlinear)), total);
977 cpl_mask_delete(mnonlinear);
980 cpl_frameset * usedframes = cpl_frameset_new();
981 cpl_frameset_insert(usedframes, cpl_frame_duplicate
984 CPL_BPP_8_UNSIGNED, RECIPE_STRING,
985 VISIR_CALIB_STATIC_MASK, NULL, NULL,
986 visir_pipe_id, RECIPE_STRING
"_bpm"
988 cpl_frameset_delete(usedframes);
991 cpl_msg_warning(cpl_func,
"Provided bad pixel mask does not have "
992 "correct size, skipping");
1000 cx_list_destroy(alist, repack_framestate_delete);
1001 cx_list_destroy(blist, repack_framestate_delete);
1002 cpl_image_delete(bpm);
1003 cpl_image_delete(nonlinear);
1004 cpl_bivector_delete(lintable);
1005 cpl_free(frametype);
1007 for (
size_t i = 0; i <
sizeof(mean)/
sizeof(mean[0]); i++)
1008 cpl_image_delete(mean[i]);
1010 return cpl_error_get_code();
1027 static cpl_error_code
1029 const cpl_imagelist * subtracted,
1030 const cpl_imagelist * jit_cor,
1031 const cpl_propertylist * plist)
1033 const cpl_size nsub = cpl_imagelist_get_size(subtracted);
1034 cpl_ensure_code(jit_cor == NULL || cpl_imagelist_get_size(jit_cor) == nsub,
1035 CPL_ERROR_ILLEGAL_INPUT);
1038 for (cpl_size j = 0; j < nsub; j++) {
1039 const cpl_image * img = cpl_imagelist_get_const(subtracted, j);
1040 cpl_io_type compress = 0;
1044 cpl_image_add(state->mean_on, cpl_imagelist_get_const(jit_cor, j));
1046 cpl_image_add(state->mean_on, img);
1047 (*state->nmean_on)++;
1049 if (state->compress && cpl_image_get_type(img) == CPL_TYPE_INT) {
1051 save_type = CPL_TYPE_INT;
1052 compress = CPL_IO_COMPRESS_RICE;
1055 save_type = get_optimum_save_type(img);
1057 skip_if(cpl_image_save(img, state->onname, save_type,
1058 plist, CPL_IO_EXTEND | compress));
1063 return cpl_error_get_code();
1083 cpl_imagelist * images,
1084 const cpl_propertylist * plist,
1085 const cpl_boolean on)
1087 const char * name = on ? state->onname : state->offname;
1088 const cpl_size n = cpl_imagelist_get_size(images);
1089 cpl_image * mimg = on ? state->mean_on : state->mean_off;
1090 cpl_size * nmean = on ? state->nmean_on : state->nmean_off;
1092 for (cpl_size j = 0; j < n; j++) {
1093 cpl_image * img = cpl_imagelist_get(images, j);
1094 cpl_io_type compress = 0;
1097 if (state->datatype == VISIR_DATA_BURST) {
1098 cpl_image_multiply_scalar(img, -1);
1099 cpl_image_add_scalar(img, VISIR_HCYCLE_OFFSET);
1102 cpl_image_add(mimg, img);
1105 if (state->compress && cpl_image_get_type(img) == CPL_TYPE_INT) {
1107 save_type = CPL_TYPE_INT;
1108 compress = CPL_IO_COMPRESS_RICE;
1111 save_type = get_optimum_save_type(img);
1113 skip_if(cpl_image_save(img, name, save_type,
1114 plist, CPL_IO_EXTEND | compress));
1119 return cpl_error_get_code();
1132 static cpl_error_code
1133 cast_list(cpl_imagelist * l,
const cpl_type type)
1135 const cpl_size n = cpl_imagelist_get_size(l);
1137 if (type == CPL_TYPE_UNSPECIFIED)
1138 return CPL_ERROR_NONE;
1140 cl = cpl_imagelist_new();
1142 for (cpl_size i = 0; i < n; i++) {
1143 cpl_image * img = cpl_imagelist_get(l, i);
1145 if (cpl_image_get_type(img) == type) {
1146 cpl_imagelist_delete(cl);
1147 return cpl_error_get_code();
1149 cast = cpl_image_cast(img, type);
1150 cpl_imagelist_set(cl, cast, i);
1153 cpl_imagelist_empty(l);
1154 for (cpl_size i = 0; i < n; i++)
1155 cpl_imagelist_set(l, cpl_imagelist_get(cl, i), i);
1157 visir_imagelist_unwrap(cl);
1159 return cpl_error_get_code();
1176 cpl_error_code load_chunk(cpl_imagelist * on, cpl_imagelist * off,
1178 const int pstart,
const int pend)
1181 if (state->datatype == VISIR_DATA_AQU_HCYCLE) {
1184 const char * filename = cpl_frame_get_filename(frame);
1185 cpl_errorstate prestate = cpl_errorstate_get();
1188 for (cpl_size iext = pstart + 1; iext < pend + 1; iext++) {
1189 cpl_image * img = cpl_image_load(filename, CPL_TYPE_FLOAT, 0, iext);
1190 cpl_propertylist * plist;
1194 cpl_msg_debug(cpl_func,
"No image-data in extension %d",
1196 cpl_errorstate_set(prestate);
1199 plist = cpl_propertylist_load_regexp(filename, iext,
1200 VISIR_PFITS_STRING_FRAME_TYPE,
1202 skip_if(plist == NULL);
1204 error_if(ftype == NULL, CPL_ERROR_DATA_NOT_FOUND,
"ESO DET FRAM "
1205 "TYPE keyword missing in extension %d of file %s",
1206 (
int)iext, filename);
1207 if (strcmp(ftype,
"HCYCLE1") == 0)
1208 cpl_imagelist_set(on, img, cpl_imagelist_get_size(on));
1209 else if (strcmp(ftype,
"HCYCLE2") == 0)
1210 cpl_imagelist_set(off, img, cpl_imagelist_get_size(off));
1212 cpl_msg_info(cpl_func,
"Skipping \"%s\" frame type", ftype);
1214 cpl_propertylist_delete(plist);
1218 else if (state->datatype == VISIR_DATA_CUBE2) {
1220 state->iframe, pstart, pend));
1223 else if (visir_data_is_burst(state->datatype))
1224 skip_if(visir_load_burst(on, off,
1227 state->plist, state->to_off,
1228 state->halfcycle, pstart, pend,
1229 state->trimlow, state->trimhigh));
1231 error_if(1, CPL_ERROR_ILLEGAL_INPUT,
"invalid data tag");
1234 cast_list(on, state->load_type);
1235 cast_list(off, state->load_type);
1239 return cpl_error_get_code();
1255 equalize_lists(cpl_imagelist * a, cpl_imagelist * b)
1257 const cpl_size na = cpl_imagelist_get_size(a);
1258 const cpl_size nb = cpl_imagelist_get_size(b);
1261 cpl_msg_warning(cpl_func,
"Unequal number of planes in on "
1262 "and off list: #on %d, #off %d. Skipping %ld"
1263 " planes.", (
int)na, (
int)nb, labs(na - nb));
1266 for (cpl_size i = 0; i < na - nb; i++)
1267 cpl_image_delete(visir_imagelist_pop(a));
1270 for (cpl_size i = 0; i < nb - na; i++)
1271 cpl_image_delete(visir_imagelist_pop(b));
1274 if (cpl_error_get_code() != CPL_ERROR_NONE)
1276 return cpl_imagelist_get_size(a);
1279 static cpl_error_code
1280 check_and_fix_cd_wcs(cpl_propertylist * plist,
const cpl_propertylist * iplist)
1282 if (!cpl_propertylist_has(plist,
"CD1_1") ||
1283 cpl_propertylist_get_double(plist,
"CD1_1") == 0.) {
1285 cpl_msg_warning(cpl_func,
"CD1_1 WCS key missing or zero, fixing to "
1286 "%g (pfov) / 3600", pfov);
1287 cpl_propertylist_update_double(plist,
"CD1_1", pfov / 3600.);
1289 if (!cpl_propertylist_has(plist,
"CD2_2") ||
1290 cpl_propertylist_get_double(plist,
"CD2_2") == 0.) {
1292 cpl_msg_warning(cpl_func,
"CD2_2 WCS key missing or zero, fixing to "
1293 "%g (-pfov) / 3600", - pfov);
1294 cpl_propertylist_update_double(plist,
"CD2_2", -pfov / 3600.);
1297 return cpl_error_get_code();
1315 static cpl_error_code
1317 double xjittera,
double yjittera,
1318 double xjitterb,
double yjitterb,
1321 cpl_frameset * usedframes = cpl_frameset_new();
1322 cpl_propertylist * onlist = cpl_propertylist_new();
1323 cpl_propertylist * offlist = cpl_propertylist_new();
1326 bug_if(cpl_propertylist_copy_property_regexp(onlist, state->plist,
"^("
1327 IRPLIB_PFITS_WCS_REGEXP
")$",
1330 bug_if(cpl_propertylist_append_double(onlist, VISIR_DRS_CONAD, state->conad));
1331 bug_if(cpl_propertylist_set_comment(onlist, VISIR_DRS_CONAD,
"Default "
1332 "single frame value: " IRPLIB_STRINGIFY
1333 (VISIR_UTIL_REPACK_CONAD)));
1335 bug_if(cpl_propertylist_append_double(onlist, VISIR_PFITS_DOUBLE_PIXSPACE,
1338 cpl_propertylist_append_double(onlist, VISIR_DRS_CUMOFFSETXA, xjittera);
1339 cpl_propertylist_append_double(onlist, VISIR_DRS_CUMOFFSETYA, yjittera);
1340 cpl_propertylist_set_comment(onlist, VISIR_DRS_CUMOFFSETXA,
1342 cpl_propertylist_set_comment(onlist, VISIR_DRS_CUMOFFSETYA,
1345 cpl_propertylist_append_double(onlist, VISIR_DRS_CUMOFFSETXB, xjitterb);
1346 cpl_propertylist_append_double(onlist, VISIR_DRS_CUMOFFSETYB, yjitterb);
1347 cpl_propertylist_set_comment(onlist, VISIR_DRS_CUMOFFSETXB,
1349 cpl_propertylist_set_comment(onlist, VISIR_DRS_CUMOFFSETYB,
1352 bug_if(cpl_propertylist_append(offlist, onlist));
1354 cpl_propertylist_append_int(onlist,
"ESO DRS DTYPE", state->datatype);
1355 cpl_propertylist_append_int(offlist,
"ESO DRS DTYPE", state->datatype);
1358 if (state->time_max_filewrite > 0) {
1359 cpl_propertylist_append_double(onlist,
"ESO DRS DATE",
1360 state->time_max_filewrite);
1361 cpl_propertylist_append_double(offlist,
"ESO DRS DATE",
1362 state->time_max_filewrite);
1363 cpl_propertylist_append_double(onlist,
"ESO DRS DATE-OBS",
1364 state->time_min_obsstart);
1365 cpl_propertylist_append_double(offlist,
"ESO DRS DATE-OBS",
1366 state->time_min_obsstart);
1370 cpl_propertylist_append_double(onlist,
"ESO DRS DATE", -1.);
1371 cpl_propertylist_append_double(offlist,
"ESO DRS DATE", -1.);
1372 cpl_propertylist_append_double(onlist,
"ESO DRS DATE-OBS", -1.);
1373 cpl_propertylist_append_double(offlist,
"ESO DRS DATE-OBS", -1.);
1375 if (state->normalize) {
1376 cpl_propertylist_append_string(onlist,
"BUNIT",
"adu / s");
1377 cpl_propertylist_append_string(offlist,
"BUNIT",
"adu / s");
1380 cpl_propertylist_append_string(onlist,
"BUNIT",
"adu");
1381 cpl_propertylist_append_string(offlist,
"BUNIT",
"adu");
1388 for (
int i = 0; i < state->nframes; i++) {
1389 const cpl_frame * frm =
1391 bug_if(cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm)));
1394 skip_if(check_and_fix_cd_wcs(onlist, state->plist));
1395 skip_if(check_and_fix_cd_wcs(offlist, state->plist));
1397 if (products == NULL)
1398 products = cpl_frameset_new();
1401 if (state->datatype == VISIR_DATA_CUBE2) {
1402 skip_if(visir_qc_append_background(onlist, state->rawframes, 0, 0));
1403 skip_if(visir_qc_append_background(offlist, state->rawframes, 0, 0));
1405 else if (!isnan(bg_mean)) {
1406 bug_if (cpl_propertylist_append_double(onlist,
"ESO QC BACKGD MEAN",
1408 bug_if (cpl_propertylist_append_double(offlist,
"ESO QC BACKGD MEAN",
1412 if (state->bkgcorrect == VISIR_SUB_CHOPCORRECT ||
1413 state->bkgcorrect == VISIR_SUB_CHOPNODCORRECT) {
1415 RECIPE_STRING, state->procatgon,
1416 onlist, state->remregexp,
1423 RECIPE_STRING, state->procatgon,
1424 onlist, state->remregexp,
1425 visir_pipe_id, state->onname));
1428 RECIPE_STRING, state->procatgoff,
1429 offlist, state->remregexp,
1430 visir_pipe_id, state->offname));
1434 cpl_frameset_delete(usedframes);
1435 cpl_propertylist_delete(onlist);
1436 cpl_propertylist_delete(offlist);
1438 return cpl_error_get_code();
1442 static cpl_imagelist *
1443 correct_jitter(
const cpl_imagelist * imgs,
double dx,
double dy)
1445 cpl_imagelist * jit_cor = cpl_imagelist_new();
1446 cpl_msg_info(cpl_func,
"Correcting jitter, x: %g y: %g", dx, dy);
1447 for (cpl_size i = 0, n = cpl_imagelist_get_size(imgs); i < n; i++) {
1448 cpl_image * img = cpl_image_duplicate(cpl_imagelist_get_const(imgs, i));
1451 skip_if(cpl_image_shift(img,
1452 -visir_round_to_int(dx),
1453 -visir_round_to_int(dy)));
1454 cpl_imagelist_set(jit_cor, img, i);
1480 static cpl_imagelist *
1483 cpl_imagelist * off,
1484 const cpl_boolean last_chunk)
1486 cpl_imagelist * sub;
1488 cpl_imagelist * subt;
1490 subt = state->datatype == VISIR_DATA_BURST ? on : off;
1491 sub = state->datatype == VISIR_DATA_BURST ? off : on;
1494 equalize_lists(on, off);
1496 cpl_imagelist_subtract(sub, subt);
1497 if (state->normalize) {
1498 cpl_imagelist_multiply_scalar(sub, 1. / (state->dit * 2));
1501 cpl_imagelist_empty(subt);
1515 compute_qc_median(
const cpl_imagelist * list, cpl_size * nimages)
1518 for (cpl_size i = 0; i < cpl_imagelist_get_size(list); i++) {
1519 const cpl_image * img = cpl_imagelist_get_const(list, i);
1520 sum += cpl_image_get_median(img);
1523 *nimages += cpl_imagelist_get_size(list);
1537 static cpl_error_code
1539 cpl_imagelist * images,
1540 const cpl_bivector * lintable, cpl_image * nonlinear)
1542 if (lintable == NULL || !visir_data_is_aqu(state->datatype)) {
1543 return CPL_ERROR_NONE;
1545 for (
size_t i = 0; i < (size_t)cpl_imagelist_get_size(images); i++) {
1546 cpl_image * img = cpl_imagelist_get(images, i);
1547 cpl_ensure_code(cpl_image_get_type(img) == CPL_TYPE_FLOAT ||
1548 cpl_image_get_type(img) == CPL_TYPE_DOUBLE,
1549 CPL_ERROR_ILLEGAL_INPUT);
1550 cpl_image * dvals = cpl_image_cast(img, CPL_TYPE_DOUBLE);
1551 cpl_image * corvals = visir_linintp_values(dvals, lintable);
1554 cpl_image_new_from_mask(cpl_image_get_bpm(corvals));
1555 cpl_image_add(nonlinear, bad);
1556 cpl_image_delete(bad);
1558 cpl_image_divide(img, corvals);
1559 cpl_image_delete(dvals);
1560 cpl_image_delete(corvals);
1563 return cpl_error_get_code();
1583 static cpl_error_code
1586 cpl_imagelist * aon,
1587 cpl_imagelist * aoff,
1588 cpl_imagelist * bon,
1589 cpl_imagelist * boff,
1590 double dxa,
double dya,
1591 double dxb,
double dyb,
1592 const cpl_boolean last_chunk)
1594 cpl_imagelist * chop_corrected_a, * chop_corrected_b;
1598 if (state->chop_on) {
1599 chop_corrected_a = chop_correct(fstatea, aon, aoff, last_chunk);
1600 chop_corrected_b = chop_correct(fstateb, bon, boff, last_chunk);
1603 chop_corrected_a = aon;
1604 chop_corrected_b = bon;
1607 if (cpl_error_get_code())
1608 return cpl_error_get_code();
1610 if (state->bkgcorrect == VISIR_SUB_CHOPCORRECT) {
1612 save_subtract_images(fstatea, chop_corrected_a, NULL, NULL);
1613 save_subtract_images(fstateb, chop_corrected_b, NULL, NULL);
1619 cpl_imagelist * jca = NULL;
1620 cpl_imagelist * jcb = NULL;
1623 equalize_lists(chop_corrected_a, chop_corrected_b);
1625 if (state->normalize) {
1626 cpl_imagelist_divide_scalar(chop_corrected_a, 2);
1627 cpl_imagelist_divide_scalar(chop_corrected_b, 2);
1630 if (visir_round_to_int(dxa) != 0 ||
1631 visir_round_to_int(dya) != 0 ||
1632 visir_round_to_int(dxb) != 0 ||
1633 visir_round_to_int(dyb) != 0) {
1634 jca = correct_jitter(chop_corrected_a, dxa, dya);
1635 jcb = correct_jitter(chop_corrected_b, dxb, dyb);
1636 cpl_imagelist_subtract(jca, jcb);
1639 cpl_imagelist_subtract(chop_corrected_a, chop_corrected_b);
1641 save_subtract_images(state, chop_corrected_a, jca, NULL);
1642 cpl_imagelist_delete(jcb);
1643 cpl_imagelist_delete(jca);
1646 return cpl_error_get_code();
1649 static cpl_error_code
1652 cpl_imagelist * aon,
1653 cpl_imagelist * aoff,
1654 cpl_imagelist * bon,
1655 cpl_imagelist * boff)
1658 if (state->normalize) {
1659 cpl_imagelist_multiply_scalar(aon, 1. / fstatea->dit);
1660 cpl_imagelist_multiply_scalar(aoff, 1. / fstatea->dit);
1661 cpl_imagelist_multiply_scalar(bon, 1. / fstateb->dit);
1662 cpl_imagelist_multiply_scalar(boff, 1. / fstateb->dit);
1664 append_images(fstatea, aon, NULL, CPL_TRUE);
1665 append_images(fstatea, aoff, NULL, CPL_FALSE);
1666 append_images(fstateb, bon, NULL, CPL_TRUE);
1667 append_images(fstateb, boff, NULL, CPL_FALSE);
1668 cpl_imagelist_empty(aon);
1669 cpl_imagelist_empty(aoff);
1670 cpl_imagelist_empty(bon);
1671 cpl_imagelist_empty(boff);
1673 return cpl_error_get_code();
1676 #define VISIR_SWAP(a, b)\
1678 cpl_imagelist * tmp = a; \
1697 static cpl_error_code
1700 cpl_frameset * products,
1702 cpl_image * nonlinear,
1703 double xjitter0,
double yjitter0,
1704 const cpl_bivector * lintable)
1707 cpl_errorstate cleanstate = cpl_errorstate_get();
1709 int chunksize = 200;
1710 cpl_imagelist * aon = NULL;
1711 cpl_imagelist * aoff = NULL;
1712 cpl_imagelist * bon = NULL;
1713 cpl_imagelist * boff = NULL;
1715 cpl_imagelist * aon_next = NULL;
1716 cpl_imagelist * aoff_next = NULL;
1717 cpl_imagelist * bon_next = NULL;
1718 cpl_imagelist * boff_next = NULL;
1721 double dxa = fstatea->offsetx - xjitter0;
1722 double dya = fstatea->offsety - yjitter0;
1723 double dxb = fstateb->offsetx - xjitter0;
1724 double dyb = fstateb->offsety - yjitter0;
1726 double qc_bkg_sum = 0.;
1727 cpl_size qc_bkg_count = 0;
1732 if (visir_data_is_burst(state->datatype)) {
1733 chunksize = 2 * state->halfcycle;
1735 error_if(state->planeend - state->planestart < 2 * state->halfcycle,
1736 CPL_ERROR_ILLEGAL_INPUT,
1737 "Number of planes to be repacked must be larger than "
1738 "a full cycle of %d planes.", state->halfcycle * 2);
1742 if (chopnod_dir == NULL) {
1743 chopnod_dir =
"PARALLEL";
1744 cpl_errorstate_set(cleanstate);
1752 cpl_msg_info(cpl_func,
"POSANG: %g; Offset: (%g, %g); Throw: %g; "
1753 "Jitterwidth %g", fstateb->posang * CPL_MATH_RAD_DEG, dxb,
1754 dyb, fstateb->pthrow, fstateb->jitterwidth);
1755 if ((
int)rint(fstateb->posang * CPL_MATH_RAD_DEG) % 90 == 0) {
1756 if (dxb >= fstateb->pthrow - fstateb->jitterwidth - 10.) {
1757 dxb -= fstateb->pthrow;
1759 else if (dxb <= -(fstateb->pthrow - fstateb->jitterwidth - 10.)) {
1760 dxb += fstateb->pthrow;
1762 if (dyb >= fstateb->pthrow - fstateb->jitterwidth - 10.) {
1763 dyb -= fstateb->pthrow;
1765 else if (dyb <= -(fstateb->pthrow - fstateb->jitterwidth - 10.)) {
1766 dyb += fstateb->pthrow;
1769 dxb = fabs(dxb) < 0.001 ? 0. : dxb;
1770 dyb = fabs(dyb) < 0.001 ? 0. : dyb;
1774 if (fstateb->jitterwidth != 0.) {
1775 cpl_msg_warning(cpl_func,
1776 "Can't do jitter correction on non normal POSANG");
1782 aon = cpl_imagelist_new();
1783 aoff = cpl_imagelist_new();
1784 bon = cpl_imagelist_new();
1785 boff = cpl_imagelist_new();
1789 if (state->datatype != VISIR_DATA_AQU_INT) {
1790 const int pstart = state->planestart;
1791 const int pend = CX_MIN(pstart + chunksize, state->planeend);
1792 load_chunk(aon, aoff, fstatea, pstart, pend);
1793 load_chunk(bon, boff, fstateb, pstart, pend);
1795 if ((visir_data_is_aqu(state->datatype) || visir_data_is_burst(state->datatype)) &&
1796 state->datatype != VISIR_DATA_AQU_INT) {
1798 qc_bkg_sum += compute_qc_median(aon, &qc_bkg_count);
1799 qc_bkg_sum += compute_qc_median(aoff, &qc_bkg_count);
1800 qc_bkg_sum += compute_qc_median(bon, &qc_bkg_count);
1801 qc_bkg_sum += compute_qc_median(boff, &qc_bkg_count);
1805 if (state->bkgcorrect == VISIR_SUB_CHOPCORRECT ||
1806 state->bkgcorrect == VISIR_SUB_NOCORRECT) {
1807 prepare_output(fstatea, products, dxa, dya, dxb, dyb, qc_bkg_sum / qc_bkg_count);
1808 prepare_output(fstateb, products, dxa, dya, dxb, dyb, qc_bkg_sum / qc_bkg_count);
1810 else if (state->bkgcorrect == VISIR_SUB_CHOPNODCORRECT) {
1811 if (state->chop_on == CPL_FALSE)
1812 cpl_msg_info(cpl_func, VISIR_PFITS_BOOL_CHOP_STATUS
1813 " false, only doing nod correction.");
1814 prepare_output(state, products, dxa, dya, dxb, dyb, qc_bkg_sum / qc_bkg_count);
1818 if (state->datatype == VISIR_DATA_AQU_INT) {
1819 cpl_imagelist * a = cpl_imagelist_new();
1820 cpl_imagelist * b = cpl_imagelist_new();
1821 cpl_imagelist * jca = NULL;
1822 cpl_imagelist * jcb = NULL;
1823 const cpl_frame * frame;
1824 const char * filename;
1829 filename = cpl_frame_get_filename(frame);
1830 img = cpl_image_load(filename, CPL_TYPE_FLOAT, 0, 1);
1831 cpl_imagelist_set(a, img, cpl_imagelist_get_size(a));
1835 filename = cpl_frame_get_filename(frame);
1836 img = cpl_image_load(filename, CPL_TYPE_FLOAT, 0, 1);
1837 cpl_imagelist_set(b, img, cpl_imagelist_get_size(b));
1839 if (fstatea->normalize) {
1840 cpl_imagelist_multiply_scalar(a, 1. / (state->dit * 4));
1841 cpl_imagelist_multiply_scalar(b, 1. / (state->dit * 4));
1844 if (visir_round_to_int(dxa) != 0 ||
1845 visir_round_to_int(dya) != 0 ||
1846 visir_round_to_int(dxb) != 0 ||
1847 visir_round_to_int(dyb) != 0) {
1848 jca = correct_jitter(a, dxa, dya);
1849 jcb = correct_jitter(b, dxb, dyb);
1850 cpl_imagelist_subtract(jca, jcb);
1851 cpl_imagelist_subtract(a, b);
1852 save_subtract_images(fstatea, a, jca, NULL);
1855 cpl_imagelist_subtract(a, b);
1856 save_subtract_images(fstatea, a, jca, NULL);
1859 cpl_imagelist_delete(a);
1860 cpl_imagelist_delete(b);
1861 cpl_imagelist_delete(jca);
1862 cpl_imagelist_delete(jcb);
1865 aon_next = cpl_imagelist_new();
1866 aoff_next = cpl_imagelist_new();
1867 bon_next = cpl_imagelist_new();
1868 boff_next = cpl_imagelist_new();
1870 for (
int pstart = state->planestart;
1871 pstart < state->planeend + chunksize - 1 &&
1872 state->datatype != VISIR_DATA_AQU_INT;
1873 pstart += chunksize) {
1874 const int pend = CX_MIN(pstart + chunksize, state->planeend);
1884 if (pstart != state->planestart) {
1887 cpl_imagelist_empty(aon);
1888 cpl_imagelist_empty(aoff);
1889 cpl_imagelist_empty(bon);
1890 cpl_imagelist_empty(boff);
1893 OMP3_PRAGMA(omp taskwait);
1895 VISIR_SWAP(aon, aon_next);
1896 VISIR_SWAP(aoff, aoff_next);
1897 VISIR_SWAP(bon, bon_next);
1898 VISIR_SWAP(boff, boff_next);
1902 if (pend < state->planeend) {
1903 int pend_next = CX_MIN(pend + chunksize, state->planeend);
1904 OMP3_PRAGMA(omp task) {
1905 load_chunk(aon_next, aoff_next, fstatea, pend, pend_next);
1906 load_chunk(bon_next, boff_next, fstateb, pend, pend_next);
1910 if (*pbpm == NULL && state->datatype == VISIR_DATA_CUBE2) {
1912 *pbpm = cpl_image_duplicate(cpl_imagelist_get(aon, 0));
1913 cpl_image_threshold(*pbpm, state->bpmthresh,
1914 state->bpmthresh, 0.0, 1.0);
1918 correct_linearity(fstatea, aon, lintable, nonlinear);
1919 correct_linearity(fstatea, aoff, lintable, nonlinear);
1920 correct_linearity(fstateb, bon, lintable, nonlinear);
1921 correct_linearity(fstateb, boff, lintable, nonlinear);
1923 if (state->bkgcorrect == VISIR_SUB_CHOPCORRECT ||
1924 state->bkgcorrect == VISIR_SUB_CHOPNODCORRECT) {
1925 cpl_boolean last_chunk = pstart + chunksize >= pend;
1926 skip_if(save_corrected(fstatea, fstateb,
1927 aon, aoff, bon, boff,
1928 dxa, dya, dxb, dyb, last_chunk));
1931 skip_if(save_uncorrected(fstatea, fstateb, aon, aoff, bon, boff));
1936 cpl_imagelist_delete(aon);
1937 cpl_imagelist_delete(aoff);
1938 cpl_imagelist_delete(bon);
1939 cpl_imagelist_delete(boff);
1940 cpl_imagelist_delete(aon_next);
1941 cpl_imagelist_delete(aoff_next);
1942 cpl_imagelist_delete(bon_next);
1943 cpl_imagelist_delete(boff_next);
1945 return cpl_error_get_code();
1959 static inline cpl_error_code visir_util_repack_check(
const cpl_image *
self,
1960 const cpl_imagelist * on,
1961 const cpl_imagelist * off)
1964 cpl_image * meanon = cpl_imagelist_collapse_create(on);
1965 cpl_image * meanoff = cpl_imagelist_collapse_create(off);
1966 const cpl_error_code err1 = cpl_image_subtract(meanon, meanoff);
1967 const cpl_error_code err2 = cpl_image_subtract(meanon,
self);
1968 const unsigned bitmask = CPL_STATS_MIN | CPL_STATS_MAX | CPL_STATS_MEAN
1969 | CPL_STATS_MEDIAN | CPL_STATS_MEDIAN_DEV | CPL_STATS_STDEV;
1971 cpl_stats * stats = cpl_stats_new_from_image(meanon, bitmask);
1973 bug_if(err1 + err2);
1975 bug_if(cpl_stats_dump(stats, bitmask, stderr));
1979 cpl_image_delete(meanon);
1980 cpl_image_delete(meanoff);
1981 cpl_stats_delete(stats);
1983 return cpl_error_get_code();
double visir_pfits_get_cumoffsetx(const cpl_propertylist *self)
The cumulative offset in X.
int visir_pfits_get_naxis2(const cpl_propertylist *self)
The NAXIS2 key.
int visir_pfits_get_win_ny(const cpl_propertylist *self)
The WIN NY key.
double visir_pfits_get_chop_pthrow(const cpl_propertylist *self)
The chopping throw in pixels.
int visir_pfits_get_naxis3(const cpl_propertylist *self)
The NAXIS3 key.
int visir_pfits_get_start_x(const cpl_propertylist *self)
The WIN STRX key.
int visir_pfits_get_naxis1(const cpl_propertylist *self)
The NAXIS1 key.
cpl_error_code irplib_dfs_save_propertylist(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save a propertylist as a DFS-compliant pipeline product.
irplib_framelist * irplib_framelist_extract_regexp(const irplib_framelist *self, const char *regexp, cpl_boolean invert)
Extract the frames with the given tag from a framelist.
const char * visir_pfits_get_frame_type(const cpl_propertylist *self)
The frame type.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
double visir_pfits_get_chop_posang(const cpl_propertylist *self)
The chopping position angle in rad.
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.
int visir_pfits_get_win_nx(const cpl_propertylist *self)
The WIN NX key.
int visir_pfits_get_ndit(const cpl_propertylist *self)
The NDIT keyword.
double visir_pfits_get_cumoffsety(const cpl_propertylist *self)
The cumulative offset in Y.
cpl_frame * irplib_framelist_get(irplib_framelist *self, int pos)
Get the specified frame from the framelist.
double visir_pfits_get_chop_freq(const cpl_propertylist *self)
The chopping frequency.
double visir_pfits_get_pixspace(const cpl_propertylist *self)
The pixel spacing.
const char * visir_pfits_get_nodpos(const cpl_propertylist *self)
The nodding position.
int visir_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
double visir_pfits_get_dit(const cpl_propertylist *self)
The DIT.
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
double visir_pfits_get_pixscale(const cpl_propertylist *self)
The pixel scale.
double visir_pfits_get_chop_stat(const cpl_propertylist *self)
The chopping status.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
const char * visir_pfits_get_chopnod_dir(const cpl_propertylist *self)
The chopping direction.
int visir_pfits_get_start_y(const cpl_propertylist *self)
The WIN STRY key.
cpl_error_code irplib_framelist_load_propertylist(irplib_framelist *self, int pos, int ind, const char *regexp, cpl_boolean invert)
Load the propertylist of the specified frame in the framelist.
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.