HAWKI Pipeline Reference Manual  1.8.12
hawki_cal_illum.c
1 /* $Id: hawki_cal_illum.c,v 1.8 2010/06/04 09:45:43 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: 2010/06/04 09:45:43 $
24  * $Revision: 1.8 $
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 
39 #include "irplib_utils.h"
40 #include "irplib_strehl.h"
41 
42 #include "hawki_utils.h"
43 #include "hawki_calib.h"
44 #include "hawki_pfits.h"
45 #include "hawki_dfs.h"
46 #include "hawki_load.h"
47 #include "hawki_save.h"
48 
49 /*-----------------------------------------------------------------------------
50  Functions prototypes
51  -----------------------------------------------------------------------------*/
52 
53 static int hawki_cal_illum_create(cpl_plugin *) ;
54 static int hawki_cal_illum_exec(cpl_plugin *) ;
55 static int hawki_cal_illum_destroy(cpl_plugin *) ;
56 static int hawki_cal_illum(cpl_parameterlist *, cpl_frameset *) ;
57 static int hawki_cal_illum_save(const cpl_image **, const cpl_table **,
58  cpl_parameterlist *, cpl_frameset *) ;
59 static cpl_image * hawki_cal_illum_compute(cpl_frameset *, int,
60  const char *, const char *, cpl_table **) ;
61 static cpl_vector * hawki_cal_illum_phot(cpl_imagelist *, cpl_bivector *,
62  int *) ;
63 static cpl_bivector * hawki_cal_illum_find_pos(cpl_imagelist *,
64  cpl_bivector *, int) ;
65 
66 /*-----------------------------------------------------------------------------
67  Static variables
68  -----------------------------------------------------------------------------*/
69 
70 static struct {
71  /* Inputs */
72  int subtract ;
73  int degree ;
74  int s_hx ;
75  int s_hy ;
76  double star_r ;
77  double bg_r1 ;
78  double bg_r2 ;
79 } hawki_cal_illum_config ;
80 
81 static char hawki_cal_illum_description[] =
82 "hawki_cal_illum -- Illumination recipe\n"
83 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
84 "raw-file.fits "HAWKI_CAL_ILLUM_RAW" or\n"
85 "flat-file.fits "HAWKI_CALPRO_FLAT" or\n"
86 "bpm-file.fits "HAWKI_CALPRO_BPM"\n" ;
87 
88 /*-----------------------------------------------------------------------------
89  Functions code
90  -----------------------------------------------------------------------------*/
91 
92 /*----------------------------------------------------------------------------*/
101 /*----------------------------------------------------------------------------*/
102 int cpl_plugin_get_info(cpl_pluginlist * list)
103 {
104  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe ) ;
105  cpl_plugin * plugin = &recipe->interface ;
106 
107  cpl_plugin_init(plugin,
108  CPL_PLUGIN_API,
109  HAWKI_BINARY_VERSION,
110  CPL_PLUGIN_TYPE_RECIPE,
111  "hawki_cal_illum",
112  "Illumination recipe",
113  hawki_cal_illum_description,
114  "Yves Jung",
115  PACKAGE_BUGREPORT,
117  hawki_cal_illum_create,
118  hawki_cal_illum_exec,
119  hawki_cal_illum_destroy) ;
120 
121  cpl_pluginlist_append(list, plugin) ;
122 
123  return 0;
124 }
125 
126 /*----------------------------------------------------------------------------*/
134 /*----------------------------------------------------------------------------*/
135 static int hawki_cal_illum_create(cpl_plugin * plugin)
136 {
137  cpl_recipe * recipe ;
138  cpl_parameter * p ;
139 
140  /* Check that the plugin is part of a valid recipe */
141  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
142  recipe = (cpl_recipe *)plugin ;
143  else return -1 ;
144 
145  /* Create the parameters list in the cpl_recipe object */
146  recipe->parameters = cpl_parameterlist_new() ;
147 
148  /* Fill the parameters list */
149  /* --subtract */
150  p = cpl_parameter_new_value("hawki.hawki_cal_illum.subtract",
151  CPL_TYPE_BOOL, "Flag to subtract the next images",
152  "hawki.hawki_cal_illum", TRUE) ;
153  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "subtract") ;
154  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
155  cpl_parameterlist_append(recipe->parameters, p) ;
156  /* --degree */
157  p = cpl_parameter_new_value("hawki.hawki_cal_illum.degree",
158  CPL_TYPE_INT, "Polynomial degree for the fit",
159  "hawki.hawki_cal_illum", 3) ;
160  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "degree") ;
161  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
162  cpl_parameterlist_append(recipe->parameters, p) ;
163  /* --star_r */
164  p = cpl_parameter_new_value("hawki.hawki_cal_illum.star_r", CPL_TYPE_DOUBLE,
165  "the star radius", "hawki.hawki_cal_illum", -1.0) ;
166  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "star_r") ;
167  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
168  cpl_parameterlist_append(recipe->parameters, p) ;
169  /* --bg_r1 */
170  p = cpl_parameter_new_value("hawki.hawki_cal_illum.bg_r1", CPL_TYPE_DOUBLE,
171  "the internal background radius", "hawki.hawki_cal_illum", -1.0) ;
172  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bg_r1") ;
173  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
174  cpl_parameterlist_append(recipe->parameters, p) ;
175  /* --bg_r2 */
176  p = cpl_parameter_new_value("hawki.hawki_cal_illum.bg_r2", CPL_TYPE_DOUBLE,
177  "the external background radius", "hawki.hawki_cal_illum", -1.0) ;
178  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bg_r2") ;
179  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
180  cpl_parameterlist_append(recipe->parameters, p) ;
181  /* --s_hx */
182  p = cpl_parameter_new_value("hawki.hawki_cal_illum.s_hx", CPL_TYPE_INT,
183  "Half size of the seach box in x", "hawki.hawki_cal_illum", 50) ;
184  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "s_hx") ;
185  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
186  cpl_parameterlist_append(recipe->parameters, p) ;
187  /* --s_hy */
188  p = cpl_parameter_new_value("hawki.hawki_cal_illum.s_hy", CPL_TYPE_INT,
189  "Half size of the seach box in y", "hawki.hawki_cal_illum", 50) ;
190  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "s_hy") ;
191  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
192  cpl_parameterlist_append(recipe->parameters, p) ;
193 
194  /* Return */
195  return 0;
196 }
197 
198 /*----------------------------------------------------------------------------*/
204 /*----------------------------------------------------------------------------*/
205 static int hawki_cal_illum_exec(cpl_plugin * plugin)
206 {
207  cpl_recipe * recipe ;
208 
209  /* Get the recipe out of the plugin */
210  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
211  recipe = (cpl_recipe *)plugin ;
212  else return -1 ;
213 
214  /* Issue a banner */
216 
217  return hawki_cal_illum(recipe->parameters, recipe->frames) ;
218 }
219 
220 /*----------------------------------------------------------------------------*/
226 /*----------------------------------------------------------------------------*/
227 static int hawki_cal_illum_destroy(cpl_plugin * plugin)
228 {
229  cpl_recipe * recipe ;
230 
231  /* Get the recipe out of the plugin */
232  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
233  recipe = (cpl_recipe *)plugin ;
234  else return -1 ;
235 
236  cpl_parameterlist_delete(recipe->parameters) ;
237  return 0 ;
238 }
239 
240 /*----------------------------------------------------------------------------*/
247 /*----------------------------------------------------------------------------*/
248 static int hawki_cal_illum(
249  cpl_parameterlist * parlist,
250  cpl_frameset * frameset)
251 {
252  cpl_parameter * par ;
253  const char * flat ;
254  const char * bpm ;
255  cpl_frameset * rawframes ;
256  cpl_frameset * cur_frames ;
257  int * labels ;
258  cpl_image * illum[HAWKI_NB_DETECTORS] ;
259  cpl_table * flux[HAWKI_NB_DETECTORS] ;
260  int i ;
261 
262  /* Initialise */
263  rawframes = NULL ;
264 
265  /* Retrieve input parameters */
266  par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_illum.subtract") ;
267  hawki_cal_illum_config.subtract = cpl_parameter_get_bool(par) ;
268  par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_illum.degree") ;
269  hawki_cal_illum_config.degree = cpl_parameter_get_int(par) ;
270  par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_illum.s_hx") ;
271  hawki_cal_illum_config.s_hx = cpl_parameter_get_int(par) ;
272  par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_illum.s_hy") ;
273  hawki_cal_illum_config.s_hy = cpl_parameter_get_int(par) ;
274  par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_illum.star_r") ;
275  hawki_cal_illum_config.star_r = cpl_parameter_get_double(par) ;
276  par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_illum.bg_r1") ;
277  hawki_cal_illum_config.bg_r1 = cpl_parameter_get_double(par) ;
278  par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_illum.bg_r2") ;
279  hawki_cal_illum_config.bg_r2 = cpl_parameter_get_double(par) ;
280 
281  /* Identify the RAW and CALIB frames in the input frameset */
282  if (hawki_dfs_set_groups(frameset)) {
283  cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
284  return -1 ;
285  }
286 
287  /* Retrieve calibration data */
288  flat = hawki_extract_first_filename(frameset, HAWKI_CALPRO_FLAT) ;
289  bpm = hawki_extract_first_filename(frameset, HAWKI_CALPRO_BPM) ;
290 
291  /* Retrieve raw frames */
292  if ((rawframes = hawki_extract_frameset(frameset,
293  HAWKI_CAL_ILLUM_RAW)) == NULL) {
294  cpl_msg_error(__func__, "No raw frame in input") ;
295  return -1 ;
296  }
297 
298  /* Labelise frames */
299  cpl_msg_info(__func__, "Labelise the frames") ;
300  if ((labels = hawki_detectors_labelise(rawframes)) == NULL) {
301  cpl_msg_error(__func__, "Cannot labelise") ;
302  cpl_frameset_delete(rawframes) ;
303  return -1 ;
304  }
305 
306  /* Loop on the chips */
307  for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
308  cpl_msg_info(__func__, "Reduce chip nb %d", i+1) ;
309 
310  /* Initialise */
311  illum[i] = NULL ;
312 
313  /* Get the frames for which the star is in chip number i+1 */
314  if ((cur_frames = cpl_frameset_extract(rawframes, labels,
315  i+1)) == NULL) {
316  cpl_msg_warning(__func__, "No frames for chip nb %d", i+1) ;
317  /* Create the flux table */
318  flux[i] = cpl_table_new(1) ;
319  cpl_table_new_column(flux[i],HAWKI_COL_ILLUM_POSX, CPL_TYPE_DOUBLE);
320  cpl_table_new_column(flux[i],HAWKI_COL_ILLUM_POSY, CPL_TYPE_DOUBLE);
321  cpl_table_new_column(flux[i],HAWKI_COL_ILLUM_FLUX, CPL_TYPE_DOUBLE);
322  } else {
323  /* Create the flux table */
324  flux[i] = cpl_table_new(cpl_frameset_get_size(cur_frames)) ;
325  cpl_table_new_column(flux[i],HAWKI_COL_ILLUM_POSX, CPL_TYPE_DOUBLE);
326  cpl_table_new_column(flux[i],HAWKI_COL_ILLUM_POSY, CPL_TYPE_DOUBLE);
327  cpl_table_new_column(flux[i],HAWKI_COL_ILLUM_FLUX, CPL_TYPE_DOUBLE);
328 
329  /* Get the illumination */
330  if ((illum[i] = hawki_cal_illum_compute(cur_frames, i+1,
331  bpm, flat, &(flux[i]))) == NULL) {
332  cpl_msg_warning(__func__, "Cannot compute for chip %d", i+1) ;
333  cpl_error_reset() ;
334  }
335  cpl_frameset_delete(cur_frames) ;
336  }
337  }
338  cpl_frameset_delete(rawframes) ;
339  cpl_free(labels) ;
340 
341  /* Save the product */
342  cpl_msg_info(__func__, "Save the product") ;
343  cpl_msg_indent_more() ;
344  if (hawki_cal_illum_save((const cpl_image **)illum,
345  (const cpl_table **)flux, parlist, frameset)) {
346  cpl_msg_error(__func__, "Cannot save the product") ;
347  for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) cpl_table_delete(flux[i]) ;
348  for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) cpl_image_delete(illum[i]) ;
349  cpl_msg_indent_less() ;
350  return -1 ;
351  }
352  for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) cpl_table_delete(flux[i]) ;
353  for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) cpl_image_delete(illum[i]) ;
354  cpl_msg_indent_less() ;
355 
356  /* Return */
357  if (cpl_error_get_code()) return -1 ;
358  else return 0 ;
359 }
360 
361 /*----------------------------------------------------------------------------*/
371 /*----------------------------------------------------------------------------*/
372 static cpl_image * hawki_cal_illum_compute(
373  cpl_frameset * raw,
374  int chip,
375  const char * bpm,
376  const char * flat,
377  cpl_table ** fl)
378 {
379  cpl_bivector * offsets ;
380  cpl_imagelist * in ;
381  cpl_image * ima1 ;
382  cpl_image * ima2 ;
383  cpl_bivector * positions ;
384  cpl_bivector * purged_pos ;
385  double * positions_x,
386  * positions_y,
387  * purged_pos_x,
388  * purged_pos_y ;
389  cpl_vector * flux ;
390  cpl_vector * purged_flux ;
391  cpl_polynomial * poly ;
392  cpl_image * poly_ima ;
393  int nval, nx, ny ;
394  double val ;
395  int ival ;
396  int i, j ;
397 
398  /* Check entries */
399  if (chip < 1 || chip > HAWKI_NB_DETECTORS) return NULL ;
400  if (raw == NULL) return NULL ;
401  if (fl == NULL) return NULL ;
402 
403  /* Get the offsets from the raw frames */
404  cpl_msg_info(__func__, "Get the offsets from the files headers") ;
405  cpl_msg_indent_more() ;
406  if ((offsets = hawki_get_header_tel_offsets(raw)) == NULL) {
407  cpl_msg_error(__func__, "Cannot get the offsets") ;
408  cpl_msg_indent_less() ;
409  return NULL ;
410  }
411  cpl_msg_indent_less() ;
412 
413  /* Load the input data */
414  cpl_msg_info(__func__, "Load the input data") ;
415  cpl_msg_indent_more() ;
416  if ((in = hawki_load_detector(raw, chip, CPL_TYPE_FLOAT)) == NULL) {
417  cpl_msg_error(__func__, "Cannot load input data") ;
418  cpl_bivector_delete(offsets) ;
419  cpl_msg_indent_less() ;
420  return NULL ;
421  }
422  cpl_msg_indent_less() ;
423 
424  /* Apply the calibrations */
425  if (flat || bpm) {
426  cpl_msg_indent_more() ;
427  if (hawki_flat_bpm_detector_calib(in, flat, bpm) == -1) {
428  cpl_msg_error(__func__, "Cannot apply calibrations") ;
429  cpl_bivector_delete(offsets) ;
430  cpl_imagelist_delete(in) ;
431  cpl_msg_indent_less() ;
432  return NULL ;
433  }
434  cpl_msg_indent_less() ;
435  }
436 
437  /* Subtract the consecutive frames */
438  if (hawki_cal_illum_config.subtract) {
439  cpl_msg_info(__func__, "Subtract the next images") ;
440  ima1 = cpl_image_duplicate(cpl_imagelist_get(in, 0)) ;
441  for (i=0 ; i<cpl_imagelist_get_size(in) ; i++) {
442  if (i==cpl_imagelist_get_size(in)-1) {
443  ima2 = ima1 ;
444  } else {
445  ima2 = cpl_imagelist_get(in, i+1) ;
446  }
447  cpl_image_subtract(cpl_imagelist_get(in, i), ima2) ;
448  }
449  cpl_image_delete(ima1) ;
450  }
451 
452  /* Find the positions */
453  cpl_msg_info(__func__, "Find the positions") ;
454  cpl_msg_indent_more() ;
455  if ((positions=hawki_cal_illum_find_pos(in, offsets, chip)) == NULL) {
456  cpl_msg_error(__func__, "Cannot find the positions") ;
457  cpl_imagelist_delete(in) ;
458  cpl_bivector_delete(offsets) ;
459  cpl_msg_indent_less() ;
460  return NULL ;
461  }
462  cpl_bivector_delete(offsets) ;
463  cpl_msg_indent_less() ;
464 
465  /* Compute the photometry */
466  cpl_msg_info(__func__, "Compute the photometry") ;
467  cpl_msg_indent_more() ;
468  if ((flux=hawki_cal_illum_phot(in, positions, &nval)) == NULL) {
469  cpl_msg_error(__func__, "Cannot find the positions") ;
470  cpl_imagelist_delete(in) ;
471  cpl_bivector_delete(positions) ;
472  cpl_msg_indent_less() ;
473  return NULL ;
474  }
475  nx = cpl_image_get_size_x(cpl_imagelist_get(in, 0)) ;
476  ny = cpl_image_get_size_y(cpl_imagelist_get(in, 0)) ;
477  cpl_imagelist_delete(in) ;
478  cpl_msg_indent_less() ;
479  if (nval < 1) {
480  cpl_msg_error(__func__, "No flux computed") ;
481  cpl_bivector_delete(positions) ;
482  cpl_vector_delete(flux) ;
483  return NULL ;
484  }
485 
486  /* Purge positions */
487  purged_pos = cpl_bivector_new(nval) ;
488  purged_pos_x = cpl_bivector_get_x_data(purged_pos) ;
489  purged_pos_y = cpl_bivector_get_y_data(purged_pos) ;
490  positions_x = cpl_bivector_get_x_data(positions) ;
491  positions_y = cpl_bivector_get_y_data(positions) ;
492  purged_flux = cpl_vector_new(nval) ;
493  j = 0 ;
494  for (i=0 ; i<cpl_vector_get_size(flux) ; i++) {
495  if (fabs(cpl_vector_get(flux, i)) > 0) {
496  purged_pos_x[j] = positions_x[i] ;
497  purged_pos_y[j] = positions_y[i] ;
498  cpl_vector_set(purged_flux, j, cpl_vector_get(flux, i)) ;
499  j++ ;
500  }
501  }
502 
503  /* Fill the flux table */
504  for (i=0 ; i<cpl_vector_get_size(flux) ; i++) {
505  cpl_table_set_double(*fl, HAWKI_COL_ILLUM_POSX, i, positions_x[i]) ;
506  cpl_table_set_double(*fl, HAWKI_COL_ILLUM_POSY, i, positions_y[i]) ;
507  cpl_table_set_double(*fl, HAWKI_COL_ILLUM_FLUX, i,
508  cpl_vector_get(flux, i)) ;
509  }
510  cpl_bivector_delete(positions) ;
511  cpl_vector_delete(flux) ;
512 
513  /* Fit the polynomial */
514  cpl_msg_info(__func__, "Compute the polynomial") ;
515  if ((poly = cpl_polynomial_fit_2d_create(purged_pos, purged_flux,
516  hawki_cal_illum_config.degree, NULL)) == NULL) {
517  cpl_msg_error(__func__, "Cannot fit the polynomial") ;
518  cpl_bivector_delete(purged_pos) ;
519  cpl_vector_delete(purged_flux) ;
520  return NULL ;
521  }
522  cpl_bivector_delete(purged_pos) ;
523  cpl_vector_delete(purged_flux) ;
524 
525  /* Create the polynomial image */
526  poly_ima = cpl_image_new(nx, ny, CPL_TYPE_FLOAT) ;
527  cpl_image_fill_polynomial(poly_ima, poly, 1.0, 1.0, 1.0, 1.0) ;
528  cpl_polynomial_delete(poly) ;
529 
530  /* Normalise the image */
531  val = cpl_image_get(poly_ima, 1024, 1024, &ival) ;
532  cpl_image_divide_scalar(poly_ima, val) ;
533 
534  return poly_ima ;
535 }
536 
537 /*----------------------------------------------------------------------------*/
545 /*----------------------------------------------------------------------------*/
546 static cpl_vector * hawki_cal_illum_phot(
547  cpl_imagelist * ilist,
548  cpl_bivector * positions,
549  int * nvalid)
550 {
551  cpl_vector * flux ;
552  cpl_image * cur_ima ;
553  double * pos_x ;
554  double * pos_y ;
555  int ni ;
556  int nok ;
557  double bg, fl ;
558  cpl_bivector * iqe_res ;
559  double fwhm_x, fwhm_y, r, r1, r2 ;
560  int i ;
561 
562  /* Test entries */
563  if (ilist == NULL || positions == NULL || nvalid == NULL) return NULL ;
564  ni = cpl_imagelist_get_size(ilist) ;
565  pos_x = cpl_bivector_get_x_data(positions) ;
566  pos_y = cpl_bivector_get_y_data(positions) ;
567  nok = 0 ;
568 
569  /* Create the flux vector */
570  flux = cpl_vector_new(ni) ;
571 
572  /* Loop on the frames */
573  for (i=0 ; i<ni ; i++) {
574  cur_ima = cpl_imagelist_get(ilist, i) ;
575 
576  /* FWHM_X / FWHM_Y */
577  if ((iqe_res = cpl_image_iqe(cur_ima,
578  (int)(pos_x[i]-10.0), (int)(pos_y[i]-10.0),
579  (int)(pos_x[i]+10.0), (int)(pos_y[i]+10.0))) == NULL) {
580  cpl_msg_debug(__func__,"Cannot get FWHM for image %d", i+1);
581  fwhm_x = fwhm_y = -1.0 ;
582  cpl_error_reset() ;
583  } else {
584  fwhm_x = cpl_vector_get(cpl_bivector_get_x(iqe_res), 2) ;
585  fwhm_y = cpl_vector_get(cpl_bivector_get_x(iqe_res), 3) ;
586  cpl_bivector_delete(iqe_res) ;
587  }
588 
589  /* Determine the radii */
590  r = hawki_cal_illum_config.star_r ;
591  if (r < 0) {
592  if (fwhm_x>0 && fwhm_y>0) r = 5*(fwhm_x+fwhm_y)/2.0 ;
593  else r = HAWKI_PHOT_STAR_RADIUS ;
594  }
595  r1 = hawki_cal_illum_config.bg_r1 ;
596  r2 = hawki_cal_illum_config.bg_r2 ;
597  if (r1 < 0) r1 = r + 10.0 ;
598  if (r2 < 0) r2 = r1 + 20.0 ;
599 
600  bg = irplib_strehl_ring_background(cur_ima, (int)pos_x[i],
601  (int)pos_y[i], r1, r2, IRPLIB_BG_METHOD_MEDIAN) ;
602  fl = irplib_strehl_disk_flux(cur_ima, (int)pos_x[i], (int)pos_y[i],
603  r, bg) ;
604  cpl_vector_set(flux, i, fl);
605  if (fabs(fl)>1e-3) nok++ ;
606  cpl_msg_info(__func__, "Flux for image %d: %g (r=%g, r1=%g, r2=%g)",
607  i+1, fl, r, r1, r2) ;
608  }
609  *nvalid = nok ;
610  return flux ;
611 }
612 
613 /*----------------------------------------------------------------------------*/
621 /*----------------------------------------------------------------------------*/
622 static cpl_bivector * hawki_cal_illum_find_pos(
623  cpl_imagelist * ilist,
624  cpl_bivector * offsets,
625  int chip)
626 {
627  cpl_bivector * positions ;
628  double * positions_x ;
629  double * positions_y ;
630  double * offsets_x ;
631  double * offsets_y ;
632  cpl_image * tmp_ima ;
633  cpl_image * cur_ima ;
634  cpl_image * filtered_ima ;
635  cpl_matrix * kernel ;
636  int nx, ny, ni ;
637  int llx, lly, urx, ury, posx, posy, gap ;
638  int i ;
639 
640  /* Test entries */
641  if (ilist == NULL || offsets == NULL) return NULL ;
642  if (chip < 1 || chip > HAWKI_NB_DETECTORS) return NULL ;
643  ni = cpl_imagelist_get_size(ilist) ;
644  gap = 147 ;
645 
646  /* Create the positions bivector */
647  positions = cpl_bivector_new(ni) ;
648  positions_x = cpl_bivector_get_x_data(positions) ;
649  positions_y = cpl_bivector_get_y_data(positions) ;
650  offsets_x = cpl_bivector_get_x_data(offsets) ;
651  offsets_y = cpl_bivector_get_y_data(offsets) ;
652 
653  /* Create the kernel */
654  kernel = cpl_matrix_new(3, 3) ;
655  cpl_matrix_fill(kernel, 1.0) ;
656 
657  /* Loop on all the images */
658  for (i=0 ; i<ni ; i++) {
659  cur_ima = cpl_imagelist_get(ilist, i) ;
660  nx = cpl_image_get_size_x(cur_ima) ;
661  ny = cpl_image_get_size_y(cur_ima) ;
662 
663  /* Define zone */
664  if (chip == 1) {
665  llx = nx + gap/2.0 + offsets_x[i] - hawki_cal_illum_config.s_hx ;
666  urx = nx + gap/2.0 + offsets_x[i] + hawki_cal_illum_config.s_hx ;
667  lly = ny + gap/2.0 + offsets_y[i] - hawki_cal_illum_config.s_hy ;
668  ury = ny + gap/2.0 + offsets_y[i] + hawki_cal_illum_config.s_hy ;
669  } else if (chip == 2) {
670  llx = offsets_x[i] - gap/2.0 - hawki_cal_illum_config.s_hx ;
671  urx = offsets_x[i] - gap/2.0 + hawki_cal_illum_config.s_hx ;
672  lly = ny + gap/2.0 + offsets_y[i] - hawki_cal_illum_config.s_hy ;
673  ury = ny + gap/2.0 + offsets_y[i] + hawki_cal_illum_config.s_hy ;
674  } else if (chip == 3) {
675  llx = offsets_x[i] - gap/2.0 - hawki_cal_illum_config.s_hx ;
676  urx = offsets_x[i] - gap/2.0 + hawki_cal_illum_config.s_hx ;
677  lly = offsets_y[i] - gap/2.0 - hawki_cal_illum_config.s_hy ;
678  ury = offsets_y[i] - gap/2.0 + hawki_cal_illum_config.s_hy ;
679  } else if (chip == 4) {
680  llx = nx + gap/2.0 + offsets_x[i] - hawki_cal_illum_config.s_hx ;
681  urx = nx + gap/2.0 + offsets_x[i] + hawki_cal_illum_config.s_hx ;
682  lly = offsets_y[i] - gap/2.0 - hawki_cal_illum_config.s_hy ;
683  ury = offsets_y[i] - gap/2.0 + hawki_cal_illum_config.s_hy ;
684  }
685 
686  /* Test zone */
687  if (llx>urx || lly>ury || llx<1 || urx>nx || lly<1 || ury>ny) {
688  cpl_msg_error(__func__, "Bad specified zone") ;
689  cpl_bivector_delete(positions) ;
690  cpl_matrix_delete(kernel) ;
691  return NULL ;
692  }
693 
694  /* Extract */
695  tmp_ima = cpl_image_extract(cur_ima, llx, lly, urx, ury) ;
696  filtered_ima =cpl_image_filter_median(tmp_ima, kernel) ;
697  cpl_image_delete(tmp_ima) ;
698 
699  /* Find the max */
700  cpl_image_get_maxpos(filtered_ima, &posx, &posy) ;
701  positions_x[i] = llx + posx ;
702  positions_y[i] = lly + posy ;
703  cpl_image_delete(filtered_ima) ;
704  cpl_msg_info(__func__, "Star found at pos %g, %g in image %d",
705  positions_x[i], positions_y[i], i+1) ;
706  }
707  cpl_matrix_delete(kernel) ;
708 
709  return positions ;
710 }
711 
712 /*----------------------------------------------------------------------------*/
721 /*----------------------------------------------------------------------------*/
722 static int hawki_cal_illum_save(
723  const cpl_image ** illum,
724  const cpl_table ** flux,
725  cpl_parameterlist * parlist,
726  cpl_frameset * set)
727 {
728  cpl_propertylist ** qclists ;
729  cpl_propertylist * paflist ;
730  cpl_propertylist * paflist_cur ;
731  const cpl_frame * ref_frame ;
732  cpl_propertylist * inputlist ;
733  int ext_nb ;
734  char * filename ;
735  char sval[16] ;
736  const char * recipe_name = "hawki_cal_illum" ;
737  int i;
738 
739  /* Get the reference frame */
740  ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
741 
742  /* Create the QC lists */
743  qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
744  for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
745  qclists[i] = cpl_propertylist_new() ;
746  cpl_propertylist_append_double(qclists[i], "ESO QC DATANCOM",
747  cpl_frameset_get_size(set)) ;
748 
749  /* Propagate some keywords from input raw frame extensions */
750  ext_nb=hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), i+1);
751  inputlist = cpl_propertylist_load_regexp(
752  cpl_frame_get_filename(ref_frame), ext_nb,
753  HAWKI_HEADER_EXT_FORWARD, 0) ;
754  cpl_propertylist_copy_property_regexp(qclists[i], inputlist, "", 0) ;
755  cpl_propertylist_delete(inputlist) ;
756  }
757 
758  /* Write the image */
759  hawki_images_save(set,
760  parlist,
761  set,
762  (const cpl_image **)illum,
763  recipe_name,
764  HAWKI_CALPRO_ILLUM,
765  HAWKI_PROTYPE_ILLUM,
766  NULL,
767  (const cpl_propertylist**)qclists,
768  "hawki_cal_illum.fits") ;
769  /* To handle cases where a chip is missing */
770  if (cpl_error_get_code() == CPL_ERROR_NULL_INPUT) cpl_error_reset() ;
771 
772  /* Write the flux table */
773  hawki_tables_save(set,
774  parlist,
775  set,
776  (const cpl_table **)flux,
777  recipe_name,
778  HAWKI_CALPRO_ILLUM_PHOTOM,
779  HAWKI_PROTYPE_ILLUM_PHOTOM,
780  NULL,
781  (const cpl_propertylist**)qclists,
782  "hawki_cal_illum_photom.fits") ;
783  /* To handle cases where a chip is missing */
784  if (cpl_error_get_code() == CPL_ERROR_NULL_INPUT) cpl_error_reset() ;
785 
786  /* Remove the keywords for the FITS extensions */
787  for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
788  cpl_propertylist_erase_regexp(qclists[i], HAWKI_HEADER_EXT_FORWARD, 0) ;
789  }
790 
791  /* Get FITS header from reference file */
792  paflist = cpl_propertylist_load_regexp(cpl_frame_get_filename(ref_frame),
793  0, HAWKI_HEADER_PRI_TOPAF, 0) ;
794 
795  /* Add the PRO REC1 ID in the paf files */
796  cpl_propertylist_prepend_string(paflist, "PRO REC1 ID", recipe_name) ;
797 
798  /* Add the PRO CATG keyword. This is a workaround, since the current
799  * implemented behaviour is not to have PAF files associated to products.
800  * All this will be removed with the FITS2PAF utility in esorex
801  */
802  cpl_propertylist_prepend_string(paflist, "PRO CATG", HAWKI_CALPRO_ILLUM);
803 
804  /* Write the extension PAF files */
805  for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
806  /* Duplicate paflist */
807  paflist_cur = cpl_propertylist_duplicate(paflist) ;
808 
809  /* Add the EXTNAME keyword in the PAF */
810  sprintf(sval, "CHIP%d.INT1", i+1) ;
811  cpl_propertylist_prepend_string(paflist_cur, "EXTNAME", sval) ;
812 
813  /* Get FITS header from reference file extension */
814  ext_nb=hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), i+1);
815  inputlist = cpl_propertylist_load_regexp(
816  cpl_frame_get_filename(ref_frame), ext_nb,
817  HAWKI_HEADER_EXT_TOPAF, 0) ;
818  cpl_propertylist_copy_property_regexp(paflist_cur, inputlist, "", 0) ;
819  cpl_propertylist_delete(inputlist) ;
820 
821  /* End of Workaround */
822 
823  /* Copy the QC in paflist */
824  cpl_propertylist_copy_property_regexp(paflist_cur, qclists[i], "", 0) ;
825 
826  /* Paf file name */
827  filename = cpl_sprintf("%s_%02d.paf", recipe_name, i+1) ;
828 
829  /* Save the PAF file */
830  cpl_dfs_save_paf("HAWKI",
831  recipe_name,
832  paflist_cur,
833  filename) ;
834  cpl_free(filename) ;
835  cpl_propertylist_delete(paflist_cur) ;
836  }
837 
838  /* Free and return */
839  for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) {
840  cpl_propertylist_delete(qclists[i]) ;
841  }
842  cpl_free(qclists) ;
843  cpl_propertylist_delete(paflist) ;
844  return 0;
845 }
846