HAWKI Pipeline Reference Manual 1.8.12
|
00001 /* $Id: hawki_cal_distortion.c,v 1.17 2013/02/01 17:18:05 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/02/01 17:18:05 $ 00024 * $Revision: 1.17 $ 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 00042 #include "hawki_alloc.h" 00043 #include "hawki_utils.h" 00044 #include "hawki_calib.h" 00045 #include "hawki_distortion.h" 00046 #include "hawki_load.h" 00047 #include "hawki_save.h" 00048 #include "hawki_pfits.h" 00049 #include "hawki_dfs.h" 00050 #include "irplib_cat.h" 00051 #include "irplib_stdstar.h" 00052 #include "irplib_match_cats.h" 00053 #include "hawki_match_cats.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_cal_distortion_create(cpl_plugin *) ; 00065 static int hawki_cal_distortion_exec(cpl_plugin *) ; 00066 static int hawki_cal_distortion_destroy(cpl_plugin *) ; 00067 static int hawki_cal_distortion(cpl_parameterlist * parlist, 00068 cpl_frameset * frameset); 00069 00070 00071 static int hawki_cal_distortion_get_apertures_from_raw_distor 00072 (cpl_frameset * raw_target, 00073 const cpl_frame * flat, 00074 const cpl_frame * dark, 00075 const cpl_frame * bpm, 00076 cpl_image ** master_sky, 00077 double sigma_det, 00078 cpl_apertures *** apertures); 00079 00080 static int hawki_cal_distortion_load_master_calib 00081 (const cpl_frame * flat, 00082 const cpl_frame * dark, 00083 const cpl_frame * bpm, 00084 cpl_imagelist ** flat_images, 00085 cpl_imagelist ** dark_images, 00086 cpl_imagelist ** bpm_images); 00087 00088 static cpl_image ** hawki_cal_distortion_get_master_sky 00089 (cpl_frameset * raw_target, 00090 const cpl_frame * flat, 00091 const cpl_frame * dark, 00092 const cpl_frame * bpm); 00093 00094 static int hawki_cal_distortion_subtract_sky 00095 (cpl_imagelist * distor_corrected, 00096 cpl_image * master_sky); 00097 00098 static hawki_distortion ** hawki_cal_distortion_compute_dist_solution 00099 (cpl_apertures *** apertures, 00100 int nframes, 00101 cpl_bivector * offsets, 00102 int grid_points, 00103 int * nmatched_pairs, 00104 double * rms, 00105 hawki_distortion ** distortion_guess); 00106 00107 static cpl_apertures * hawki_cal_distortion_get_image_apertures 00108 (cpl_image * image, 00109 double sigma_det); 00110 00111 static int hawki_cal_distortion_fill_obj_pos 00112 (cpl_table * objects_positions, 00113 cpl_apertures * apertures); 00114 00115 static int hawki_cal_distortion_add_offset_to_positions 00116 (cpl_table ** objects_positions, 00117 cpl_bivector * offsets); 00118 00119 static int hawki_cal_distortion_fit_first_order_solution 00120 (hawki_distortion * distortion, 00121 cpl_polynomial * fit2d_x, 00122 cpl_polynomial * fit2d_y); 00123 00124 static cpl_propertylist ** hawki_cal_distortion_qc 00125 (hawki_distortion ** distortion, 00126 int * nmatched_pairs, 00127 double * rms); 00128 00129 static int hawki_cal_distortion_save 00130 (hawki_distortion ** distortion, 00131 cpl_parameterlist * parlist, 00132 cpl_propertylist ** qclists, 00133 cpl_frameset * recipe_set); 00134 00135 static int hawki_cal_distortion_retrieve_input_param 00136 (cpl_parameterlist * parlist); 00137 00138 00139 /*----------------------------------------------------------------------------- 00140 Static variables 00141 -----------------------------------------------------------------------------*/ 00142 00143 static struct 00144 { 00145 /* Inputs */ 00146 double sigma_det; 00147 int grid_points; 00148 int borders; 00149 int subtract_linear; 00150 } hawki_cal_distortion_config; 00151 00152 static char hawki_cal_distortion_description[] = 00153 "hawki_cal_distortion -- HAWK-I distortion and astrometry autocalibration.\n\n" 00154 "The input files must be tagged:\n" 00155 "distortion_field.fits "HAWKI_CAL_DISTOR_RAW"\n" 00156 "sky_distortion.fits "HAWKI_CAL_DISTOR_SKY_RAW"\n" 00157 "flat-file.fits "HAWKI_CALPRO_FLAT" (optional)\n" 00158 "dark-file.fits "HAWKI_CALPRO_DARK" (optional)\n" 00159 "bpm-file.fits "HAWKI_CALPRO_BPM" (optional)\n\n" 00160 "The recipe creates as an output:\n" 00161 "hawki_cal_distortion_distx.fits ("HAWKI_CALPRO_DISTORTION_X") \n" 00162 "hawki_cal_distortion_disty.fits ("HAWKI_CALPRO_DISTORTION_Y") \n\n" 00163 "The recipe performs the following steps:\n" 00164 "-Basic calibration of astrometry fields\n" 00165 "-Autocalibration of distortion, using method in A&A 454,1029 (2006)\n\n" 00166 "Return code:\n" 00167 "esorex exits with an error code of 0 if the recipe completes successfully\n" 00168 "or 1 otherwise"; 00169 00170 /*----------------------------------------------------------------------------- 00171 Functions code 00172 -----------------------------------------------------------------------------*/ 00173 00174 /*----------------------------------------------------------------------------*/ 00182 /*----------------------------------------------------------------------------*/ 00183 int cpl_plugin_get_info(cpl_pluginlist * list) 00184 { 00185 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ; 00186 cpl_plugin * plugin = &recipe->interface ; 00187 00188 cpl_plugin_init(plugin, 00189 CPL_PLUGIN_API, 00190 HAWKI_BINARY_VERSION, 00191 CPL_PLUGIN_TYPE_RECIPE, 00192 "hawki_cal_distortion", 00193 "Distortion autocalibration", 00194 hawki_cal_distortion_description, 00195 "Cesar Enrique Garcia Dabo", 00196 PACKAGE_BUGREPORT, 00197 hawki_get_license(), 00198 hawki_cal_distortion_create, 00199 hawki_cal_distortion_exec, 00200 hawki_cal_distortion_destroy); 00201 00202 cpl_pluginlist_append(list, plugin) ; 00203 00204 return 0; 00205 } 00206 00207 /*----------------------------------------------------------------------------*/ 00216 /*----------------------------------------------------------------------------*/ 00217 static int hawki_cal_distortion_create(cpl_plugin * plugin) 00218 { 00219 cpl_recipe * recipe ; 00220 cpl_parameter * p ; 00221 00222 /* Get the recipe out of the plugin */ 00223 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00224 recipe = (cpl_recipe *)plugin ; 00225 else return -1 ; 00226 00227 /* Create the parameters list in the cpl_recipe object */ 00228 recipe->parameters = cpl_parameterlist_new() ; 00229 if (recipe->parameters == NULL) 00230 return 1; 00231 00232 /* Fill the parameters list */ 00233 /* --sigma_det */ 00234 p = cpl_parameter_new_value("hawki.hawki_cal_distortion.sigma_det", 00235 CPL_TYPE_DOUBLE, "detection level", 00236 "hawki.hawki_cal_distortion", 6.) ; 00237 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma_det") ; 00238 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00239 cpl_parameterlist_append(recipe->parameters, p) ; 00240 00241 /* --grid_points */ 00242 p = cpl_parameter_new_value("hawki.hawki_cal_distortion.grid_points", 00243 CPL_TYPE_INT, 00244 "number of points in distortion grid", 00245 "hawki.hawki_cal_distortion", 9) ; 00246 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "grid_points") ; 00247 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00248 cpl_parameterlist_append(recipe->parameters, p) ; 00249 00250 /* --borders */ 00251 p = cpl_parameter_new_value("hawki.hawki_cal_distortion.borders", 00252 CPL_TYPE_INT, 00253 "number of pixels to trim at the borders", 00254 "hawki.hawki_cal_distortion", 6) ; 00255 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "borders") ; 00256 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00257 cpl_parameterlist_append(recipe->parameters, p) ; 00258 00259 /* --subtract_linear */ 00260 p = cpl_parameter_new_value("hawki.hawki_cal_distortion.subtract_linear", 00261 CPL_TYPE_BOOL, 00262 "Subtract a linear term to the solution", 00263 "hawki.hawki_cal_distortion", TRUE) ; 00264 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "subtract_linear") ; 00265 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00266 cpl_parameterlist_append(recipe->parameters, p) ; 00267 00268 /* Return */ 00269 return 0; 00270 } 00271 00272 /*----------------------------------------------------------------------------*/ 00278 /*----------------------------------------------------------------------------*/ 00279 static int hawki_cal_distortion_exec(cpl_plugin * plugin) 00280 { 00281 cpl_recipe * recipe ; 00282 00283 /* Get the recipe out of the plugin */ 00284 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00285 recipe = (cpl_recipe *)plugin ; 00286 else return -1 ; 00287 00288 /* Issue a banner */ 00289 hawki_print_banner(); 00290 00291 return hawki_cal_distortion(recipe->parameters, recipe->frames) ; 00292 } 00293 00294 /*----------------------------------------------------------------------------*/ 00300 /*----------------------------------------------------------------------------*/ 00301 static int hawki_cal_distortion_destroy(cpl_plugin * plugin) 00302 { 00303 cpl_recipe * recipe ; 00304 00305 /* Get the recipe out of the plugin */ 00306 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00307 recipe = (cpl_recipe *)plugin ; 00308 else return -1 ; 00309 00310 cpl_parameterlist_delete(recipe->parameters) ; 00311 return 0 ; 00312 } 00313 00314 /*----------------------------------------------------------------------------*/ 00320 /*----------------------------------------------------------------------------*/ 00321 static int hawki_cal_distortion(cpl_parameterlist * parlist, 00322 cpl_frameset * frameset) 00323 { 00324 const cpl_frame * flat = NULL; 00325 const cpl_frame * dark = NULL; 00326 const cpl_frame * bpm = NULL; 00327 cpl_frameset * distorframes = NULL; 00328 cpl_frameset * skyframes = NULL; 00329 const cpl_frame * distorxguess = NULL; 00330 const cpl_frame * distoryguess = NULL; 00331 hawki_distortion ** distortionguess = NULL; 00332 hawki_distortion ** distortion = NULL; 00333 cpl_propertylist ** qclists = NULL; 00334 cpl_image ** master_sky = NULL; 00335 cpl_bivector * nominal_offsets = NULL; 00336 cpl_apertures ** apertures[HAWKI_NB_DETECTORS]; 00337 int nmatched_pairs[HAWKI_NB_DETECTORS]; 00338 double rms[HAWKI_NB_DETECTORS]; 00339 int idet; 00340 int ioff; 00341 int iframe; 00342 int nframes; 00343 00344 00345 /* Retrieve input parameters */ 00346 if(hawki_cal_distortion_retrieve_input_param(parlist)) 00347 { 00348 cpl_msg_error(__func__, "Wrong parameters"); 00349 return -1; 00350 } 00351 00352 /* Identify the RAW and CALIB frames in the input frameset */ 00353 if (hawki_dfs_set_groups(frameset)) { 00354 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00355 return -1 ; 00356 } 00357 00358 /* Retrieve calibration data */ 00359 cpl_msg_info(__func__, "Identifying calibration data"); 00360 flat = cpl_frameset_find_const(frameset, HAWKI_CALPRO_FLAT); 00361 dark = cpl_frameset_find_const(frameset, HAWKI_CALPRO_DARK); 00362 bpm = cpl_frameset_find_const(frameset, HAWKI_CALPRO_BPM); 00363 00364 /* Retrieve raw frames */ 00365 cpl_msg_info(__func__, "Identifying distortion and sky data"); 00366 distorframes = hawki_extract_frameset(frameset, HAWKI_CAL_DISTOR_RAW) ; 00367 if (distorframes == NULL) 00368 { 00369 cpl_msg_error(__func__, "Distortion images have to be provided (%s)", 00370 HAWKI_CAL_DISTOR_RAW); 00371 return -1 ; 00372 } 00373 /* Retrieve sky frames */ 00374 skyframes = hawki_extract_frameset(frameset, HAWKI_CAL_DISTOR_SKY_RAW) ; 00375 if (skyframes == NULL) 00376 { 00377 cpl_msg_error(__func__, "Sky images have to be provided (%s)", 00378 HAWKI_CAL_DISTOR_SKY_RAW); 00379 cpl_frameset_delete(distorframes); 00380 return -1 ; 00381 } 00382 /* Retrieve the distortion first guess (if provided) */ 00383 distorxguess = cpl_frameset_find_const(frameset, HAWKI_CALPRO_DISTORTION_X); 00384 distoryguess = cpl_frameset_find_const(frameset, HAWKI_CALPRO_DISTORTION_Y); 00385 if(distorxguess != NULL && distoryguess != NULL) 00386 { 00387 //distortionguess = hawki_distortion_load(distorxtguess) 00388 } 00389 00390 /* Get the master sky frame */ 00391 cpl_msg_info(__func__, "Computing the master sky image"); 00392 master_sky = hawki_cal_distortion_get_master_sky(skyframes, flat, dark, bpm); 00393 if(master_sky == NULL) 00394 { 00395 cpl_msg_error(__func__, "Cannot get master sky image") ; 00396 cpl_frameset_delete(distorframes); 00397 cpl_frameset_delete(skyframes); 00398 return -1; 00399 } 00400 00401 /* Aperture detection, basic reduction and sky subtraction of distortion images */ 00402 cpl_msg_info(__func__, "Getting objects from distortion images"); 00403 if(hawki_cal_distortion_get_apertures_from_raw_distor 00404 (distorframes, flat, dark, bpm, master_sky, 00405 hawki_cal_distortion_config.sigma_det, apertures) == -1) 00406 { 00407 cpl_msg_error(__func__, 00408 "Cannot get objects from distortion images"); 00409 for(idet = 0; idet < HAWKI_NB_DETECTORS ; ++idet) 00410 cpl_image_delete(master_sky[idet]); 00411 cpl_free(master_sky); 00412 cpl_frameset_delete(distorframes); 00413 cpl_frameset_delete(skyframes); 00414 return -1 ; 00415 } 00416 for(idet = 0; idet < HAWKI_NB_DETECTORS ; ++idet) 00417 cpl_image_delete(master_sky[idet]); 00418 cpl_free(master_sky); 00419 00420 /* Get the nominal offsets from the header */ 00421 cpl_msg_info(__func__,"Getting the nominal offsets"); 00422 nominal_offsets = hawki_get_header_tel_offsets(distorframes); 00423 if (nominal_offsets == NULL) 00424 { 00425 cpl_msg_error(__func__, "Cannot load the header offsets") ; 00426 cpl_frameset_delete(distorframes); 00427 cpl_frameset_delete(skyframes); 00428 return -1; 00429 } 00430 00431 /* Get the oposite offsets. This is to change from 00432 * telescope convention to cpl convention */ 00433 cpl_vector_multiply_scalar(cpl_bivector_get_x(nominal_offsets), -1.0); 00434 cpl_vector_multiply_scalar(cpl_bivector_get_y(nominal_offsets), -1.0); 00435 00436 /* Print the header offsets */ 00437 cpl_msg_indent_more(); 00438 for (ioff=0 ; ioff<cpl_bivector_get_size(nominal_offsets) ; ioff++) 00439 { 00440 cpl_msg_info(__func__, "Telescope offsets (Frame %d): %g %g", ioff+1, 00441 cpl_bivector_get_x_data(nominal_offsets)[ioff], 00442 cpl_bivector_get_y_data(nominal_offsets)[ioff]); 00443 } 00444 cpl_msg_indent_less(); 00445 00446 /* Get the distortion solution, the real stuff */ 00447 cpl_msg_info(__func__, "Computing the distortion"); 00448 nframes = cpl_frameset_get_size(distorframes); 00449 distortion = hawki_cal_distortion_compute_dist_solution 00450 (apertures, nframes, nominal_offsets, 00451 hawki_cal_distortion_config.grid_points, 00452 nmatched_pairs, rms, 00453 distortionguess); 00454 cpl_bivector_delete(nominal_offsets); 00455 if(distortion == NULL) 00456 { 00457 cpl_frameset_delete(distorframes); 00458 cpl_frameset_delete(skyframes); 00459 return -1; 00460 } 00461 00462 /* Get some QC */ 00463 qclists = hawki_cal_distortion_qc(distortion, nmatched_pairs, rms); 00464 00465 /* Save the products */ 00466 cpl_msg_info(__func__,"Saving products"); 00467 if(hawki_cal_distortion_save(distortion, 00468 parlist, qclists, frameset) == -1) 00469 { 00470 cpl_msg_error(__func__,"Could not save products"); 00471 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00472 cpl_propertylist_delete(qclists[idet]); 00473 cpl_free(qclists); 00474 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00475 hawki_distortion_delete(distortion[idet]); 00476 cpl_free(distortion); 00477 cpl_frameset_delete(distorframes); 00478 cpl_frameset_delete(skyframes); 00479 return -1; 00480 } 00481 00482 /* Free and return */ 00483 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00484 cpl_propertylist_delete(qclists[idet]); 00485 cpl_free(qclists); 00486 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00487 hawki_distortion_delete(distortion[idet]); 00488 cpl_free(distortion); 00489 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00490 { 00491 for(iframe = 0 ; iframe < nframes; iframe++) 00492 cpl_apertures_delete(apertures[idet][iframe]); 00493 cpl_free(apertures[idet]); 00494 } 00495 cpl_frameset_delete(distorframes); 00496 cpl_frameset_delete(skyframes); 00497 00498 00499 /* Return */ 00500 if (cpl_error_get_code()) 00501 { 00502 cpl_msg_error(__func__, 00503 "HAWK-I pipeline could not recover from previous errors"); 00504 return -1 ; 00505 } 00506 else return 0 ; 00507 } 00508 00509 /*----------------------------------------------------------------------------*/ 00520 /*----------------------------------------------------------------------------*/ 00521 static int hawki_cal_distortion_load_master_calib 00522 (const cpl_frame * flat, 00523 const cpl_frame * dark, 00524 const cpl_frame * bpm, 00525 cpl_imagelist ** flat_images, 00526 cpl_imagelist ** dark_images, 00527 cpl_imagelist ** bpm_images) 00528 { 00529 cpl_errorstate error_prevstate = cpl_errorstate_get(); 00530 00531 /* Initializing the pointers */ 00532 *flat_images = NULL; 00533 *dark_images = NULL; 00534 *bpm_images = NULL; 00535 00536 /* Loading the calibration files */ 00537 cpl_msg_info(__func__, "Loading the calibration data") ; 00538 if(flat != NULL) 00539 { 00540 *flat_images = hawki_load_frame(flat, CPL_TYPE_FLOAT); 00541 if(*flat_images == NULL) 00542 { 00543 cpl_msg_error(__func__, "Error reading flat") ; 00544 return -1; 00545 } 00546 } 00547 if(dark != NULL) 00548 { 00549 *dark_images = hawki_load_frame(dark, CPL_TYPE_FLOAT); 00550 if(*dark_images == NULL) 00551 { 00552 cpl_msg_error(__func__, "Error reading dark") ; 00553 cpl_imagelist_delete(*flat_images); 00554 return -1; 00555 } 00556 } 00557 if(bpm != NULL) 00558 { 00559 *bpm_images = hawki_load_frame(bpm, CPL_TYPE_INT); 00560 if(*bpm_images == NULL) 00561 { 00562 cpl_msg_error(__func__, "Error reading bpm") ; 00563 cpl_imagelist_delete(*flat_images); 00564 cpl_imagelist_delete(*dark_images); 00565 return -1; 00566 } 00567 } 00568 00569 if(!cpl_errorstate_is_equal(error_prevstate )) 00570 { 00571 cpl_msg_error(__func__, "A problem happened loading calibration"); 00572 cpl_imagelist_delete(*flat_images); 00573 cpl_imagelist_delete(*dark_images); 00574 cpl_imagelist_delete(*bpm_images); 00575 return -1; 00576 } 00577 return 0; 00578 } 00579 00580 /*----------------------------------------------------------------------------*/ 00590 /*----------------------------------------------------------------------------*/ 00591 static int hawki_cal_distortion_get_apertures_from_raw_distor 00592 (cpl_frameset * raw_distor, 00593 const cpl_frame * flat, 00594 const cpl_frame * dark, 00595 const cpl_frame * bpm, 00596 cpl_image ** master_sky, 00597 double sigma_det, 00598 cpl_apertures *** apertures) 00599 { 00600 cpl_imagelist * flat_images; 00601 cpl_imagelist * dark_images; 00602 cpl_imagelist * bpm_images; 00603 cpl_propertylist * plist; 00604 00605 double science_dit; 00606 int iframe; 00607 int nframes; 00608 int idet; 00609 00610 cpl_errorstate error_prevstate = cpl_errorstate_get(); 00611 00612 /* Indentation */ 00613 cpl_msg_indent_more(); 00614 00615 /* Loading calibrations */ 00616 hawki_cal_distortion_load_master_calib 00617 (flat, dark, bpm, &flat_images, &dark_images, &bpm_images); 00618 00619 /* Multiply the dark image by the science exposure time */ 00620 if(dark != NULL) 00621 { 00622 if ((plist=cpl_propertylist_load 00623 (cpl_frame_get_filename 00624 (cpl_frameset_get_first_const(raw_distor)), 0)) == NULL) 00625 { 00626 cpl_msg_error(__func__, "Cannot get header from frame"); 00627 cpl_imagelist_delete(flat_images); 00628 cpl_imagelist_delete(dark_images); 00629 return -1; 00630 } 00631 science_dit = hawki_pfits_get_dit(plist); 00632 cpl_imagelist_multiply_scalar(dark_images, science_dit); 00633 cpl_propertylist_delete(plist); 00634 } 00635 00636 /* Loop on detectors */ 00637 nframes = cpl_frameset_get_size(raw_distor); 00638 for(idet = 0; idet < HAWKI_NB_DETECTORS ; ++idet) 00639 { 00640 cpl_imagelist * distor_serie; 00641 cpl_imagelist * distor_serie_trimmed; 00642 cpl_image * flat_det = NULL; 00643 cpl_image * dark_det = NULL; 00644 cpl_image * bpm_det = NULL; 00645 00646 cpl_msg_info(__func__, "Working on detector %d", idet + 1); 00647 cpl_msg_indent_more(); 00648 00649 /* Loading the distortion images for one detector */ 00650 cpl_msg_info(__func__, "Loading distortion images"); 00651 distor_serie = hawki_load_detector(raw_distor, idet + 1, CPL_TYPE_FLOAT); 00652 if(distor_serie== NULL) 00653 { 00654 cpl_msg_error(__func__, "Error reading distortion images"); 00655 return -1; 00656 } 00657 00658 /* Getting the calibs */ 00659 if(flat_images != NULL) 00660 flat_det = cpl_imagelist_get(flat_images, idet); 00661 if(dark_images != NULL) 00662 dark_det = cpl_imagelist_get(dark_images, idet); 00663 if(bpm_images != NULL) 00664 bpm_det = cpl_imagelist_get(bpm_images, idet); 00665 00666 if(!cpl_errorstate_is_equal(error_prevstate )) 00667 cpl_msg_warning(cpl_func,"PPPPPP5"); 00668 00669 /* Applying the calibrations */ 00670 cpl_msg_info(__func__, "Applying basic calibration") ; 00671 cpl_msg_indent_more(); 00672 if (hawki_flat_dark_bpm_detector_calib 00673 (distor_serie, flat_det, dark_det, bpm_det) == -1) 00674 { 00675 cpl_msg_error(__func__, "Cannot calibrate frame") ; 00676 cpl_imagelist_delete(flat_images); 00677 cpl_imagelist_delete(dark_images); 00678 cpl_imagelist_delete(bpm_images); 00679 cpl_imagelist_delete(distor_serie); 00680 cpl_msg_indent_less() ; 00681 return -1; 00682 } 00683 cpl_msg_indent_less(); 00684 00685 /* Discard the pixels on the sides */ 00686 if (hawki_cal_distortion_config.borders > 0) 00687 { 00688 distor_serie_trimmed = hawki_trim_detector_calib(distor_serie, 00689 hawki_cal_distortion_config.borders); 00690 cpl_imagelist_delete(distor_serie); 00691 } 00692 else 00693 distor_serie_trimmed = distor_serie; 00694 00695 /* Subtract sky */ 00696 cpl_msg_info(__func__, "Subtracting master sky") ; 00697 if(hawki_cal_distortion_subtract_sky(distor_serie_trimmed, master_sky[idet]) == -1) 00698 { 00699 cpl_msg_error(__func__, "Cannot subtract the sky") ; 00700 cpl_imagelist_delete(flat_images); 00701 cpl_imagelist_delete(dark_images); 00702 cpl_imagelist_delete(bpm_images); 00703 cpl_imagelist_delete(distor_serie_trimmed); 00704 return -1; 00705 } 00706 00707 /* Creating apertures */ 00708 apertures[idet] = cpl_malloc(sizeof(*(apertures[idet])) * nframes); 00709 for(iframe = 0 ; iframe < nframes; iframe++) 00710 { 00711 cpl_image * this_image = cpl_imagelist_get(distor_serie_trimmed, iframe); 00712 cpl_msg_info(__func__,"Working with distortion image %d", iframe+1); 00713 cpl_msg_indent_more(); 00714 apertures[idet][iframe] = 00715 hawki_cal_distortion_get_image_apertures(this_image, sigma_det); 00716 cpl_msg_indent_less(); 00717 } 00718 00719 /* Delete the list of images */ 00720 cpl_imagelist_delete(distor_serie_trimmed); 00721 cpl_msg_indent_less(); 00722 } 00723 cpl_imagelist_delete(flat_images); 00724 cpl_imagelist_delete(dark_images); 00725 cpl_imagelist_delete(bpm_images); 00726 00727 00728 if(!cpl_errorstate_is_equal(error_prevstate )) 00729 { 00730 cpl_msg_error(__func__, "A problem happened detecting objects"); 00731 return -1 ; 00732 } 00733 return 0; 00734 } 00735 00736 static cpl_image ** hawki_cal_distortion_get_master_sky 00737 (cpl_frameset * raw_sky_frames, 00738 const cpl_frame * flat, 00739 const cpl_frame * dark, 00740 const cpl_frame * bpm) 00741 { 00742 cpl_propertylist * plist; 00743 double science_dit; 00744 int idet; 00745 int jdet; 00746 cpl_imagelist * flat_images; 00747 cpl_imagelist * dark_images; 00748 cpl_imagelist * bpm_images; 00749 cpl_image ** bkg_images = NULL; 00750 00751 cpl_errorstate error_prevstate = cpl_errorstate_get(); 00752 00753 /* Indentation */ 00754 cpl_msg_indent_more(); 00755 00756 /* Reading calibrations */ 00757 hawki_cal_distortion_load_master_calib 00758 (flat, dark, bpm, &flat_images, &dark_images, &bpm_images); 00759 00760 /* Multiply the dark image by the science exposure time */ 00761 if(dark != NULL) 00762 { 00763 if ((plist=cpl_propertylist_load 00764 (cpl_frame_get_filename 00765 (cpl_frameset_get_first_const(raw_sky_frames)), 0)) == NULL) 00766 { 00767 cpl_msg_error(__func__, "Cannot get header from frame"); 00768 cpl_imagelist_delete(flat_images); 00769 cpl_imagelist_delete(dark_images); 00770 cpl_imagelist_delete(bpm_images); 00771 return NULL; 00772 } 00773 science_dit = hawki_pfits_get_dit(plist); 00774 cpl_imagelist_multiply_scalar(dark_images, science_dit); 00775 cpl_propertylist_delete(plist); 00776 } 00777 00778 /* Compute the sky median */ 00779 bkg_images = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(*bkg_images)); 00780 for(idet = 0; idet < HAWKI_NB_DETECTORS ; ++idet) 00781 { 00782 cpl_imagelist * sky_serie; 00783 cpl_imagelist * sky_serie_trimmed; 00784 cpl_image * flat_det = NULL; 00785 cpl_image * dark_det = NULL; 00786 cpl_image * bpm_det = NULL; 00787 00788 /* Loading the sky images for one detector */ 00789 sky_serie = hawki_load_detector(raw_sky_frames, idet + 1, CPL_TYPE_FLOAT); 00790 if(sky_serie== NULL) 00791 { 00792 cpl_msg_error(__func__, "Error reading object image") ; 00793 return NULL; 00794 } 00795 00796 /* Getting the calibs */ 00797 if(flat_images != NULL) 00798 flat_det = cpl_imagelist_get(flat_images, idet); 00799 if(dark_images != NULL) 00800 dark_det = cpl_imagelist_get(dark_images, idet); 00801 if(bpm_images != NULL) 00802 bpm_det = cpl_imagelist_get(bpm_images, idet); 00803 00804 /* Applying the calibrations */ 00805 cpl_msg_info(__func__, "Working on detector %d", idet + 1); 00806 cpl_msg_indent_more(); 00807 if (hawki_flat_dark_bpm_detector_calib 00808 (sky_serie, flat_det, dark_det, bpm_det) == -1) 00809 { 00810 cpl_msg_error(__func__, "Cannot calibrate frame") ; 00811 cpl_imagelist_delete(flat_images); 00812 cpl_imagelist_delete(dark_images); 00813 cpl_imagelist_delete(bpm_images); 00814 cpl_imagelist_delete(sky_serie); 00815 for(jdet = 0; jdet < idet; ++jdet) 00816 cpl_image_delete(bkg_images[jdet]); 00817 cpl_free(bkg_images); 00818 cpl_msg_indent_less() ; 00819 return NULL; 00820 } 00821 00822 /* Discard the pixels on the sides */ 00823 if (hawki_cal_distortion_config.borders > 0) 00824 { 00825 sky_serie_trimmed = hawki_trim_detector_calib(sky_serie, 00826 hawki_cal_distortion_config.borders); 00827 cpl_imagelist_delete(sky_serie); 00828 } 00829 else 00830 sky_serie_trimmed = sky_serie; 00831 00832 /* Averaging */ 00833 if ((bkg_images[idet] = 00834 cpl_imagelist_collapse_median_create(sky_serie_trimmed)) == NULL) 00835 { 00836 cpl_msg_error(__func__, "Cannot compute the median of obj images"); 00837 cpl_imagelist_delete(flat_images); 00838 cpl_imagelist_delete(dark_images); 00839 cpl_imagelist_delete(bpm_images); 00840 cpl_imagelist_delete(sky_serie_trimmed); 00841 for(jdet = 0; jdet < idet; ++jdet) 00842 cpl_image_delete(bkg_images[jdet]); 00843 cpl_free(bkg_images); 00844 cpl_msg_indent_less(); 00845 return NULL; 00846 } 00847 cpl_imagelist_delete(sky_serie_trimmed); 00848 cpl_msg_indent_less(); 00849 } 00850 00851 /* Subtract the median of the frame */ 00852 for(idet = 0; idet < HAWKI_NB_DETECTORS ; ++idet) 00853 cpl_image_subtract_scalar(bkg_images[idet], 00854 cpl_image_get_median(bkg_images[idet])); 00855 00856 /* Cleaning up */ 00857 cpl_msg_indent_less(); 00858 cpl_imagelist_delete(flat_images); 00859 cpl_imagelist_delete(dark_images); 00860 cpl_imagelist_delete(bpm_images); 00861 00862 if(!cpl_errorstate_is_equal(error_prevstate )) 00863 { 00864 cpl_msg_error(__func__, "A problem happened with basic calibration"); 00865 for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet) 00866 cpl_image_delete(bkg_images[idet]); 00867 cpl_free(bkg_images); 00868 return NULL ; 00869 } 00870 return bkg_images; 00871 } 00872 00873 static int hawki_cal_distortion_subtract_sky 00874 (cpl_imagelist * distor_corrected, 00875 cpl_image * master_sky) 00876 { 00877 cpl_errorstate error_prevstate = cpl_errorstate_get(); 00878 00879 /* Subtract the background to each object frame */ 00880 int idist, ndistor; 00881 ndistor = cpl_imagelist_get_size(distor_corrected); 00882 for(idist = 0; idist < ndistor; ++idist) 00883 { 00884 cpl_image * target_image = 00885 cpl_imagelist_get(distor_corrected, idist); 00886 /* First subtract the median of the image */ 00887 cpl_image_subtract_scalar 00888 (target_image, cpl_image_get_median(target_image)); 00889 00890 if (cpl_image_subtract 00891 (target_image, master_sky)!=CPL_ERROR_NONE) 00892 { 00893 cpl_msg_error(cpl_func,"Cannot apply the bkg to the images"); 00894 return -1 ; 00895 } 00896 } 00897 00898 /* Free and return */ 00899 if(!cpl_errorstate_is_equal(error_prevstate )) 00900 { 00901 cpl_msg_error(__func__, "A problem happened with sky subtraction"); 00902 return -1; 00903 } 00904 return 0; 00905 } 00906 00907 00908 /*----------------------------------------------------------------------------*/ 00918 /*----------------------------------------------------------------------------*/ 00919 static hawki_distortion ** hawki_cal_distortion_compute_dist_solution 00920 (cpl_apertures *** apertures, 00921 int nframes, 00922 cpl_bivector * offsets, 00923 int grid_points, 00924 int * nmatched_pairs, 00925 double * rms, 00926 hawki_distortion ** distortion_guess) 00927 { 00928 int idet; 00929 hawki_distortion ** distortion = NULL; 00930 00931 cpl_errorstate error_prevstate = cpl_errorstate_get(); 00932 00933 /* Allocate the distortion */ 00934 distortion = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(*distortion)); 00935 00936 /* Loop on the detectors */ 00937 cpl_msg_indent_more(); 00938 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00939 { 00940 cpl_table ** obj_pos; 00941 cpl_table ** obj_pos_offset; 00942 int iframe; 00943 cpl_table * matches; 00944 hawki_distortion * dist_guess; 00945 cpl_polynomial * fit2d_x = NULL; 00946 cpl_polynomial * fit2d_y = NULL; 00947 00948 00949 cpl_msg_info(__func__, "Working on detector %d", idet+1); 00950 cpl_msg_indent_more(); 00951 00952 /* Initialize the objects positions */ 00953 obj_pos = 00954 cpl_malloc(sizeof(*obj_pos) * nframes); 00955 obj_pos_offset = 00956 cpl_malloc(sizeof(*obj_pos_offset) * nframes); 00957 for(iframe = 0; iframe < nframes; ++iframe) 00958 { 00959 obj_pos[iframe] = cpl_table_new(0); 00960 cpl_table_new_column 00961 (obj_pos[iframe], HAWKI_COL_OBJ_POSX, CPL_TYPE_DOUBLE); 00962 cpl_table_new_column 00963 (obj_pos[iframe], HAWKI_COL_OBJ_POSY, CPL_TYPE_DOUBLE); 00964 } 00965 00966 /* Loop on images to fill object_positions */ 00967 for(iframe = 0 ; iframe < nframes ; ++iframe) 00968 { 00969 cpl_apertures * this_apertures; 00970 00971 /* Create the detected apertures list */ 00972 this_apertures = apertures[idet][iframe]; 00973 00974 /* Fill the objects position table */ 00975 hawki_cal_distortion_fill_obj_pos(obj_pos[iframe], 00976 this_apertures); 00977 obj_pos_offset[iframe] = cpl_table_duplicate(obj_pos[iframe]); 00978 } 00979 00980 /* Get the objects positions with offsets */ 00981 hawki_cal_distortion_add_offset_to_positions 00982 (obj_pos_offset, offsets); 00983 00984 /* Get the all the matching pairs */ 00985 cpl_msg_info(__func__, "Matching all catalogs (may take a while)"); 00986 matches = irplib_match_cat_pairs(obj_pos_offset, nframes, 00987 hawki_match_condition_5_pix); 00988 for(iframe = 0; iframe < nframes; ++iframe) 00989 cpl_table_delete(obj_pos_offset[iframe]); 00990 cpl_free(obj_pos_offset); 00991 if(matches == NULL) 00992 { 00993 cpl_msg_error(__func__, "Cannot match objects "); 00994 for(iframe = 0; iframe < nframes; ++iframe) 00995 cpl_table_delete(obj_pos[iframe]); 00996 cpl_free(obj_pos); 00997 return NULL; 00998 } 00999 cpl_msg_info(__func__,"Number of matching pairs %"CPL_SIZE_FORMAT, 01000 cpl_table_get_nrow(matches)); 01001 nmatched_pairs[idet] = cpl_table_get_nrow(matches); 01002 01003 /* Compute the distortion */ 01004 cpl_msg_info(__func__, "Computing distortion with the matched objects"); 01005 cpl_msg_info(__func__, " (This step will take a long time to run)"); 01006 if(distortion_guess != NULL) 01007 dist_guess = distortion_guess[idet]; 01008 else 01009 dist_guess = NULL; 01010 distortion[idet] = hawki_distortion_compute_solution 01011 ((const cpl_table **)obj_pos, offsets, matches, 01012 nframes, HAWKI_DET_NPIX_X , HAWKI_DET_NPIX_Y, grid_points, 01013 dist_guess, rms + idet); 01014 if(distortion[idet] == NULL) 01015 { 01016 int jdet; 01017 cpl_msg_error(__func__,"Could not get the distortion"); 01018 for(iframe = 0; iframe < nframes; ++iframe) 01019 cpl_table_delete(obj_pos[iframe]); 01020 cpl_free(obj_pos); 01021 for(jdet = 0; jdet < idet; ++jdet) 01022 hawki_distortion_delete(distortion[idet]); 01023 cpl_table_delete(matches); 01024 return NULL; 01025 } 01026 01027 /* Removing the first order polinomial to the distortion */ 01028 if(hawki_cal_distortion_config.subtract_linear) 01029 { 01030 cpl_msg_info(__func__,"Subtracting first order polynomial"); 01031 fit2d_x = cpl_polynomial_new(2); 01032 fit2d_y = cpl_polynomial_new(2); 01033 hawki_cal_distortion_fit_first_order_solution 01034 (distortion[idet], fit2d_x, fit2d_y); 01035 } 01036 01037 /* Free */ 01038 for(iframe = 0; iframe < nframes; ++iframe) 01039 cpl_table_delete(obj_pos[iframe]); 01040 cpl_free(obj_pos); 01041 if(hawki_cal_distortion_config.subtract_linear) 01042 { 01043 cpl_polynomial_delete(fit2d_x); 01044 cpl_polynomial_delete(fit2d_y); 01045 } 01046 cpl_table_delete(matches); 01047 cpl_msg_indent_less(); 01048 } 01049 01050 if(!cpl_errorstate_is_equal(error_prevstate )) 01051 { 01052 cpl_msg_error(__func__, "A problem happened computing the distortion"); 01053 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 01054 hawki_distortion_delete(distortion[idet]); 01055 return NULL ; 01056 } 01057 /* Free and return */ 01058 return distortion; 01059 } 01060 01061 static cpl_apertures * hawki_cal_distortion_get_image_apertures 01062 (cpl_image * image, 01063 double sigma_det) 01064 { 01065 cpl_apertures * apertures = NULL; 01066 cpl_mask * kernel = NULL; 01067 cpl_mask * object_mask = NULL; 01068 cpl_image * labels = NULL; 01069 cpl_size nobj; 01070 double median; 01071 double med_dist; 01072 double threshold; 01073 01074 /* Get the threshold */ 01075 median = cpl_image_get_median_dev(image, &med_dist); 01076 threshold = median + sigma_det * med_dist; 01077 cpl_msg_info(__func__,"Detection threshold: %f", threshold); 01078 01079 /* Create the mask */ 01080 object_mask = cpl_mask_threshold_image_create 01081 (image, threshold, DBL_MAX); 01082 if (object_mask == NULL) 01083 return NULL; 01084 01085 /* Apply morphological opening to remove single pixel detections */ 01086 kernel = cpl_mask_new(3,3); 01087 cpl_mask_not(kernel); 01088 01089 if (cpl_mask_filter(object_mask, object_mask, kernel, 01090 CPL_FILTER_OPENING, CPL_BORDER_ZERO) != CPL_ERROR_NONE) { 01091 cpl_mask_delete(object_mask) ; 01092 cpl_mask_delete(kernel) ; 01093 return NULL; 01094 } 01095 cpl_mask_delete(kernel); 01096 01097 /* Labelise the different detected apertures */ 01098 labels = cpl_image_labelise_mask_create(object_mask, &nobj); 01099 if (labels == NULL) 01100 { 01101 cpl_mask_delete(object_mask); 01102 return NULL; 01103 } 01104 cpl_mask_delete(object_mask); 01105 cpl_msg_info(__func__, "Number of objects detected: %"CPL_SIZE_FORMAT, 01106 nobj); 01107 01108 /* Create the detected apertures list */ 01109 apertures = cpl_apertures_new_from_image(image, labels); 01110 if (apertures == NULL) 01111 { 01112 cpl_image_delete(labels); 01113 return NULL; 01114 } 01115 cpl_image_delete(labels); 01116 return apertures; 01117 } 01118 01119 static int hawki_cal_distortion_fill_obj_pos 01120 (cpl_table * objects_positions, 01121 cpl_apertures * apertures) 01122 { 01123 cpl_size nobjs; 01124 cpl_size iobj; 01125 double border_off = 0; 01126 01127 /* Take into account that the images have been trimmed */ 01128 if(hawki_cal_distortion_config.borders > 0) 01129 border_off = hawki_cal_distortion_config.borders; 01130 01131 nobjs = cpl_apertures_get_size(apertures); 01132 cpl_table_set_size(objects_positions, nobjs); 01133 01134 for (iobj=0 ; iobj<nobjs ; iobj++) 01135 { 01136 /* Fill with the already known information */ 01137 cpl_table_set_double(objects_positions, HAWKI_COL_OBJ_POSX, iobj, 01138 cpl_apertures_get_centroid_x(apertures, 01139 iobj+1) + border_off); 01140 cpl_table_set_double(objects_positions, HAWKI_COL_OBJ_POSY, iobj, 01141 cpl_apertures_get_centroid_y(apertures, 01142 iobj+1) + border_off); 01143 } 01144 01145 return 0; 01146 } 01147 01148 static int hawki_cal_distortion_add_offset_to_positions 01149 (cpl_table ** objects_positions, 01150 cpl_bivector * offsets) 01151 { 01152 int nframes; 01153 int iframe; 01154 cpl_size nobjs; 01155 cpl_size iobj; 01156 01157 nframes = cpl_bivector_get_size(offsets); 01158 01159 for(iframe = 0 ; iframe < nframes ; ++iframe) 01160 { 01161 double offset_x; 01162 double offset_y; 01163 int null; 01164 offset_x = cpl_bivector_get_x_data(offsets)[iframe]; 01165 offset_y = cpl_bivector_get_y_data(offsets)[iframe]; 01166 nobjs = cpl_table_get_nrow(objects_positions[iframe]); 01167 for (iobj=0 ; iobj<nobjs ; iobj++) 01168 { 01169 cpl_table_set_double(objects_positions[iframe], 01170 HAWKI_COL_OBJ_POSX, iobj, 01171 cpl_table_get_double(objects_positions[iframe], 01172 HAWKI_COL_OBJ_POSX, iobj, &null) + offset_x); 01173 cpl_table_set_double(objects_positions[iframe], 01174 HAWKI_COL_OBJ_POSY, iobj, 01175 cpl_table_get_double(objects_positions[iframe], 01176 HAWKI_COL_OBJ_POSY, iobj, &null) + offset_y); 01177 } 01178 } 01179 01180 return 0; 01181 } 01182 01183 static int hawki_cal_distortion_fit_first_order_solution 01184 (hawki_distortion * distortion, 01185 cpl_polynomial * fit2d_x, 01186 cpl_polynomial * fit2d_y) 01187 { 01188 cpl_matrix * pixel_pos; 01189 cpl_vector * dist_x_val; 01190 cpl_vector * dist_y_val; 01191 int nx; 01192 int ny; 01193 int i; 01194 int j; 01195 int null; 01196 const cpl_size mindeg2d[] = {0, 0}; 01197 const cpl_size maxdeg2d[] = {1, 1}; 01198 cpl_errorstate error_prevstate = cpl_errorstate_get(); 01199 cpl_vector * pix; 01200 cpl_image * dist_x_plane; 01201 cpl_image * dist_y_plane; 01202 double dist_x_mean; 01203 double dist_y_mean; 01204 01205 /* Fill the bivector with pixel positions in X,Y */ 01206 nx = hawki_distortion_get_size_x(distortion); 01207 ny = hawki_distortion_get_size_y(distortion); 01208 pixel_pos = cpl_matrix_new(2, nx * ny); 01209 dist_x_val = cpl_vector_new(nx*ny); 01210 dist_y_val = cpl_vector_new(nx*ny); 01211 for(i = 0; i < nx; ++i) 01212 for(j = 0; j < ny; ++j) 01213 { 01214 cpl_matrix_set(pixel_pos, 0, i + nx * j, (double)i); 01215 cpl_matrix_set(pixel_pos, 1, i + nx * j, (double)j); 01216 cpl_vector_set(dist_x_val, i + nx * j, 01217 cpl_image_get(distortion->dist_x, i+1, j+1, &null)); 01218 cpl_vector_set(dist_y_val, i + nx * j, 01219 cpl_image_get(distortion->dist_y, i+1, j+1, &null)); 01220 } 01221 01222 /* Fit the polynomial */ 01223 cpl_polynomial_fit(fit2d_x, pixel_pos, NULL, dist_x_val, 01224 NULL, CPL_FALSE, mindeg2d, maxdeg2d); 01225 cpl_polynomial_fit(fit2d_y, pixel_pos, NULL, dist_y_val, 01226 NULL, CPL_FALSE, mindeg2d, maxdeg2d); 01227 /* Removing the constant term */ 01228 cpl_polynomial_set_coeff(fit2d_x, mindeg2d, 0.); 01229 cpl_polynomial_set_coeff(fit2d_y, mindeg2d, 0.); 01230 01231 /* Subtract the linear term */ 01232 pix = cpl_vector_new(2); 01233 dist_x_plane = cpl_image_new(nx,ny,cpl_image_get_type(distortion->dist_x)); 01234 dist_y_plane = cpl_image_new(nx,ny,cpl_image_get_type(distortion->dist_y)); 01235 for(i = 0; i < nx; ++i) 01236 for(j = 0; j < ny; ++j) 01237 { 01238 double fit_value_x; 01239 double fit_value_y; 01240 cpl_vector_set(pix, 0, (double)i); 01241 cpl_vector_set(pix, 1, (double)j); 01242 fit_value_x = cpl_polynomial_eval(fit2d_x, pix); 01243 fit_value_y = cpl_polynomial_eval(fit2d_y, pix); 01244 cpl_image_set(dist_x_plane, i+1, j+1, fit_value_x); 01245 cpl_image_set(dist_y_plane, i+1, j+1, fit_value_y); 01246 } 01247 cpl_image_subtract(distortion->dist_x, dist_x_plane); 01248 cpl_image_subtract(distortion->dist_y, dist_y_plane); 01249 01250 /* Subtract the mean distortion, again */ 01251 dist_x_mean = cpl_image_get_mean(distortion->dist_x); 01252 dist_y_mean = cpl_image_get_mean(distortion->dist_y); 01253 cpl_msg_warning(__func__,"Subtracting mean distortion in X %f",dist_x_mean); 01254 cpl_msg_warning(__func__,"Subtracting mean distortion in Y %f",dist_y_mean); 01255 cpl_image_subtract_scalar(distortion->dist_x, dist_x_mean); 01256 cpl_image_subtract_scalar(distortion->dist_y, dist_y_mean); 01257 01258 /* Free and return */ 01259 cpl_matrix_delete(pixel_pos); 01260 cpl_vector_delete(dist_x_val); 01261 cpl_vector_delete(dist_y_val); 01262 cpl_vector_delete(pix); 01263 cpl_image_delete(dist_x_plane); 01264 cpl_image_delete(dist_y_plane); 01265 01266 if(!cpl_errorstate_is_equal(error_prevstate )) 01267 { 01268 cpl_msg_error(__func__, "A problem happened computing the linear term"); 01269 cpl_msg_error(__func__,"Error %s",cpl_error_get_message()); 01270 //cpl_msg_error(__func__,"Where %s",cpl_error_get_where()); 01271 return -1; 01272 } 01273 return 0; 01274 } 01275 01276 /*----------------------------------------------------------------------------*/ 01281 /*----------------------------------------------------------------------------*/ 01282 static cpl_propertylist ** hawki_cal_distortion_qc 01283 (hawki_distortion ** distortion, 01284 int * nmatched_pairs, 01285 double * rms) 01286 { 01287 int idet; 01288 cpl_propertylist ** qclists; 01289 01290 /* Allocate the qclists */ 01291 qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ; 01292 01293 /* Loop on the detectors to get the mean zpoint */ 01294 for(idet = 0 ; idet < HAWKI_NB_DETECTORS ; ++idet) 01295 { 01296 /* Allocate this qclist */ 01297 qclists[idet] = cpl_propertylist_new() ; 01298 01299 cpl_propertylist_append_double 01300 (qclists[idet], "ESO QC DIST NMATCHED", nmatched_pairs[idet]); 01301 01302 cpl_propertylist_append_double 01303 (qclists[idet], "ESO QC DIST TOTAL RMS", rms[idet]); 01304 01305 /* Getting the jacobian of the distortion map */ 01306 /* The jacobian has to be definitive positive in all the detector to 01307 * be have a biyective function invertible anywhere: 01308 * http://en.wikipedia.org/wiki/Jacobian_matrix_and_determinant#Jacobian_determinant 01309 * http://en.wikipedia.org/wiki/Inverse_function#Inverses_and_derivatives 01310 * This should be a QC check. 01311 */ 01312 01313 01314 //cpl_propertylist_append_double 01315 //(qclists[idet], "ESO QC DIST JACOBIAN_1_1", jacobian[1][1]); 01316 } 01317 01318 return qclists; 01319 } 01320 01321 /*----------------------------------------------------------------------------*/ 01331 /*----------------------------------------------------------------------------*/ 01332 static int hawki_cal_distortion_save 01333 (hawki_distortion ** distortion, 01334 cpl_parameterlist * parlist, 01335 cpl_propertylist ** qclists, 01336 cpl_frameset * recipe_set) 01337 { 01338 const char * recipe_name = "hawki_cal_distortion"; 01339 01340 /* Write the distortion in both axes */ 01341 hawki_distortion_save(recipe_set, 01342 parlist, 01343 recipe_set, 01344 (const hawki_distortion **) distortion, 01345 recipe_name, 01346 NULL, 01347 (const cpl_propertylist **)qclists, 01348 "hawki_cal_distortion_x.fits", 01349 "hawki_cal_distortion_y.fits"); 01350 01351 /* Free and return */ 01352 return 0; 01353 } 01354 01355 static int hawki_cal_distortion_retrieve_input_param 01356 (cpl_parameterlist * parlist) 01357 { 01358 cpl_parameter * par ; 01359 01360 par = NULL ; 01361 par = cpl_parameterlist_find 01362 (parlist, "hawki.hawki_cal_distortion.sigma_det"); 01363 hawki_cal_distortion_config.sigma_det = cpl_parameter_get_double(par); 01364 par = cpl_parameterlist_find 01365 (parlist, "hawki.hawki_cal_distortion.grid_points"); 01366 hawki_cal_distortion_config.grid_points = cpl_parameter_get_int(par); 01367 par = cpl_parameterlist_find 01368 (parlist, "hawki.hawki_cal_distortion.borders"); 01369 hawki_cal_distortion_config.borders = cpl_parameter_get_int(par); 01370 par = cpl_parameterlist_find 01371 (parlist, "hawki.hawki_cal_distortion.subtract_linear"); 01372 hawki_cal_distortion_config.subtract_linear = cpl_parameter_get_bool(par); 01373 01374 01375 return 0; 01376 }