HAWKI Pipeline Reference Manual  1.8.12
hawki_step_refine_offsets.c
1 /* $Id: hawki_step_refine_offsets.c,v 1.17 2011/10/24 10:42:12 cgarcia Exp $
2  *
3  * This file is part of the HAWKI Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: cgarcia $
23  * $Date: 2011/10/24 10:42:12 $
24  * $Revision: 1.17 $
25  * $Name: hawki-1_8_12 $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include <math.h>
37 #include <cpl.h>
38 #include <string.h>
39 
40 #include "irplib_utils.h"
41 #include "irplib_calib.h"
42 
43 #include "hawki_utils.h"
44 #include "hawki_calib.h"
45 #include "hawki_load.h"
46 #include "hawki_save.h"
47 #include "hawki_pfits.h"
48 #include "hawki_dfs.h"
49 #include "hawki_saa.h"
50 #include "hawki_bkg.h"
51 #include "hawki_distortion.h"
52 #include "hawki_properties_tel.h"
53 #include "hawki_image_stats.h"
54 
55 /*-----------------------------------------------------------------------------
56  Define
57  -----------------------------------------------------------------------------*/
58 
59 #define NEGLIG_OFF_DIFF 0.1
60 #define SQR(x) ((x)*(x))
61 
62 /*-----------------------------------------------------------------------------
63  Functions prototypes
64  -----------------------------------------------------------------------------*/
65 
66 static int hawki_step_refine_offsets_create(cpl_plugin *) ;
67 static int hawki_step_refine_offsets_exec(cpl_plugin *) ;
68 static int hawki_step_refine_offsets_destroy(cpl_plugin *) ;
69 static int hawki_step_refine_offsets(cpl_parameterlist *, cpl_frameset *) ;
70 
71 static int hawki_step_refine_offsets_retrieve_input_param
72 (cpl_parameterlist * parlist);
73 static int hawki_step_refine_offsets_fine
74 (const cpl_frameset * science_objects_frames,
75  const cpl_frameset * reference_objects_frames,
76  cpl_bivector ** refined_offsets,
77  cpl_vector ** correl);
78 
79 static int hawki_step_refine_offsets_save
80 (cpl_bivector ** refined_offsets,
81  cpl_vector ** correlations,
82  cpl_parameterlist * recipe_parlist,
83  cpl_frameset * recipe_frameset);
84 
85 static cpl_bivector ** hawki_step_refine_offsets_read_select_objects
86 (const cpl_frameset * reference_obj_frames,
87  double first_image_off_x,
88  double first_image_off_y,
89  int nx,
90  int ny);
91 
92 /*-----------------------------------------------------------------------------
93  Static variables
94  -----------------------------------------------------------------------------*/
95 
96 static struct
97 {
98  /* Inputs */
99  int nbrightest;
100  int sx ;
101  int sy ;
102  int mx ;
103  int my ;
104 } hawki_step_refine_offsets_config;
105 
106 static char hawki_step_refine_offsets_description[] =
107 "hawki_step_refine_offsets -- utility to refine the nominal offsets.\n"
108 "This utility will take the offsets in the header as a first approach\n"
109 "and tries to refine them correlating the input images at the points\n"
110 "given by the detected objects.\n"
111 "The input of the recipe files listed in the Set Of Frames (sof-file)\n"
112 "must be tagged as:\n"
113 "images.fits "HAWKI_CALPRO_DIST_CORRECTED" or\n"
114 "images.fits "HAWKI_CALPRO_BKG_SUBTRACTED" and\n"
115 "det_obj_stats.fits "HAWKI_CALPRO_OBJ_PARAM"\n"
116 "The recipe creates as an output:\n"
117 "hawki_step_refine_offsets.fits ("HAWKI_CALPRO_OFFSETS"): Table with refined offsets\n"
118 "Return code:\n"
119 "esorex exits with an error code of 0 if the recipe completes successfully\n"
120 "or 1 otherwise";
121 
122 
123 /*-----------------------------------------------------------------------------
124  Functions code
125  -----------------------------------------------------------------------------*/
126 
127 /*----------------------------------------------------------------------------*/
135 /*----------------------------------------------------------------------------*/
136 int cpl_plugin_get_info(cpl_pluginlist * list)
137 {
138  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
139  cpl_plugin * plugin = &recipe->interface ;
140 
141  cpl_plugin_init(plugin,
142  CPL_PLUGIN_API,
143  HAWKI_BINARY_VERSION,
144  CPL_PLUGIN_TYPE_RECIPE,
145  "hawki_step_refine_offsets",
146  "Jitter recipe",
147  hawki_step_refine_offsets_description,
148  "Cesar Enrique Garcia Dabo",
149  PACKAGE_BUGREPORT,
151  hawki_step_refine_offsets_create,
152  hawki_step_refine_offsets_exec,
153  hawki_step_refine_offsets_destroy) ;
154 
155  cpl_pluginlist_append(list, plugin) ;
156 
157  return 0;
158 }
159 
160 /*----------------------------------------------------------------------------*/
169 /*----------------------------------------------------------------------------*/
170 static int hawki_step_refine_offsets_create(cpl_plugin * plugin)
171 {
172  cpl_recipe * recipe ;
173  cpl_parameter * p ;
174 
175  /* Get the recipe out of the plugin */
176  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
177  recipe = (cpl_recipe *)plugin ;
178  else return -1 ;
179 
180  /* Create the parameters list in the cpl_recipe object */
181  recipe->parameters = cpl_parameterlist_new() ;
182  if (recipe->parameters == NULL)
183  return 1;
184 
185  /* Fill the parameters list */
186  /* --xcorr */
187  p = cpl_parameter_new_value("hawki.hawki_step_refine_offsets.xcorr",
188  CPL_TYPE_STRING,
189  "Cross correlation search and measure sizes",
190  "hawki.hawki_step_refine_offsets",
191  "20,20,25,25") ;
192  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcorr") ;
193  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
194  cpl_parameterlist_append(recipe->parameters, p) ;
195 
196  /* --nbrightest */
197  p = cpl_parameter_new_value("hawki.hawki_step_refine_offsets.nbrightest",
198  CPL_TYPE_INT,
199  "Number of brightest objects to use",
200  "hawki.hawki_step_refine_offsets",
201  3);
202  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nbrightest") ;
203  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
204  cpl_parameterlist_append(recipe->parameters, p) ;
205 
206  /* Return */
207  return 0;
208 }
209 
210 /*----------------------------------------------------------------------------*/
216 /*----------------------------------------------------------------------------*/
217 static int hawki_step_refine_offsets_exec(cpl_plugin * plugin)
218 {
219  cpl_recipe * recipe ;
220 
221  /* Get the recipe out of the plugin */
222  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
223  recipe = (cpl_recipe *)plugin ;
224  else return -1 ;
225 
226  /* Issue a banner */
228 
229  return hawki_step_refine_offsets(recipe->parameters, recipe->frames) ;
230 }
231 
232 /*----------------------------------------------------------------------------*/
238 /*----------------------------------------------------------------------------*/
239 static int hawki_step_refine_offsets_destroy(cpl_plugin * plugin)
240 {
241  cpl_recipe * recipe ;
242 
243  /* Get the recipe out of the plugin */
244  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
245  recipe = (cpl_recipe *)plugin ;
246  else return -1 ;
247 
248  cpl_parameterlist_delete(recipe->parameters) ;
249  return 0 ;
250 }
251 
252 /*----------------------------------------------------------------------------*/
259 /*----------------------------------------------------------------------------*/
260 static int hawki_step_refine_offsets(
261  cpl_parameterlist * parlist,
262  cpl_frameset * framelist)
263 {
264  cpl_frameset * science_obj_frames ;
265  cpl_frameset * reference_obj_frames ;
266  cpl_bivector ** refined_offsets;
267  cpl_vector ** correl;
268  int idet;
269 
270  /* Retrieve input parameters */
271  if(hawki_step_refine_offsets_retrieve_input_param(parlist))
272  {
273  cpl_msg_error(__func__, "Wrong parameters");
274  return -1;
275  }
276 
277  /* Identify the RAW and CALIB frames in the input frameset */
278  if (hawki_dfs_set_groups(framelist)) {
279  cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
280  return -1 ;
281  }
282 
283  /* Get the object images frames */
284  cpl_msg_info(__func__, "Identifying input frames");
285  science_obj_frames =
286  hawki_extract_frameset(framelist, HAWKI_CALPRO_DIST_CORRECTED);
287  if (science_obj_frames == NULL)
288  {
289  science_obj_frames =
290  hawki_extract_frameset(framelist, HAWKI_CALPRO_BKG_SUBTRACTED);
291  if (science_obj_frames == NULL)
292  {
293  cpl_msg_error(__func__, "No science object frames provided (%s)",
294  HAWKI_CALPRO_DIST_CORRECTED);
295  return -1 ;
296  }
297  }
298 
299  /* Get the detected "objects" frame */
300  reference_obj_frames =
301  hawki_extract_frameset(framelist, HAWKI_CALPRO_OBJ_PARAM);
302  if(cpl_frameset_get_size(reference_obj_frames) != 1)
303  {
304  cpl_msg_error(__func__, "One object parameters frame must be provided (%s)",
305  HAWKI_CALPRO_OBJ_PARAM);
306  cpl_frameset_delete(science_obj_frames) ;
307  if(reference_obj_frames != NULL)
308  cpl_frameset_delete(reference_obj_frames);
309  return -1 ;
310  }
311 
312  /* Get the offsets refinement */
313  refined_offsets = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_bivector *));
314  correl = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_vector *));
315  for(idet = 0 ; idet < HAWKI_NB_DETECTORS; ++idet)
316  {
317  refined_offsets[idet] = cpl_bivector_new
318  (cpl_frameset_get_size(science_obj_frames));
319  correl[idet] = cpl_vector_new
320  (cpl_frameset_get_size(science_obj_frames));
321  }
322  if (hawki_step_refine_offsets_fine
323  (science_obj_frames, reference_obj_frames,
324  refined_offsets, correl) == -1)
325  {
326  cpl_msg_error(__func__, "Cannot refine the objects") ;
327  cpl_frameset_delete(reference_obj_frames) ;
328  cpl_frameset_delete(science_obj_frames) ;
329  for(idet = 0 ; idet < HAWKI_NB_DETECTORS; ++idet)
330  {
331  cpl_bivector_delete(refined_offsets[idet]);
332  cpl_vector_delete(correl[idet]);
333  }
334  cpl_free(refined_offsets);
335  cpl_free(correl);
336  return -1 ;
337  }
338 
339  /* Save the products */
340  cpl_msg_info(__func__, "Save the products") ;
341  if (hawki_step_refine_offsets_save
342  (refined_offsets, correl, parlist, framelist) == -1)
343  {
344  cpl_msg_warning(__func__,"Some data could not be saved. "
345  "Check permisions or disk space");
346  cpl_frameset_delete(science_obj_frames);
347  cpl_frameset_delete(reference_obj_frames);
348  for(idet = 0 ; idet < HAWKI_NB_DETECTORS; ++idet)
349  {
350  cpl_bivector_delete(refined_offsets[idet]);
351  cpl_vector_delete(correl[idet]);
352  }
353  cpl_free(refined_offsets);
354  cpl_free(correl);
355  return -1 ;
356  }
357 
358  /* Free and return */
359  cpl_frameset_delete(science_obj_frames);
360  cpl_frameset_delete(reference_obj_frames);
361  for(idet = 0 ; idet < HAWKI_NB_DETECTORS; ++idet)
362  {
363  cpl_bivector_delete(refined_offsets[idet]);
364  cpl_vector_delete(correl[idet]);
365  }
366  cpl_free(refined_offsets);
367  cpl_free(correl);
368 
369  /* Return */
370  if (cpl_error_get_code())
371  {
372  cpl_msg_error(__func__,
373  "HAWK-I pipeline could not recover from previous errors");
374  return -1 ;
375  }
376  else return 0 ;
377 }
378 
379 int hawki_step_refine_offsets_retrieve_input_param
380 (cpl_parameterlist * parlist)
381 {
382  cpl_parameter * par ;
383  const char * sval ;
384  par = NULL ;
385  par = cpl_parameterlist_find
386  (parlist, "hawki.hawki_step_refine_offsets.nbrightest");
387  hawki_step_refine_offsets_config.nbrightest =
388  cpl_parameter_get_int(par);
389  par = cpl_parameterlist_find
390  (parlist, "hawki.hawki_step_refine_offsets.xcorr");
391  sval = cpl_parameter_get_string(par);
392  if (sscanf(sval, "%d,%d,%d,%d",
393  &hawki_step_refine_offsets_config.sx,
394  &hawki_step_refine_offsets_config.sy,
395  &hawki_step_refine_offsets_config.mx,
396  &hawki_step_refine_offsets_config.my)!=4)
397  {
398  return -1;
399  }
400  return 0;
401 }
402 
403 
404 
405 /*----------------------------------------------------------------------------*/
410 /*----------------------------------------------------------------------------*/
411 static int hawki_step_refine_offsets_fine
412 (const cpl_frameset * science_obj_frames,
413  const cpl_frameset * reference_obj_frames,
414  cpl_bivector ** refined_offsets,
415  cpl_vector ** correl)
416 {
417  cpl_imagelist * in ;
418  cpl_bivector * nominal_offsets ;
419  cpl_bivector ** reference_objects;
420  double * offs_est_x ;
421  double * offs_est_y ;
422  double off_0_x;
423  double off_0_y;
424  double max_x, max_y ;
425  int idet;
426  int ioff;
427  cpl_propertylist * header;
428  int nx;
429  int ny;
430 
431  /* Get the nominal offsets from the header */
432  cpl_msg_info(__func__,"Getting the nominal offsets");
433  nominal_offsets = hawki_get_header_tel_offsets(science_obj_frames);
434  if (nominal_offsets == NULL)
435  {
436  cpl_msg_error(__func__, "Cannot load the header offsets") ;
437  return -1;
438  }
439  offs_est_x = cpl_bivector_get_x_data(nominal_offsets);
440  offs_est_y = cpl_bivector_get_y_data(nominal_offsets);
441 
442  /* Print the header offsets */
443  cpl_msg_indent_more();
444  for (ioff=0 ; ioff<cpl_bivector_get_size(nominal_offsets) ; ioff++)
445  {
446  cpl_msg_info(__func__, "Telescope offsets (Frame %d): %g %g", ioff+1,
447  offs_est_x[ioff], offs_est_y[ioff]) ;
448  }
449  cpl_msg_indent_less();
450 
451  /* Get the size of the detectors of the first extension */
452  header = cpl_propertylist_load
453  (cpl_frame_get_filename
454  (cpl_frameset_get_first_const(science_obj_frames)), 1);
455  nx = hawki_pfits_get_naxis1(header);
456  ny = hawki_pfits_get_naxis2(header);
457  cpl_propertylist_delete(header);
458 
459  /* Get the first offset to all offsets */
460  off_0_x = offs_est_x[0];
461  off_0_y = offs_est_y[0];
462 
463  /* Get the objects (anchor points)*/
464  /* They are already in the "first image" reference system */
465  reference_objects =
466  hawki_step_refine_offsets_read_select_objects(reference_obj_frames,
467  off_0_x,
468  off_0_y,
469  nx,
470  ny);
471  if(reference_objects == NULL)
472  {
473  cpl_msg_error(__func__,"Error reading the reference objects");
474  cpl_bivector_delete(nominal_offsets);
475  return -1;
476  }
477 
478  /* Subtract the first offset to all offsets */
479  max_x = max_y = 0.0 ;
480  for (ioff=1 ; ioff<cpl_bivector_get_size(nominal_offsets) ; ioff++)
481  {
482  offs_est_x[ioff] -= off_0_x;
483  offs_est_y[ioff] -= off_0_y;
484  if (fabs(offs_est_x[ioff]) > max_x) max_x = fabs(offs_est_x[ioff]) ;
485  if (fabs(offs_est_y[ioff]) > max_y) max_y = fabs(offs_est_y[ioff]) ;
486  }
487  offs_est_x[0] = offs_est_y[0] = 0.00 ;
488 
489  /* Get the opposite offsets. This is to change from
490  * telescope convention to cpl convention */
491  cpl_vector_multiply_scalar(cpl_bivector_get_x(nominal_offsets), -1.0);
492  cpl_vector_multiply_scalar(cpl_bivector_get_y(nominal_offsets), -1.0);
493 
494  /* Loop on the detectors */
495  for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
496  {
497  cpl_msg_info(__func__, "Working on detector number %d", idet+1) ;
498  cpl_msg_indent_more();
499 
500  /* Load the input data */
501  cpl_msg_info(__func__, "Loading the input data") ;
502  cpl_msg_indent_more() ;
503  if ((in = hawki_load_detector(science_obj_frames,
504  idet+1, CPL_TYPE_FLOAT)) == NULL)
505  {
506  cpl_msg_error(__func__, "Cannot load chip %d", idet+1) ;
507  cpl_bivector_delete(nominal_offsets) ;
508  for (idet=0 ; idet< HAWKI_NB_DETECTORS ; idet++)
509  {
510  cpl_bivector_delete(reference_objects[idet]);
511  }
512  cpl_free(reference_objects);
513  cpl_msg_indent_less() ;
514  cpl_msg_indent_less() ;
515  return -1;
516  }
517 
518  /* Get the refinement */
519  cpl_msg_info(__func__, "Getting the refinement");
520  cpl_msg_indent_more() ;
521  if (hawki_geom_refine_images_offsets
522  (in,
523  nominal_offsets,
524  reference_objects[idet],
525  hawki_step_refine_offsets_config.sx,
526  hawki_step_refine_offsets_config.sy,
527  hawki_step_refine_offsets_config.mx,
528  hawki_step_refine_offsets_config.my,
529  refined_offsets[idet],
530  correl[idet]) == -1)
531  {
532  cpl_msg_error(__func__, "Cannot apply the shift and add") ;
533  cpl_imagelist_delete(in) ;
534  cpl_bivector_delete(nominal_offsets) ;
535  for (idet=0 ; idet< HAWKI_NB_DETECTORS ; idet++)
536  cpl_bivector_delete(reference_objects[idet]);
537  cpl_free(reference_objects);
538  cpl_msg_indent_less() ;
539  cpl_msg_indent_less() ;
540  return -1;
541  }
542 
543  /* Convert to "telescope criteria" */
544  /* Also add the offset of the first image */
545  cpl_vector_multiply_scalar
546  (cpl_bivector_get_x(refined_offsets[idet]), -1.0);
547  cpl_vector_multiply_scalar
548  (cpl_bivector_get_y(refined_offsets[idet]), -1.0);
549  cpl_vector_add_scalar
550  (cpl_bivector_get_x(refined_offsets[idet]), off_0_x);
551  cpl_vector_add_scalar
552  (cpl_bivector_get_y(refined_offsets[idet]), off_0_y);
553 
554  /* Print the new offsets */
555  for (ioff=0 ; ioff<cpl_bivector_get_size(refined_offsets[idet]); ioff++)
556  {
557  cpl_msg_info(__func__,"Refined telescope offsets (Frame %d): %g %g",
558  ioff+1,
559  cpl_vector_get(cpl_bivector_get_x
560  (refined_offsets[idet]), ioff),
561  cpl_vector_get(cpl_bivector_get_y
562  (refined_offsets[idet]), ioff));
563  }
564  cpl_imagelist_delete(in) ;
565  cpl_msg_indent_less() ;
566  cpl_msg_indent_less() ;
567  }
568 
569  /* Freeing */
570  cpl_bivector_delete(nominal_offsets);
571  for (idet=0 ; idet< HAWKI_NB_DETECTORS ; idet++)
572  cpl_bivector_delete(reference_objects[idet]);
573  cpl_free(reference_objects);
574 
575  return 0;
576 }
577 
578 /*----------------------------------------------------------------------------*/
586 /*----------------------------------------------------------------------------*/
587 
588 static int hawki_step_refine_offsets_save
589 (cpl_bivector ** refined_offsets,
590  cpl_vector ** correlations,
591  cpl_parameterlist * recipe_parlist,
592  cpl_frameset * recipe_frameset)
593 {
594  cpl_table ** offset_tables;
595  int ioff;
596  int idet;
597  int noff;
598  const char * recipe_name = "hawki_step_refine_offsets";
599  cpl_errorstate error_prevstate = cpl_errorstate_get();
600 
601 
602  /* Convert the offsets to a table */
603  offset_tables = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table *));
604  for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet)
605  {
606  offset_tables[idet] = cpl_table_new
607  (cpl_bivector_get_size(refined_offsets[idet]));
608  cpl_table_new_column(offset_tables[idet],
609  HAWKI_COL_OFFSET_X, CPL_TYPE_FLOAT);
610  cpl_table_set_column_unit(offset_tables[idet],HAWKI_COL_OFFSET_X,"pix");
611  cpl_table_new_column(offset_tables[idet],
612  HAWKI_COL_OFFSET_Y, CPL_TYPE_FLOAT);
613  cpl_table_set_column_unit(offset_tables[idet],HAWKI_COL_OFFSET_Y,"pix");
614  cpl_table_new_column(offset_tables[idet],
615  HAWKI_COL_CORRELATION, CPL_TYPE_FLOAT);
616  noff = cpl_bivector_get_size(refined_offsets[idet]);
617  for(ioff = 0; ioff < noff; ++ioff)
618  {
619  double xoffset, yoffset, corr;
620  xoffset = cpl_vector_get
621  (cpl_bivector_get_x(refined_offsets[idet]), ioff);
622  yoffset = cpl_vector_get
623  (cpl_bivector_get_y(refined_offsets[idet]), ioff);
624  corr = cpl_vector_get(correlations[idet], ioff);
625  cpl_table_set
626  (offset_tables[idet], HAWKI_COL_OFFSET_X, ioff, xoffset);
627  cpl_table_set
628  (offset_tables[idet], HAWKI_COL_OFFSET_Y, ioff, yoffset);
629  cpl_table_set
630  (offset_tables[idet], HAWKI_COL_CORRELATION, ioff, corr);
631  }
632  }
633 
634  /* Write the table with the statistics */
635  if (hawki_tables_save(recipe_frameset,
636  recipe_parlist,
637  recipe_frameset,
638  (const cpl_table **)offset_tables,
639  recipe_name,
640  HAWKI_CALPRO_OFFSETS,
641  HAWKI_PROTYPE_OFFSETS,
642  NULL,
643  NULL,
644  "hawki_step_refine_offsets.fits") != CPL_ERROR_NONE)
645  {
646  cpl_msg_error(__func__, "Cannot save the first extension table") ;
647  for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet)
648  cpl_table_delete(offset_tables[idet]);
649  cpl_free(offset_tables);
650  return -1 ;
651  }
652 
653  /* Free and return */
654  for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet)
655  cpl_table_delete(offset_tables[idet]);
656  cpl_free(offset_tables);
657  if(!cpl_errorstate_is_equal(error_prevstate))
658  {
659  cpl_errorstate_set(CPL_ERROR_NONE);
660  return -1;
661  }
662  return 0;
663 }
664 
665 /*----------------------------------------------------------------------------*/
680 /*----------------------------------------------------------------------------*/
681 static cpl_bivector ** hawki_step_refine_offsets_read_select_objects
682 (const cpl_frameset * reference_obj_frames,
683  double first_image_off_x,
684  double first_image_off_y,
685  int nx,
686  int ny)
687 {
688  const cpl_frame * reference_obj_frame;
689  cpl_table ** obj_param;
690  cpl_propertylist * sort_column;
691  cpl_bivector ** reference_objects;
692  int idet;
693 
694  /* Get the objects */
695  cpl_msg_info(__func__,"Getting the reference object positions");
696  reference_obj_frame = cpl_frameset_get_first_const(reference_obj_frames);
697  obj_param = hawki_load_tables(reference_obj_frame);
698  if(obj_param == NULL)
699  {
700  cpl_msg_error(__func__,"Could not read the reference objects parameters");
701  return NULL;
702  }
703 
704  /* Create the sorting criteria: by flux */
705  sort_column = cpl_propertylist_new();
706  cpl_propertylist_append_bool(sort_column, HAWKI_COL_OBJ_FLUX, CPL_TRUE);
707 
708  /* Allocate partially the reference objects */
709  reference_objects = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_bivector *));
710 
711  /* Loop on detectors */
712  cpl_msg_indent_more();
713  for (idet=0 ; idet< HAWKI_NB_DETECTORS ; idet++)
714  {
715  cpl_propertylist * objects_plist;
716  cpl_vector * obj_x;
717  cpl_vector * obj_y;
718  int nobj;
719  int nselect;
720  int iobj;
721  int ext_nb;
722  double reference_offset_x;
723  double reference_offset_y;
724 
725  /* Get the global offset */
726  /* This allows to know which is the reference point of the detected
727  * objects positions (which are referred in general to the combined image */
729  (cpl_frame_get_filename(reference_obj_frame), idet + 1);
730  objects_plist = cpl_propertylist_load
731  (cpl_frame_get_filename(reference_obj_frame), ext_nb);
732  reference_offset_x =
733  hawki_pfits_get_comb_cumoffsetx(objects_plist);
734  reference_offset_y =
735  hawki_pfits_get_comb_cumoffsety(objects_plist);
736  if(cpl_error_get_code() != CPL_ERROR_NONE)
737  {
738  cpl_msg_error(__func__,"Could not find keywords "
739  "ESO QC COMBINED CUMOFFSETX,Y in reference objects frame");
740  cpl_propertylist_delete(objects_plist);
741  cpl_propertylist_delete(sort_column);
742  return NULL;
743  }
744  cpl_msg_info(__func__,"Objects offsets wrt telescope: %f %f",
745  reference_offset_x, reference_offset_y);
746  cpl_propertylist_delete(objects_plist);
747 
748  /* Sort the table by flux */
749  cpl_table_sort(obj_param[idet], sort_column);
750  nobj = cpl_table_get_nrow(obj_param[idet]);
751 
752  /* Allocate objects vector */
753  reference_objects[idet] = cpl_bivector_new(nobj);
754  obj_x = cpl_bivector_get_x(reference_objects[idet]);
755  obj_y = cpl_bivector_get_y(reference_objects[idet]);
756  cpl_msg_info(__func__, "Number of objects in chip %d: %d", idet+1,nobj);
757 
758  /* Keep only those objects within the first image */
759  cpl_table_unselect_all(obj_param[idet]);
760  for(iobj = 0 ; iobj < nobj; ++iobj)
761  {
762  double xpos_orig = cpl_table_get
763  (obj_param[idet], HAWKI_COL_OBJ_POSX, iobj, NULL);
764  double ypos_orig = cpl_table_get
765  (obj_param[idet], HAWKI_COL_OBJ_POSY, iobj, NULL);
766  double xpos_rel = xpos_orig - reference_offset_x + first_image_off_x;
767  double ypos_rel = ypos_orig - reference_offset_y + first_image_off_y;
768  if(xpos_rel < 0.0 || xpos_rel >= nx ||
769  ypos_rel < 0.0 || ypos_rel >= ny)
770  {
771  cpl_table_select_row(obj_param[idet], iobj);
772  }
773  }
774  cpl_table_erase_selected(obj_param[idet]);
775  nobj = cpl_table_get_nrow(obj_param[idet]);
776  cpl_msg_info(__func__, "Number of objects within limits of detector "
777  "in chip %d: %d", idet+1,nobj);
778 
779  /* Apply the flux criteria */
780  nselect = hawki_step_refine_offsets_config.nbrightest;
781  if(nselect < 0 || nselect > nobj)
782  nselect = nobj;
783  cpl_msg_info(__func__, "Number of selected objects: %d", nselect);
784  for(iobj = 0 ; iobj < nselect; ++iobj)
785  {
786  double xpos_orig = cpl_table_get
787  (obj_param[idet], HAWKI_COL_OBJ_POSX, iobj, NULL);
788  double ypos_orig = cpl_table_get
789  (obj_param[idet], HAWKI_COL_OBJ_POSY, iobj, NULL);
790 
791  cpl_vector_set
792  (obj_x, iobj, xpos_orig - reference_offset_x + first_image_off_x);
793  cpl_vector_set
794  (obj_y, iobj, ypos_orig - reference_offset_y + first_image_off_y);
795  cpl_msg_debug(__func__,"Using anchor point at %f,%f",
796  cpl_vector_get(obj_x,iobj),
797  cpl_vector_get(obj_y,iobj));
798 
799  }
800  cpl_vector_set_size(obj_x, nselect);
801  cpl_vector_set_size(obj_y, nselect);
802 
803  }
804  cpl_msg_indent_less();
805 
806  /* Freeing */
807  for (idet=0 ; idet< HAWKI_NB_DETECTORS ; idet++)
808  cpl_table_delete(obj_param[idet]);
809  cpl_free(obj_param);
810  cpl_propertylist_delete(sort_column);
811 
812  return reference_objects;
813 }