HAWKI Pipeline Reference Manual  1.8.12
hawki_util_extinction.c
1 /* $Id: hawki_util_extinction.c,v 1.4 2013/03/11 11:03:00 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: 2013/03/11 11:03:00 $
24  * $Revision: 1.4 $
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 <string.h>
37 #include <math.h>
38 #include <cpl.h>
39 
40 #include "irplib_utils.h"
41 #include "irplib_strehl.h"
42 #include "irplib_stdstar.h"
43 #include "irplib_cat.h"
44 
45 #include "hawki_utils.h"
46 #include "hawki_calib.h"
47 #include "hawki_load.h"
48 #include "hawki_save.h"
49 #include "hawki_pfits.h"
50 #include "hawki_dfs.h"
51 #include "hawki_alloc.h"
52 
53 /*-----------------------------------------------------------------------------
54  Functions prototypes
55  -----------------------------------------------------------------------------*/
56 
57 #ifdef __cplusplus
58 extern "C"
59 #endif
60 int cpl_plugin_get_info(cpl_pluginlist * list);
61 
62 static int hawki_util_extinction_create(cpl_plugin *) ;
63 static int hawki_util_extinction_exec(cpl_plugin *) ;
64 static int hawki_util_extinction_destroy(cpl_plugin *) ;
65 static int hawki_util_extinction(cpl_parameterlist *, cpl_frameset *) ;
66 
67 static cpl_table ** hawki_util_extinction_reduce
68 (cpl_frameset * set,
69  const char * stdstars,
70  const char * bpm,
71  const char * flat,
72  cpl_table ** raw_zpoint_stats,
73  int * star_labels,
74  int * det_labels,
75  cpl_imagelist ** images);
76 static int hawki_util_extinction_save_photsol
77 (cpl_table ** photsol_table,
78  cpl_frameset * zpoint_frames,
79  cpl_parameterlist * parlist,
80  cpl_frameset * set);
81 static cpl_table ** hawki_util_extinction_photom
82 (cpl_frameset * std_stars_photom);
83 static cpl_table * hawki_util_extinction_get_photomsol
84 (cpl_table * std_stars_photom);
85 static int hawki_util_extinction_compute_keywords
86 (cpl_frameset * set,
87  int * det_labels);
88 
89 /*-----------------------------------------------------------------------------
90  Static variables
91  -----------------------------------------------------------------------------*/
92 
93 
94 static char hawki_util_extinction_description[] =
95 "hawki_util_extinction -- Zero point recipe with extinction\n"
96 "The input of the recipe files listed in the Set Of Frames (sof-file)\n"
97 "must be tagged as:\n"
98 "hawki_util_extinction.fits ("HAWKI_CALPRO_ZPOINT_TAB"): Zero point solution table\n"
99 "The recipe creates as an output:\n"
100 "hawki_cal_photom.fits ("HAWKI_CALPRO_PHOT_TAB"): Photometric solution\n"
101 "Return code:\n"
102 "esorex exits with an error code of 0 if the recipe completes successfully\n"
103 "or 1 otherwise";
104 
105 /*-----------------------------------------------------------------------------
106  Functions code
107  -----------------------------------------------------------------------------*/
108 
109 /*----------------------------------------------------------------------------*/
117 /*----------------------------------------------------------------------------*/
118 int cpl_plugin_get_info(cpl_pluginlist * list)
119 {
120  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
121  cpl_plugin * plugin = &recipe->interface ;
122 
123  cpl_plugin_init(plugin,
124  CPL_PLUGIN_API,
125  HAWKI_BINARY_VERSION,
126  CPL_PLUGIN_TYPE_RECIPE,
127  "hawki_util_extinction",
128  "Zero point with extinction computation recipe",
129  hawki_util_extinction_description,
130  "Cesar Enrique Garcia Dabo",
131  "cgarcia@eso.org",
133  hawki_util_extinction_create,
134  hawki_util_extinction_exec,
135  hawki_util_extinction_destroy) ;
136 
137  cpl_pluginlist_append(list, plugin) ;
138 
139  return 0;
140 }
141 
142 /*----------------------------------------------------------------------------*/
151 /*----------------------------------------------------------------------------*/
152 static int hawki_util_extinction_create(cpl_plugin * plugin)
153 {
154  cpl_recipe * recipe ;
155  cpl_parameter * p ;
156 
157  /* Get the recipe out of the plugin */
158  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
159  recipe = (cpl_recipe *)plugin ;
160  else return -1 ;
161 
162  /* Create the parameters list in the cpl_recipe object */
163  recipe->parameters = cpl_parameterlist_new() ;
164  if (recipe->parameters == NULL)
165  return 1;
166 
167  /* Fill the parameters list */
168 
169  /* Return */
170  return 0;
171 }
172 
173 /*----------------------------------------------------------------------------*/
179 /*----------------------------------------------------------------------------*/
180 static int hawki_util_extinction_exec(cpl_plugin * plugin)
181 {
182  cpl_recipe * recipe ;
183 
184  /* Get the recipe out of the plugin */
185  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
186  recipe = (cpl_recipe *)plugin ;
187  else return -1 ;
188 
189  /* Issue a banner */
191 
192  return hawki_util_extinction(recipe->parameters, recipe->frames) ;
193 }
194 
195 /*----------------------------------------------------------------------------*/
201 /*----------------------------------------------------------------------------*/
202 static int hawki_util_extinction_destroy(cpl_plugin * plugin)
203 {
204  cpl_recipe * recipe ;
205 
206  /* Get the recipe out of the plugin */
207  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
208  recipe = (cpl_recipe *)plugin ;
209  else return -1 ;
210 
211  cpl_parameterlist_delete(recipe->parameters) ;
212  return 0 ;
213 }
214 
215 /*----------------------------------------------------------------------------*/
222 /*----------------------------------------------------------------------------*/
223 static int hawki_util_extinction(
224  cpl_parameterlist * parlist,
225  cpl_frameset * framelist)
226 {
227  cpl_frameset * std_stars_photom ;
228  cpl_table ** zpoint_tables;
229 
230  /* Initialise Output */
231  std_stars_photom = NULL ;
232 
233  /* Identify the RAW and CALIB frames in the input frameset */
234  if (hawki_dfs_set_groups(framelist)) {
235  cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
236  return -1 ;
237  }
238 
239  /* Retrieve zpoint tables */
240  if ((std_stars_photom = hawki_extract_frameset
241  (framelist, HAWKI_CALPRO_ZPOINT_TAB)) == NULL)
242  {
243  cpl_msg_error(__func__, "Cannot find std stars info (%s)",
244  HAWKI_CALPRO_ZPOINT_TAB);
245  return -1 ;
246  }
247 
248  /* Compute the zpoint values */
249  cpl_msg_info(__func__, "Reduce the data") ;
250  cpl_msg_indent_more() ;
251  if ((zpoint_tables = hawki_util_extinction_photom(std_stars_photom))==NULL)
252  {
253  cpl_msg_error(__func__, "Cannot compute photometric solution") ;
254  cpl_frameset_delete(std_stars_photom) ;
255  cpl_msg_indent_less() ;
256  return -1 ;
257  }
258  cpl_msg_indent_less() ;
259 
260  /* Save the products */
261  cpl_msg_info(__func__, "Save the products");
262  cpl_msg_indent_more() ;
263  if (hawki_util_extinction_save_photsol
264  (zpoint_tables, std_stars_photom,
265  parlist, framelist) == -1)
266  {
267  cpl_msg_warning(__func__, "Data could not be saved. "
268  "Check permisions or disk space") ;
269  hawki_table_delete(zpoint_tables) ;
270  cpl_frameset_delete(std_stars_photom);
271  cpl_msg_indent_less() ;
272  return -1 ;
273  }
274  cpl_msg_indent_less() ;
275 
276  /* Free and return */
277  cpl_frameset_delete(std_stars_photom);
278  hawki_table_delete(zpoint_tables);
279 
280  /* Return */
281  if (cpl_error_get_code()) return -1 ;
282  else return 0 ;
283 }
284 
285 /*----------------------------------------------------------------------------*/
295 /*----------------------------------------------------------------------------*/
296 static cpl_table ** hawki_util_extinction_photom
297 (cpl_frameset * std_stars_photom)
298 
299 {
300  cpl_table ** photsol;
301  int nframes;
302  double extinction;
303  cpl_bivector * iqe_res ;
304  int iframe;
305  int idet;
306  int jdet;
307  int iext;
308  int ext_nb;
309  cpl_frame * ref_frame;
310 
311  /* Test entries */
312  if (std_stars_photom == NULL) return NULL ;
313 
314  /* Initialise */
315  photsol = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table*));
316  nframes = cpl_frameset_get_size(std_stars_photom) ;
317 
318  /* Get reference */
319  ref_frame = cpl_frameset_get_first(std_stars_photom);
320  nframes = cpl_frameset_get_size(std_stars_photom);
321 
322  /* Loop on detectors */
323  for (idet=0 ; idet<HAWKI_NB_DETECTORS; idet++)
324  {
325  cpl_table * merged_std_stars_photom;
326 
327  cpl_msg_info(cpl_func, "Working on detector %d", idet +1);
328  cpl_msg_indent_more();
329  /* Get the extension */
330  ext_nb=hawki_get_ext_from_detector(cpl_frame_get_filename(ref_frame), idet+1);
331 
332  /* Load all the tables and merge them */
333  for( iframe = 0 ; iframe < nframes ; ++iframe)
334  {
335  cpl_frame * this_frame;
336  cpl_table * this_table;
337  /* Get the current image */
338  this_frame = cpl_frameset_get_frame(std_stars_photom, iframe);
339  if(iframe == 0)
340  merged_std_stars_photom = cpl_table_load
341  (cpl_frame_get_filename(this_frame),ext_nb, 1);
342  else
343  {
344  cpl_table * this_table =
345  cpl_table_load(cpl_frame_get_filename(this_frame),ext_nb, 1);
346  cpl_table_insert(merged_std_stars_photom, this_table,
347  cpl_table_get_nrow(merged_std_stars_photom));
348  cpl_table_delete(this_table);
349  }
350  }
351 
352  if(cpl_table_get_nrow(merged_std_stars_photom) < 2)
353  {
354  cpl_msg_error(__func__, "%d stars found. At least 2 stars must be present",
355  cpl_table_get_nrow(merged_std_stars_photom));
356  cpl_table_delete(merged_std_stars_photom);
357  return NULL;
358  }
359  cpl_msg_info(__func__,"Number of star measurements %d",
360  cpl_table_get_nrow(merged_std_stars_photom));
361 
362  if((photsol[idet] = hawki_util_extinction_get_photomsol
363  (merged_std_stars_photom)) == NULL)
364  {
365  cpl_table_delete(merged_std_stars_photom);
366  for(jdet=0; jdet < idet; jdet++)
367  cpl_table_delete(photsol[jdet]);
368  cpl_free(photsol);
369  return NULL;
370  }
371 
372  cpl_table_delete(merged_std_stars_photom);
373  cpl_msg_indent_less();
374  }
375  return photsol;
376 }
377 
378 static cpl_table * hawki_util_extinction_get_photomsol
379 (cpl_table * std_stars_photom)
380 {
381  const double * instrmag;
382  const double * airmass;
383  const double * catmag;
384  cpl_table * photsol;
385  double zeropoint;
386  double extcoeff;
387  cpl_matrix * xpos;
388  cpl_vector * ypos;
389  cpl_polynomial * phot_coeff;
390  int nstars;
391  int istar;
392  const cpl_boolean sampsym = CPL_TRUE;
393  const cpl_size mindeg1d = 0;
394  const cpl_size maxdeg1d = 1;
395  cpl_size pows;
396 
397 
398  nstars = cpl_table_get_nrow(std_stars_photom);
399 
400  photsol = cpl_table_new(1);
401  instrmag = cpl_table_get_data_double_const
402  (std_stars_photom, HAWKI_COL_ZPOINT_INSTRMAG);
403  airmass = cpl_table_get_data_double_const
404  (std_stars_photom, HAWKI_COL_ZPOINT_AIRMASS);
405  catmag = cpl_table_get_data_double_const
406  (std_stars_photom, HAWKI_COL_ZPOINT_STARMAG);
407 
408  if(instrmag == NULL || airmass == NULL || catmag == NULL)
409  {
410  cpl_msg_error(cpl_func, "Some of the following columns not found "
411  "in table: %s, %s, %s", HAWKI_COL_ZPOINT_INSTRMAG,
412  HAWKI_COL_ZPOINT_AIRMASS, HAWKI_COL_ZPOINT_STARMAG);
413  cpl_table_delete(photsol);
414  return NULL;
415  }
416 
417  cpl_table_new_column(photsol, HAWKI_COL_PHOT_FILTER, CPL_TYPE_STRING);
418  cpl_table_new_column(photsol, HAWKI_COL_PHOT_ZEROPOINT, CPL_TYPE_DOUBLE);
419  cpl_table_set_column_unit(photsol,HAWKI_COL_PHOT_ZEROPOINT,"mag");
420  cpl_table_new_column(photsol, HAWKI_COL_PHOT_EXTCOEFF, CPL_TYPE_DOUBLE);
421  cpl_table_set_column_unit(photsol,HAWKI_COL_PHOT_EXTCOEFF,"mag/airmass");
422 
423  /* Make the fit to get the coefficients */
424  xpos = cpl_matrix_new(1, nstars);
425  ypos = cpl_vector_new(nstars);
426  for(istar = 0; istar < nstars; ++istar)
427  {
428  double y;
429  cpl_matrix_set(xpos, 0, istar, airmass[istar]);
430  y = catmag[istar] + instrmag[istar];
431  cpl_vector_set(ypos, istar, y);
432  }
433  /* phot_coeff[0] --> ZP
434  * phot_coeff[1] --> -extcoeff
435  */
436  phot_coeff = cpl_polynomial_new(1);
437  if(cpl_polynomial_fit(phot_coeff, xpos, NULL, ypos, NULL,
438  CPL_FALSE, &mindeg1d, &maxdeg1d) != CPL_ERROR_NONE)
439  {
440  cpl_msg_error(cpl_func,"Cannot get the photometric solution");
441  cpl_table_delete(photsol);
442  return NULL;
443  }
444  cpl_matrix_delete(xpos);
445  cpl_vector_delete(ypos);
446  pows = 0;
447  zeropoint = cpl_polynomial_get_coeff(phot_coeff, &pows);
448  pows = 1;
449  extcoeff = -cpl_polynomial_get_coeff(phot_coeff, &pows);
450  cpl_polynomial_delete(phot_coeff);
451 
452  cpl_table_set_double(photsol, HAWKI_COL_PHOT_ZEROPOINT, 0,
453  zeropoint);
454  cpl_table_set_double(photsol, HAWKI_COL_PHOT_EXTCOEFF, 0,
455  extcoeff);
456 
457  /* Output results */
458  cpl_msg_indent_more();
459  cpl_msg_info(__func__, "Zero point: %f", zeropoint);
460  cpl_msg_info(__func__, "Extinction coefficient: %f", extcoeff);
461  cpl_msg_indent_less();
462 
463  return photsol;
464 }
465 
466 /*----------------------------------------------------------------------------*/
475 /*----------------------------------------------------------------------------*/
476 static int hawki_util_extinction_save_photsol
477 (cpl_table ** photsol_table,
478  cpl_frameset * zpoint_frames,
479  cpl_parameterlist * parlist,
480  cpl_frameset * set)
481 {
482  cpl_propertylist ** qclists ;
483  const char * ref_filename;
484  cpl_propertylist * inputlist ;
485  int ext_nb, nframes ;
486  const char * recipe_name = "hawki_util_extinction" ;
487  int idet;
488  int iframe;
489  cpl_errorstate error_prevstate = cpl_errorstate_get();
490 
491 
492  /* Initialise */
493  nframes = cpl_frameset_get_size(set) ;
494 
495  /* Get the reference frame */
496  ref_filename = hawki_get_extref_file(set);
497 
498  /* Create the QC lists for the extensions */
499  qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
500  for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++)
501  {
502  int this_iframe = -1;
503 
504  qclists[idet] = cpl_propertylist_new() ;
505  /* These QC are common to all extensions */
506 
507 
508  /* Propagate some keywords from input raw frame extensions */
509  ext_nb=hawki_get_ext_from_detector(ref_filename, idet+1);
510  inputlist = cpl_propertylist_load_regexp(ref_filename, ext_nb,
511  HAWKI_HEADER_EXT_FORWARD, 0) ;
512  cpl_propertylist_append(qclists[idet], inputlist) ;
513  cpl_propertylist_delete(inputlist) ;
514 
515  }
516 
517  /* Write the photometric table */
518  hawki_tables_save(set,
519  parlist,
520  zpoint_frames,
521  (const cpl_table **)photsol_table,
522  recipe_name,
523  HAWKI_CALPRO_PHOT_TAB,
524  HAWKI_PROTYPE_PHOT_TAB,
525  NULL,
526  (const cpl_propertylist **)qclists,
527  "hawki_util_extinction.fits");
528 
529  /* Free */
530  for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) {
531  cpl_propertylist_delete(qclists[idet]) ;
532  }
533  cpl_free(qclists) ;
534 
535  /* Free */
536  if(!cpl_errorstate_is_equal(error_prevstate))
537  {
538  cpl_errorstate_set(CPL_ERROR_NONE);
539  return -1;
540  }
541  return 0;
542 }