HAWKI Pipeline Reference Manual 1.8.6
|
00001 /* $Id: hawki_sci_jitter.c,v 1.30 2011/12/22 15:27:06 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: 2011/12/22 15:27:06 $ 00024 * $Revision: 1.30 $ 00025 * $Name: hawki-1_8_6 $ 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 #include "hawki_obj_det.h" 00055 00056 /*----------------------------------------------------------------------------- 00057 Define 00058 -----------------------------------------------------------------------------*/ 00059 00060 #define NEGLIG_OFF_DIFF 0.1 00061 #define SQR(x) ((x)*(x)) 00062 00063 /*----------------------------------------------------------------------------- 00064 Functions prototypes 00065 -----------------------------------------------------------------------------*/ 00066 00067 static int hawki_sci_jitter_create(cpl_plugin *) ; 00068 static int hawki_sci_jitter_exec(cpl_plugin *) ; 00069 static int hawki_sci_jitter_destroy(cpl_plugin *) ; 00070 static int hawki_sci_jitter(cpl_parameterlist *, cpl_frameset *) ; 00071 00072 static int hawki_sci_jitter_retrieve_input_param 00073 (cpl_parameterlist * parlist); 00074 static cpl_image ** hawki_sci_jitter_reduce 00075 (cpl_frameset * jitters, 00076 cpl_frameset * sky, 00077 const char * flat, 00078 const char * dark, 00079 const char * bpm, 00080 cpl_table ** bkg_stats); 00081 static int hawki_sci_jitter_sky 00082 (cpl_imagelist * jitters, 00083 cpl_imagelist * skys, 00084 cpl_table ** bkg_stats, 00085 int idet); 00086 static int hawki_sci_jitter_sky_running 00087 (cpl_imagelist * in, 00088 cpl_table ** bkg_stats, 00089 int idet); 00090 static cpl_image ** hawki_sci_jitter_saa(cpl_imagelist **, cpl_bivector *, 00091 double *, double *); 00092 static int hawki_sci_jitter_qc 00093 (cpl_frameset * science_frames, 00094 cpl_image ** combined, 00095 cpl_table ** obj_charac); 00096 static int hawki_sci_jitter_read_calib 00097 (const char * flat, 00098 const char * dark, 00099 const char * bpm, 00100 cpl_image ** flat_image, 00101 cpl_image ** dark_image, 00102 cpl_image ** bpm_image, 00103 int idet); 00104 static int hawki_sci_jitter_save 00105 (cpl_image ** combined, 00106 cpl_image * stitched, 00107 cpl_table ** objs_charac, 00108 cpl_table ** raw_jitter_stats, 00109 cpl_table ** bkg_stats, 00110 const cpl_table * raw_obj_tel_info, 00111 cpl_frameset * science_frames, 00112 cpl_frameset * calib_frames, 00113 cpl_parameterlist * parlist, 00114 cpl_frameset * set); 00115 int hawki_sci_jitter_whole_image_algo 00116 (cpl_frameset * obj, 00117 cpl_table ** raw_jitter_stats, 00118 cpl_table * raw_obj_tel_info, 00119 cpl_parameterlist * parlist, 00120 cpl_frameset * recipe_set); 00121 int hawki_sci_jitter_save_stats 00122 (cpl_table ** raw_jitter_stats, 00123 cpl_table * raw_obj_tel_info, 00124 cpl_frameset * jitter_frames, 00125 cpl_parameterlist * parlist, 00126 cpl_frameset * recipe_set); 00127 00128 /*----------------------------------------------------------------------------- 00129 Static variables 00130 -----------------------------------------------------------------------------*/ 00131 00132 static struct 00133 { 00134 /* Inputs */ 00135 const char * offsets ; 00136 const char * objects ; 00137 int offset_max ; 00138 int sky_minnb ; 00139 int sky_halfw ; 00140 int sky_rejmin ; 00141 int sky_rejmax ; 00142 int refine ; 00143 int sx ; 00144 int sy ; 00145 int mx ; 00146 int my ; 00147 int borders ; 00148 cpl_geom_combine comb_meth ; 00149 int rej_low ; 00150 int rej_high ; 00151 int max_njitter; 00152 } hawki_sci_jitter_config; 00153 00154 static struct 00155 { 00156 /* Outputs */ 00157 double pixscale; 00158 double dit; 00159 double mean_airmass; 00160 double iq[HAWKI_NB_DETECTORS]; 00161 int nbobjs[HAWKI_NB_DETECTORS]; 00162 double fwhm_pix[HAWKI_NB_DETECTORS]; 00163 double fwhm_arcsec[HAWKI_NB_DETECTORS]; 00164 double fwhm_mode[HAWKI_NB_DETECTORS]; 00165 double combined_pos_x[HAWKI_NB_DETECTORS]; 00166 double combined_pos_y[HAWKI_NB_DETECTORS]; 00167 double combined_cumoffset_x[HAWKI_NB_DETECTORS]; 00168 double combined_cumoffset_y[HAWKI_NB_DETECTORS]; 00169 int ncomb[HAWKI_NB_DETECTORS]; 00170 } hawki_sci_jitter_output; 00171 00172 static char hawki_sci_jitter_description[] = 00173 "hawki_sci_jitter -- hawki imaging jitter recipe.\n\n" 00174 "The input of the recipe files listed in the Set Of Frames (sof-file)\n" 00175 "must be tagged as:\n" 00176 "raw-file.fits "HAWKI_IMG_JITTER_RAW" or\n" 00177 "raw-file.fits "HAWKI_IMG_JITTER_SKY_RAW" or\n" 00178 "flat-file.fits "HAWKI_CALPRO_FLAT" or\n" 00179 "dark-file.fits "HAWKI_CALPRO_DARK" \n" 00180 "bpm-file.fits "HAWKI_CALPRO_BPM"\n" 00181 "distortion_x-file.fits "HAWKI_CALPRO_DISTORTION_X"\n" 00182 "distortion_y-file.fits "HAWKI_CALPRO_DISTORTION_Y"\n\n" 00183 "The recipe creates as an output:\n" 00184 "hawki_sci_jitter.fits ("HAWKI_CALPRO_COMBINED")\n" 00185 "hawki_sci_jitter_stitched.fits ("HAWKI_CALPRO_STITCHED")\n" 00186 "hawki_sci_jitter_stars.fits ("HAWKI_CALPRO_OBJ_PARAM"): Detected objects properties\n" 00187 "hawki_sci_jitter_stats.fits ("HAWKI_CALPRO_JITTER_STATS"): Stats of the individual images\n" 00188 "hawki_sci_jitter_bkg_stats.fits ("HAWKI_CALPRO_JITTER_BKG_STATS"): Statistics on the bkg\n\n" 00189 "The recipe performs the following steps:\n" 00190 "1) Frame statistics\n" 00191 "2) Basic reduction (using "HAWKI_CALPRO_FLAT" and "HAWKI_CALPRO_BPM")\n" 00192 "3) Background computation (the algorithm depends on parameter --sky_par) \n" 00193 "4) Offset refinement (uses parameters --off, --refine and --xcorr)\n" 00194 "5) Stacking of jitter frames (uses --comb_meth, --rej,\n" 00195 " --offset_max, --borders, --max_njitter)\n" 00196 "6) Stitching of the four detectors into one image\n" 00197 "7) Object detection in the stacked image\n\n" 00198 "Return code:\n" 00199 "esorex exits with an error code of 0 if the recipe completes successfully\n" 00200 "or 1 otherwise"; 00201 00202 /*----------------------------------------------------------------------------- 00203 Functions code 00204 -----------------------------------------------------------------------------*/ 00205 00206 /*----------------------------------------------------------------------------*/ 00214 /*----------------------------------------------------------------------------*/ 00215 int cpl_plugin_get_info(cpl_pluginlist * list) 00216 { 00217 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ; 00218 cpl_plugin * plugin = &recipe->interface ; 00219 00220 cpl_plugin_init(plugin, 00221 CPL_PLUGIN_API, 00222 HAWKI_BINARY_VERSION, 00223 CPL_PLUGIN_TYPE_RECIPE, 00224 "hawki_sci_jitter", 00225 "Jitter recipe", 00226 hawki_sci_jitter_description, 00227 "Cesar Enrique Garcia", 00228 PACKAGE_BUGREPORT, 00229 hawki_get_license(), 00230 hawki_sci_jitter_create, 00231 hawki_sci_jitter_exec, 00232 hawki_sci_jitter_destroy) ; 00233 00234 cpl_pluginlist_append(list, plugin) ; 00235 00236 return 0; 00237 } 00238 00239 /*----------------------------------------------------------------------------*/ 00248 /*----------------------------------------------------------------------------*/ 00249 static int hawki_sci_jitter_create(cpl_plugin * plugin) 00250 { 00251 cpl_recipe * recipe ; 00252 cpl_parameter * p ; 00253 00254 /* Get the recipe out of the plugin */ 00255 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00256 recipe = (cpl_recipe *)plugin ; 00257 else return -1 ; 00258 00259 /* Create the parameters list in the cpl_recipe object */ 00260 recipe->parameters = cpl_parameterlist_new() ; 00261 if (recipe->parameters == NULL) 00262 return 1; 00263 00264 /* Fill the parameters list */ 00265 /* --offsets */ 00266 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.offsets", 00267 CPL_TYPE_STRING, "offsets file", "hawki.hawki_sci_jitter", NULL) ; 00268 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "offsets") ; 00269 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00270 cpl_parameterlist_append(recipe->parameters, p) ; 00271 00272 /* --objects */ 00273 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.objects", 00274 CPL_TYPE_STRING, "objects file", "hawki.hawki_sci_jitter", NULL) ; 00275 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "objects") ; 00276 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00277 cpl_parameterlist_append(recipe->parameters, p) ; 00278 00279 /* --offset_max */ 00280 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.offset_max", 00281 CPL_TYPE_INT, 00282 "Maximum offset allowed", 00283 "hawki.hawki_sci_jitter", 00284 1500) ; 00285 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "offset_max") ; 00286 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00287 cpl_parameterlist_append(recipe->parameters, p) ; 00288 00289 /* --sky_par */ 00290 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.sky_par", 00291 CPL_TYPE_STRING, 00292 "Rejection parameters for sky filtering", 00293 "hawki.hawki_sci_jitter", 00294 "10,7,3,3") ; 00295 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_par") ; 00296 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00297 cpl_parameterlist_append(recipe->parameters, p) ; 00298 00299 /* --refine */ 00300 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.refine", 00301 CPL_TYPE_BOOL, "refine offsets", "hawki.hawki_sci_jitter", 00302 FALSE); 00303 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "refine") ; 00304 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00305 cpl_parameterlist_append(recipe->parameters, p) ; 00306 00307 /* --xcorr */ 00308 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.xcorr", 00309 CPL_TYPE_STRING, 00310 "Cross correlation search and measure sizes", 00311 "hawki.hawki_sci_jitter", 00312 "20,20,25,25") ; 00313 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcorr") ; 00314 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00315 cpl_parameterlist_append(recipe->parameters, p) ; 00316 00317 /* --comb_meth */ 00318 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.comb_meth", 00319 CPL_TYPE_STRING, "union / inter / first", "hawki.hawki_sci_jitter", 00320 "union") ; 00321 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "comb_meth") ; 00322 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00323 cpl_parameterlist_append(recipe->parameters, p) ; 00324 00325 /* --rej */ 00326 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.rej", 00327 CPL_TYPE_STRING, 00328 "Low and high number of rejected values", 00329 "hawki.hawki_sci_jitter", 00330 "1,1") ; 00331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rej") ; 00332 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00333 cpl_parameterlist_append(recipe->parameters, p) ; 00334 00335 /* --borders */ 00336 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.borders", 00337 CPL_TYPE_INT, 00338 "Borders rejected", 00339 "hawki.hawki_sci_jitter", 00340 4) ; 00341 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "borders") ; 00342 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00343 cpl_parameterlist_append(recipe->parameters, p) ; 00344 00345 /* --max_njitter */ 00346 p = cpl_parameter_new_value("hawki.hawki_sci_jitter.max_njitter", 00347 CPL_TYPE_INT, 00348 "Maximum numbers of jitter frames to combine", 00349 "hawki.hawki_sci_jitter", 00350 -1); 00351 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "max_njitter"); 00352 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00353 cpl_parameterlist_append(recipe->parameters, p); 00354 00355 /* Return */ 00356 return 0; 00357 } 00358 00359 /*----------------------------------------------------------------------------*/ 00365 /*----------------------------------------------------------------------------*/ 00366 static int hawki_sci_jitter_exec(cpl_plugin * plugin) 00367 { 00368 cpl_recipe * recipe ; 00369 00370 /* Get the recipe out of the plugin */ 00371 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00372 recipe = (cpl_recipe *)plugin ; 00373 else return -1 ; 00374 00375 /* Issue a banner */ 00376 hawki_print_banner(); 00377 00378 return hawki_sci_jitter(recipe->parameters, recipe->frames) ; 00379 } 00380 00381 /*----------------------------------------------------------------------------*/ 00387 /*----------------------------------------------------------------------------*/ 00388 static int hawki_sci_jitter_destroy(cpl_plugin * plugin) 00389 { 00390 cpl_recipe * recipe ; 00391 00392 /* Get the recipe out of the plugin */ 00393 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00394 recipe = (cpl_recipe *)plugin ; 00395 else return -1 ; 00396 00397 cpl_parameterlist_delete(recipe->parameters) ; 00398 return 0 ; 00399 } 00400 00401 /*----------------------------------------------------------------------------*/ 00408 /*----------------------------------------------------------------------------*/ 00409 static int hawki_sci_jitter( 00410 cpl_parameterlist * parlist, 00411 cpl_frameset * framelist) 00412 { 00413 const char * flat; 00414 const char * dark; 00415 const char * bpm; 00416 const cpl_frame * distx; 00417 const cpl_frame * disty; 00418 cpl_frameset * jitterframes ; 00419 cpl_frameset * skyframes ; 00420 cpl_frameset * science_frames; 00421 cpl_frameset * calib_frames; 00422 cpl_image ** combined ; 00423 cpl_table ** obj_charac; 00424 cpl_table ** raw_jitter_stats; 00425 cpl_table ** bkg_stats; 00426 cpl_table * raw_obj_tel_info; 00427 cpl_image * stitched ; 00428 int i; 00429 00430 /* Initialise */ 00431 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00432 { 00433 hawki_sci_jitter_output.iq[i] = -1.0 ; 00434 hawki_sci_jitter_output.nbobjs[i] = -1 ; 00435 hawki_sci_jitter_output.fwhm_pix[i] = -1.0 ; 00436 hawki_sci_jitter_output.fwhm_arcsec[i] = -1.0 ; 00437 hawki_sci_jitter_output.fwhm_mode[i] = -1.0 ; 00438 hawki_sci_jitter_output.combined_pos_x[i] = -1.0 ; 00439 hawki_sci_jitter_output.combined_pos_y[i] = -1.0 ; 00440 hawki_sci_jitter_output.combined_cumoffset_x[i] = -1.0 ; 00441 hawki_sci_jitter_output.combined_cumoffset_y[i] = -1.0 ; 00442 } 00443 hawki_sci_jitter_output.pixscale = -1.0 ; 00444 hawki_sci_jitter_output.dit = -1.0 ; 00445 hawki_sci_jitter_config.offsets = NULL ; 00446 hawki_sci_jitter_config.objects = NULL ; 00447 calib_frames = cpl_frameset_new(); 00448 00449 /* Retrieve input parameters */ 00450 if(hawki_sci_jitter_retrieve_input_param(parlist)) 00451 { 00452 cpl_msg_error(cpl_func, "Wrong parameters"); 00453 cpl_frameset_delete(calib_frames); 00454 return -1; 00455 } 00456 00457 /* Identify the RAW and CALIB frames in the input frameset */ 00458 if (hawki_dfs_set_groups(framelist)) { 00459 cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames") ; 00460 cpl_frameset_delete(calib_frames); 00461 return -1 ; 00462 } 00463 00464 /* Retrieve calibration data */ 00465 flat = hawki_extract_first_filename(framelist, HAWKI_CALPRO_FLAT) ; 00466 dark = hawki_extract_first_filename(framelist, HAWKI_CALPRO_DARK); 00467 bpm = hawki_extract_first_filename(framelist, HAWKI_CALPRO_BPM) ; 00468 distx = cpl_frameset_find_const(framelist, HAWKI_CALPRO_DISTORTION_X); 00469 disty = cpl_frameset_find_const(framelist, HAWKI_CALPRO_DISTORTION_Y); 00470 if((distx == NULL && disty !=NULL) || (distx != NULL && disty ==NULL)) 00471 { 00472 cpl_msg_error(cpl_func, "Both distortion in X (%s) and Y (%s) must be provided", 00473 HAWKI_CALPRO_DISTORTION_X, HAWKI_CALPRO_DISTORTION_Y); 00474 cpl_frameset_delete(calib_frames); 00475 return -1 ; 00476 } 00477 if(flat) 00478 cpl_frameset_insert(calib_frames, cpl_frame_duplicate( 00479 cpl_frameset_find_const(framelist, HAWKI_CALPRO_FLAT))); 00480 if(dark) 00481 cpl_frameset_insert(calib_frames, cpl_frame_duplicate( 00482 cpl_frameset_find_const(framelist, HAWKI_CALPRO_DARK))); 00483 if(bpm) 00484 cpl_frameset_insert(calib_frames, cpl_frame_duplicate( 00485 cpl_frameset_find_const(framelist, HAWKI_CALPRO_BPM))); 00486 if(distx) 00487 { 00488 cpl_frameset_insert(calib_frames, cpl_frame_duplicate(distx)); 00489 cpl_frameset_insert(calib_frames, cpl_frame_duplicate(disty)); 00490 } 00491 00492 00493 /* Retrieve raw frames */ 00494 jitterframes = hawki_extract_frameset(framelist, HAWKI_IMG_JITTER_RAW) ; 00495 if (jitterframes == NULL) { 00496 cpl_msg_error(cpl_func, "Cannot find jitter frames in the input list (%s)", 00497 HAWKI_IMG_JITTER_RAW); 00498 cpl_frameset_delete(calib_frames); 00499 return -1 ; 00500 } 00501 science_frames = cpl_frameset_duplicate(jitterframes); 00502 skyframes = hawki_extract_frameset(framelist, HAWKI_IMG_JITTER_SKY_RAW) ; 00503 if (skyframes != NULL) 00504 { 00505 int isky; 00506 for(isky = 0; isky< cpl_frameset_get_size(skyframes); ++isky) 00507 cpl_frameset_insert(science_frames, 00508 cpl_frame_duplicate(cpl_frameset_get_frame(skyframes, isky))); 00509 } 00510 00511 /* Create the statistics table */ 00512 raw_jitter_stats = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table *)); 00513 for( i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00514 { 00515 raw_jitter_stats[i] = cpl_table_new(cpl_frameset_get_size(jitterframes)); 00516 } 00517 hawki_image_stats_initialize(raw_jitter_stats); 00518 bkg_stats = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table *)); 00519 for( i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00520 { 00521 bkg_stats[i] = cpl_table_new(cpl_frameset_get_size(jitterframes)); 00522 } 00523 hawki_image_stats_initialize(bkg_stats); 00524 00525 /* Create the telescope statistics parameters from the raw images */ 00526 raw_obj_tel_info = cpl_table_new(cpl_frameset_get_size(jitterframes)); 00527 /* Add the proper columns of the pcs table */ 00528 if(hawki_prop_tel_initialize(raw_obj_tel_info)) 00529 { 00530 cpl_msg_error(cpl_func,"Could not initialize the pcs table"); 00531 cpl_frameset_delete(jitterframes) ; 00532 for( i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00533 { 00534 cpl_table_delete(raw_jitter_stats[i]) ; 00535 cpl_table_delete(bkg_stats[i]) ; 00536 } 00537 cpl_free(raw_jitter_stats) ; 00538 cpl_free(bkg_stats) ; 00539 cpl_table_delete(raw_obj_tel_info); 00540 if (skyframes) cpl_frameset_delete(skyframes) ; 00541 cpl_frameset_delete(calib_frames); 00542 cpl_msg_indent_less() ; 00543 return -1; 00544 } 00545 00546 /* Do the algorithms that need the whole image */ 00547 hawki_sci_jitter_whole_image_algo(jitterframes, 00548 raw_jitter_stats, 00549 raw_obj_tel_info, 00550 parlist, 00551 framelist); 00552 00553 /* Apply the reduction */ 00554 /* Do the algorithms that can be applied to subsection of the images */ 00555 cpl_msg_info(cpl_func, "Apply the data combination") ; 00556 cpl_msg_indent_more() ; 00557 if ((combined = hawki_sci_jitter_reduce(jitterframes, skyframes, flat, dark, 00558 bpm, bkg_stats)) == NULL) 00559 { 00560 cpl_msg_error(cpl_func, "Cannot recombine the data"); 00561 cpl_frameset_delete(jitterframes); 00562 for( i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00563 { 00564 cpl_table_delete(raw_jitter_stats[i]) ; 00565 cpl_table_delete(bkg_stats[i]) ; 00566 } 00567 cpl_free(raw_jitter_stats) ; 00568 cpl_free(bkg_stats) ; 00569 cpl_table_delete(raw_obj_tel_info); 00570 if (skyframes) cpl_frameset_delete(skyframes) ; 00571 cpl_frameset_delete(calib_frames); 00572 cpl_msg_indent_less() ; 00573 return -1 ; 00574 } 00575 cpl_msg_indent_less() ; 00576 00577 /* Compute QC parameters from the combined image */ 00578 cpl_msg_info(cpl_func, "Compute QC parameters from the combined images") ; 00579 cpl_msg_indent_more() ; 00580 obj_charac = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table*)) ; 00581 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00582 { 00583 obj_charac[i] = cpl_table_new(0); 00584 } 00585 if ((hawki_sci_jitter_qc(jitterframes, combined, obj_charac)) != 0) 00586 { 00587 cpl_msg_warning(cpl_func, "Cannot compute all parameters") ; 00588 } 00589 cpl_msg_indent_less(); 00590 cpl_frameset_delete(jitterframes); 00591 if (skyframes) cpl_frameset_delete(skyframes); 00592 00593 00594 /* Correct for the distortion */ 00595 if (distx && disty) 00596 { 00597 cpl_msg_info(cpl_func, "Applying the distortion correction") ; 00598 cpl_msg_indent_more() ; 00599 if (hawki_distortion_correct_alldetectors(combined, distx, disty) == -1) 00600 { 00601 cpl_msg_error(cpl_func, "Cannot correct the distortion") ; 00602 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00603 cpl_image_delete(combined[i]) ; 00604 cpl_free(combined) ; 00605 if (obj_charac) { 00606 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00607 cpl_table_delete(obj_charac[i]) ; 00608 cpl_free(obj_charac); 00609 } 00610 cpl_table_delete(raw_obj_tel_info); 00611 for( i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00612 { 00613 cpl_table_delete(raw_jitter_stats[i]); 00614 cpl_table_delete(bkg_stats[i]); 00615 } 00616 cpl_free(raw_jitter_stats); 00617 cpl_free(bkg_stats); 00618 cpl_frameset_delete(calib_frames); 00619 cpl_frameset_delete(science_frames); 00620 cpl_msg_indent_less() ; 00621 return -1; 00622 } 00623 cpl_msg_indent_less() ; 00624 } 00625 00626 /* Compute the stitched image */ 00627 cpl_msg_info(cpl_func, "Compute the stiched image") ; 00628 if ((stitched = hawki_images_stitch(combined, 00629 hawki_sci_jitter_output.combined_pos_x, 00630 hawki_sci_jitter_output.combined_pos_y)) == NULL) 00631 { 00632 cpl_msg_error(cpl_func, "Cannot stitch the images") ; 00633 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00634 cpl_image_delete(combined[i]) ; 00635 cpl_free(combined) ; 00636 if (obj_charac) { 00637 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00638 cpl_table_delete(obj_charac[i]) ; 00639 cpl_free(obj_charac); 00640 } 00641 cpl_table_delete(raw_obj_tel_info); 00642 for( i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00643 { 00644 cpl_table_delete(raw_jitter_stats[i]); 00645 cpl_table_delete(bkg_stats[i]); 00646 } 00647 cpl_free(raw_jitter_stats); 00648 cpl_free(bkg_stats); 00649 cpl_frameset_delete(calib_frames); 00650 cpl_frameset_delete(science_frames); 00651 return -1; 00652 } 00653 00654 /* Save the products */ 00655 cpl_msg_info(cpl_func, "Save the products") ; 00656 cpl_msg_indent_more() ; 00657 if (hawki_sci_jitter_save(combined, stitched, obj_charac, 00658 raw_jitter_stats, bkg_stats, 00659 raw_obj_tel_info, 00660 science_frames, 00661 calib_frames, 00662 parlist, framelist) == -1) 00663 cpl_msg_warning(cpl_func,"Some data could not be saved. " 00664 "Check permisions or disk space"); 00665 00666 /* Return */ 00667 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00668 cpl_image_delete(combined[i]) ; 00669 cpl_free(combined) ; 00670 if (obj_charac) { 00671 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00672 cpl_table_delete(obj_charac[i]) ; 00673 cpl_free(obj_charac); 00674 } 00675 if (stitched) cpl_image_delete(stitched) ; 00676 cpl_table_delete(raw_obj_tel_info); 00677 for( i=0 ; i<HAWKI_NB_DETECTORS ; i++) 00678 { 00679 cpl_table_delete(raw_jitter_stats[i]); 00680 cpl_table_delete(bkg_stats[i]); 00681 } 00682 cpl_free(raw_jitter_stats); 00683 cpl_free(bkg_stats); 00684 cpl_frameset_delete(calib_frames); 00685 cpl_frameset_delete(science_frames); 00686 cpl_msg_indent_less() ; 00687 00688 /* Return */ 00689 if (cpl_error_get_code()) 00690 { 00691 cpl_msg_error(cpl_func, 00692 "HAWK-I pipeline could not recover from previous errors"); 00693 return -1 ; 00694 } 00695 else return 0 ; 00696 } 00697 00698 int hawki_sci_jitter_retrieve_input_param 00699 (cpl_parameterlist * parlist) 00700 { 00701 cpl_parameter * par ; 00702 const char * sval ; 00703 par = NULL ; 00704 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.offsets"); 00705 hawki_sci_jitter_config.offsets = cpl_parameter_get_string(par); 00706 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.objects"); 00707 hawki_sci_jitter_config.objects = cpl_parameter_get_string(par); 00708 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.offset_max"); 00709 hawki_sci_jitter_config.offset_max = cpl_parameter_get_int(par); 00710 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.sky_par"); 00711 sval = cpl_parameter_get_string(par); 00712 if (sscanf(sval, "%d,%d,%d,%d", 00713 &hawki_sci_jitter_config.sky_minnb, 00714 &hawki_sci_jitter_config.sky_halfw, 00715 &hawki_sci_jitter_config.sky_rejmin, 00716 &hawki_sci_jitter_config.sky_rejmax)!=4) 00717 { 00718 return -1; 00719 } 00720 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.xcorr"); 00721 sval = cpl_parameter_get_string(par); 00722 if (sscanf(sval, "%d,%d,%d,%d", 00723 &hawki_sci_jitter_config.sx, 00724 &hawki_sci_jitter_config.sy, 00725 &hawki_sci_jitter_config.mx, 00726 &hawki_sci_jitter_config.my)!=4) 00727 { 00728 return -1; 00729 } 00730 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.refine"); 00731 hawki_sci_jitter_config.refine = cpl_parameter_get_bool(par); 00732 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.comb_meth"); 00733 sval = cpl_parameter_get_string(par); 00734 if (!strcmp(sval, "union")) 00735 hawki_sci_jitter_config.comb_meth = CPL_GEOM_UNION; 00736 else if (!strcmp(sval, "inter")) 00737 hawki_sci_jitter_config.comb_meth = CPL_GEOM_INTERSECT; 00738 else if (!strcmp(sval, "first")) 00739 hawki_sci_jitter_config.comb_meth = CPL_GEOM_FIRST; 00740 else 00741 { 00742 cpl_msg_error(cpl_func, "Invalid combine method specified"); 00743 return -1; 00744 } 00745 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.borders"); 00746 hawki_sci_jitter_config.borders = cpl_parameter_get_int(par); 00747 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.rej"); 00748 sval = cpl_parameter_get_string(par); 00749 if (sscanf(sval, "%d,%d", 00750 &hawki_sci_jitter_config.rej_low, 00751 &hawki_sci_jitter_config.rej_high)!=2) 00752 { 00753 return -1; 00754 } 00755 par = cpl_parameterlist_find(parlist, "hawki.hawki_sci_jitter.max_njitter"); 00756 hawki_sci_jitter_config.max_njitter = cpl_parameter_get_int(par); 00757 return 0; 00758 } 00759 00760 00761 00762 /*----------------------------------------------------------------------------*/ 00773 /*----------------------------------------------------------------------------*/ 00774 static cpl_image ** hawki_sci_jitter_reduce 00775 (cpl_frameset * jitters, 00776 cpl_frameset * sky, 00777 const char * flat, 00778 const char * dark, 00779 const char * bpm, 00780 cpl_table ** bkg_stats) 00781 { 00782 cpl_frame * frame ; 00783 cpl_propertylist * plist ; 00784 cpl_image ** comb_chip ; 00785 cpl_image ** combined ; 00786 cpl_bivector * offsets ; 00787 cpl_vector * offset_x_sort; 00788 cpl_vector * offset_y_sort; 00789 double * offs_est_x ; 00790 double * offs_est_y ; 00791 double off_0_x; 00792 double off_0_y; 00793 double max_x, max_y ; 00794 int idet; 00795 int ioff; 00796 00797 /* Get the header infos */ 00798 frame = cpl_frameset_get_frame(jitters, 0) ; 00799 plist=cpl_propertylist_load(cpl_frame_get_filename(frame), 0) ; 00800 hawki_sci_jitter_output.pixscale = hawki_pfits_get_pixscale(plist) ; 00801 hawki_sci_jitter_output.dit = hawki_pfits_get_dit(plist) ; 00802 cpl_propertylist_delete(plist) ; 00803 if (cpl_error_get_code()) { 00804 cpl_msg_error(cpl_func, "Missing keyword in FITS header") ; 00805 return NULL ; 00806 } 00807 00808 /* Check that DIT/NDIT and NDSAMPLES are the same for all the frames */ 00809 if(!hawki_utils_check_equal_double_keys(jitters, &hawki_pfits_get_dit) || 00810 !hawki_utils_check_equal_int_keys(jitters, &hawki_pfits_get_ndit)|| 00811 !hawki_utils_check_equal_int_keys(jitters, &hawki_pfits_get_ndsamples)) 00812 { 00813 cpl_msg_error(__func__, "Not all input science have the same " 00814 "DIT/NDIT/NDSAMPLES values"); 00815 cpl_msg_indent_less() ; 00816 return NULL; 00817 } 00818 00819 /* Get the offsets */ 00820 if ((offsets = hawki_get_header_tel_offsets(jitters)) == NULL) { 00821 cpl_msg_error(cpl_func, "Cannot load the offsets") ; 00822 return NULL ; 00823 } 00824 offs_est_x = cpl_bivector_get_x_data(offsets) ; 00825 offs_est_y = cpl_bivector_get_y_data(offsets) ; 00826 00827 /* Print the header offsets */ 00828 for (ioff=0 ; ioff<cpl_bivector_get_size(offsets) ; ioff++) { 00829 cpl_msg_info(cpl_func, "Telescope offsets (Frame %d): %g %g", ioff+1, 00830 offs_est_x[ioff], offs_est_y[ioff]) ; 00831 } 00832 00833 /* Subtract the first offset to all offsets */ 00834 off_0_x = -offs_est_x[0]; // This is to get the cpl convention 00835 off_0_y = -offs_est_y[0]; 00836 for (ioff=1 ; ioff<cpl_bivector_get_size(offsets) ; ioff++) 00837 { 00838 offs_est_x[ioff] -= offs_est_x[0] ; 00839 offs_est_y[ioff] -= offs_est_y[0] ; 00840 } 00841 offs_est_x[0] = offs_est_y[0] = 0.00 ; 00842 00843 /* Check if the max offset is not too big */ 00844 /* The criteria is that for a given frame, the closest frame cannot be 00845 * further than hawki_sci_jitter_config.offset_max (in both dimensions) */ 00846 offset_x_sort = cpl_vector_duplicate(cpl_bivector_get_x(offsets)); 00847 offset_y_sort = cpl_vector_duplicate(cpl_bivector_get_y(offsets)); 00848 cpl_vector_sort(offset_x_sort, +1); 00849 cpl_vector_sort(offset_y_sort, +1); 00850 for (ioff=0 ; ioff<cpl_bivector_get_size(offsets) - 1 ; ioff++) 00851 { 00852 double diff_x, diff_y; 00853 diff_x = cpl_vector_get(offset_x_sort,ioff+1)-cpl_vector_get(offset_x_sort,ioff); 00854 cpl_vector_set(offset_x_sort, ioff, diff_x); 00855 diff_y = cpl_vector_get(offset_y_sort,ioff+1)-cpl_vector_get(offset_y_sort,ioff); 00856 cpl_vector_set(offset_y_sort, ioff, diff_y); 00857 } 00858 cpl_vector_set(offset_x_sort, cpl_bivector_get_size(offsets)-1, 0.); 00859 cpl_vector_set(offset_y_sort, cpl_bivector_get_size(offsets)-1, 0.); 00860 max_x = cpl_vector_get_max(offset_x_sort); 00861 max_y = cpl_vector_get_max(offset_y_sort); 00862 cpl_vector_delete(offset_x_sort); 00863 cpl_vector_delete(offset_y_sort); 00864 00865 if (max_x > hawki_sci_jitter_config.offset_max || 00866 max_y > hawki_sci_jitter_config.offset_max) 00867 { 00868 cpl_msg_error(cpl_func, "Sorry, no support for frames further than %d from its closest neighbour", 00869 hawki_sci_jitter_config.offset_max) ; 00870 cpl_bivector_delete(offsets); 00871 return NULL ; 00872 } 00873 00874 /* Create output object */ 00875 combined = cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_image*)) ; 00876 00877 /* Loop on the detectors */ 00878 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00879 { 00880 cpl_frameset * selected_jitter; 00881 cpl_bivector * selected_offsets; 00882 cpl_image * flat_ima = NULL; 00883 cpl_image * dark_ima = NULL; 00884 cpl_image * bpm_ima = NULL; 00885 cpl_imagelist * in = NULL; 00886 cpl_imagelist * in_sky = NULL; 00887 int nrejected; 00888 00889 cpl_msg_info(cpl_func, "Combine chip number %d", idet+1) ; 00890 cpl_msg_indent_more() ; 00891 00892 /* Apply frame selection based on offset values */ 00893 selected_jitter = cpl_frameset_duplicate(jitters); 00894 selected_offsets = cpl_bivector_duplicate(offsets); 00895 if(hawki_sci_jitter_config.max_njitter != -1) 00896 { 00897 if(hawki_sci_jitter_config.max_njitter < 00898 cpl_frameset_get_size(selected_jitter)) 00899 { 00900 while(cpl_frameset_get_size(selected_jitter) > 00901 hawki_sci_jitter_config.max_njitter) 00902 { 00903 int irm = cpl_frameset_get_size(selected_jitter) - 1; 00904 cpl_frameset_erase_frame 00905 (selected_jitter, 00906 cpl_frameset_get_frame(selected_jitter,irm)); 00907 } 00908 cpl_vector_set_size(cpl_bivector_get_x(selected_offsets), 00909 hawki_sci_jitter_config.max_njitter); 00910 cpl_vector_set_size(cpl_bivector_get_y(selected_offsets), 00911 hawki_sci_jitter_config.max_njitter); 00912 } 00913 } 00914 hawki_sci_jitter_output.ncomb[idet] = 00915 cpl_frameset_get_size(selected_jitter); 00916 nrejected = cpl_frameset_get_size(selected_jitter) - 00917 cpl_frameset_get_size(jitters); 00918 if(nrejected != 0) 00919 cpl_msg_info(cpl_func,"%d frames reject due to large offsets", 00920 nrejected); 00921 00922 00923 /* Load the input data */ 00924 cpl_msg_info(cpl_func, "Load the input data") ; 00925 cpl_msg_indent_more() ; 00926 if ((in = hawki_load_detector(selected_jitter, 00927 idet+1, CPL_TYPE_FLOAT)) == NULL) { 00928 cpl_msg_error(cpl_func, "Cannot load chip %d", idet+1) ; 00929 cpl_free(combined) ; 00930 cpl_bivector_delete(offsets) ; 00931 cpl_msg_indent_less() ; 00932 cpl_msg_indent_less() ; 00933 return NULL ; 00934 } 00935 if (sky) { 00936 if ((in_sky = hawki_load_detector(sky, idet+1, CPL_TYPE_FLOAT)) == NULL) 00937 { 00938 cpl_msg_warning(cpl_func, "Cannot load sky for chip %d",idet+1); 00939 } 00940 } else in_sky = NULL ; 00941 cpl_msg_indent_less() ; 00942 00943 /* Read the calibrations */ 00944 cpl_msg_info(cpl_func, "Load the calibration data") ; 00945 if(hawki_sci_jitter_read_calib(flat, dark, bpm, 00946 &flat_ima, &dark_ima, &bpm_ima, 00947 idet) != 0) 00948 { 00949 cpl_msg_error(cpl_func, "Cannot read some of the calibrations"); 00950 cpl_imagelist_delete(in); 00951 cpl_free(combined); 00952 if (in_sky) cpl_imagelist_delete(in_sky); 00953 cpl_bivector_delete(offsets); 00954 cpl_msg_indent_less(); 00955 cpl_msg_indent_less(); 00956 return NULL ; 00957 } 00958 00959 /* Apply the calibrations */ 00960 if (flat || dark || bpm ) 00961 { 00962 cpl_msg_info(cpl_func, "Apply the calibrations") ; 00963 cpl_msg_indent_more() ; 00964 /* Basic calibration of the OBJECTS */ 00965 if (hawki_flat_dark_bpm_detector_calib 00966 (in, flat_ima, dark_ima, bpm_ima) == -1) 00967 { 00968 cpl_msg_error(cpl_func, "Cannot calibrate the objects") ; 00969 cpl_imagelist_delete(in) ; 00970 cpl_free(combined) ; 00971 if (in_sky) cpl_imagelist_delete(in_sky) ; 00972 cpl_bivector_delete(offsets) ; 00973 cpl_image_delete(flat_ima); 00974 cpl_image_delete(dark_ima); 00975 cpl_image_delete(bpm_ima); 00976 cpl_msg_indent_less() ; 00977 cpl_msg_indent_less() ; 00978 return NULL ; 00979 } 00980 /* Basic calibration of the SKY */ 00981 if (in_sky) { 00982 if (hawki_flat_dark_bpm_detector_calib 00983 (in_sky, flat_ima, dark_ima, bpm_ima) == -1) 00984 { 00985 cpl_msg_warning(cpl_func, "Cannot calibrate the sky") ; 00986 cpl_imagelist_delete(in_sky) ; 00987 in_sky = NULL ; 00988 } 00989 } 00990 cpl_msg_indent_less() ; 00991 } 00992 cpl_image_delete(flat_ima); 00993 cpl_image_delete(dark_ima); 00994 cpl_image_delete(bpm_ima); 00995 00996 /* Apply the sky correction */ 00997 cpl_msg_info(cpl_func, "Sky estimation and correction") ; 00998 cpl_msg_indent_more() ; 00999 if (hawki_sci_jitter_sky(in, in_sky, bkg_stats, idet) == -1) 01000 { 01001 cpl_msg_error(cpl_func, "Cannot estimate the sky") ; 01002 cpl_imagelist_delete(in) ; 01003 if (in_sky) cpl_imagelist_delete(in_sky) ; 01004 cpl_free(combined) ; 01005 cpl_bivector_delete(offsets) ; 01006 cpl_msg_indent_less() ; 01007 cpl_msg_indent_less() ; 01008 return NULL ; 01009 } 01010 if (in_sky) cpl_imagelist_delete(in_sky) ; 01011 cpl_msg_indent_less() ; 01012 01013 /* Apply the shift and add */ 01014 cpl_msg_info(cpl_func, "Shift and stacking") ; 01015 cpl_msg_indent_more() ; 01016 comb_chip = hawki_sci_jitter_saa(&in, selected_offsets, 01017 &(hawki_sci_jitter_output.combined_pos_x[idet]), 01018 &(hawki_sci_jitter_output.combined_pos_y[idet])) ; 01019 hawki_sci_jitter_output.combined_cumoffset_x[idet] = 01020 hawki_sci_jitter_output.combined_pos_x[idet] - off_0_x; 01021 hawki_sci_jitter_output.combined_cumoffset_y[idet] = 01022 hawki_sci_jitter_output.combined_pos_y[idet] - off_0_y; 01023 if (comb_chip == NULL) { 01024 cpl_msg_error(cpl_func, "Cannot apply the shift and add") ; 01025 cpl_imagelist_delete(in) ; 01026 cpl_free(combined) ; 01027 cpl_bivector_delete(offsets) ; 01028 cpl_msg_indent_less() ; 01029 cpl_msg_indent_less() ; 01030 return NULL ; 01031 } 01032 cpl_imagelist_delete(in) ; 01033 cpl_msg_indent_less() ; 01034 01035 /* Put the results in the image list */ 01036 combined[idet] = comb_chip[0] ; 01037 cpl_image_delete(comb_chip[1]) ; 01038 cpl_free(comb_chip) ; 01039 cpl_msg_indent_less() ; 01040 01041 /* Free */ 01042 cpl_frameset_delete(selected_jitter); 01043 cpl_bivector_delete(selected_offsets); 01044 } 01045 cpl_bivector_delete(offsets) ; 01046 01047 return combined ; 01048 } 01049 01050 /*----------------------------------------------------------------------------*/ 01057 /*----------------------------------------------------------------------------*/ 01058 static int hawki_sci_jitter_sky 01059 (cpl_imagelist * objs, 01060 cpl_imagelist * skys, 01061 cpl_table ** bkg_stats, 01062 int idet) 01063 { 01064 cpl_image * sky ; 01065 int nframes; 01066 double median ; 01067 cpl_image * cur_ima ; 01068 int i ; 01069 01070 /* Initialise */ 01071 nframes = cpl_imagelist_get_size(objs) ; 01072 01073 /* Compute the sky frame */ 01074 if (skys != NULL) { 01075 cpl_msg_info(cpl_func, "Median of sky images") ; 01076 /* Use sky images */ 01077 if ((sky = cpl_imagelist_collapse_median_create(skys)) == NULL) { 01078 cpl_msg_error(cpl_func, "Cannot compute the median of sky images") ; 01079 return -1; 01080 } 01081 01082 /* Statistics on the background */ 01083 if(bkg_stats != NULL) 01084 { 01085 cpl_table_set_size(bkg_stats[idet], 1); 01086 hawki_image_stats_fill_from_image 01087 (bkg_stats, sky, 01088 1, 01089 1, 01090 cpl_image_get_size_x(sky), 01091 cpl_image_get_size_y(sky), 01092 idet, 0); 01093 } 01094 01095 /* Correct the objects images */ 01096 if (cpl_imagelist_subtract_image(objs, sky) != CPL_ERROR_NONE) { 01097 cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky"); 01098 cpl_image_delete(sky) ; 01099 return -1; 01100 } 01101 cpl_image_delete(sky) ; 01102 /* Normalise the object planes */ 01103 for (i=0 ; i<nframes ; i++) { 01104 cur_ima = cpl_imagelist_get(objs, i) ; 01105 median = cpl_image_get_median(cur_ima) ; 01106 cpl_image_subtract_scalar(cur_ima, median) ; 01107 } 01108 } else if (hawki_sci_jitter_config.sky_minnb > nframes) { 01109 cpl_msg_info(cpl_func, "Median of object images") ; 01110 /* Use objs images */ 01111 if ((sky = cpl_imagelist_collapse_median_create(objs)) == NULL) { 01112 cpl_msg_error(cpl_func, "Cannot compute the median of obj images") ; 01113 return -1; 01114 } 01115 01116 /* Statistics on the background */ 01117 if(bkg_stats != NULL) 01118 { 01119 cpl_table_set_size(bkg_stats[idet], 1); 01120 hawki_image_stats_fill_from_image 01121 (bkg_stats, sky, 01122 1, 01123 1, 01124 cpl_image_get_size_x(sky), 01125 cpl_image_get_size_y(sky), 01126 idet, 0); 01127 } 01128 01129 /* Correct the objects images */ 01130 if (cpl_imagelist_subtract_image(objs, sky) != CPL_ERROR_NONE) { 01131 cpl_msg_error(cpl_func, "Cannot corr. the obj images from the sky"); 01132 cpl_image_delete(sky) ; 01133 return -1; 01134 } 01135 /* Normalise the object planes */ 01136 for (i=0 ; i<nframes ; i++) { 01137 cur_ima = cpl_imagelist_get(objs, i) ; 01138 median = cpl_image_get_median(cur_ima) ; 01139 cpl_image_subtract_scalar(cur_ima, median) ; 01140 } 01141 /* Delete sky image */ 01142 cpl_image_delete(sky) ; 01143 } else { 01144 cpl_msg_info(cpl_func, "Computing running median on jitter images") ; 01145 /* Use objects images */ 01146 if (hawki_sci_jitter_sky_running(objs, bkg_stats, idet) == -1) 01147 { 01148 cpl_msg_error(cpl_func, 01149 "Cannot apply the running median"); 01150 return -1; 01151 } 01152 } 01153 return 0; 01154 } 01155 01156 /*----------------------------------------------------------------------------*/ 01175 /*----------------------------------------------------------------------------*/ 01176 static int hawki_sci_jitter_sky_running 01177 (cpl_imagelist * in, 01178 cpl_table ** bkg_stats, 01179 int idet) 01180 { 01181 int rejmin, rejmax, halfw; 01182 cpl_imagelist * result_buffer; 01183 int ni, nx, ny; 01184 cpl_vector * medians; 01185 cpl_image * cur_ima; 01186 cpl_image * tmp_ima; 01187 double one_med; 01188 int i, k; 01189 int first_buffered = 0; 01190 int next_not_to_be_used; 01191 01192 /* Test entries */ 01193 if (in==NULL) return -1; 01194 01195 /* Initialise */ 01196 rejmin = hawki_sci_jitter_config.sky_rejmin ; 01197 rejmax = hawki_sci_jitter_config.sky_rejmax ; 01198 halfw = hawki_sci_jitter_config.sky_halfw ; 01199 ni = cpl_imagelist_get_size(in) ; 01200 cur_ima = cpl_imagelist_get(in, 0) ; 01201 nx = cpl_image_get_size_x(cur_ima) ; 01202 ny = cpl_image_get_size_y(cur_ima) ; 01203 01204 /* Tests on validity of rejection parameters */ 01205 if (((rejmin+rejmax)>=halfw) || (halfw<1) || (rejmin<0) || (rejmax<0)) { 01206 cpl_msg_error(cpl_func, "cannot run filter with rej parms %d (%d-%d)", 01207 halfw, rejmin, rejmax); 01208 return -1; 01209 } 01210 /* Pre-compute median value in each plane */ 01211 medians = cpl_vector_new(ni) ; 01212 for (i=0 ; i<ni ; i++) { 01213 cur_ima = cpl_imagelist_get(in, i) ; 01214 cpl_vector_set(medians, i, cpl_image_get_median(cur_ima)) ; 01215 } 01216 /* Allocate output cube */ 01217 result_buffer = cpl_imagelist_new() ; 01218 01219 /* Allocate output bg stats */ 01220 cpl_table_set_size(bkg_stats[idet], ni); 01221 01222 /* Main loop over input planes */ 01223 for (k=0 ; k<ni ; k++) 01224 { 01225 cpl_image * bkg; 01226 01227 /* Create the background image, to later compute stats */ 01228 bkg = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01229 01230 hawki_bkg_from_running_mean_detector 01231 (in, medians, k, halfw, rejmin, rejmax, bkg); 01232 01233 /* Subtract the background from the current image */ 01234 tmp_ima = cpl_image_subtract_create(cpl_imagelist_get(in, k), bkg); 01235 01236 /* Statistics on the background */ 01237 if(bkg_stats != NULL) 01238 { 01239 hawki_image_stats_fill_from_image 01240 (bkg_stats, bkg, 01241 1, 1, nx, ny, 01242 idet, k); 01243 } 01244 cpl_image_delete(bkg); 01245 01246 /* Place the new image in a result buffer */ 01247 cpl_imagelist_set(result_buffer, tmp_ima, 01248 cpl_imagelist_get_size(result_buffer)); 01249 01250 /* Empty the buffer as much as possible */ 01251 next_not_to_be_used = k - halfw; 01252 while(next_not_to_be_used >= first_buffered) 01253 { 01254 cpl_imagelist_set(in, cpl_imagelist_unset(result_buffer, 0), 01255 first_buffered); 01256 first_buffered++; 01257 } 01258 } 01259 /* Empty the buffer finally */ 01260 next_not_to_be_used = ni - 1; 01261 while(next_not_to_be_used >= first_buffered) 01262 { 01263 cpl_imagelist_set(in, cpl_imagelist_unset(result_buffer, 0), 01264 first_buffered); 01265 first_buffered++; 01266 } 01267 cpl_imagelist_delete(result_buffer); 01268 cpl_vector_delete(medians); 01269 01270 /* Subtract median from each frame */ 01271 for (i=0 ; i<ni ; i++) { 01272 cur_ima = cpl_imagelist_get(in, i); 01273 one_med = cpl_image_get_median(cur_ima) ; 01274 cpl_image_subtract_scalar(cur_ima, one_med) ; 01275 } 01276 return 0; 01277 } 01278 01279 /*----------------------------------------------------------------------------*/ 01288 /*----------------------------------------------------------------------------*/ 01289 static cpl_image ** hawki_sci_jitter_saa( 01290 cpl_imagelist ** in, 01291 cpl_bivector * offsets, 01292 double * pos_x, 01293 double * pos_y) 01294 { 01295 cpl_bivector * offs_est; 01296 cpl_bivector * offs_used; 01297 cpl_bivector * objs ; 01298 cpl_image ** combined ; 01299 int nfiles, ngood, nima, nx, ny ; 01300 int i; 01301 01302 /* Check entries */ 01303 if (pos_x == NULL || pos_y == NULL) return NULL ; 01304 if (offsets == NULL) return NULL ; 01305 01306 /* Get the number of images */ 01307 nfiles = cpl_imagelist_get_size(*in) ; 01308 if (cpl_bivector_get_size(offsets) != nfiles) { 01309 cpl_msg_error(cpl_func, "Invalid input objects sizes") ; 01310 return NULL ; 01311 } 01312 01313 /* Get the offsets estimation of each input file pair */ 01314 cpl_msg_info(cpl_func, "Get the offsets estimation") ; 01315 offs_est = NULL ; 01316 if (hawki_sci_jitter_config.offsets && 01317 hawki_sci_jitter_config.offsets[0] != (char)0) { 01318 /* A file has been provided on the command line */ 01319 offs_est = cpl_bivector_read((char*)hawki_sci_jitter_config.offsets); 01320 if ((offs_est==NULL)||(cpl_bivector_get_size(offs_est)!=nfiles)) { 01321 cpl_msg_error(cpl_func, "Cannot get offsets from %s", 01322 hawki_sci_jitter_config.offsets) ; 01323 return NULL ; 01324 } 01325 } else { 01326 /* Use the offsets from the header */ 01327 offs_est = cpl_bivector_duplicate(offsets) ; 01328 cpl_vector_multiply_scalar(cpl_bivector_get_x(offs_est), -1.0) ; 01329 cpl_vector_multiply_scalar(cpl_bivector_get_y(offs_est), -1.0) ; 01330 } 01331 01332 /* Read the provided objects file if provided */ 01333 objs = NULL ; 01334 if (hawki_sci_jitter_config.refine && 01335 hawki_sci_jitter_config.objects && 01336 hawki_sci_jitter_config.objects[0] != (char)0) { 01337 cpl_msg_info(cpl_func, "Get the user provided correlation objects") ; 01338 /* A file has been provided on the command line */ 01339 objs = cpl_bivector_read((char*)hawki_sci_jitter_config.objects) ; 01340 if (objs==NULL) { 01341 cpl_msg_error(cpl_func, "Cannot get objects from %s", 01342 hawki_sci_jitter_config.objects) ; 01343 cpl_bivector_delete(offs_est) ; 01344 return NULL ; 01345 } 01346 } 01347 01348 /* Get a correlation point from the difference of the first images */ 01349 if (hawki_sci_jitter_config.refine && objs == NULL) { 01350 cpl_apertures * aperts; 01351 cpl_image * detect_image; 01352 cpl_vector * thresh_vect; 01353 double * objs_x ; 01354 double * objs_y ; 01355 cpl_msg_info(cpl_func, "Get a cross-correlation point") ; 01356 thresh_vect = cpl_vector_new(4) ; 01357 cpl_vector_set(thresh_vect, 0, 5.0) ; 01358 cpl_vector_set(thresh_vect, 1, 2.0) ; 01359 cpl_vector_set(thresh_vect, 2, 1.0) ; 01360 cpl_vector_set(thresh_vect, 3, 0.5) ; 01361 detect_image = cpl_imagelist_get(*in, 0); 01362 if ((aperts = cpl_apertures_extract_window(detect_image, thresh_vect, 01363 400, 400, 1600, 1600, NULL)) == NULL) { 01364 cpl_msg_error(cpl_func, "Cannot find any cross-correlation point") ; 01365 cpl_bivector_delete(offs_est) ; 01366 cpl_vector_delete(thresh_vect) ; 01367 return NULL ; 01368 } 01369 cpl_vector_delete(thresh_vect) ; 01370 cpl_apertures_sort_by_npix(aperts) ; 01371 objs = cpl_bivector_new(1) ; 01372 objs_x = cpl_bivector_get_x_data(objs) ; 01373 objs_y = cpl_bivector_get_y_data(objs) ; 01374 objs_x[0] = cpl_apertures_get_pos_x(aperts, 1) ; 01375 objs_y[0] = cpl_apertures_get_pos_y(aperts, 1) ; 01376 cpl_apertures_delete(aperts) ; 01377 if (objs == NULL) { 01378 cpl_msg_error(cpl_func, "Cannot find any cross-correlation point") ; 01379 cpl_bivector_delete(offs_est) ; 01380 return NULL ; 01381 } 01382 cpl_msg_info(cpl_func, 01383 "Correlation point: %g %g\n", objs_x[0], objs_y[0]); 01384 } 01385 01386 /* Refine the offsets */ 01387 if (hawki_sci_jitter_config.refine) { 01388 cpl_bivector * offs_refined; 01389 double * offs_refined_x; 01390 double * offs_refined_y; 01391 double * offs_est_x; 01392 double * offs_est_y; 01393 cpl_vector * correl ; 01394 double * correl_data ; 01395 cpl_msg_info(cpl_func, "Refine the offsets"); 01396 cpl_msg_indent_more() ; 01397 nima = cpl_imagelist_get_size(*in) ; 01398 correl = cpl_vector_new(nima) ; 01399 if ((offs_refined = cpl_geom_img_offset_fine(*in, offs_est, objs, 01400 hawki_sci_jitter_config.sx, 01401 hawki_sci_jitter_config.sy, 01402 hawki_sci_jitter_config.mx, 01403 hawki_sci_jitter_config.my, 01404 correl)) == NULL) { 01405 cpl_msg_error(cpl_func, "Cannot refine the offsets"); 01406 cpl_bivector_delete(offs_est) ; 01407 if (objs != NULL) cpl_bivector_delete(objs) ; 01408 cpl_vector_delete(correl) ; 01409 return NULL ; 01410 } 01411 if (objs != NULL) cpl_bivector_delete(objs) ; 01412 01413 /* Display the results */ 01414 offs_est_x = cpl_bivector_get_x_data(offs_est); 01415 offs_est_y = cpl_bivector_get_y_data(offs_est); 01416 offs_refined_x = cpl_bivector_get_x_data(offs_refined); 01417 offs_refined_y = cpl_bivector_get_y_data(offs_refined) ; 01418 correl_data = cpl_vector_get_data(correl) ; 01419 cpl_msg_info(cpl_func, "Refined offsets [correlation factor]") ; 01420 ngood = 0 ; 01421 for (i=0 ; i<nima ; i++) { 01422 cpl_msg_info(cpl_func, "#%02d: %8.2f %8.2f [%12.2f]", 01423 i+1, offs_refined_x[i], offs_refined_y[i], correl_data[i]); 01424 if (correl_data[i] > -0.5) ngood++ ; 01425 } 01426 if (ngood == 0) { 01427 cpl_msg_error(cpl_func, "No frame correctly correlated") ; 01428 cpl_bivector_delete(offs_est); 01429 cpl_bivector_delete(offs_refined); 01430 cpl_vector_delete(correl); 01431 return NULL ; 01432 } 01433 cpl_msg_indent_less(); 01434 01435 /* Replace bad correlated images with the nominal offsets */ 01436 cpl_msg_info(cpl_func, "Using nominal offsets for badly " 01437 "correlated images (%d out of %d)", nima-ngood, nima); 01438 for (i=0 ; i<nima ; i++) { 01439 if (correl_data[i] < -0.5) { 01440 offs_refined_x[i] = offs_est_x[i]; 01441 offs_refined_y[i] = offs_est_y[i]; 01442 } 01443 } 01444 offs_used = cpl_bivector_duplicate(offs_refined); 01445 cpl_bivector_delete(offs_est); 01446 cpl_bivector_delete(offs_refined); 01447 cpl_vector_delete(correl); 01448 } 01449 else 01450 { 01451 offs_used = cpl_bivector_duplicate(offs_est); 01452 cpl_bivector_delete(offs_est); 01453 } 01454 01455 /* Discard the pixels on the sides */ 01456 if (hawki_sci_jitter_config.borders > 0) { 01457 cpl_imagelist * in_ext ; 01458 cpl_image * tmp1 ; 01459 cpl_image * tmp2 ; 01460 nx = cpl_image_get_size_x(cpl_imagelist_get(*in, 0)) ; 01461 ny = cpl_image_get_size_y(cpl_imagelist_get(*in, 0)) ; 01462 in_ext = cpl_imagelist_new() ; 01463 while(cpl_imagelist_get_size(*in) > 0) 01464 { 01465 tmp1 = cpl_imagelist_unset(*in, 0); 01466 tmp2 = cpl_image_extract(tmp1, 01467 hawki_sci_jitter_config.borders+1, 01468 hawki_sci_jitter_config.borders+1, 01469 nx-hawki_sci_jitter_config.borders, 01470 ny-hawki_sci_jitter_config.borders) ; 01471 cpl_image_delete(tmp1); 01472 cpl_imagelist_set(in_ext, tmp2, cpl_imagelist_get_size(in_ext)) ; 01473 } 01474 cpl_imagelist_delete(*in) ; 01475 *in = in_ext ; 01476 } 01477 01478 /* Apply the shift & add */ 01479 cpl_msg_info(cpl_func, "Recombine the images set") ; 01480 cpl_msg_indent_more() ; 01481 if ((combined=cpl_geom_img_offset_saa(*in, offs_used, 01482 CPL_KERNEL_DEFAULT, 01483 hawki_sci_jitter_config.rej_low, 01484 hawki_sci_jitter_config.rej_high, 01485 hawki_sci_jitter_config.comb_meth, 01486 pos_x, pos_y)) == NULL) { 01487 cpl_msg_error(cpl_func, "Cannot apply the shift and add") ; 01488 cpl_bivector_delete(offs_used) ; 01489 cpl_msg_indent_less() ; 01490 return NULL ; 01491 } 01492 cpl_msg_indent_less() ; 01493 *pos_x -= hawki_sci_jitter_config.borders ; 01494 *pos_y -= hawki_sci_jitter_config.borders ; 01495 01496 /* Free and return */ 01497 cpl_bivector_delete(offs_used) ; 01498 return combined ; 01499 } 01500 01501 /*----------------------------------------------------------------------------*/ 01508 /*----------------------------------------------------------------------------*/ 01509 static int hawki_sci_jitter_qc 01510 (cpl_frameset * science_frames, 01511 cpl_image ** combined_images, 01512 cpl_table ** obj_charac) 01513 { 01514 cpl_vector * thresh_vec ; 01515 cpl_apertures * aperts ; 01516 int nb_objs ; 01517 double angle ; 01518 double * fwhms_x ; 01519 double * fwhms_y ; 01520 cpl_bivector * iqe ; 01521 int nb_good ; 01522 cpl_vector * fwhms_good ; 01523 double * fwhms_good_data ; 01524 double f_min, f_max, fr, fx, fy ; 01525 int chip; 01526 int iobj; 01527 int j; 01528 01529 /* Initialise */ 01530 double seeing_min_arcsec = 0.1 ; 01531 double seeing_max_arcsec = 5.0 ; 01532 double seeing_fwhm_var = 0.2 ; 01533 01534 /* Check entries */ 01535 if (combined_images == NULL) return -1 ; 01536 if (obj_charac == NULL) return -1 ; 01537 01538 /* Create the vector for the detection thresholds */ 01539 thresh_vec = cpl_vector_new(11) ; 01540 cpl_vector_set(thresh_vec, 0, 100.0) ; 01541 cpl_vector_set(thresh_vec, 0, 90.0) ; 01542 cpl_vector_set(thresh_vec, 0, 80.0) ; 01543 cpl_vector_set(thresh_vec, 0, 70.0) ; 01544 cpl_vector_set(thresh_vec, 0, 60.0) ; 01545 cpl_vector_set(thresh_vec, 0, 50.0) ; 01546 cpl_vector_set(thresh_vec, 1, 40.0) ; 01547 cpl_vector_set(thresh_vec, 1, 30.0) ; 01548 cpl_vector_set(thresh_vec, 1, 20.0) ; 01549 cpl_vector_set(thresh_vec, 1, 10.0) ; 01550 cpl_vector_set(thresh_vec, 2, 5.0) ; 01551 01552 /* Get the mean airmass */ 01553 hawki_sci_jitter_output.mean_airmass = 01554 hawki_get_mean_airmass(science_frames);; 01555 01556 /* Loop on the HAWK-I detectors */ 01557 for (chip=0 ; chip<HAWKI_NB_DETECTORS ; chip++) 01558 { 01559 /* Check entries */ 01560 if (combined_images[chip] == NULL) return -1 ; 01561 if (obj_charac[chip] == NULL) return -1 ; 01562 01563 /* Detect apertures */ 01564 if ((aperts = cpl_apertures_extract 01565 (combined_images[chip], thresh_vec, NULL)) == NULL) { 01566 cpl_msg_warning(cpl_func, "Cannot detect any aperture on chip %d", 01567 chip+1) ; 01568 continue; 01569 } 01570 01571 /* Number of detected objects */ 01572 nb_objs = cpl_apertures_get_size(aperts); 01573 cpl_msg_info(cpl_func, "%d objects detected on chip %d",nb_objs,chip+1); 01574 hawki_sci_jitter_output.nbobjs[chip] = nb_objs ; 01575 fwhms_x = cpl_malloc(nb_objs * sizeof(double)) ; 01576 fwhms_y = cpl_malloc(nb_objs * sizeof(double)) ; 01577 01578 /* Initialize the output table */ 01579 cpl_table_set_size(obj_charac[chip], nb_objs); 01580 cpl_table_new_column 01581 (obj_charac[chip], HAWKI_COL_OBJ_POSX, CPL_TYPE_DOUBLE); 01582 cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_POSX,"pix"); 01583 cpl_table_new_column 01584 (obj_charac[chip], HAWKI_COL_OBJ_POSY, CPL_TYPE_DOUBLE); 01585 cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_POSY,"pix"); 01586 cpl_table_new_column 01587 (obj_charac[chip], HAWKI_COL_OBJ_ANGLE, CPL_TYPE_DOUBLE); 01588 cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_ANGLE,"grad"); 01589 cpl_table_new_column 01590 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MAJAX, CPL_TYPE_DOUBLE); 01591 cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FWHM_MAJAX,"pix"); 01592 cpl_table_new_column 01593 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MINAX, CPL_TYPE_DOUBLE); 01594 cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FWHM_MINAX,"pix"); 01595 cpl_table_new_column 01596 (obj_charac[chip], HAWKI_COL_OBJ_ELLIP, CPL_TYPE_DOUBLE); 01597 cpl_table_new_column 01598 (obj_charac[chip], HAWKI_COL_OBJ_FLUX, CPL_TYPE_DOUBLE); 01599 cpl_table_set_column_unit(obj_charac[chip],HAWKI_COL_OBJ_FLUX,"ADU"); 01600 for (iobj=0 ; iobj<nb_objs ; iobj++) 01601 { 01602 /* Fill with the already known information */ 01603 cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_POSX, iobj, 01604 cpl_apertures_get_centroid_x(aperts, iobj+1)); 01605 cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_POSY, iobj, 01606 cpl_apertures_get_centroid_y(aperts, iobj+1)); 01607 cpl_table_set_double(obj_charac[chip], HAWKI_COL_OBJ_FLUX, iobj, 01608 cpl_apertures_get_flux(aperts, iobj+1)) ; 01609 /* Compute the FWHM informations */ 01610 if ((iqe = cpl_image_iqe(combined_images[chip], 01611 (int)cpl_apertures_get_centroid_x(aperts, iobj+1) - 10, 01612 (int)cpl_apertures_get_centroid_y(aperts, iobj+1) - 10, 01613 (int)cpl_apertures_get_centroid_x(aperts, iobj+1) + 10, 01614 (int)cpl_apertures_get_centroid_y(aperts, iobj+1) + 10))==NULL) 01615 { 01616 cpl_error_reset() ; 01617 cpl_msg_debug(cpl_func, "Cannot get FWHM for obj at pos %g %g", 01618 cpl_apertures_get_centroid_x(aperts, iobj+1), 01619 cpl_apertures_get_centroid_y(aperts, iobj+1)) ; 01620 fwhms_x[iobj] = -1.0 ; 01621 fwhms_y[iobj] = -1.0 ; 01622 angle = 0.0 ; 01623 } 01624 else 01625 { 01626 fwhms_x[iobj] = cpl_vector_get(cpl_bivector_get_x(iqe), 2) ; 01627 fwhms_y[iobj] = cpl_vector_get(cpl_bivector_get_x(iqe), 3) ; 01628 angle = cpl_vector_get(cpl_bivector_get_x(iqe), 4) ; 01629 cpl_bivector_delete(iqe) ; 01630 cpl_msg_debug(cpl_func, 01631 "FWHM for obj at pos %g %g: %g x %g (%g)", 01632 cpl_apertures_get_centroid_x(aperts, iobj+1), 01633 cpl_apertures_get_centroid_y(aperts, iobj+1), 01634 fwhms_x[iobj], fwhms_y[iobj], angle) ; 01635 } 01636 cpl_table_set_double 01637 (obj_charac[chip], HAWKI_COL_OBJ_ANGLE, iobj, angle) ; 01638 cpl_table_set_double 01639 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MAJAX, iobj, 01640 fwhms_x[iobj]); 01641 cpl_table_set_double 01642 (obj_charac[chip], HAWKI_COL_OBJ_FWHM_MINAX, iobj, 01643 fwhms_y[iobj]); 01644 cpl_table_set_double 01645 (obj_charac[chip], HAWKI_COL_OBJ_ELLIP, iobj, 01646 1 - fwhms_y[iobj] / fwhms_x[iobj]); 01647 } 01648 cpl_apertures_delete(aperts) ; 01649 01650 /* Get the number of good values */ 01651 nb_good = 0 ; 01652 for (iobj=0 ; iobj<nb_objs ; iobj++) 01653 { 01654 if ((fwhms_x[iobj] > 0.0) && (fwhms_y[iobj] > 0.0)) nb_good++ ; 01655 } 01656 if (nb_good == 0) 01657 { 01658 cpl_msg_warning(cpl_func, "No objects to compute FWHM on chip %d", 01659 chip+1); 01660 cpl_free(fwhms_x) ; 01661 cpl_free(fwhms_y) ; 01662 continue; 01663 } 01664 01665 /* Get the good values */ 01666 fwhms_good = cpl_vector_new(nb_good) ; 01667 fwhms_good_data = cpl_vector_get_data(fwhms_good) ; 01668 j=0 ; 01669 for (iobj=0 ; iobj<nb_objs ; iobj++) 01670 { 01671 if ((fwhms_x[iobj] > 0.0) && (fwhms_y[iobj] > 0.0)) 01672 { 01673 fwhms_good_data[j] = (fwhms_x[iobj]+fwhms_y[iobj])/2.0 ; 01674 j++ ; 01675 } 01676 } 01677 01678 /* Compute the fwhm */ 01679 if (nb_good < 3) 01680 { 01681 /* Too few values to compute the median */ 01682 hawki_sci_jitter_output.fwhm_pix[chip] = fwhms_good_data[0] ; 01683 } 01684 else 01685 { 01686 /* Compute the median */ 01687 hawki_sci_jitter_output.fwhm_pix[chip] = 01688 cpl_vector_get_median_const(fwhms_good) ; 01689 } 01690 hawki_sci_jitter_output.fwhm_arcsec[chip] = 01691 hawki_sci_jitter_output.fwhm_pix[chip] * 01692 hawki_sci_jitter_output.pixscale ; 01693 01694 /* Compute the mode of the FWHMs */ 01695 if (nb_good > 5) 01696 { 01697 hawki_sci_jitter_output.fwhm_mode[chip] = 01698 hawki_vector_get_mode(fwhms_good); 01699 hawki_sci_jitter_output.fwhm_mode[chip] *= 01700 hawki_sci_jitter_output.pixscale ; 01701 } 01702 cpl_vector_delete(fwhms_good) ; 01703 01704 /* IQ is the median of the (fwhm_x+fwhm_y/2) of the good stars */ 01705 /* Compute f_min and f_max */ 01706 f_min = seeing_min_arcsec / hawki_sci_jitter_output.pixscale ; 01707 f_max = seeing_max_arcsec / hawki_sci_jitter_output.pixscale ; 01708 01709 /* Get the number of good values */ 01710 nb_good = 0 ; 01711 for (iobj=0 ; iobj<nb_objs ; iobj++) 01712 { 01713 fx = fwhms_x[iobj] ; 01714 fy = fwhms_y[iobj] ; 01715 fr = 2.0 * fabs(fx-fy) / (fx+fy) ; 01716 if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) && 01717 (fr < seeing_fwhm_var)) nb_good++ ; 01718 } 01719 if (nb_good == 0) 01720 { 01721 cpl_msg_warning(cpl_func, "No objects to compute IQ on chip %d", 01722 chip+1); 01723 cpl_free(fwhms_x) ; 01724 cpl_free(fwhms_y) ; 01725 continue; 01726 } 01727 01728 /* Get the good values */ 01729 fwhms_good = cpl_vector_new(nb_good) ; 01730 fwhms_good_data = cpl_vector_get_data(fwhms_good) ; 01731 j=0 ; 01732 for (iobj=0 ; iobj<nb_objs ; iobj++) 01733 { 01734 fx = fwhms_x[iobj] ; 01735 fy = fwhms_y[iobj] ; 01736 fr = 2.0 * fabs(fx-fy) / (fx+fy) ; 01737 if ((fx > f_min) && (fx < f_max) && (fy > f_min) && (fy < f_max) && 01738 (fr < seeing_fwhm_var)) 01739 { 01740 fwhms_good_data[j] = (fx + fy)/2.0 ; 01741 j++ ; 01742 } 01743 } 01744 cpl_free(fwhms_x) ; 01745 cpl_free(fwhms_y) ; 01746 01747 /* Compute the fwhm */ 01748 if (nb_good < 3) 01749 { 01750 /* Too few values to compute the median */ 01751 hawki_sci_jitter_output.iq[chip] = fwhms_good_data[0] ; 01752 } 01753 else 01754 { 01755 /* Compute the median */ 01756 hawki_sci_jitter_output.iq[chip] = 01757 cpl_vector_get_median_const(fwhms_good) ; 01758 } 01759 cpl_vector_delete(fwhms_good) ; 01760 hawki_sci_jitter_output.iq[chip] *= hawki_sci_jitter_output.pixscale ; 01761 } 01762 01763 /* Cleanup */ 01764 cpl_vector_delete(thresh_vec) ; 01765 01766 return 0; 01767 } 01768 01769 /*----------------------------------------------------------------------------*/ 01781 /*----------------------------------------------------------------------------*/ 01782 static int hawki_sci_jitter_read_calib 01783 (const char * flat, 01784 const char * dark, 01785 const char * bpm, 01786 cpl_image ** flat_image, 01787 cpl_image ** dark_image, 01788 cpl_image ** bpm_image, 01789 int idet) 01790 { 01791 const char * reffile; 01792 int ext_nb; 01793 01794 if(flat == NULL && dark == NULL && bpm == NULL) 01795 return 0; 01796 if(*flat_image != NULL || *dark_image != NULL || *bpm_image != NULL) 01797 return 0; 01798 01799 /* Get the extension number for this detector */ 01800 if(flat != NULL) 01801 reffile = flat; 01802 else if(dark != NULL) 01803 reffile = dark; 01804 else 01805 reffile = bpm; 01806 01807 /* Guess which is the extension to read */ 01808 if ((ext_nb = hawki_get_ext_from_detector(reffile, idet + 1)) == -1) { 01809 cpl_msg_error(cpl_func, "Cannot get the extension with detector %d", 01810 idet + 1); 01811 return -1; 01812 } 01813 01814 /* Load the dark image */ 01815 if(dark != NULL) 01816 *dark_image = cpl_image_load(dark, CPL_TYPE_FLOAT, 0, ext_nb); 01817 /* Load the flat image */ 01818 if(flat != NULL) 01819 *flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, ext_nb); 01820 /* Load the bpm image */ 01821 if(bpm != NULL) 01822 *bpm_image = cpl_image_load(bpm, CPL_TYPE_FLOAT, 0, ext_nb); 01823 01824 /* Multiply the dark image by the science exposure time */ 01825 if(dark != NULL) 01826 cpl_image_multiply_scalar(*dark_image, hawki_sci_jitter_output.dit); 01827 01828 /* Return */ 01829 return 0; 01830 } 01831 01832 /*----------------------------------------------------------------------------*/ 01841 /*----------------------------------------------------------------------------*/ 01842 static int hawki_sci_jitter_save 01843 (cpl_image ** combined, 01844 cpl_image * stitched, 01845 cpl_table ** obj_charac, 01846 cpl_table ** raw_jitter_stats, 01847 cpl_table ** bkg_stats, 01848 const cpl_table * raw_obj_tel_info, 01849 cpl_frameset * science_frames, 01850 cpl_frameset * calib_frames, 01851 cpl_parameterlist * parlist, 01852 cpl_frameset * set) 01853 { 01854 cpl_propertylist * plist ; 01855 double pscale, dit, bg_mean, bg_stdev, bg_instmag ; 01856 cpl_propertylist ** qclists ; 01857 const cpl_frame * ref_frame ; 01858 cpl_frameset * used_frames; 01859 cpl_propertylist * wcslist ; 01860 cpl_propertylist * telstats; 01861 cpl_propertylist * inputlist ; 01862 double crpix1, crpix2 ; 01863 int ext_nb ; 01864 const char * recipe_name = "hawki_sci_jitter" ; 01865 int i; 01866 int ext_chip_1; 01867 cpl_errorstate error_prevstate = cpl_errorstate_get(); 01868 01869 /* Initialise */ 01870 pscale = hawki_sci_jitter_output.pixscale; 01871 dit = hawki_sci_jitter_output.dit; 01872 01873 /* Get reference frame */ 01874 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW); 01875 01876 /* Get the used frames */ 01877 used_frames = cpl_frameset_duplicate(science_frames); 01878 for(i = 0; i< cpl_frameset_get_size(calib_frames); ++i) 01879 cpl_frameset_insert(used_frames, 01880 cpl_frame_duplicate(cpl_frameset_get_frame(calib_frames, i))); 01881 01882 /* Create the telescope data statistics */ 01883 telstats = cpl_propertylist_new(); 01884 hawki_compute_prop_tel_qc_stats(raw_obj_tel_info, telstats); 01885 01886 /* Create the QC lists */ 01887 qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ; 01888 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) { 01889 01890 /* Get the extension number */ 01891 ext_nb=hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), i+1); 01892 01893 /* Handle WCS keys */ 01894 wcslist = cpl_propertylist_load_regexp( 01895 cpl_frame_get_filename(ref_frame), ext_nb, HAWKI_HEADER_WCS, 0); 01896 qclists[i] = cpl_propertylist_new() ; 01897 01898 /* Compute bg_instmag */ 01899 bg_mean = cpl_table_get_column_mean(bkg_stats[i], HAWKI_COL_STAT_MEAN); 01900 if (cpl_table_get_nrow(bkg_stats[i]) < 2) bg_stdev = 0 ; 01901 else bg_stdev = cpl_table_get_column_stdev 01902 (bkg_stats[i], HAWKI_COL_STAT_MEAN); 01903 if(bg_mean >= 0) 01904 bg_instmag = -2.5 * log10(bg_mean/(pscale*pscale*dit)); 01905 else 01906 bg_instmag = 0; 01907 01908 /* Fill the QC */ 01909 cpl_propertylist_append_double 01910 (qclists[i], "ESO QC BACKGD MEAN", bg_mean) ; 01911 cpl_propertylist_append_double 01912 (qclists[i], "ESO QC BACKGD STDEV", bg_stdev); 01913 cpl_propertylist_append_double 01914 (qclists[i], "ESO QC BACKGD INSTMAG", bg_instmag) ; 01915 cpl_propertylist_append_int 01916 (qclists[i], "ESO QC NBOBJS", hawki_sci_jitter_output.nbobjs[i]); 01917 cpl_propertylist_append_double 01918 (qclists[i], "ESO QC IQ", hawki_sci_jitter_output.iq[i]); 01919 cpl_propertylist_append_double 01920 (qclists[i], "ESO QC IQ DIFF AMBI", 01921 hawki_sci_jitter_output.iq[i] - cpl_propertylist_get_double 01922 (telstats, "ESO QC TEL AMBI FWHM MEAN")); 01923 cpl_propertylist_append_double 01924 (qclists[i], "ESO QC IQ DIFF TEL", 01925 hawki_sci_jitter_output.iq[i] - cpl_propertylist_get_double 01926 (telstats, "ESO QC TEL IA FWHM MEAN")); 01927 cpl_propertylist_append_double 01928 (qclists[i], "ESO QC FWHM PIX", 01929 hawki_sci_jitter_output.fwhm_pix[i]); 01930 cpl_propertylist_append_double 01931 (qclists[i], "ESO QC FWHM ARCSEC", 01932 hawki_sci_jitter_output.fwhm_arcsec[i]); 01933 cpl_propertylist_append_double 01934 (qclists[i], "ESO QC FWHM MODE", 01935 hawki_sci_jitter_output.fwhm_mode[i]); 01936 cpl_propertylist_append_double 01937 (qclists[i], "ESO QC COMBINED POSX", 01938 hawki_sci_jitter_output.combined_pos_x[i]); 01939 cpl_propertylist_append_double 01940 (qclists[i], "ESO QC COMBINED POSY", 01941 hawki_sci_jitter_output.combined_pos_y[i]); 01942 cpl_propertylist_append_double 01943 (qclists[i], "ESO QC COMBINED CUMOFFSETX", 01944 hawki_sci_jitter_output.combined_cumoffset_x[i]); 01945 cpl_propertylist_append_double 01946 (qclists[i], "ESO QC COMBINED CUMOFFSETY", 01947 hawki_sci_jitter_output.combined_cumoffset_y[i]); 01948 cpl_propertylist_append_int 01949 (qclists[i], "ESO QC DATANCOM",hawki_sci_jitter_output.ncomb[i]); 01950 cpl_propertylist_append_double 01951 (qclists[i], "ESO QC AIRMASS MEAN", 01952 hawki_sci_jitter_output.mean_airmass); 01953 01954 /* Update WCS and write them */ 01955 crpix1 = cpl_propertylist_get_double(wcslist, "CRPIX1"); 01956 crpix1 += hawki_sci_jitter_output.combined_pos_x[i]; 01957 cpl_propertylist_update_double(wcslist, "CRPIX1", crpix1) ; 01958 crpix2 = cpl_propertylist_get_double(wcslist, "CRPIX2"); 01959 crpix2 += hawki_sci_jitter_output.combined_pos_y[i] ; 01960 cpl_propertylist_update_double(wcslist, "CRPIX2", crpix2) ; 01961 cpl_propertylist_copy_property_regexp 01962 (qclists[i], wcslist, HAWKI_HEADER_WCS, 0) ; 01963 cpl_propertylist_delete(wcslist); 01964 01965 /* Propagate some keywords from input raw frame extensions */ 01966 inputlist = cpl_propertylist_load_regexp( 01967 cpl_frame_get_filename(ref_frame), ext_nb, 01968 HAWKI_HEADER_EXT_FORWARD, 0) ; 01969 cpl_propertylist_append(qclists[i], inputlist); 01970 cpl_propertylist_delete(inputlist) ; 01971 } 01972 01973 /* Statistics of the raw images in the QC */ 01974 hawki_image_stats_stats(raw_jitter_stats, qclists); 01975 01976 /* Statistics of the detected objects in the QC */ 01977 hawki_obj_prop_stats(obj_charac, qclists); 01978 01979 /* Write the combined image */ 01980 hawki_images_save(set, 01981 parlist, 01982 used_frames, 01983 (const cpl_image **)combined, 01984 recipe_name, 01985 HAWKI_CALPRO_COMBINED, 01986 HAWKI_PROTYPE_COMBINED, 01987 NULL, 01988 (const cpl_propertylist**)qclists, 01989 "hawki_sci_jitter.fits"); 01990 01991 /* Erase the WCS */ 01992 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) { 01993 cpl_propertylist_erase_regexp(qclists[i], HAWKI_HEADER_WCS, 0) ; 01994 } 01995 01996 /* Create a propertylist for PRO.x */ 01997 plist = cpl_propertylist_new(); 01998 cpl_propertylist_append_string(plist, CPL_DFS_PRO_TYPE, 01999 HAWKI_PROTYPE_STITCHED) ; 02000 cpl_propertylist_append_string(plist, CPL_DFS_PRO_CATG, 02001 HAWKI_CALPRO_STITCHED) ; 02002 /* Handle WCS keys */ 02003 ext_chip_1 = 1; 02004 wcslist = cpl_propertylist_load_regexp( 02005 cpl_frame_get_filename(ref_frame), ext_chip_1, HAWKI_HEADER_WCS, 0); 02006 /* Update WCS and write them */ 02007 crpix1 = cpl_propertylist_get_double(wcslist, "CRPIX1"); 02008 crpix1 += hawki_sci_jitter_output.combined_pos_x[0]; 02009 cpl_propertylist_update_double(wcslist, "CRPIX1", crpix1) ; 02010 crpix2 = cpl_propertylist_get_double(wcslist, "CRPIX2"); 02011 crpix2 += hawki_sci_jitter_output.combined_pos_y[0] ; 02012 cpl_propertylist_update_double(wcslist, "CRPIX2", crpix2) ; 02013 cpl_propertylist_append(plist, wcslist); 02014 cpl_propertylist_delete(wcslist) ; 02015 /* Write the stitched image */ 02016 cpl_dfs_save_image(set, 02017 NULL, 02018 parlist, 02019 used_frames, 02020 NULL, 02021 stitched, 02022 CPL_BPP_IEEE_FLOAT, 02023 recipe_name, 02024 plist, 02025 NULL, 02026 PACKAGE "/" PACKAGE_VERSION, 02027 "hawki_sci_jitter_stitched.fits"); 02028 cpl_propertylist_delete(plist); 02029 02030 /* Write the FITS table with the objects statistics */ 02031 if (obj_charac) 02032 { 02033 hawki_tables_save(set, 02034 parlist, 02035 used_frames, 02036 (const cpl_table **)obj_charac, 02037 recipe_name, 02038 HAWKI_CALPRO_OBJ_PARAM, 02039 HAWKI_PROTYPE_OBJ_PARAM, 02040 NULL, 02041 (const cpl_propertylist**)qclists, 02042 "hawki_sci_jitter_stars.fits"); 02043 } 02044 02045 /* Write the table with the background statistics */ 02046 hawki_tables_save(set, 02047 parlist, 02048 used_frames, 02049 (const cpl_table **)bkg_stats, 02050 recipe_name, 02051 HAWKI_CALPRO_JITTER_BKG_STATS, 02052 HAWKI_PROTYPE_JITTER_BKG_STATS, 02053 NULL, 02054 (const cpl_propertylist **)qclists, 02055 "hawki_sci_jitter_bkg_stats.fits"); 02056 02057 /* Free and return */ 02058 cpl_frameset_delete(used_frames); 02059 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) { 02060 cpl_propertylist_delete(qclists[i]) ; 02061 } 02062 cpl_propertylist_delete(telstats) ; 02063 cpl_free(qclists) ; 02064 if(!cpl_errorstate_is_equal(error_prevstate)) 02065 { 02066 cpl_errorstate_set(CPL_ERROR_NONE); 02067 return -1; 02068 } 02069 return 0; 02070 } 02071 02072 int hawki_sci_jitter_whole_image_algo 02073 (cpl_frameset * obj, 02074 cpl_table ** raw_jitter_stats, 02075 cpl_table * raw_obj_tel_info, 02076 cpl_parameterlist * parlist, 02077 cpl_frameset * recipe_set) 02078 { 02079 int nframes; 02080 int iframe; 02081 02082 02083 nframes = cpl_frameset_get_size(obj); 02084 for( iframe = 0 ; iframe < nframes ; ++iframe) 02085 { 02086 /* Local storage variables */ 02087 cpl_frame * this_target_frame; 02088 cpl_propertylist * this_properties; 02089 02090 /* Computing statistics for this frame */ 02091 cpl_msg_info(cpl_func, "Getting statistics for image %d", iframe + 1); 02092 this_target_frame = cpl_frameset_get_frame(obj, iframe); 02093 hawki_image_stats_fill_from_frame 02094 (raw_jitter_stats, this_target_frame, iframe); 02095 02096 /* Compute the telescope pcs statistics */ 02097 this_properties = cpl_propertylist_load 02098 (cpl_frame_get_filename(this_target_frame), 0); 02099 if(this_properties == NULL) 02100 { 02101 cpl_msg_error(cpl_func,"Could not read the header of object frame"); 02102 return -1; 02103 } 02104 if(hawki_extract_prop_tel_qc(this_properties, raw_obj_tel_info, iframe)) 02105 { 02106 cpl_msg_warning(cpl_func,"Some telescope properties could not be " 02107 "read for image %d", iframe+1); 02108 cpl_errorstate_set(CPL_ERROR_NONE); 02109 } 02110 cpl_propertylist_delete(this_properties); 02111 } 02112 02113 /* Saving the already computed products */ 02114 cpl_msg_info(cpl_func, "Saving image statistics"); 02115 if(hawki_sci_jitter_save_stats(raw_jitter_stats, raw_obj_tel_info, 02116 obj, 02117 parlist, recipe_set) != 0) 02118 cpl_msg_warning(cpl_func,"Some data could not be saved. " 02119 "Check permisions or disk space"); 02120 02121 02122 /* Free and return */ 02123 return 0; 02124 } 02125 02126 int hawki_sci_jitter_save_stats 02127 (cpl_table ** raw_jitter_stats, 02128 cpl_table * raw_obj_tel_info, 02129 cpl_frameset * jitter_frames, 02130 cpl_parameterlist * parlist, 02131 cpl_frameset * recipe_set) 02132 { 02133 int idet; 02134 const cpl_frame * ref_frame; 02135 cpl_propertylist ** qcstats; 02136 cpl_propertylist * telstats; 02137 const char * recipe_name = "hawki_sci_jitter" ; 02138 cpl_errorstate error_prevstate = cpl_errorstate_get(); 02139 02140 /* Statistics of the raw images in the QC */ 02141 qcstats = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)); 02142 /* Create the QC lists */ 02143 ref_frame = irplib_frameset_get_first_from_group 02144 (recipe_set, CPL_FRAME_GROUP_RAW); 02145 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 02146 { 02147 int ext_nb; 02148 cpl_propertylist * reflist; 02149 02150 qcstats[idet] = cpl_propertylist_new(); 02151 /* Propagate some keywords from input raw frame extensions */ 02152 ext_nb = 02153 hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), idet+1); 02154 reflist = cpl_propertylist_load_regexp 02155 (cpl_frame_get_filename(ref_frame), ext_nb, 02156 HAWKI_HEADER_EXT_FORWARD, 0) ; 02157 cpl_propertylist_append(qcstats[idet], reflist); 02158 cpl_propertylist_delete(reflist); 02159 } 02160 hawki_image_stats_stats(raw_jitter_stats, qcstats); 02161 /* Write the table with the raw jitter objects statistics */ 02162 hawki_tables_save(recipe_set, 02163 parlist, 02164 jitter_frames, 02165 (const cpl_table **)raw_jitter_stats, 02166 recipe_name, 02167 HAWKI_CALPRO_JITTER_STATS, 02168 HAWKI_PROTYPE_JITTER_STATS, 02169 NULL, 02170 (const cpl_propertylist**)qcstats, 02171 "hawki_sci_jitter_stats.fits"); 02172 /* Free qcstats */ 02173 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 02174 cpl_propertylist_delete(qcstats[idet]); 02175 02176 /* Write the FITS table with the raw telescope data */ 02177 telstats = cpl_propertylist_new(); 02178 cpl_propertylist_append_string(telstats, CPL_DFS_PRO_TYPE, 02179 HAWKI_PROTYPE_SCIENCE_PCS); 02180 cpl_propertylist_append_string(telstats, CPL_DFS_PRO_CATG, 02181 HAWKI_CALPRO_SCIENCE_PCS); 02182 hawki_compute_prop_tel_qc_stats(raw_obj_tel_info, telstats); 02183 if(cpl_dfs_save_table(recipe_set, 02184 NULL, 02185 parlist, 02186 jitter_frames, 02187 NULL, 02188 raw_obj_tel_info, 02189 NULL, 02190 recipe_name, 02191 telstats, 02192 NULL, 02193 PACKAGE "/" PACKAGE_VERSION, 02194 "hawki_sci_jitter_pcs.fits") != CPL_ERROR_NONE) 02195 cpl_msg_error(cpl_func,"Cannot save PCS table"); 02196 02197 /* Free and return */ 02198 cpl_propertylist_delete(telstats); 02199 cpl_free(qcstats); 02200 if(!cpl_errorstate_is_equal(error_prevstate)) 02201 { 02202 cpl_errorstate_set(CPL_ERROR_NONE); 02203 return -1; 02204 } 02205 02206 return 0; 02207 }