HAWKI Pipeline Reference Manual 1.8.12
|
00001 /* $Id: hawki_step_combine.c,v 1.26 2013/01/14 15:18:44 cgarcia Exp $ 00002 * 00003 * This file is part of the HAWKI Pipeline 00004 * Copyright (C) 2002,2003 European Southern Observatory 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 */ 00020 00021 /* 00022 * $Author: cgarcia $ 00023 * $Date: 2013/01/14 15:18:44 $ 00024 * $Revision: 1.26 $ 00025 * $Name: hawki-1_8_12 $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 /*----------------------------------------------------------------------------- 00033 Includes 00034 -----------------------------------------------------------------------------*/ 00035 00036 #include <math.h> 00037 #include <cpl.h> 00038 #include <string.h> 00039 00040 #include "irplib_utils.h" 00041 #include "irplib_calib.h" 00042 00043 #include "hawki_utils.h" 00044 #include "hawki_calib.h" 00045 #include "hawki_load.h" 00046 #include "hawki_save.h" 00047 #include "hawki_pfits.h" 00048 #include "hawki_dfs.h" 00049 #include "hawki_saa.h" 00050 #include "hawki_bkg.h" 00051 #include "hawki_distortion.h" 00052 #include "hawki_properties_tel.h" 00053 #include "hawki_image_stats.h" 00054 00055 /*----------------------------------------------------------------------------- 00056 Functions prototypes 00057 -----------------------------------------------------------------------------*/ 00058 00059 #ifdef __cplusplus 00060 extern "C" 00061 #endif 00062 int cpl_plugin_get_info(cpl_pluginlist * list); 00063 00064 static int hawki_step_combine_create(cpl_plugin *) ; 00065 static int hawki_step_combine_exec(cpl_plugin *) ; 00066 static int hawki_step_combine_destroy(cpl_plugin *) ; 00067 static int hawki_step_combine(cpl_parameterlist *, cpl_frameset *) ; 00068 00069 static int hawki_step_combine_retrieve_input_param 00070 (cpl_parameterlist * parlist); 00071 static cpl_image ** hawki_step_combine_apply_comb 00072 (cpl_frameset * obj, 00073 cpl_frameset * offsets, 00074 cpl_frameset * bpm, 00075 cpl_frameset * bkg_bpm_frames); 00076 static cpl_image ** hawki_step_combine_chip 00077 (cpl_imagelist * in, 00078 cpl_bivector * offsets, 00079 double * pos_x, 00080 double * pos_y); 00081 static int hawki_step_combine_interpolate_badpix 00082 (cpl_image * image); 00083 static int hawki_step_combine_save 00084 (cpl_image ** combined, 00085 cpl_image ** contrib_map, 00086 cpl_frameset * used_frames, 00087 cpl_parameterlist * parlist, 00088 cpl_frameset * recipe_frameset); 00089 00090 /*----------------------------------------------------------------------------- 00091 Static variables 00092 -----------------------------------------------------------------------------*/ 00093 00094 static struct 00095 { 00096 /* Inputs */ 00097 int offset_max ; 00098 int borders ; 00099 cpl_geom_combine comb_meth ; 00100 int rej_low; 00101 int rej_high; 00102 cpl_kernel resamp_kernel; 00103 } hawki_step_combine_config; 00104 00105 static struct 00106 { 00107 /* Outputs */ 00108 double mean_airmass; 00109 double combined_pos_x[HAWKI_NB_DETECTORS]; 00110 double combined_pos_y[HAWKI_NB_DETECTORS]; 00111 double combined_cumoffset_x[HAWKI_NB_DETECTORS]; 00112 double combined_cumoffset_y[HAWKI_NB_DETECTORS]; 00113 } hawki_step_combine_output; 00114 00115 static char hawki_step_combine_description[] = 00116 "hawki_step_combine -- hawki combine jitter images.\n" 00117 "The files listed in the Set Of Frames (sof-file) must be tagged:\n" 00118 "science-file.fits "HAWKI_CALPRO_DIST_CORRECTED" or\n" 00119 "science-file.fits "HAWKI_CALPRO_BKG_SUBTRACTED" or\n" 00120 "bpm-file.fits "HAWKI_CALPRO_BPM" (optional) \n" 00121 "bkg_bpm-file.fits "HAWKI_CALPRO_BKGBPM" (optional) \n" 00122 "offsets-file.fits "HAWKI_CALPRO_OFFSETS" (optional) \n" 00123 "The recipe creates as an output:\n" 00124 "hawki_step_combine.fits ("HAWKI_CALPRO_COMBINED"): \n" 00125 "The recipe does the following steps:\n" 00126 "-Allocate an image with the proper combined size \n" 00127 " (depends on parameters --comb_meth and --borders)\n" 00128 "-Retrieve the offsets either from the offsets-file.fits or from the header\n" 00129 "-For each combined pixel, the contribution of each individual frame \n" 00130 " is added using a resampling kernel. If any of the pixels involved in\n" 00131 " the resampling is a bad pixel (defined in bpm-file.fits), it is not\n" 00132 " taken into account.\n" 00133 " With the remaining pixels a minmax rejection is performed\n" 00134 "Return code:\n" 00135 "esorex exits with an error code of 0 if the recipe completes successfully\n" 00136 "or 1 otherwise"; 00137 00138 /*----------------------------------------------------------------------------- 00139 Functions code 00140 -----------------------------------------------------------------------------*/ 00141 00142 /*----------------------------------------------------------------------------*/ 00150 /*----------------------------------------------------------------------------*/ 00151 int cpl_plugin_get_info(cpl_pluginlist * list) 00152 { 00153 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ; 00154 cpl_plugin * plugin = &recipe->interface ; 00155 00156 cpl_plugin_init(plugin, 00157 CPL_PLUGIN_API, 00158 HAWKI_BINARY_VERSION, 00159 CPL_PLUGIN_TYPE_RECIPE, 00160 "hawki_step_combine", 00161 "Jitter image combination recipe", 00162 hawki_step_combine_description, 00163 "Cesar Enrique Garcia Dabo", 00164 PACKAGE_BUGREPORT, 00165 hawki_get_license(), 00166 hawki_step_combine_create, 00167 hawki_step_combine_exec, 00168 hawki_step_combine_destroy) ; 00169 00170 cpl_pluginlist_append(list, plugin) ; 00171 00172 return 0; 00173 } 00174 00175 /*----------------------------------------------------------------------------*/ 00184 /*----------------------------------------------------------------------------*/ 00185 static int hawki_step_combine_create(cpl_plugin * plugin) 00186 { 00187 cpl_recipe * recipe ; 00188 cpl_parameter * p ; 00189 00190 /* Get the recipe out of the plugin */ 00191 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00192 recipe = (cpl_recipe *)plugin ; 00193 else return -1 ; 00194 00195 /* Create the parameters list in the cpl_recipe object */ 00196 recipe->parameters = cpl_parameterlist_new() ; 00197 if (recipe->parameters == NULL) 00198 return 1; 00199 00200 /* Fill the parameters list */ 00201 /* --offset_max */ 00202 p = cpl_parameter_new_value("hawki.hawki_step_combine.offset_max", 00203 CPL_TYPE_INT, 00204 "Maximum offset allowed", 00205 "hawki.hawki_step_combine", 00206 1500) ; 00207 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "offset_max") ; 00208 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00209 cpl_parameterlist_append(recipe->parameters, p) ; 00210 00211 /* --comb_meth */ 00212 p = cpl_parameter_new_value("hawki.hawki_step_combine.comb_meth", 00213 CPL_TYPE_STRING, 00214 "Final size of combination (union / inter / first)", 00215 "hawki.hawki_step_combine", 00216 "union") ; 00217 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "comb_meth") ; 00218 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00219 cpl_parameterlist_append(recipe->parameters, p) ; 00220 00221 /* --rej */ 00222 p = cpl_parameter_new_value("hawki.hawki_step_combine.rej", 00223 CPL_TYPE_STRING, 00224 "Low and high number of rejected values", 00225 "hawki.hawki_step_combine", 00226 "1,1") ; 00227 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rej") ; 00228 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00229 cpl_parameterlist_append(recipe->parameters, p) ; 00230 00231 /* --borders */ 00232 p = cpl_parameter_new_value("hawki.hawki_step_combine.borders", 00233 CPL_TYPE_INT, 00234 "Border pixels trimmed", 00235 "hawki.hawki_step_combine", 00236 4) ; 00237 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "borders") ; 00238 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00239 cpl_parameterlist_append(recipe->parameters, p) ; 00240 00241 /* --resamp_kernel */ 00242 p = cpl_parameter_new_value("hawki.hawki_step_combine.resamp_kernel", 00243 CPL_TYPE_STRING, 00244 "Resampling kernel (default/tanh/sinc/sinc2/lanczos/hamming/hann)", 00245 "hawki.hawki_step_combine", 00246 "default") ; 00247 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "resamp_kernel") ; 00248 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00249 cpl_parameterlist_append(recipe->parameters, p) ; 00250 00251 /* Return */ 00252 return 0; 00253 } 00254 00255 /*----------------------------------------------------------------------------*/ 00261 /*----------------------------------------------------------------------------*/ 00262 static int hawki_step_combine_exec(cpl_plugin * plugin) 00263 { 00264 cpl_recipe * recipe ; 00265 00266 /* Get the recipe out of the plugin */ 00267 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00268 recipe = (cpl_recipe *)plugin ; 00269 else return -1 ; 00270 00271 /* Issue a banner */ 00272 hawki_print_banner(); 00273 00274 return hawki_step_combine(recipe->parameters, recipe->frames) ; 00275 } 00276 00277 /*----------------------------------------------------------------------------*/ 00283 /*----------------------------------------------------------------------------*/ 00284 static int hawki_step_combine_destroy(cpl_plugin * plugin) 00285 { 00286 cpl_recipe * recipe ; 00287 00288 /* Get the recipe out of the plugin */ 00289 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00290 recipe = (cpl_recipe *)plugin ; 00291 else return -1 ; 00292 00293 cpl_parameterlist_delete(recipe->parameters) ; 00294 return 0 ; 00295 } 00296 00297 /*----------------------------------------------------------------------------*/ 00304 /*----------------------------------------------------------------------------*/ 00305 static int hawki_step_combine( 00306 cpl_parameterlist * parlist, 00307 cpl_frameset * framelist) 00308 { 00309 cpl_frameset * objframes ; 00310 cpl_frameset * offsets; 00311 cpl_frameset * bpm; 00312 cpl_frameset * bpmbkg; 00313 cpl_frameset * used_frames; 00314 cpl_image ** combined_contrib; 00315 cpl_image ** combined; 00316 cpl_image ** contrib_map; 00317 int idet; 00318 00319 /* Retrieve input parameters */ 00320 if(hawki_step_combine_retrieve_input_param(parlist)) 00321 { 00322 cpl_msg_error(__func__, "Wrong parameters"); 00323 return -1; 00324 } 00325 00326 /* Identify the RAW and CALIB frames in the input frameset */ 00327 if (hawki_dfs_set_groups(framelist)) { 00328 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00329 return -1 ; 00330 } 00331 00332 /* Retrieve raw frames */ 00333 objframes = hawki_extract_frameset(framelist, HAWKI_CALPRO_DIST_CORRECTED); 00334 if (objframes == NULL) 00335 { 00336 objframes = hawki_extract_frameset 00337 (framelist, HAWKI_CALPRO_BKG_SUBTRACTED); 00338 if (objframes == NULL) 00339 { 00340 cpl_msg_error(__func__,"Cannot find objs frames in the input list (%s or %s)", 00341 HAWKI_CALPRO_DIST_CORRECTED, HAWKI_CALPRO_BKG_SUBTRACTED); 00342 return -1 ; 00343 } 00344 } 00345 /* Check that pointing is the same for all the frames */ 00346 if(!hawki_utils_check_equal_double_keys(objframes, &hawki_pfits_get_targ_alpha) || 00347 !hawki_utils_check_equal_double_keys(objframes, &hawki_pfits_get_targ_delta)) 00348 { 00349 cpl_msg_error(__func__, "Not all input science frames belong to the " 00350 "same pointing/target. Check keywords TEL TARG ALPHA/DELTA"); 00351 cpl_frameset_delete(objframes); 00352 return -1; 00353 } 00354 used_frames = cpl_frameset_duplicate(objframes); 00355 00356 /* Retrieve the refined offsets, if provided */ 00357 offsets = hawki_extract_frameset(framelist, HAWKI_CALPRO_OFFSETS); 00358 if(offsets) 00359 cpl_frameset_insert(used_frames, cpl_frame_duplicate( 00360 cpl_frameset_get_position(offsets, 0))); 00361 00362 /* Retrieve the general bad pixel mask, if provided */ 00363 bpm = hawki_extract_frameset(framelist, HAWKI_CALPRO_BPM); 00364 if(bpm) 00365 cpl_frameset_insert(used_frames, cpl_frame_duplicate( 00366 cpl_frameset_get_position(bpm, 0))); 00367 00368 /* Retrieve the background bad pixel masks, if provided */ 00369 bpmbkg = hawki_extract_frameset(framelist, HAWKI_CALPRO_BKGBPM); 00370 if(bpmbkg) 00371 { 00372 int iframe; 00373 for(iframe=0; iframe < cpl_frameset_get_size(bpmbkg); iframe++) 00374 cpl_frameset_insert(used_frames, cpl_frame_duplicate( 00375 cpl_frameset_get_frame(bpmbkg,iframe))); 00376 if(cpl_frameset_get_size(bpmbkg) != cpl_frameset_get_size(objframes)) 00377 { 00378 cpl_msg_error(__func__,"Incompatible number of science and bad bkg" 00379 " images."); 00380 cpl_msg_error(__func__,"Supply as many bad bkg images as objects"); 00381 cpl_frameset_delete(objframes); 00382 cpl_frameset_delete(used_frames); 00383 cpl_frameset_delete(offsets); 00384 cpl_frameset_delete(bpm); 00385 cpl_frameset_delete(bpmbkg); 00386 return -1; 00387 } 00388 } 00389 00390 /* Apply the combination */ 00391 cpl_msg_info(__func__, "Apply the data recombination"); 00392 cpl_msg_indent_more() ; 00393 if ((combined_contrib = hawki_step_combine_apply_comb 00394 (objframes, offsets, bpm, bpmbkg)) == NULL) 00395 { 00396 cpl_msg_error(__func__, "Cannot combine the data"); 00397 cpl_frameset_delete(objframes); 00398 cpl_frameset_delete(used_frames); 00399 if(offsets != NULL) 00400 cpl_frameset_delete(offsets); 00401 if(bpm != NULL) 00402 cpl_frameset_delete(bpm); 00403 cpl_msg_indent_less() ; 00404 return -1 ; 00405 } 00406 00407 /* Get both the combination and the contribution map */ 00408 combined = combined_contrib; 00409 contrib_map = combined_contrib + HAWKI_NB_DETECTORS; 00410 cpl_msg_indent_less() ; 00411 cpl_frameset_delete(objframes); 00412 if(offsets != NULL) 00413 cpl_frameset_delete(offsets); 00414 if(bpm != NULL) 00415 cpl_frameset_delete(bpm); 00416 if(bpmbkg != NULL) 00417 cpl_frameset_delete(bpmbkg); 00418 00419 /* Save the products */ 00420 cpl_msg_info(__func__, "Save the products") ; 00421 cpl_msg_indent_more() ; 00422 if (hawki_step_combine_save(combined, contrib_map, 00423 used_frames, parlist, framelist) != 0) 00424 { 00425 cpl_msg_warning(__func__, "Some error happened saving the data. " 00426 "Check permisions or disk space") ; 00427 for(idet=0; idet< 2 * HAWKI_NB_DETECTORS; ++idet) 00428 cpl_image_delete(combined_contrib[idet]); 00429 cpl_frameset_delete(used_frames); 00430 cpl_free(combined_contrib); 00431 cpl_msg_indent_less() ; 00432 return -1 ; 00433 } 00434 cpl_msg_indent_less() ; 00435 00436 /* Return */ 00437 for(idet=0; idet< 2 * HAWKI_NB_DETECTORS; ++idet) 00438 cpl_image_delete(combined_contrib[idet]); 00439 cpl_free(combined_contrib); 00440 cpl_frameset_delete(used_frames); 00441 00442 /* Return */ 00443 if (cpl_error_get_code()) 00444 { 00445 cpl_msg_error(__func__, 00446 "HAWK-I pipeline could not recover from previous errors"); 00447 return -1 ; 00448 } 00449 else return 0 ; 00450 } 00451 00452 int hawki_step_combine_retrieve_input_param 00453 (cpl_parameterlist * parlist) 00454 { 00455 cpl_parameter * par ; 00456 const char * sval ; 00457 par = NULL ; 00458 par = cpl_parameterlist_find(parlist, 00459 "hawki.hawki_step_combine.offset_max"); 00460 hawki_step_combine_config.offset_max = cpl_parameter_get_int(par); 00461 par = cpl_parameterlist_find(parlist, 00462 "hawki.hawki_step_combine.comb_meth"); 00463 sval = cpl_parameter_get_string(par); 00464 if (!strcmp(sval, "union")) 00465 hawki_step_combine_config.comb_meth = CPL_GEOM_UNION; 00466 else if (!strcmp(sval, "inter")) 00467 hawki_step_combine_config.comb_meth = CPL_GEOM_INTERSECT; 00468 else if (!strcmp(sval, "first")) 00469 hawki_step_combine_config.comb_meth = CPL_GEOM_FIRST; 00470 else 00471 { 00472 cpl_msg_error(__func__, "Invalid combine method specified"); 00473 return -1; 00474 } 00475 par = cpl_parameterlist_find(parlist, 00476 "hawki.hawki_step_combine.borders"); 00477 hawki_step_combine_config.borders = cpl_parameter_get_int(par); 00478 if(hawki_step_combine_config.borders < 0 ) 00479 { 00480 cpl_msg_error(__func__, "Borders cannot be less than zero"); 00481 return -1; 00482 } 00483 par = cpl_parameterlist_find(parlist, 00484 "hawki.hawki_step_combine.rej"); 00485 sval = cpl_parameter_get_string(par); 00486 if (sscanf(sval, "%d,%d", 00487 &hawki_step_combine_config.rej_low, 00488 &hawki_step_combine_config.rej_high)!=2) 00489 { 00490 return -1; 00491 } 00492 par = cpl_parameterlist_find(parlist, 00493 "hawki.hawki_step_combine.resamp_kernel"); 00494 sval = cpl_parameter_get_string(par); 00495 if (!strcmp(sval, "tanh")) 00496 hawki_step_combine_config.resamp_kernel = CPL_KERNEL_TANH; 00497 else if (!strcmp(sval, "sinc")) 00498 hawki_step_combine_config.resamp_kernel = CPL_KERNEL_SINC; 00499 else if (!strcmp(sval, "sinc2")) 00500 hawki_step_combine_config.resamp_kernel = CPL_KERNEL_SINC2; 00501 else if (!strcmp(sval, "lanczos")) 00502 hawki_step_combine_config.resamp_kernel = CPL_KERNEL_LANCZOS; 00503 else if (!strcmp(sval, "hamming")) 00504 hawki_step_combine_config.resamp_kernel = CPL_KERNEL_HAMMING; 00505 else if (!strcmp(sval, "hann")) 00506 hawki_step_combine_config.resamp_kernel = CPL_KERNEL_HANN; 00507 else if (!strcmp(sval, "default")) 00508 hawki_step_combine_config.resamp_kernel = CPL_KERNEL_DEFAULT; 00509 else 00510 { 00511 cpl_msg_error(__func__, "Invalid resampling kernel specified"); 00512 return -1; 00513 } 00514 00515 return 0; 00516 } 00517 00518 00519 00520 /*----------------------------------------------------------------------------*/ 00526 /*----------------------------------------------------------------------------*/ 00527 static cpl_image ** hawki_step_combine_apply_comb 00528 (cpl_frameset * obj, 00529 cpl_frameset * offsets_frames, 00530 cpl_frameset * bpm_frame, 00531 cpl_frameset * bkg_bpm_frames) 00532 { 00533 cpl_image ** combined_contrib; 00534 cpl_bivector ** offsets; 00535 cpl_mask * bpm_masks[HAWKI_NB_DETECTORS]; 00536 int idet; 00537 int ioff; 00538 00539 if(offsets_frames == NULL) 00540 { 00541 cpl_bivector * offsets_single_chip; 00542 if ((offsets_single_chip = hawki_get_header_tel_offsets(obj)) == NULL) 00543 { 00544 cpl_msg_error(__func__, "Cannot load the header offsets"); 00545 return NULL; 00546 } 00547 offsets = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_bivector *)); 00548 for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet) 00549 offsets[idet] = cpl_bivector_duplicate(offsets_single_chip); 00550 cpl_bivector_delete(offsets_single_chip); 00551 } 00552 else 00553 { 00554 offsets = hawki_load_refined_offsets 00555 (cpl_frameset_get_first(offsets_frames)); 00556 if(offsets == NULL) 00557 { 00558 cpl_msg_error(__func__, "Cannot load the refined offsets"); 00559 return NULL; 00560 } 00561 } 00562 /* Get the oposite offsets. This is to change from 00563 * telescope convention to cpl convention 00564 * WARNING: It may appear that the img_jitter function 00565 * does not apply the multiplication by -1, but it really does it in 00566 * hawki_img_jitter_saa instead of when it reads the offsets */ 00567 for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet) 00568 { 00569 cpl_vector_multiply_scalar(cpl_bivector_get_x(offsets[idet]), -1.0); 00570 cpl_vector_multiply_scalar(cpl_bivector_get_y(offsets[idet]), -1.0); 00571 } 00572 00573 /* Load the bpm */ 00574 if(bpm_frame != NULL) 00575 { 00576 cpl_imagelist * bpm_images = NULL; 00577 bpm_images = hawki_load_frame 00578 (cpl_frameset_get_first(bpm_frame), CPL_TYPE_INT); 00579 if(bpm_images == NULL) 00580 { 00581 cpl_msg_error(__func__, "Cannot load the bad pixel mask"); 00582 return NULL; 00583 } 00584 for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet) 00585 { 00586 bpm_masks[idet] = cpl_mask_threshold_image_create 00587 (cpl_imagelist_get(bpm_images, idet), 0.5, 1.5); 00588 } 00589 cpl_imagelist_delete(bpm_images); 00590 } 00591 00592 /* Create output object */ 00593 combined_contrib = cpl_malloc(2 * HAWKI_NB_DETECTORS * sizeof(cpl_image *)); 00594 00595 /* Loop on the detectors */ 00596 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00597 { 00598 cpl_imagelist * in ; 00599 cpl_imagelist * bpm_bkg_im = NULL; 00600 cpl_image ** comb_contrib_chip ; 00601 double * offs_est_x ; 00602 double * offs_est_y ; 00603 double max_x, max_y ; 00604 double off_0_x; 00605 double off_0_y; 00606 int jdet; 00607 int iframe; 00608 00609 cpl_msg_info(__func__, "Combine chip number %d", idet+1) ; 00610 cpl_msg_indent_more() ; 00611 00612 /* Print the offsets */ 00613 offs_est_x = cpl_bivector_get_x_data(offsets[idet]) ; 00614 offs_est_y = cpl_bivector_get_y_data(offsets[idet]) ; 00615 for (ioff=0 ; ioff<cpl_bivector_get_size(offsets[idet]) ; ioff++) { 00616 cpl_msg_info(__func__,"Telescope offsets (Frame %d): %g %g", ioff+1, 00617 -offs_est_x[ioff], -offs_est_y[ioff]) ; 00618 } 00619 00620 /* Subtract the first offset to all offsets */ 00621 max_x = max_y = 0.0 ; 00622 off_0_x = offs_est_x[0]; 00623 off_0_y = offs_est_y[0]; 00624 for (ioff=1 ; ioff<cpl_bivector_get_size(offsets[idet]) ; ioff++) 00625 { 00626 offs_est_x[ioff] -= offs_est_x[0] ; 00627 offs_est_y[ioff] -= offs_est_y[0] ; 00628 if (fabs(offs_est_x[ioff]) > max_x) max_x = fabs(offs_est_x[ioff]); 00629 if (fabs(offs_est_y[ioff]) > max_y) max_y = fabs(offs_est_y[ioff]); 00630 } 00631 offs_est_x[0] = offs_est_y[0] = 0.00 ; 00632 00633 /* Check if the max offset is not too big */ 00634 if (max_x > hawki_step_combine_config.offset_max || 00635 max_y > hawki_step_combine_config.offset_max) 00636 { 00637 cpl_msg_error(__func__,"Sorry, no support for offsets larger than %d", 00638 hawki_step_combine_config.offset_max); 00639 for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet) 00640 { 00641 cpl_bivector_delete(offsets[idet]); 00642 if(bpm_frame != NULL) 00643 cpl_mask_delete(bpm_masks[idet]); 00644 } 00645 for(jdet = 0; jdet < idet; ++jdet) 00646 { 00647 cpl_image_delete(combined_contrib[idet]); 00648 cpl_image_delete(combined_contrib[idet+HAWKI_NB_DETECTORS]); 00649 } 00650 cpl_free(combined_contrib); 00651 return NULL ; 00652 } 00653 00654 /* Load the input data */ 00655 cpl_msg_info(__func__, "Load the input data") ; 00656 cpl_msg_indent_more(); 00657 if ((in = hawki_load_detector(obj, idet+1, CPL_TYPE_FLOAT)) == NULL) { 00658 cpl_msg_error(__func__, "Cannot load chip %d",idet+1); 00659 //TODO: there is probably a memory leak here. It should be checked. 00660 for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet) 00661 { 00662 cpl_bivector_delete(offsets[idet]); 00663 if(bpm_frame != NULL) 00664 cpl_mask_delete(bpm_masks[idet]); 00665 } 00666 for(jdet = 0; jdet < idet; ++jdet) 00667 { 00668 cpl_image_delete(combined_contrib[idet]); 00669 cpl_image_delete(combined_contrib[idet+HAWKI_NB_DETECTORS]); 00670 } 00671 cpl_free(combined_contrib); 00672 cpl_free(offsets); 00673 cpl_msg_indent_less() ; 00674 cpl_msg_indent_less() ; 00675 return NULL ; 00676 } 00677 00678 /* Load the bad bkg images */ 00679 if(bkg_bpm_frames != NULL) 00680 { 00681 cpl_msg_info(__func__, "Load the bad bkg images"); 00682 cpl_msg_indent_more() ; 00683 if ((bpm_bkg_im = hawki_load_detector(bkg_bpm_frames, idet+1, 00684 CPL_TYPE_FLOAT)) == NULL) 00685 { 00686 cpl_msg_error(__func__, "Cannot load chip %d",idet+1); 00687 for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet) 00688 { 00689 cpl_bivector_delete(offsets[idet]); 00690 if(bpm_frame != NULL) 00691 cpl_mask_delete(bpm_masks[idet]); 00692 } 00693 for(jdet = 0; jdet < idet; ++jdet) 00694 { 00695 cpl_image_delete(combined_contrib[idet]); 00696 cpl_image_delete(combined_contrib[idet+HAWKI_NB_DETECTORS]); 00697 } 00698 cpl_free(combined_contrib); 00699 cpl_imagelist_delete(in); 00700 cpl_free(offsets); 00701 cpl_msg_indent_less() ; 00702 cpl_msg_indent_less() ; 00703 return NULL ; 00704 } 00705 cpl_msg_indent_less() ; 00706 } 00707 cpl_msg_indent_less() ; 00708 00709 /* Add the general bpm or background bpms in case they were specified */ 00710 if(bpm_frame != NULL || bkg_bpm_frames != NULL) 00711 { 00712 for(iframe = 0 ; iframe <cpl_imagelist_get_size(in) ; ++iframe) 00713 { 00714 cpl_mask * final_mask; 00715 cpl_image * target_image = cpl_imagelist_get(in, iframe); 00716 final_mask = cpl_mask_new(cpl_image_get_size_x(target_image), 00717 cpl_image_get_size_y(target_image)); 00718 //Add the common bpm 00719 if(bpm_frame != NULL) 00720 cpl_mask_or(final_mask, bpm_masks[idet]); 00721 //Add the background mask if provided 00722 if(bkg_bpm_frames != NULL) 00723 { 00724 cpl_mask * bpm_bkg_mask = 00725 cpl_mask_threshold_image_create 00726 (cpl_imagelist_get(bpm_bkg_im, iframe), 0.5, FLT_MAX); 00727 cpl_mask_or(final_mask, bpm_bkg_mask); 00728 cpl_mask_delete(bpm_bkg_mask); 00729 } 00730 cpl_image_reject_from_mask(target_image, final_mask); 00731 cpl_mask_delete(final_mask); 00732 } 00733 } 00734 00735 if(bkg_bpm_frames != NULL) 00736 cpl_imagelist_delete(bpm_bkg_im); 00737 00738 /* Apply the shift and add */ 00739 cpl_msg_info(__func__, "Shift and add") ; 00740 cpl_msg_indent_more() ; 00741 comb_contrib_chip = hawki_step_combine_chip(in, offsets[idet], 00742 &(hawki_step_combine_output.combined_pos_x[idet]), 00743 &(hawki_step_combine_output.combined_pos_y[idet])) ; 00744 if (comb_contrib_chip == NULL) 00745 { 00746 cpl_msg_error(__func__, "Cannot apply the shift and add") ; 00747 cpl_imagelist_delete(in) ; 00748 for(jdet = 0; jdet < HAWKI_NB_DETECTORS; ++jdet) 00749 cpl_bivector_delete(offsets[jdet]); 00750 { 00751 cpl_image_delete(combined_contrib[idet]); 00752 cpl_image_delete(combined_contrib[idet+HAWKI_NB_DETECTORS]); 00753 } 00754 cpl_free(combined_contrib); 00755 cpl_free(offsets); 00756 cpl_msg_indent_less() ; 00757 cpl_msg_indent_less() ; 00758 return NULL ; 00759 } 00760 00761 /* The cumoffset have the opposite criteria as cpl */ 00762 hawki_step_combine_output.combined_cumoffset_x[idet] = 00763 hawki_step_combine_output.combined_pos_x[idet] - off_0_x; 00764 hawki_step_combine_output.combined_cumoffset_y[idet] = 00765 hawki_step_combine_output.combined_pos_y[idet] - off_0_y; 00766 cpl_imagelist_delete(in) ; 00767 cpl_msg_indent_less() ; 00768 00769 /* Interpolate bad pixels */ 00770 hawki_step_combine_interpolate_badpix(comb_contrib_chip[0]); 00771 00772 /* Put the results in the image list */ 00773 combined_contrib[idet] = comb_contrib_chip[0]; 00774 combined_contrib[idet+HAWKI_NB_DETECTORS] = comb_contrib_chip[1]; 00775 cpl_free(comb_contrib_chip); 00776 cpl_msg_indent_less() ; 00777 } 00778 00779 /* Compute the mean airmass */ 00780 hawki_step_combine_output.mean_airmass = hawki_get_mean_airmass(obj); 00781 00782 for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet) 00783 { 00784 cpl_bivector_delete(offsets[idet]); 00785 if(bpm_frame != NULL) 00786 cpl_mask_delete(bpm_masks[idet]); 00787 } 00788 cpl_free(offsets); 00789 return combined_contrib; 00790 } 00791 00792 /*----------------------------------------------------------------------------*/ 00801 /*----------------------------------------------------------------------------*/ 00802 static cpl_image ** hawki_step_combine_chip( 00803 cpl_imagelist * in, 00804 cpl_bivector * offsets, 00805 double * pos_x, 00806 double * pos_y) 00807 { 00808 cpl_image ** combined_contrib; 00809 cpl_imagelist * in_ext ; 00810 cpl_image * tmp1 ; 00811 cpl_image * tmp2 ; 00812 int nfiles, nx, ny ; 00813 int i; 00814 00815 /* Check entries */ 00816 if (pos_x == NULL || pos_y == NULL) return NULL ; 00817 if (offsets == NULL) return NULL ; 00818 00819 /* Get the number of images */ 00820 nfiles = cpl_imagelist_get_size(in) ; 00821 if (cpl_bivector_get_size(offsets) != nfiles) { 00822 cpl_msg_error(__func__, "Number of refined offsets in table """ 00823 "is different than number of frames to combine"); 00824 return NULL ; 00825 } 00826 00827 /* Discard the pixels on the sides */ 00828 if (hawki_step_combine_config.borders > 0) { 00829 nx = cpl_image_get_size_x(cpl_imagelist_get(in, 0)) ; 00830 ny = cpl_image_get_size_y(cpl_imagelist_get(in, 0)) ; 00831 in_ext = cpl_imagelist_new() ; 00832 for (i=0 ; i<cpl_imagelist_get_size(in) ; i++) { 00833 tmp1 = cpl_imagelist_get(in, i) ; 00834 tmp2 = cpl_image_extract(tmp1, 00835 hawki_step_combine_config.borders+1, 00836 hawki_step_combine_config.borders+1, 00837 nx-hawki_step_combine_config.borders, 00838 ny-hawki_step_combine_config.borders) ; 00839 cpl_imagelist_set(in_ext, tmp2, i) ; 00840 } 00841 } 00842 else 00843 { 00844 in_ext = cpl_imagelist_duplicate(in); 00845 } 00846 00847 /* Apply the shift & add */ 00848 cpl_msg_info(__func__, "Recombine the images set") ; 00849 cpl_msg_indent_more() ; 00850 if ((combined_contrib=cpl_geom_img_offset_saa(in_ext, offsets, 00851 hawki_step_combine_config.resamp_kernel, 00852 hawki_step_combine_config.rej_low, 00853 hawki_step_combine_config.rej_high, 00854 hawki_step_combine_config.comb_meth, 00855 pos_x, pos_y)) == NULL) { 00856 cpl_msg_error(cpl_func, "Cannot apply the shift and add") ; 00857 cpl_msg_indent_less(); 00858 return NULL; 00859 } 00860 cpl_msg_indent_less(); 00861 *pos_x -= hawki_step_combine_config.borders; 00862 *pos_y -= hawki_step_combine_config.borders; 00863 00864 /* Free and return */ 00865 cpl_imagelist_delete(in_ext); 00866 return combined_contrib; 00867 } 00868 00869 /*----------------------------------------------------------------------------*/ 00875 /*----------------------------------------------------------------------------*/ 00876 static int hawki_step_combine_interpolate_badpix 00877 (cpl_image * image) 00878 { 00879 int nbadpixels = cpl_image_count_rejected(image); 00880 if(nbadpixels !=0) 00881 cpl_msg_info(__func__,"Number of pixels with no combined value available: %d ", 00882 nbadpixels); 00883 if(cpl_image_count_rejected(image) > 0) 00884 { 00885 //I use this even if DFS08929 is still not solved 00886 cpl_detector_interpolate_rejected(image); 00887 } 00888 return 0; 00889 } 00890 00891 /*----------------------------------------------------------------------------*/ 00900 /*----------------------------------------------------------------------------*/ 00901 static int hawki_step_combine_save 00902 (cpl_image ** combined, 00903 cpl_image ** contrib_map, 00904 cpl_frameset * used_frames, 00905 cpl_parameterlist * parlist, 00906 cpl_frameset * recipe_frameset) 00907 { 00908 cpl_propertylist ** extproplists ; 00909 const cpl_frame * ref_frame ; 00910 cpl_propertylist * wcslist ; 00911 cpl_propertylist * inputlist ; 00912 double crpix1, crpix2 ; 00913 int ext_nb ; 00914 const char * recipe_name = "hawki_step_combine" ; 00915 int idet; 00916 cpl_errorstate error_prevstate = cpl_errorstate_get(); 00917 00918 /* Get a reference frame for the WCS keys */ 00919 ref_frame = irplib_frameset_get_first_from_group 00920 (recipe_frameset, CPL_FRAME_GROUP_RAW) ; 00921 00922 if(ref_frame == NULL) 00923 { 00924 cpl_msg_error(__func__, "Cannot get a reference frame"); 00925 return -1; 00926 } 00927 00928 /* Create the QC lists */ 00929 extproplists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ; 00930 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00931 { 00932 00933 /* Initialize qclists */ 00934 extproplists[idet] = cpl_propertylist_new() ; 00935 00936 /* Get the extension number */ 00937 ext_nb=hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), idet+1); 00938 00939 /* Handle WCS keys */ 00940 wcslist = cpl_propertylist_load_regexp( 00941 cpl_frame_get_filename(ref_frame), ext_nb, HAWKI_HEADER_WCS, 0); 00942 00943 /* Update WCS and write them */ 00944 crpix1 = cpl_propertylist_get_double(wcslist, "CRPIX1"); 00945 crpix1 += hawki_step_combine_output.combined_pos_x[idet]; 00946 cpl_propertylist_update_double(wcslist, "CRPIX1", crpix1) ; 00947 crpix2 = cpl_propertylist_get_double(wcslist, "CRPIX2"); 00948 crpix2 += hawki_step_combine_output.combined_pos_y[idet] ; 00949 cpl_propertylist_update_double(wcslist, "CRPIX2", crpix2) ; 00950 cpl_propertylist_copy_property_regexp 00951 (extproplists[idet], wcslist, HAWKI_HEADER_WCS, 0); 00952 cpl_propertylist_delete(wcslist) ; 00953 00954 /* Keywords for the relative position of the combined image */ 00955 cpl_propertylist_append_double 00956 (extproplists[idet], "ESO QC COMBINED CUMOFFSETX", 00957 hawki_step_combine_output.combined_cumoffset_x[idet]); 00958 cpl_propertylist_append_double 00959 (extproplists[idet], "ESO QC COMBINED CUMOFFSETY", 00960 hawki_step_combine_output.combined_cumoffset_y[idet]); 00961 cpl_propertylist_append_double 00962 (extproplists[idet], "ESO QC COMBINED POSX", 00963 hawki_step_combine_output.combined_pos_x[idet]); 00964 cpl_propertylist_append_double 00965 (extproplists[idet], "ESO QC COMBINED POSY", 00966 hawki_step_combine_output.combined_pos_y[idet]); 00967 cpl_propertylist_append_double 00968 (extproplists[idet], "ESO QC AIRMASS MEAN", 00969 hawki_step_combine_output.mean_airmass); 00970 00971 /* Propagate some keywords from input raw frame extensions */ 00972 inputlist = cpl_propertylist_load_regexp( 00973 cpl_frame_get_filename(ref_frame), ext_nb, 00974 HAWKI_HEADER_EXT_FORWARD, 0) ; 00975 cpl_propertylist_append(extproplists[idet], inputlist); 00976 cpl_propertylist_delete(inputlist) ; 00977 } 00978 00979 /* Write the combined image */ 00980 if(hawki_images_save(recipe_frameset, 00981 parlist, 00982 used_frames, 00983 (const cpl_image **)combined, 00984 recipe_name, 00985 HAWKI_CALPRO_COMBINED, 00986 HAWKI_PROTYPE_COMBINED, 00987 NULL, 00988 (const cpl_propertylist**)extproplists, 00989 "hawki_step_combine.fits") != 0) 00990 { 00991 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) { 00992 cpl_propertylist_delete(extproplists[idet]) ; 00993 } 00994 cpl_free(extproplists) ; 00995 return -1; 00996 } 00997 00998 /* Write the contrib map */ 00999 if(hawki_images_save(recipe_frameset, 01000 parlist, 01001 used_frames, 01002 (const cpl_image **)contrib_map, 01003 recipe_name, 01004 HAWKI_CALPRO_COMB_CONTRIB_MAP, 01005 HAWKI_PROTYPE_COMB_CONTRIB_MAP, 01006 NULL, 01007 (const cpl_propertylist**)extproplists, 01008 "hawki_step_combine_contrib_map.fits") != 0) 01009 { 01010 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) { 01011 cpl_propertylist_delete(extproplists[idet]); 01012 } 01013 cpl_free(extproplists) ; 01014 return -1; 01015 } 01016 01017 /* Free and return */ 01018 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) { 01019 cpl_propertylist_delete(extproplists[idet]) ; 01020 } 01021 cpl_free(extproplists) ; 01022 01023 if(!cpl_errorstate_is_equal(error_prevstate)) 01024 { 01025 cpl_errorstate_set(CPL_ERROR_NONE); 01026 return 1; 01027 } 01028 01029 return 0; 01030 } 01031