24#include "eris_nix_img_supersky.h"
25#include "eris_nix_utils.h"
26#include "eris_nix_dfs.h"
27#include "eris_pfits.h"
28#include "eris_utils.h"
32static hdrl_image * eris_create_sky_flat_first(
33 hdrl_imagelist * image_list,
38 const cpl_size plane_id);
40static hdrl_image * eris_create_sky_flat_final(
41 hdrl_imagelist * image_list,
46 const cpl_size plane_id);
48static cpl_mask * eris_detect_sources_hdrl_catalogue(
49 const cpl_image * image,
52static cpl_mask * eris_dilate_mask(
53 const cpl_mask * input_mask,
57eris_image_stats(
const hdrl_image *in_image,
72eris_first_sky_sub(
const hdrl_imagelist* science_images,
const hdrl_image* sky_flat_0,
73 hdrl_imagelist** skysub_images);
76eris_locate_and_mask_sources(hdrl_imagelist* skysub_images,
const cpl_image* bpm_image,
77 const cpl_parameterlist* parlist,
const char* RECIPE_NAME, cpl_mask** source_masks);
80eris_load_data_and_crea_error(
const char* fname,
const cpl_size kk,
const cpl_mask* bad_pixel_map,
81 hdrl_imagelist** science_images);
84eris_load_data_and_error_simple(
const char* fname,
const cpl_size kk,
const cpl_mask* bad_pixel_map,
85 hdrl_imagelist** science_images);
88eris_load_and_error_cube(
const char* fname,
const cpl_mask* bad_pixel_map, cpl_size* kkk,
89 hdrl_imagelist** science_images);
93eris_create_final_skysub_products(
const hdrl_imagelist* science_iml,
const hdrl_image* sky_flat, cpl_frameset** products);
96eris_crea_imagelist_all(cpl_frameset* raw_frames, cpl_mask* bad_pixel_map);
99eris_check_format_is_cube_of_same_size(
const cpl_frameset * raw_frames);
102eris_load_and_error_cube_slice(
const char* fname,
const cpl_mask* bad_pixel_map,
const cpl_size k,
103 const cpl_size kkk, hdrl_imagelist** science_images);
105eris_save_sky_flat_final(
const cpl_frameset* raw_frames,
const hdrl_image* sky_flat_final, cpl_frameset** product_frames);
107static const int debug = 0;
129cpl_error_code eris_nix_img_supersky_run(
130 cpl_frameset * frameset,
131 const cpl_parameterlist * parlist,
132 const char* RECIPE_NAME,
133 cpl_frameset ** product_frames)
135 cpl_frameset * raw_frames = NULL;
136 const cpl_frame * bpm_frame = NULL;
137 cpl_mask * bad_pixel_map = NULL;
138 hdrl_imagelist * science_images = NULL;
139 hdrl_imagelist * skysub_images_0 = NULL;
140 cpl_mask ** source_masks = NULL;
141 hdrl_image * sky_flat_0 = NULL;
142 hdrl_image * sky_flat_final = NULL;
147 const char * combine_method;
150 cpl_boolean save_skysub;
151 cpl_error_code error = CPL_ERROR_NONE;
153 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
154 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
155 cpl_ensure_code(product_frames, CPL_ERROR_NULL_INPUT);
158 combine_method = cpl_parameter_get_string(
159 cpl_parameterlist_find_const(parlist,
"eris.eris_nix_img_supersky.combine_method"));
160 sigma_clip = cpl_parameter_get_double(
161 cpl_parameterlist_find_const(parlist,
"eris.eris_nix_img_supersky.sigma_clip"));
162 max_iter = cpl_parameter_get_int(
163 cpl_parameterlist_find_const(parlist,
"eris.eris_nix_img_supersky.max_iter"));
164 save_skysub = cpl_parameter_get_bool(
165 cpl_parameterlist_find_const(parlist,
"eris.eris_nix_img_supersky.save_skysub"));
169 if (!raw_frames || cpl_frameset_get_size(raw_frames) == 0) {
172 if (!raw_frames || cpl_frameset_get_size(raw_frames) == 0) {
173 cpl_msg_error(cpl_func,
"No science frames found with tag %s or %s",
174 ERIS_NIX_IMG_SUPERSKY_OBJ_RAW, ERIS_NIX_IMG_SUPERSKY_STD_RAW);
175 error = CPL_ERROR_DATA_NOT_FOUND;
178 num_frames = cpl_frameset_get_size(raw_frames);
179 cpl_msg_info(cpl_func,
"Processing %d science frames", num_frames);
182 bpm_frame = cpl_frameset_find_const(frameset, ERIS_NIX_IMG_SUPERSKY_BPM);
184 cpl_msg_warning(cpl_func,
"No bad pixel map found with tag %s", ERIS_NIX_IMG_SUPERSKY_BPM);
186 cpl_image * bpm_image = NULL;
189 bpm_image = cpl_image_load(cpl_frame_get_filename(bpm_frame), CPL_TYPE_INT, 0, 0);
192 bad_pixel_map = cpl_mask_threshold_image_create(bpm_image, 0.5, DBL_MAX);
194 cpl_mask_save(bad_pixel_map,
"bad_pixel_map.fits", NULL, CPL_IO_DEFAULT);
198 cpl_boolean format_is_cube_of_same_size = CPL_TRUE;
199 cpl_boolean test_cubes_slices = CPL_TRUE;
200 format_is_cube_of_same_size = eris_check_format_is_cube_of_same_size(raw_frames);
201 cpl_size num_tot_images = 0;
203 *product_frames = cpl_frameset_new();
204 if(!format_is_cube_of_same_size) {
207 science_images = eris_crea_imagelist_all(raw_frames, bad_pixel_map);
210 cpl_msg_info(cpl_func,
"Creating first-pass super-sky flat...");
211 sky_flat_0 = eris_create_sky_flat_first(science_images, bad_pixel_map, combine_method, sigma_clip,
215 eris_first_sky_sub(science_images, sky_flat_0, &skysub_images_0);
218 eris_print_rec_status(300);
221 cpl_msg_info(cpl_func,
"num_tot_images: %lld",num_tot_images);
222 source_masks = cpl_calloc(num_tot_images,
sizeof(cpl_mask *));
224 eris_locate_and_mask_sources(skysub_images_0, bpm_image, parlist, RECIPE_NAME, source_masks);
226 eris_print_rec_status(400);
228 cpl_msg_info(cpl_func,
"Creating final super-sky flat with source masking...");
229 sky_flat_final = eris_create_sky_flat_final(science_images, source_masks,
230 combine_method, sigma_clip, max_iter, -1);
231 eris_print_rec_status(450);
233 eris_print_rec_status(460);
235 if (!sky_flat_final) {
236 cpl_msg_error(cpl_func,
"Failed to create final sky flat");
237 error = CPL_ERROR_ILLEGAL_OUTPUT;
243 eris_print_rec_status(500);
245 eris_save_sky_flat_final(raw_frames, sky_flat_final, product_frames);
251 eris_create_final_skysub_products(science_images, sky_flat_final, product_frames);
257 if (source_masks != NULL) {
258 for (
int i = 0; i < num_tot_images; i++) {
259 if (source_masks[i]) cpl_mask_delete(source_masks[i]);
261 cpl_free(source_masks);
264 cpl_msg_warning(cpl_func,
"cube format, process slice by slice");
266 const cpl_frame * frame = cpl_frameset_get_position_const(raw_frames, 0);
267 const char * filename = cpl_frame_get_filename(frame);
268 cpl_imagelist * data_iml = cpl_imagelist_load(filename, CPL_TYPE_DOUBLE, 1);
269 cpl_size nplanes = cpl_imagelist_get_size(data_iml);
271 for(cpl_size k = 0; k < nplanes; k++) {
273 for(cpl_size kkk = 0; kkk < num_frames; kkk++) {
274 frame = cpl_frameset_get_position_const(raw_frames, kkk);
275 filename = cpl_frame_get_filename(frame);
276 eris_load_and_error_cube_slice(filename, bad_pixel_map, k, kkk, &science_images);
280 cpl_msg_info(cpl_func,
"Creating first-pass super-sky flat...");
281 sky_flat_0 = eris_create_sky_flat_first(science_images, bad_pixel_map, combine_method, sigma_clip, max_iter, k);
284 eris_first_sky_sub(science_images, sky_flat_0, &skysub_images_0);
286 eris_print_rec_status(300);
289 cpl_msg_info(cpl_func,
"num_tot_images: %lld",num_tot_images);
290 source_masks = cpl_calloc(num_tot_images,
sizeof(cpl_mask *));
292 eris_locate_and_mask_sources(skysub_images_0, bpm_image, parlist, RECIPE_NAME, source_masks);
294 eris_print_rec_status(400);
296 cpl_msg_info(cpl_func,
"Creating final super-sky flat with source masking...");
298 sky_flat_final = eris_create_sky_flat_final(science_images, source_masks,
299 combine_method, sigma_clip, max_iter, k);
302 eris_create_final_skysub_products(science_images, sky_flat_final, product_frames);
311 if (source_masks != NULL) {
312 for (
int i = 0; i < num_tot_images; i++) {
313 if (source_masks[i]) cpl_mask_delete(source_masks[i]);
315 cpl_free(source_masks);
318 cpl_imagelist_delete(data_iml);
321 eris_print_rec_status(700);
323 eris_print_rec_status(800);
324 cpl_msg_info(cpl_func,
"Super-sky recipe completed successfully");
327 eris_print_rec_status(600);
328 if (raw_frames) cpl_frameset_delete(raw_frames);
329 if (bad_pixel_map) cpl_mask_delete(bad_pixel_map);
332 if(bpm_image !=NULL) cpl_image_delete(bpm_image);
339eris_save_sky_flat_final(
const cpl_frameset* raw_frames,
const hdrl_image* sky_flat_final, cpl_frameset** product_frames)
343 cpl_size num_frames = cpl_frameset_get_size(raw_frames);
344 eris_print_rec_status(500);
349 cpl_propertylist* plist = cpl_propertylist_load(cpl_frame_get_filename(
350 cpl_frameset_get_position_const(raw_frames, 0)), 0);
351 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG, ERIS_NIX_IMG_SUPERSKY_SKYFLAT);
352 cpl_propertylist_update_double(plist,
"ESO QC SKY MEDIAN", med_sky_final.data);
353 cpl_propertylist_update_int(plist,
"ESO QC NFRAMES", num_frames);
354 eris_print_rec_status(600);
355 char* fname = cpl_sprintf(
"sky_flat_2nd.fits");
359 cpl_frame * product = cpl_frame_new();
360 cpl_frame_set_filename(product, fname);
361 cpl_frame_set_tag(product, ERIS_NIX_IMG_SUPERSKY_SKYFLAT);
362 cpl_frame_set_type(product, CPL_FRAME_TYPE_IMAGE);
363 cpl_frame_set_group(product, CPL_FRAME_GROUP_PRODUCT);
364 cpl_frameset_insert(*product_frames, product);
367 cpl_propertylist_delete(plist);
370 return cpl_error_get_code();
373static hdrl_imagelist*
374eris_crea_imagelist_all(cpl_frameset* raw_frames, cpl_mask* bad_pixel_map)
379 cpl_size num_frames = cpl_frameset_get_size(raw_frames);
381 const char* format = NULL;
382 cpl_propertylist* pheader = NULL;
383 eris_print_rec_status(100);
385 for (cpl_size kk = 0; kk < num_frames; kk++) {
386 const cpl_frame * frame = cpl_frameset_get_position_const(raw_frames, kk);
387 const char * filename = cpl_frame_get_filename(frame);
388 next = cpl_frame_get_nextensions(frame);
389 pheader = cpl_propertylist_load(filename,0);
393 eris_load_data_and_crea_error(filename, kk, bad_pixel_map, &science_images);
395 cpl_msg_info(cpl_func,
"sci data with extentions %s", filename);
396 if(!strcmp(format,
"single")) {
397 eris_load_data_and_error_simple(filename, kk, bad_pixel_map, &science_images);
399 eris_load_and_error_cube(filename, bad_pixel_map, &kkk, &science_images);
402 cpl_propertylist_delete(pheader);
407 cpl_msg_info(cpl_func,
"Image dimensions: %lld x %lld", nx, ny);
411 return science_images;
415eris_check_format_is_cube_of_same_size(
const cpl_frameset * raw_frames)
418 cpl_boolean result = CPL_TRUE;
419 cpl_size nplanes = 0;
420 cpl_size nplanes_tmp = 0;
422 cpl_size num_frames = cpl_frameset_get_size(raw_frames);
424 for (
int kk = 0; kk < num_frames; kk++) {
425 const cpl_frame * frame = cpl_frameset_get_position_const(raw_frames, kk);
426 next = cpl_frame_get_nextensions(frame);
429 const char * fname = cpl_frame_get_filename(frame);
431 cpl_propertylist* xhead = cpl_propertylist_load(fname,1);
432 if(cpl_propertylist_has(xhead,
"CD3_3")) {
433 cpl_imagelist * data_iml = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 1);
435 nplanes_tmp = cpl_imagelist_get_size(data_iml);
437 nplanes = nplanes_tmp;
438 }
else if (nplanes_tmp != nplanes) {
439 cpl_msg_info(cpl_func,
"cubes not of same size");
442 cpl_imagelist_delete(data_iml);
444 cpl_msg_info(cpl_func,
"Input Data are simple format (images)");
445 cpl_propertylist_delete(xhead);
448 cpl_propertylist_delete(xhead);
450 cpl_msg_info(cpl_func,
"Data with less than 4 extensions");
470eris_create_final_skysub_products(
const hdrl_imagelist* science_iml,
const hdrl_image* sky_flat, cpl_frameset** products)
473 cpl_msg_info(cpl_func,
"Saving sky-subtracted frames...");
477 for (
int i = 0; i < num_tot_images; i++) {
482 scale.data = med_img.data / med_sky.data;
491 snprintf(outfile, 256,
"sci_skysub_2nd_%03d.fits", i);
494 cpl_msg_info(cpl_func,
"ESO QC SKY_MED: %g",med_img.data);
495 cpl_msg_info(cpl_func,
"ESO QC SKYSUB_MED: %g", med_skyub.data);
509 cpl_frame * product = cpl_frame_new();
510 cpl_frame_set_filename(product, outfile);
511 cpl_frame_set_tag(product, ERIS_NIX_IMG_SUPERSKY_SKYSUB);
512 cpl_frame_set_type(product, CPL_FRAME_TYPE_IMAGE);
513 cpl_frame_set_group(product, CPL_FRAME_GROUP_PRODUCT);
514 cpl_frameset_insert(*products, product);
521 return cpl_error_get_code();
535eris_load_and_error_cube(
const char* fname,
const cpl_mask* bad_pixel_map, cpl_size* kkk,
536 hdrl_imagelist** science_images){
538 eris_print_rec_status(0);
539 cpl_imagelist * data_iml = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 1);
540 cpl_imagelist * error_iml = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 2);
541 cpl_mask * dqual_msk = cpl_mask_load(fname, 0, 3);
542 cpl_imagelist * confm_iml = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 4);
544 double* pconf_img = cpl_image_get_data_double(cpl_imagelist_get(confm_iml,0));
546 cpl_binary* pbpm = cpl_mask_get_data(dqual_msk);
547 cpl_size sx = cpl_mask_get_size_x(dqual_msk);
548 cpl_size sy = cpl_mask_get_size_y(dqual_msk);
549 cpl_size sz = cpl_imagelist_get_size(data_iml);
551 cpl_mask* mask_tot = cpl_mask_duplicate(dqual_msk);
553 cpl_mask_or(mask_tot, bad_pixel_map);
555 double* pdata = NULL;
556 cpl_image * data_img = NULL;
557 cpl_image * error_img = NULL;
560 for (cpl_size k = 0; k < sz; k++) {
561 data_img = cpl_imagelist_get(data_iml,k);
562 error_img = cpl_imagelist_get(error_iml,k);
563 pdata = cpl_image_get_data(cpl_imagelist_get(data_iml,k));
564 for (cpl_size j = 0; j < sy; j++) {
567 for (cpl_size i = 0; i < sx; i++) {
570 if((pconf_img[pixel] == 0) || !isfinite(pdata[pixel])) {
571 pbpm[pixel] = CPL_BINARY_1;
577 cpl_image_reject_from_mask(data_img, mask_tot);
578 cpl_image_reject_from_mask(error_img, mask_tot);
585 cpl_mask_delete(mask_tot);
586 cpl_mask_delete(dqual_msk);
587 cpl_imagelist_delete(data_iml);
588 cpl_imagelist_delete(error_iml);
589 cpl_imagelist_delete(confm_iml);
592 return cpl_error_get_code();
610eris_load_and_error_cube_slice(
const char* fname,
const cpl_mask* bad_pixel_map,
const cpl_size k,
611 const cpl_size kkk, hdrl_imagelist** science_images){
614 cpl_imagelist * data_iml = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 1);
615 cpl_imagelist * error_iml = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 2);
616 cpl_mask * dqual_msk = cpl_mask_load(fname, 0, 3);
617 cpl_imagelist * confm_iml = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 4);
619 double* pconf_img = cpl_image_get_data_double(cpl_imagelist_get(confm_iml,0));
621 cpl_binary* pbpm = cpl_mask_get_data(dqual_msk);
622 cpl_size sx = cpl_mask_get_size_x(dqual_msk);
623 cpl_size sy = cpl_mask_get_size_y(dqual_msk);
625 cpl_mask* mask_tot = cpl_mask_duplicate(dqual_msk);
627 cpl_mask_or(mask_tot, bad_pixel_map);
629 double* pdata = NULL;
630 cpl_image * data_img = NULL;
631 cpl_image * error_img = NULL;
635 data_img = cpl_imagelist_get(data_iml,k);
636 error_img = cpl_imagelist_get(error_iml,k);
637 pdata = cpl_image_get_data(cpl_imagelist_get(data_iml,k));
639 for (cpl_size j = 0; j < sy; j++) {
642 for (cpl_size i = 0; i < sx; i++) {
645 if((pconf_img[pixel] == 0) || !isfinite(pdata[pixel])) {
646 pbpm[pixel] = CPL_BINARY_1;
652 cpl_image_reject_from_mask(data_img, mask_tot);
653 cpl_image_reject_from_mask(error_img, mask_tot);
657 cpl_mask_delete(mask_tot);
658 cpl_mask_delete(dqual_msk);
659 cpl_imagelist_delete(data_iml);
660 cpl_imagelist_delete(error_iml);
661 cpl_imagelist_delete(confm_iml);
664 return cpl_error_get_code();
681eris_load_data_and_error_simple(
const char* fname,
const cpl_size kk,
const cpl_mask* bad_pixel_map,
682 hdrl_imagelist** science_images)
685 cpl_ensure_code(fname, CPL_ERROR_NULL_INPUT);
686 cpl_image * data_img = cpl_image_load(fname, CPL_TYPE_DOUBLE, 0, 1);
687 cpl_image * error_img = cpl_image_load(fname, CPL_TYPE_DOUBLE, 0, 2);
688 cpl_mask* dqual_msk = cpl_mask_load(fname, 0, 3);
689 cpl_image* confm_img = cpl_image_load(fname, CPL_TYPE_DOUBLE, 0, 4);
690 double* pdata = cpl_image_get_data(data_img);
691 double* pconf_img = cpl_image_get_data_double(confm_img);
692 cpl_binary* pbpm = cpl_mask_get_data(dqual_msk);
693 cpl_size sx = cpl_image_get_size_x(confm_img);
694 cpl_size sy = cpl_image_get_size_y(confm_img);
697 for (cpl_size j = 0; j < sy; j++) {
700 for (cpl_size i = 0; i < sx; i++) {
703 if((pconf_img[pixel] == 0) || !isfinite(pdata[pixel])) {
704 pbpm[pixel] = CPL_BINARY_1;
710 cpl_mask* mask_tot = cpl_mask_duplicate(dqual_msk);
712 cpl_mask_or(mask_tot, bad_pixel_map);
714 cpl_image_reject_from_mask(data_img, mask_tot);
715 cpl_image_reject_from_mask(error_img, mask_tot);
723 cpl_image_delete(data_img);
724 cpl_image_delete(error_img);
725 cpl_mask_delete(mask_tot);
726 cpl_mask_delete(dqual_msk);
727 cpl_image_delete(confm_img);
731 double median=0, mean=0, stdev=0,tmean=0, tstd=0, mad=0, min_val=0, max_val=0;
738 &median, &mean, &stdev, &tmean, &tstd, &mad, &min_val, &max_val
741 cpl_msg_info(cpl_func,
"process file: %s", fname);
742 cpl_msg_info(cpl_func,
"Median=%.3f, Mean=%.3f, StdDev=%.3f "
743 "Trimmed: Mean=%.3f, StdDev=%.3f, MAD=%.3f "
744 "Range: [%.3f, %.3f]", median, mean, stdev, tmean, tstd, mad, min_val, max_val);
747 return cpl_error_get_code();
762eris_load_data_and_crea_error(
const char* fname,
const cpl_size kk,
const cpl_mask* bad_pixel_map,
763 hdrl_imagelist** science_images)
765 cpl_ensure_code(fname, CPL_ERROR_NULL_INPUT);
766 cpl_image * data_img = NULL;
767 cpl_image * error_img = NULL;
768 cpl_msg_info(cpl_func,
"sci data with less than 4 extensions");
769 data_img = cpl_image_load(fname, CPL_TYPE_DOUBLE, 0, 0);
771 cpl_msg_error(cpl_func,
"Failed to load frame %s", fname);
773 return cpl_error_get_code();
775 double* pdata = NULL;
776 cpl_mask * dqual_msk = NULL;
777 pdata = cpl_image_get_data(data_img);
778 dqual_msk = cpl_image_get_bpm(data_img);
779 cpl_size sx = cpl_image_get_size_x(data_img);
780 cpl_size sy = cpl_image_get_size_y(data_img);
781 cpl_binary* pbpm = cpl_mask_get_data(dqual_msk);
784 for (cpl_size j = 0; j < sy; j++) {
786 for (cpl_size i = 0; i < sx; i++) {
788 if(!isfinite(pdata[pixel])) {
789 pbpm[pixel] = CPL_BINARY_1;
794 cpl_mask* mask_tot = cpl_mask_duplicate(dqual_msk);
796 cpl_mask_or(mask_tot, bad_pixel_map);
799 cpl_image_reject_from_mask(data_img, mask_tot);
802 error_img = cpl_image_duplicate(data_img);
803 cpl_image_abs(error_img);
804 cpl_image_add_scalar(error_img, 1.0);
805 cpl_image_power(error_img, 0.5);
811 cpl_image_delete(data_img);
812 cpl_image_delete(error_img);
813 cpl_mask_delete(mask_tot);
816 return cpl_error_get_code();
832eris_locate_and_mask_sources(hdrl_imagelist* skysub_images,
const cpl_image* bpm_image,
833 const cpl_parameterlist* parlist,
const char* RECIPE_NAME, cpl_mask** source_masks)
835 cpl_msg_info(cpl_func,
"Detecting sources...");
841 const hdrl_catalogue_options opt = HDRL_CATALOGUE_SEGMAP;
846 for (
int i = 0; i < num_tot_images; i++) {
850 cpl_mask *bpm = cpl_mask_threshold_image_create(bpm_image, 0, INT_MAX);
851 cpl_image_reject_from_mask(data, bpm);
852 cpl_mask_delete(bpm);
854 source_masks[i] = eris_detect_sources_hdrl_catalogue(data, par_cat);
856 char* fname = cpl_sprintf(
"msk_%d.fits",i);
857 cpl_mask_save(source_masks[i], fname, NULL, CPL_IO_DEFAULT);
861 cpl_mask* bad_pixel_map = cpl_mask_threshold_image_create(bpm_image, 0.5, DBL_MAX);
863 int nsources = cpl_mask_count(source_masks[i]) - cpl_mask_count(bad_pixel_map);
864 cpl_msg_info(cpl_func,
" Frame %d: detected %d source pixels", i+1, nsources);
866 cpl_mask_delete(bad_pixel_map);
869 for (
int i = 0; i < num_tot_images; i++) {
873 cpl_mask *bpm = cpl_mask_threshold_image_create(bpm_image, 0, INT_MAX);
874 cpl_image_reject_from_mask(data, bpm);
875 cpl_mask_delete(bpm);
877 source_masks[i] = eris_detect_sources_hdrl_catalogue(data, par_cat);
880 cpl_mask* bad_pixel_map = cpl_mask_threshold_image_create(bpm_image, 0.5, DBL_MAX);
882 int nsources = cpl_mask_count(source_masks[i]) - cpl_mask_count(bad_pixel_map);
883 cpl_msg_info(cpl_func,
" Frame %d: detected %d source pixels", i+1, nsources);
885 cpl_mask_delete(bad_pixel_map);
890 for (
int i = 0; i < num_tot_images; i++) {
894 source_masks[i] = eris_detect_sources_hdrl_catalogue(data, par_cat);
895 char* fname = cpl_sprintf(
"msk_%d.fits",i);
896 cpl_mask_save(source_masks[i], fname, NULL, CPL_IO_DEFAULT);
899 int nsources = cpl_mask_count(source_masks[i]);
900 cpl_msg_info(cpl_func,
" Frame %d: detected %d source pixels", i+1, nsources);
903 for (
int i = 0; i < num_tot_images; i++) {
907 source_masks[i] = eris_detect_sources_hdrl_catalogue(data, par_cat);
909 int nsources = cpl_mask_count(source_masks[i]);
910 cpl_msg_info(cpl_func,
" Frame %d: detected %d source pixels", i+1, nsources);
918 return cpl_error_get_code();
930eris_first_sky_sub(
const hdrl_imagelist* science_images,
const hdrl_image* sky_flat_0,
931 hdrl_imagelist** skysub_images)
934 cpl_msg_info(cpl_func,
"Subtracting first-pass sky flat...");
938 hdrl_value scale = {0, 0};
940 for (
int i = 0; i < num_tot_images; i++) {
944 scale.data = med_img.data / med_sky_0.data;
950 fname = cpl_sprintf(
"sci_%d.fits",i);
953 fname = cpl_sprintf(
"scaled_sky_0_%d.fits",i);
961 fname = cpl_sprintf(
"sci_skysub_1st_%03d.fits",i);
970 return cpl_error_get_code();
973#define HDRL_USE_PRIVATE YES
985static hdrl_image * eris_create_sky_flat_first(
986 hdrl_imagelist * image_list,
991 const cpl_size plane_id)
993 hdrl_image * result = NULL;
995 hdrl_imagelist * masked_list = NULL;
996 hdrl_parameter * collapse_par = NULL;
999 cpl_ensure(image_list, CPL_ERROR_NULL_INPUT, NULL);
1000 cpl_ensure(method, CPL_ERROR_NULL_INPUT, NULL);
1003 cpl_ensure(num_images > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1004 cpl_msg_warning(cpl_func,
"kappa: %g niter: %d", kappa, niter);
1009 for (
int i = 0; i < num_images; i++) {
1015 cpl_image_reject_from_mask(data, mask);
1020 masked_list = image_list;
1024 if (strcmp(method,
"median") == 0) {
1027 cpl_msg_info(cpl_func,
"kappa: %g niter: %d",kappa, niter);
1036 fname = cpl_sprintf(
"sky_flat_1st.fits");
1038 fname = cpl_sprintf(
"sky_flat_1st_plane_%3.3lld.fits",plane_id);
1045 cpl_image_delete(contrib);
1062static hdrl_image * eris_create_sky_flat_final(
1063 hdrl_imagelist * image_list,
1065 const char * method,
1068 const cpl_size plane_id)
1070 hdrl_image * result = NULL;
1071 hdrl_imagelist * masked_list = NULL;
1072 hdrl_parameter * collapse_par = NULL;
1073 cpl_image* contrib = NULL;
1075 cpl_ensure(image_list, CPL_ERROR_NULL_INPUT, NULL);
1076 cpl_ensure(method, CPL_ERROR_NULL_INPUT, NULL);
1079 cpl_ensure(num_images > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1085 for (
int i = 0; i < num_images; i++) {
1093 cpl_image_reject_from_mask(data, masks[i]);
1097 fname = cpl_sprintf(
"mask_%d.fits",i);
1099 fname = cpl_sprintf(
"mask_%d_%3.3lld.fits",i,plane_id);
1102 cpl_mask_save(masks[i], fname, NULL, CPL_IO_DEFAULT);
1110 masked_list = image_list;
1114 if (strcmp(method,
"median") == 0) {
1126 fname = cpl_sprintf(
"sky_flat_2nd.fits");
1128 fname = cpl_sprintf(
"sky_flat_2nd_plane_%3.3lld.fits",plane_id);
1135 if (contrib != NULL) {
1136 cpl_image_delete(contrib);
1141 if (masks && masked_list) {
1149static cpl_mask * eris_detect_sources_hdrl_catalogue(
1150 const cpl_image * image,
1154 cpl_mask * mask_res = NULL;
1164 double max = cpl_image_get_max(res->segmentation_map);
1165 mask_res = cpl_mask_threshold_image_create(res->segmentation_map, 0.9, max + 0.1);
1179static cpl_mask * eris_dilate_mask(
1180 const cpl_mask * input_mask,
1183 cpl_mask * result = NULL;
1184 cpl_mask * temp = NULL;
1187 cpl_ensure(input_mask, CPL_ERROR_NULL_INPUT, NULL);
1188 cpl_ensure(radius > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1190 nx = cpl_mask_get_size_x(input_mask);
1191 ny = cpl_mask_get_size_y(input_mask);
1193 result = cpl_mask_duplicate(input_mask);
1196 for (
int iter = 0; iter < radius; iter++) {
1197 temp = cpl_mask_duplicate(result);
1199 for (cpl_size j = 2; j < ny - 1; j++) {
1200 for (cpl_size i = 2; i < nx - 1; i++) {
1201 if (cpl_mask_get(temp, i, j) ||
1202 cpl_mask_get(temp, i-1, j) ||
1203 cpl_mask_get(temp, i+1, j) ||
1204 cpl_mask_get(temp, i, j-1) ||
1205 cpl_mask_get(temp, i, j+1)) {
1206 cpl_mask_set(result, i, j, CPL_BINARY_1);
1210 cpl_mask_delete(temp);
1248eris_image_stats(
const hdrl_image *in_image,
1251 const cpl_mask *mask,
1252 double trim_fraction,
1262 cpl_ensure_code(in_image, CPL_ERROR_NULL_INPUT);
1263 cpl_ensure_code(median, CPL_ERROR_NULL_INPUT);
1264 cpl_ensure_code(mean, CPL_ERROR_NULL_INPUT);
1265 cpl_ensure_code(stdev, CPL_ERROR_NULL_INPUT);
1266 cpl_ensure_code(tmean, CPL_ERROR_NULL_INPUT);
1267 cpl_ensure_code(tstd, CPL_ERROR_NULL_INPUT);
1268 cpl_ensure_code(mad, CPL_ERROR_NULL_INPUT);
1269 cpl_ensure_code(min_val, CPL_ERROR_NULL_INPUT);
1270 cpl_ensure_code(max_val, CPL_ERROR_NULL_INPUT);
1273 cpl_image *work_img = NULL;
1274 cpl_vector *data_vec = NULL;
1277 work_img = cpl_image_duplicate(img);
1279 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
1280 "Failed to duplicate image");
1285 cpl_image_reject_from_mask(work_img, mask);
1293 *median = median0.data;
1298 cpl_size nx = cpl_image_get_size_x(work_img);
1299 cpl_size ny = cpl_image_get_size_y(work_img);
1300 cpl_size npix = nx * ny;
1303 const cpl_mask *rej_mask = cpl_image_get_bpm_const(work_img);
1304 cpl_size nvalid = npix;
1306 nvalid = npix - cpl_mask_count(rej_mask);
1310 cpl_image_delete(work_img);
1311 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1312 "No valid pixels in image");
1316 data_vec = cpl_vector_new(nvalid);
1318 for (cpl_size j = 1; j <= ny; j++) {
1319 for (cpl_size i = 1; i <= nx; i++) {
1320 int is_rejected = 0;
1321 double val = cpl_image_get(work_img, i, j, &is_rejected);
1322 if (!is_rejected && isfinite(val)) {
1323 cpl_vector_set(data_vec, idx, val);
1331 cpl_vector *tmp = cpl_vector_extract(data_vec, 0, idx - 1, 1);
1332 cpl_vector_delete(data_vec);
1338 cpl_vector_sort(data_vec, CPL_SORT_ASCENDING);
1339 cpl_size trim_count = (cpl_size)(trim_fraction * nvalid);
1340 if (trim_count * 2 >= nvalid) {
1344 double tmean0_10 = 0.0;
1345 if (trim_count > 0) {
1347 cpl_vector *trimmed = cpl_vector_extract(data_vec, trim_count,
1348 nvalid - trim_count - 1, 1);
1349 tmean0_10 = cpl_vector_get_mean(trimmed);
1350 cpl_vector_delete(trimmed);
1352 tmean0_10 = cpl_vector_get_mean(data_vec);
1356 double rmin = tmean0_10 - l_sig * (*stdev);
1357 double rmax = tmean0_10 + u_sig * (*stdev);
1360 cpl_size nclipped = 0;
1361 double sum_clipped = 0.0;
1362 double sum_sq_clipped = 0.0;
1364 for (cpl_size i = 0; i < nvalid; i++) {
1365 double val = cpl_vector_get(data_vec, i);
1366 if (val >= rmin && val <= rmax) {
1368 sum_sq_clipped += val * val;
1374 *tmean = sum_clipped / nclipped;
1377 double variance = (sum_sq_clipped - sum_clipped * sum_clipped / nclipped)
1379 *tstd = (variance > 0.0) ? sqrt(variance) : 0.0;
1391 cpl_vector *abs_dev = cpl_vector_duplicate(data_vec);
1392 cpl_vector_subtract_scalar(abs_dev, *median);
1393 for (cpl_size i = 0; i < nvalid; i++) {
1394 double val = cpl_vector_get(abs_dev, i);
1395 cpl_vector_set(abs_dev, i, fabs(val));
1397 cpl_vector_sort(abs_dev, CPL_SORT_ASCENDING);
1408 *mad = cpl_vector_get_median(abs_dev);
1410 cpl_vector_delete(abs_dev);
1413 *min_val = cpl_vector_get_min(data_vec);
1414 *max_val = cpl_vector_get_max(data_vec);
1417 cpl_vector_delete(data_vec);
1418 cpl_image_delete(work_img);
1420 return CPL_ERROR_NONE;
const char * eris_pfits_get_frame_format(const cpl_propertylist *plist)
find out the frame format (DET FRAM FORMAT) value
cpl_error_code eris_check_error_code(const char *func_id)
handle CPL errors
cpl_frameset * eris_dfs_extract_frames_with_tag(cpl_frameset *input, const char *rtag)
Extract frames of user given tag.
hdrl_catalogue_result * hdrl_catalogue_compute(const cpl_image *image_, const cpl_image *confidence_map, const cpl_wcs *wcs, hdrl_parameter *param_)
build object catalog
void hdrl_catalogue_result_delete(hdrl_catalogue_result *result)
delete hdrl parameter result object
hdrl_parameter * hdrl_catalogue_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *prefix)
Parse parameter list to create input parameters for the catalogue.
cpl_error_code hdrl_catalogue_parameter_set_option(hdrl_parameter *par, hdrl_catalogue_options opt)
set result option of catalogue parameter
hdrl_parameter * hdrl_collapse_sigclip_parameter_create(double kappa_low, double kappa_high, int niter)
create a parameter object for sigclipped mean
hdrl_parameter * hdrl_collapse_median_parameter_create(void)
create a parameter object for median
cpl_error_code hdrl_image_sub_image(hdrl_image *self, const hdrl_image *other)
Subtract two images, store the result in the first image.
hdrl_value hdrl_image_get_median(const hdrl_image *self)
computes the median and associated error of an image.
cpl_error_code hdrl_image_mul_scalar(hdrl_image *self, hdrl_value value)
Elementwise multiplication of an image with a scalar.
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
double hdrl_image_get_stdev(const hdrl_image *self)
computes the standard deviation of the data of an image
hdrl_value hdrl_image_get_mean(const hdrl_image *self)
computes mean pixel value and associated error of an image.
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
hdrl_image * hdrl_image_create(const cpl_image *image, const cpl_image *error)
create a new hdrl_image from to existing images by copying them
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
cpl_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
cpl_error_code hdrl_imagelist_collapse(const hdrl_imagelist *himlist, const hdrl_parameter *param, hdrl_image **out, cpl_image **contrib)
collapsing of image list
hdrl_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter