OMEGA Pipeline Reference Manual  1.0.5
omega_standard_star.c
1 /* $Id: omega_standard_star.c,v 1.37 2012-08-22 09:51:58 agabasch Exp $
2  *
3  * This file is part of the OMEGA 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: agabasch $
23  * $Date: 2012-08-22 09:51:58 $
24  * $Revision: 1.37 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 #include "omega_recipe.h"
36 #include "omega_science.h"
37 
38 #include "omega_background.h"
39 #include "omega_cosmic.h"
40 #include "omega_photometry.h"
41 #include "omega_satellites.h"
42 #include "omega_wcscor.h"
43 #include "omega_utils.h"
82 /*-----------------------------------------------------------------------------
83  Functions prototypes
84  -----------------------------------------------------------------------------*/
85 
86 static int omega_standard_star_create(cpl_plugin *) ;
87 static int omega_standard_star_exec(cpl_plugin *) ;
88 static int omega_standard_star_destroy(cpl_plugin *) ;
89 static int omega_standard_star(cpl_frameset *,cpl_parameterlist *);
90 
91 /*-----------------------------------------------------------------------------
92  Private Functions
93  -----------------------------------------------------------------------------*/
94 omega_fits *omega_std_process(cpl_frameset *stdlist,cpl_parameterlist *pars, int ext);
95 static int omega_std_retrieve_input_param(const cpl_parameterlist *parlist);
96 static int omega_std_load_calib(int ext);
97 static void omega_std_init(void);
98 static void omega_std_tidy(int level);
99 
100 
101 /*-----------------------------------------------------------------------------
102  Static structures
103  -----------------------------------------------------------------------------*/
104 static struct {
105  /* Inputs. Parameters */
106  int extnum;
107  int oc;
108  int bckg;
109  int paf;
110  double MaxWcsShift;
111  /* Outputs. QC parameters */
112  int nmatches;
113  int nstars;
114  double mratio;
115  double ZP;
116  double ZPerr;
117  double Extinction;
118  double Exterr;
119  double Seeing;
120  double Ellipticity;
121 
122 }omega_std_config;
123 
124 /* Input and Output */
125 static struct {
126 
127  /* Calib frames */
128  const cpl_frame *bpmfr;
129  const cpl_frame *extfr;
130  const cpl_frame *illumfr;
131  const cpl_frame *mbiasfr;
132  const cpl_frame *mflatfr;
133  const cpl_frame *monitfr;
134  const cpl_frame *reffr;
135  const cpl_frame *stdfr;
136  const cpl_frame *usnoa2;
137  const cpl_frame *colfr;
138 
139  cpl_size *labels;
140  cpl_frameset *stdlist;
141  cpl_image *mbias;
142  cpl_image *bpm;
143  cpl_image *mflat;
144  cpl_image *illum;
145 
146  /* Products */
147  char *sname;
148  char *pname;
149  char *zname;
150  omega_fits *stdfits;
151  cpl_table *zptbl;
152  cpl_table *photbl;
153  cpl_table *extratbl;
154 
155 }ps;
156 
157 
158 /* Static variables */
159 
160 /* Static variables */
161 #define RECIPE "omega_standard_star"
162 
163 
164 /*----------------------------------------------------------------------------*/
172 /*----------------------------------------------------------------------------*/
173 int cpl_plugin_get_info(cpl_pluginlist * list)
174 {
175  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
176  cpl_plugin * plugin = &recipe->interface ;
177 
178  cpl_plugin_init(plugin,
179  CPL_PLUGIN_API,
180  OMEGA_BINARY_VERSION,
181  CPL_PLUGIN_TYPE_RECIPE,
182  "omega_standard_star",
183  "OMEGA - This recipe is used to reduce standard star observations.",
184  "The recipe assumes that the data is for a single CCD. \n"
185  "The following operations are performed: \n\n"
186  " 1. Trim and overscan correct; \n"
187  " 2. Subtract the bias and divide by the flat field; \n"
188  " 3. Correct for fringing, illumination and the background, if requested; \n"
189  " 4. Extract the zero point from the data and calculate the extinction \n"
190  " value and save both in the header and in one table. \n\n"
191  " ------------------------------------------------------------------------ \n\n"
192  " Mandatory inputs : \n\n"
193  " : a raw standard star frame \n"
194  " : a master bias frame (Calfile 541) \n"
195  " : a master flat field (Calfile 546) \n\n"
196  " : a master USNOA2 table \n"
197  " : a standard stars catalog table \n\n"
198  " Optional inputs : \n\n"
199  " : fringe map (Calfile 545) \n"
200  " : bad pixels map (Calfile 522+535) \n"
201  " : illumination correction frame (Calfile 548) \n\n"
202  " The recipe will save the extinction and zero point values in one table.",
203  "Sandra Castro",
204  "scastro@eso.org",
206  omega_standard_star_create,
207  omega_standard_star_exec,
208  omega_standard_star_destroy) ;
209 
210  cpl_pluginlist_append(list, plugin) ;
211 
212  return 0;
213 }
214 
215 /*----------------------------------------------------------------------------*/
224 /*----------------------------------------------------------------------------*/
225 static int omega_standard_star_create(cpl_plugin * plugin)
226 {
227  cpl_recipe * recipe;
228  cpl_parameter * p ;
229  char *path = NULL;
230 
231  /* Do not create the recipe if an error code is already set */
232  if (cpl_error_get_code() != CPL_ERROR_NONE) {
233  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
234  cpl_func, __LINE__, cpl_error_get_where());
235  return (int)cpl_error_get_code();
236  }
237 
238  if (plugin == NULL) {
239  cpl_msg_error(cpl_func, "Null plugin");
240  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
241  }
242 
243  /* Verify plugin type */
244  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
245  cpl_msg_error(cpl_func, "Plugin is not a recipe");
246  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
247  }
248 
249  /* Get the recipe */
250  recipe = (cpl_recipe *)plugin;
251 
252  /* Create the parameters list in the cpl_recipe object */
253  recipe->parameters = cpl_parameterlist_new() ;
254  if (recipe->parameters == NULL) {
255  cpl_msg_error(cpl_func, "Parameter list allocation failed");
256  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
257  }
258 
259  /* Fill the parameters list */
260  /*FIXME: include range in all parameters */
261 
262  /* --------------- General parameters ---------------------------*/
263  p = cpl_parameter_new_value("omega.omega_standard_star.ExtensionNumber",
264  CPL_TYPE_INT,
265  "FITS extension number to load (1 to 32). (-1 == all)",
266  "omega_standard_star",
267  -1) ;
268 
269  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"ext") ;
270  cpl_parameterlist_append(recipe->parameters, p) ;
271 
272  p = cpl_parameter_new_range("omega.omega_standard_star.OverscanMethod",
273  CPL_TYPE_INT,
274  "Overscan Correction Method",
275  "overscan",
276  0, 0, 6);
277  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"oc-meth") ;
278  cpl_parameterlist_append(recipe->parameters, p) ;
279 
280  p = cpl_parameter_new_value("omega.omega_standard_star.PAF",
281  CPL_TYPE_BOOL,
282  "Boolean value to create PAF files. 1(TRUE), 0(FALSE)",
283  "omega_standard_star",
284  1) ;
285 
286  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "paf") ;
287  cpl_parameterlist_append(recipe->parameters, p) ;
288 
289  /* --------------- Saturated pixels parameters ---------------------------*/
290 
291  p = cpl_parameter_new_value("omega.omega_standard_star.LowThreSatuPixel",
292  CPL_TYPE_DOUBLE,
293  "Low threshold for calculating the saturated pixels map.",
294  "omega_standard_star",
295  -500.0) ;
296 
297  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "lt-satu") ;
298  cpl_parameterlist_append(recipe->parameters, p) ;
299 
300  p = cpl_parameter_new_value("omega.omega_standard_star.HighThreSatuPixel",
301  CPL_TYPE_DOUBLE,
302  "High threshold for calculating the saturated pixels map.",
303  "omega_standard_star",
304  60000.0) ;
305 
306  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "ht-satu") ;
307  cpl_parameterlist_append(recipe->parameters, p) ;
308 
309  /* --------------- Satellite detection parameters ---------------------------*/
310  p = cpl_parameter_new_value("omega.omega_standard_star.DetectionThreSatellite",
311  CPL_TYPE_DOUBLE,
312  "Minimum SNR for pixels to contribute to Hough map.",
313  "omega.Hough",
314  4.0) ;
315 
316  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "det-sate") ;
317  cpl_parameterlist_append(recipe->parameters, p) ;
318 
319  p = cpl_parameter_new_value("omega.omega_standard_star.HoughThreshold",
320  CPL_TYPE_DOUBLE,
321  "Threshold for satellite tracks in Hough image.",
322  "omega.Hough",
323  400.0) ;
324 
325  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "hough-thre") ;
326  cpl_parameterlist_append(recipe->parameters, p) ;
327 
328 
329  /* --------------- Fringing parameters ---------------------------*/
330  p = cpl_parameter_new_value("omega.omega_standard_star.SigmaFringeScaling",
331  CPL_TYPE_DOUBLE,
332  "Sigma threshold in image data for scaling estimate (fringes only)",
333  "omega_standard_star",
334  5.0) ;
335 
336  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sig-fr-sc") ;
337  cpl_parameterlist_append(recipe->parameters, p) ;
338 
339  p = cpl_parameter_new_value("omega.omega_standard_star.LowThreFringe",
340  CPL_TYPE_DOUBLE,
341  "Lower bound of fringes to include in scaling (fringes only)",
342  "omega_standard_star",
343  1.5) ;
344 
345  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "lt-fr") ;
346  cpl_parameterlist_append(recipe->parameters, p) ;
347 
348  p = cpl_parameter_new_value("omega.omega_standard_star.HighThreFringe",
349  CPL_TYPE_DOUBLE,
350  "Higher bound of fringes to include in scaling (fringes only)",
351  "omega_standard_star",
352  5.0) ;
353 
354  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "ht-fr") ;
355  cpl_parameterlist_append(recipe->parameters, p) ;
356 
357 
358  /* ----------------- Background parameters ---------------------------*/
359  p = cpl_parameter_new_value("omega.omega_standard_star.BackRestore",
360  CPL_TYPE_BOOL,
361  "Boolean value to restore background after illumination correction. 1(TRUE), 0(FALSE)",
362  "omega_standard_star",
363  1) ;
364 
365  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "backg-rest") ;
366  cpl_parameterlist_append(recipe->parameters, p) ;
367 
368  p = cpl_parameter_new_value("omega.omega_standard_star.BackThreshold",
369  CPL_TYPE_DOUBLE,
370  "Detection threshold for background in image (Sextractor DETECT_THRESH)",
371  "omega_standard_star",
372  1000.) ;
373 
374  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "backthre") ;
375  cpl_parameterlist_append(recipe->parameters, p) ;
376 
377 
378  /* FIXME: need to subtract the background from the STD star?? */
379 
380 
381  /* ------------------ PATH to external executable programs --------------*/
382  path = cpl_sprintf("%s", OMEGA_BIN_PATH);
383  p = cpl_parameter_new_value("omega.omega_standard_star.BinPath",
384  CPL_TYPE_STRING,
385  "Path to any external executable program.",
386  "omega.BinPath",
387  path);
388 
389  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "bin-path");
390  cpl_parameterlist_append(recipe->parameters, p);
391  cpl_free(path);
392 
393  /* ------------------ Sextractor parameters ------------------------- */
394  path = cpl_sprintf("%s/omega.sex", OMEGA_CONFIG_PATH);
395  p = cpl_parameter_new_value("omega.omega_standard_star.SexConfig",
396  CPL_TYPE_STRING,
397  "Path to Sextractor config file.",
398  "omega.sextractor",
399  path);
400 
401  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-config");
402  cpl_parameterlist_append(recipe->parameters, p);
403  cpl_free(path);
404 
405 
406  path = cpl_sprintf("%s/omega.conv", OMEGA_CONFIG_PATH);
407  p = cpl_parameter_new_value("omega.omega_standard_star.SexConv",
408  CPL_TYPE_STRING,
409  "Path to Sextractor convolution mask file.",
410  "omega.sextractor",
411  path);
412 
413  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-conv");
414  cpl_parameterlist_append(recipe->parameters, p);
415  cpl_free(path);
416 
417 
418  path = cpl_sprintf("%s/omega.param", OMEGA_CONFIG_PATH);
419  p = cpl_parameter_new_value("omega.omega_standard_star.SexParam",
420  CPL_TYPE_STRING,
421  "Path to Sextractor parameters file.",
422  "omega.sextractor",
423  path);
424 
425  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-param");
426  cpl_parameterlist_append(recipe->parameters, p);
427  cpl_free(path);
428 
429  path = cpl_sprintf("%s/omega.nnw", OMEGA_CONFIG_PATH);
430  p = cpl_parameter_new_value("omega.omega_standard_star.SexNnw",
431  CPL_TYPE_STRING,
432  "Path to Sextractor neural network config file.",
433  "omega.sextractor",
434  path);
435 
436  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-nnw");
437  cpl_parameterlist_append(recipe->parameters, p);
438  cpl_free(path);
439 
440  p = cpl_parameter_new_value("omega.omega_standard_star.SexDetThreshold",
441  CPL_TYPE_DOUBLE,
442  "Detection threshold for Sextractor sources.",
443  "omega.sextractor",
444  1.5);
445 
446  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-dthre");
447  cpl_parameterlist_append(recipe->parameters, p);
448 
449 
450  /* ------- Cosmic rays detection parameters for Sextractor ------------*/
451  path = cpl_sprintf("%s/omega.cosmic.sex", OMEGA_CONFIG_PATH);
452  p = cpl_parameter_new_value("omega.omega_standard_star.SexCosmic",
453  CPL_TYPE_STRING,
454  "Path to Sextractor cosmic detection mode config file.",
455  "omega.Sextractor",
456  path);
457 
458  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-cosmic");
459  cpl_parameterlist_append(recipe->parameters, p);
460  cpl_free(path);
461 
462  path = cpl_sprintf("%s/omega.cosmic.param", OMEGA_CONFIG_PATH);
463  p = cpl_parameter_new_value("omega.omega_standard_star.SexCosmicParam",
464  CPL_TYPE_STRING,
465  "Path to Sextractor cosmic parameters file.",
466  "omega.Sextractor",
467  path);
468 
469  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"sex-cosmic-param");
470  cpl_parameterlist_append(recipe->parameters, p);
471  cpl_free(path);
472 
473  path = cpl_sprintf("%s/cosmic.ret", OMEGA_CONFIG_PATH);
474  p = cpl_parameter_new_value("omega.omega_standard_star.SexCosmicFilt",
475  CPL_TYPE_STRING,
476  "Path to Sextractor filter mask for cosmic detection mode.",
477  "omega.Sextractor",
478  path);
479 
480  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-cosfilt");
481  cpl_parameterlist_append(recipe->parameters, p);
482  cpl_free(path);
483 
484  p = cpl_parameter_new_value("omega.omega_standard_star.SexCosmicDet",
485  CPL_TYPE_DOUBLE,
486  "Detection threshold for detecting cosmic rays in Sextractor",
487  "omega.Sextractor",
488  5.0) ;
489 
490  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-cosmic-det") ;
491  cpl_parameterlist_append(recipe->parameters, p) ;
492 
493 
494  /* ------------------ Astrometric parameters ------------------------- */
495  p = cpl_parameter_new_value("omega.omega_standard_star.AstromDetThre",
496  CPL_TYPE_DOUBLE,
497  "Sextractor threshold to detect stars for astrometric correction.",
498  "omega.Astrom",
499  5.0) ;
500 
501  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "astrom-thre") ;
502  cpl_parameterlist_append(recipe->parameters, p) ;
503 
504  p = cpl_parameter_new_enum("omega.omega_standard_star.PlateSolution",
505  CPL_TYPE_INT,
506  "Number of constant plate fits to do for the astrometry solution.",
507  "omega.Astrom",
508  4,2,4,6);
509 
510  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "platesol");
511  cpl_parameterlist_append(recipe->parameters, p);
512 
513  p = cpl_parameter_new_value("omega.omega_standard_star.NumIterations",
514  CPL_TYPE_INT,
515  "Number of iterations for the plate solution fitting.",
516  "omega.Astrom",
517  3);
518 
519  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "niter");
520  cpl_parameterlist_append(recipe->parameters, p);
521 
522  p = cpl_parameter_new_range("omega.omega_standard_star.SextractorFlagLimit",
523  CPL_TYPE_INT,
524  "Sextractor FLAG upper limit to preselect good sources for the "
525  "astrometric correction computation.", "omega.Astrom",
526  7, 0, 256);
527  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"SextractorFlagLimit") ;
528  cpl_parameterlist_append(recipe->parameters, p) ;
529 
530  p = cpl_parameter_new_range("omega.omega_standard_star.SextractorClassStar",
531  CPL_TYPE_DOUBLE,
532  "Sextractor CLASS_STAR lower limit to preselect starlike objects "
533  "for the astrometric correction computation.", "omega.Astrom",
534  0.0, 0.0, 1.0);
535  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"SextractorClassStar") ;
536  cpl_parameterlist_append(recipe->parameters, p) ;
537 
538  p = cpl_parameter_new_value("omega.omega_standard_star.MaxWcsShift",
539  CPL_TYPE_DOUBLE,
540  "Maximum allowed x and y pixel shift of the image when refining "
541  "the WCS solution.",
542  "omega.Astrom",
543  200.);
544 
545  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "MaxWcsShift");
546  cpl_parameterlist_append(recipe->parameters, p);
547 
548 
549 
550  /* ------------------ Photometric parameters ------------------------- */
551  p = cpl_parameter_new_value("omega.omega_standard_star.PhotomDetThre",
552  CPL_TYPE_DOUBLE,
553  "Sextractor threshold to detect stars for photometric correction.",
554  "omega.Photom",
555  5.0) ;
556 
557  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "photom-thre") ;
558  cpl_parameterlist_append(recipe->parameters, p) ;
559 
560  p = cpl_parameter_new_value("omega.omega_standard_star.MatchPhotomRadius",
561  CPL_TYPE_DOUBLE,
562  "Radius within which to match photometric stds and stars",
563  "omega.Photom",
564  10.0) ;
565 
566  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "radius") ;
567  cpl_parameterlist_append(recipe->parameters, p) ;
568 
569  p = cpl_parameter_new_value("omega.omega_standard_star.PhotomAperture",
570  CPL_TYPE_DOUBLE,
571  "Aperture in pixels for photometric measurements in Sextractor",
572  "omega.Photom",
573  30.0) ;
574 
575  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "aperture") ;
576  cpl_parameterlist_append(recipe->parameters, p) ;
577 
578  /* ------------------ Pattern Matching parameters ------------------------- */
579  p = cpl_parameter_new_value("omega.omega_standard_star.Nstars",
580  CPL_TYPE_INT,
581  "Number of stars in image to use in "
582  "pattern matching",
583  "omega.Pattern",
584  25);
585 
586  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nstars");
587  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
588  cpl_parameterlist_append(recipe->parameters, p);
589 
590 
591  p = cpl_parameter_new_value("omega.omega_standard_star.Npattern",
592  CPL_TYPE_INT,
593  "Number of catalogue sources to use in "
594  "pattern matching",
595  "omega.Pattern",
596  15);
597 
598  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "npattern");
599  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
600  cpl_parameterlist_append(recipe->parameters, p);
601 
602 
603  p = cpl_parameter_new_value("omega.omega_standard_star.Tolerance",
604  CPL_TYPE_DOUBLE,
605  "Max relative difference of angles and scales from their "
606  "median value for match acceptance (tolerance)",
607  "omega.Pattern",
608  0.1);
609 
610  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "tol");
611  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
612  cpl_parameterlist_append(recipe->parameters, p);
613 
614  p = cpl_parameter_new_value("omega.omega_standard_star.SearchPatternRadius",
615  CPL_TYPE_DOUBLE,
616  "Search radius for full PPM (pixels)",
617  "omega.Pattern",
618  10.0);
619  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pradius");
620  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
621  cpl_parameterlist_append(recipe->parameters, p);
622 
623  p = cpl_parameter_new_value("omega.omega_standard_star.MaxPatternRadius",
624  CPL_TYPE_DOUBLE,
625  "Maximum search radius for full PPM (pixels)",
626  "omega.Pattern",
627  40.0);
628  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "maxpradius");
629  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
630  cpl_parameterlist_append(recipe->parameters, p);
631 
632  /* Return */
633  return 0;
634 }
635 
636 /*----------------------------------------------------------------------------*/
642 /*----------------------------------------------------------------------------*/
643 static int omega_standard_star_exec(cpl_plugin * plugin)
644 {
645  cpl_recipe * recipe;
646  int recipe_status;
647 
648  /* Return immediately if an error code is already set */
649  if (cpl_error_get_code() != CPL_ERROR_NONE) {
650  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
651  cpl_func, __LINE__, cpl_error_get_where());
652  return (int)cpl_error_get_code();
653  }
654 
655  if (plugin == NULL) {
656  cpl_msg_error(cpl_func, "Null plugin");
657  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
658  }
659 
660  /* Verify plugin type */
661  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
662  cpl_msg_error(cpl_func, "Plugin is not a recipe");
663  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
664  }
665 
666  /* Get the recipe */
667  recipe = (cpl_recipe *)plugin;
668 
669  /* Verify parameter and frame lists */
670  if (recipe->parameters == NULL) {
671  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
672  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
673  }
674  if (recipe->frames == NULL) {
675  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
676  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
677  }
678 
679  /* Invoke the recipe */
680  recipe_status = omega_standard_star(recipe->frames, recipe->parameters);
681 
682  /* Ensure DFS-compliance of the products */
683  if (cpl_dfs_update_product_header(recipe->frames)) {
684  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
685  }
686 
687  return recipe_status;
688 
689 }
690 
691 /*----------------------------------------------------------------------------*/
697 /*----------------------------------------------------------------------------*/
698 static int omega_standard_star_destroy(cpl_plugin * plugin)
699 {
700  cpl_recipe * recipe;
701 
702  if (plugin == NULL) {
703  cpl_msg_error(cpl_func, "Null plugin");
704  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
705  }
706 
707  /* Verify plugin type */
708  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
709  cpl_msg_error(cpl_func, "Plugin is not a recipe");
710  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
711  }
712 
713  /* Get the recipe */
714  recipe = (cpl_recipe *)plugin;
715 
716  cpl_parameterlist_delete(recipe->parameters) ;
717 
718  return 0 ;
719 }
720 
721 /*----------------------------------------------------------------------------*/
731 /*----------------------------------------------------------------------------*/
732 static int omega_standard_star(cpl_frameset *set, cpl_parameterlist *pars)
733 {
734  int j,jst,jfn,isfirst;
735  cpl_size nlab;
736  int nraw = 0;
737  int oscan1 = 0;
738  double exptime = 0.0;
739  double gain = 1.0;
740 
741  char *sname = NULL;
742  char *pname = NULL;
743  char *zname = NULL;
744  const char *stdname = "omega_std.fits";
745  const char * maskname= NULL;
746  omega_fits * stdfits_mask=NULL;
747  cpl_image *image_simple_mask=NULL;
748  cpl_frame *product_frame = NULL;
749  cpl_frame *product_frame_mask=NULL ;
750  cpl_frame *pframe = NULL;
751  cpl_frame *zpframe = NULL;
752  cpl_image *image = NULL;
753  cpl_propertylist *plist,*xlist,*qclist,*alist;
754  cpl_errorstate prestate = cpl_errorstate_get();
755 
756  /*Start the recipe */
757 
758  if (pars == NULL) {
759  cpl_msg_error (cpl_func, "Parameters list not found");
760  return -1;
761  }
762 
763  if (cpl_frameset_is_empty(set) == 1) {
764  cpl_msg_error (cpl_func, "Frameset not found");
765  return -1;
766  }
767 
768  /* Retrieve input parameters and initiates specific parameters lists*/
769  if(omega_std_retrieve_input_param(pars) != 0){
770  cpl_msg_error(cpl_func,"Cannot retrieve input parameters. %s", cpl_error_get_message());
771  return -1;
772  }
773 
774  /* Identify the RAW and CALIB frames in the input frameset */
775  if (oc_dfs_set_groups(set)) {
776  cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames") ;
777  return -1 ;
778  }
779 
780  /*Initialized things*/
781  omega_std_init();
782 
783  /* Verify the frameset contents. */
784  if ((ps.labels = cpl_frameset_labelise(set,omega_compare_tags,
785  &nlab)) == NULL) {
786  cpl_msg_error(cpl_func,"Cannot labelise the input frameset");
787  omega_std_tidy(0);
788  return -1;
789  }
790 
791  if ((ps.stdlist = omega_frameset_subgroup(set,ps.labels,nlab,
792  STD_RAW)) == NULL) {
793  cpl_msg_error(cpl_func,"Cannot find standard stars in input frameset");
794  omega_std_tidy(0);
795  return -1;
796  }
797  nraw = cpl_frameset_count_tags (ps.stdlist, STD_RAW);
798  cpl_msg_info (cpl_func,"There are %d %s frames in frame set",nraw, STD_RAW);
799 
800  /* Check for calibration frames */
801  /* Master Bias */
802  ps.mbiasfr = cpl_frameset_find_const(set, OMEGA_CALIB_BIAS);
803  if (ps.mbiasfr == NULL) {
804  cpl_msg_error(cpl_func,"Cannot find %s frame in frame set", OMEGA_CALIB_BIAS);
805  omega_std_tidy(0);
806  return -1;
807  }
808  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_BIAS, cpl_frame_get_filename(ps.mbiasfr));
809 
810  /* Master Flat */
811  ps.mflatfr = cpl_frameset_find_const(set, OMEGA_CALIB_FLAT);
812  if(ps.mflatfr == NULL) {
813  cpl_msg_error(cpl_func,"Cannot find %s frame in frame set", OMEGA_CALIB_FLAT);
814  omega_std_tidy(0);
815  return -1;
816  }
817  cpl_msg_info(cpl_func,"Using %s %s", OMEGA_CALIB_FLAT, cpl_frame_get_filename(ps.mflatfr));
818 
819 
820  /* Reference standard star list */
821  ps.reffr = cpl_frameset_find (set, OMEGA_CALIB_REFSTAR);
822  if (ps.reffr == NULL) {
823  cpl_msg_error(cpl_func,"Cannot find %s frame in frame set",OMEGA_CALIB_REFSTAR);
824  omega_std_tidy(0);
825  return -1;
826  }
827  cpl_msg_info(cpl_func,"Using %s %s", OMEGA_CALIB_REFSTAR, cpl_frame_get_filename(ps.reffr));
828 
829 
830  /* Monitoring report */
831  ps.monitfr = cpl_frameset_find(set, OMEGA_CALIB_MONIT);
832  if(ps.monitfr == NULL) {
833  cpl_msg_error(cpl_func,"Cannot find %s in frame set",OMEGA_CALIB_MONIT );
834  omega_std_tidy(0);
835  return -1;
836  }
837 
838  /* Extinction curve */
839  ps.extfr = cpl_frameset_find (set,OMEGA_CALIB_EXTCUR);
840  if(ps.extfr == NULL) {
841  cpl_msg_error(cpl_func,"Cannot find %s in frame set", OMEGA_CALIB_EXTCUR);
842  omega_std_tidy(0);
843  return -1;
844  }
845 
846  /* USNOA2 master table */
847  ps.usnoa2 = cpl_frameset_find (set, OMEGA_USNOA2);
848  if (ps.usnoa2 == NULL) {
849  cpl_msg_error(cpl_func,"Cannot find %s frame in frame set",OMEGA_USNOA2);
850  omega_std_tidy(0);
851  return -1;
852  }
853  else{
854  cpl_msg_info(cpl_func,"Using %s %s", OMEGA_USNOA2, cpl_frame_get_filename(ps.usnoa2));
855  }
856 
857  /* Bad Pixels Map */
858  ps.bpmfr = cpl_frameset_find (set,OMEGA_CALIB_BPM);
859  if(ps.bpmfr == NULL) {
860  cpl_msg_error(cpl_func,"Cannot find %s in frame set", OMEGA_CALIB_BPM);
861  omega_std_tidy(0);
862  return -1;
863  }
864  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_BPM,cpl_frame_get_filename(ps.bpmfr));
865 
866  /* Illumination frame */
867  ps.illumfr = cpl_frameset_find(set, OMEGA_CALIB_ILLUM);
868  if(ps.illumfr != NULL)
869  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_ILLUM,cpl_frame_get_filename(ps.illumfr));
870 
871  /* Colour terms */
872  ps.colfr = cpl_frameset_find(set,OMEGA_CALIB_COLTERMS);
873  if(ps.colfr != NULL)
874  cpl_msg_info(cpl_func,"Using %s %s", OMEGA_CALIB_COLTERMS, cpl_frame_get_filename(ps.colfr));
875 
876  /* Get first frame from frame set */
877  ps.stdfr = cpl_frameset_get_first_const(ps.stdlist);
878 
879  /* Check which image extension(s) to load */
880  omega_extensions(ps.stdfr,omega_std_config.extnum,&jst,&jfn);
881  if(omega_std_config.extnum == 0){
882  cpl_msg_error(cpl_func,"Unsupported extension request, %d",omega_std_config.extnum);
883  omega_std_tidy(0);
884  return -1;
885  }
886 
887  /* Loop over extensions */
888  for (j = jst; j <= jfn; j++) {
889  isfirst = (j == jst);
890  cpl_msg_indent_more();
891  cpl_msg_info(cpl_func,".....Working on extension %d.....",j);
892  cpl_msg_indent_less();
893 
894  omega_std_config.nmatches = 0;
895  omega_std_config.nstars = 0;
896  omega_std_config.mratio = 0.0;
897  omega_std_config.ZP = 0.0;
898  omega_std_config.ZPerr = 0.0;
899  omega_std_config.Extinction = 0.0;
900  omega_std_config.Exterr = 0.0;
901  omega_std_config.Seeing = 0.0;
902  omega_std_config.Ellipticity = 0.0;
903 
904  /* Check overscan correction method consistency */
905  if(ps.mbiasfr != NULL){
906  oscan1 = omega_pfits_get_overscan(ps.mbiasfr, j);
907  if(oscan1 != omega_std_config.oc) {
908  cpl_msg_warning (cpl_func, "Overscan correction mode for Master Bias (oc = %d) differs from "
909  "the one used here (oc = %d)", oscan1, omega_std_config.oc);
910  }
911  }
912 
913  /* Load calibration frames */
914  if(omega_std_load_calib(j) != 0){
915  cpl_msg_error(cpl_func,"Cannot load calibration frame(s)");
916  omega_std_tidy(0);
917  return -1;
918  }
919 
920  /* Call the processing routine */
921  if((ps.stdfits = omega_std_process(ps.stdlist,pars,j)) == NULL){
922  cpl_msg_error(cpl_func, "Cannot reduce image extension");
923  omega_std_tidy(0);
924  return -1;
925  }
926 
927  /* Free some space */
928  omega_std_tidy(1);
929 
930  /* Save reduced stack */
931  if(isfirst){
932  ps.sname = cpl_sprintf("%s_%s.fits", INSTRUME,STD_PROCATG);
933  product_frame = omega_product_frame(ps.sname, STD_PROCATG, CPL_FRAME_TYPE_IMAGE);
934  maskname=cpl_sprintf("%s_%s.fits", INSTRUME,"REDUCED_STD_MASK");
935  product_frame_mask = omega_product_frame(maskname, "REDUCED_STD_MASK", CPL_FRAME_TYPE_IMAGE);
936 
937  }
938  cpl_msg_info(cpl_func,"Saving STD image");
939  if((omega_save_fits(ps.stdfits,set,pars,NULL,CPL_BPP_IEEE_FLOAT,ps.sname,RECIPE,
940  product_frame,NULL,isfirst)) == -1){
941  cpl_msg_error(cpl_func,"Cannot save product");
942  cpl_free(maskname);
943  omega_std_tidy(0);
944  return -1;
945  }
946 
947 
948 
949  stdfits_mask=omega_fits_duplicate(ps.stdfits);
950  /*Extracting the mask file from the image*/
951  image_simple_mask=cpl_image_new_from_mask(cpl_image_get_bpm(stdfits_mask->image));
952  cpl_image_delete(stdfits_mask->image); stdfits_mask->image=NULL;
953  stdfits_mask->image=image_simple_mask;
954 
955  cpl_msg_info(cpl_func,"Saving STD MASK image");
956  if((omega_save_fits(stdfits_mask,set,pars,NULL,CPL_BPP_8_UNSIGNED,maskname,RECIPE,
957  product_frame_mask,NULL,isfirst)) == -1){
958  cpl_msg_error(cpl_func,"Cannot save product");
959  freefits(stdfits_mask);
960  cpl_free(maskname);
961  omega_std_tidy(0);
962  return -1;
963  }
964  freefits(stdfits_mask);
965 
966  /* Correct image to unit time (flux) for photometry.
967  * If keyword is missing or set to 0.0, catch it and
968  * try the primary header. */
969  plist = omega_fits_get_phu(ps.stdfits);
970  xlist = omega_fits_get_ehu(ps.stdfits);
971 
972  alist = cpl_propertylist_new();
973  cpl_propertylist_append_string(alist, "EXTNAME",
974  cpl_propertylist_get_string(xlist, "EXTNAME"));
975  cpl_propertylist_set_comment(alist,"EXTNAME", "Extension name");
976 
977 
978  if(cpl_propertylist_has(xlist,"ESO QC STD PPM FAILURE")){
979  cpl_propertylist_append_int(alist, "ESO QC STD PPM FAILURE",
980  cpl_propertylist_get_int(xlist, "ESO QC STD PPM FAILURE"));
981  cpl_propertylist_set_comment(alist, "ESO QC STD PPM FAILURE", "PPM failure if ZERO");
982  }
983  /*Get gain*/
984  omega_pfits_get_conad(xlist,&gain);
985 
986  /* Add DRS keywords */
987  cpl_propertylist_update_int(alist, "ESO DRS OVERSCAN METHOD", omega_std_config.oc );
988  cpl_propertylist_set_comment(alist, "ESO DRS OVERSCAN METHOD", "overscan correction method");
989 
990  exptime = omega_pfits_get_exptime(xlist);
991  if(exptime <= 0.0)
992  exptime = omega_pfits_get_exptime(plist);
993 
994  image = cpl_image_duplicate(omega_fits_get_image(ps.stdfits));
995 
996  if(exptime > 0.0)
997  cpl_image_divide_scalar(image, exptime);
998 
999  cpl_propertylist_save(plist, stdname, CPL_IO_CREATE);
1000  cpl_image_save(image,stdname,CPL_BPP_IEEE_DOUBLE,xlist,CPL_IO_EXTEND);
1001 
1002  freeimage(image);
1003  freefits(ps.stdfits);
1004  ps.stdfits = NULL;
1005 
1006  /* Create photometric table */
1007  if((ps.photbl = omega_photom_tbl(stdname, gain, ps.reffr,
1008  pars, &ps.extratbl)) == NULL){
1009  cpl_msg_warning(cpl_func,"Cannot create photometric table");
1010  cpl_msg_warning(cpl_func,"Creating an empty photometric table "
1011  "for this extension");
1012  ps.photbl = cpl_table_new(0);
1013  //omega_std_tidy(0);
1014  //return -1;
1015  }
1016 
1017  /* Save photometric table */
1018  if(isfirst){
1019  ps.pname = cpl_sprintf("%s_%s.fits", INSTRUME,PHOT_PROCATG);
1020  pframe = omega_product_frame(ps.pname, PHOT_PROCATG, CPL_FRAME_TYPE_IMAGE);
1021  }
1022  cpl_msg_info(cpl_func,"Saving Photometric table");
1023  if(omega_save_table(ps.photbl,set,pars,alist,NULL,ps.pname,RECIPE,
1024  pframe,NULL,isfirst) == -1){
1025  cpl_msg_error(cpl_func,"Cannot save photometric table");
1026  freeplist(alist);
1027  cpl_free(maskname); maskname=NULL;
1028  omega_std_tidy(0);
1029  return -1;
1030  }
1031 
1032  prestate = cpl_errorstate_get();
1033  /* Create Zeropoints table */
1034  if((ps.zptbl = omega_zeropoints(ps.photbl, ps.extratbl, ps.monitfr, ps.extfr,
1035  ps.colfr)) == NULL ){
1036  cpl_msg_warning(cpl_func,"Cannot create ZP table");
1037  cpl_msg_warning(cpl_func,"Creating an empty ZP table for this "
1038  "extension");
1039  ps.zptbl = cpl_table_new(0);
1040  //freeplist(alist);
1041  //omega_std_tidy(0);
1042  //return -1;
1043  }
1044  cpl_errorstate_set(prestate);
1045 
1046  freetable(ps.extratbl);
1047  freetable(ps.photbl);
1048 
1049  /* Get QC parameters from table */
1050  omega_std_config.ZP = cpl_table_get_double(ps.zptbl, "ZEROPOINT", 0, NULL);
1051  omega_std_config.ZPerr = cpl_table_get_double(ps.zptbl, "ZEROPOINT_ERR", 0, NULL);
1052  omega_std_config.Extinction = cpl_table_get_double(ps.zptbl, "EXTINCTION", 0, NULL);
1053  omega_std_config.Exterr = cpl_table_get_double(ps.zptbl, "EXTINCTION_ERR", 0, NULL);
1054  omega_std_config.nstars = cpl_table_get_int(ps.zptbl, "NSTARS", 0, NULL);
1055  omega_std_config.Seeing = cpl_table_get_double(ps.zptbl, "SEEING", 0, NULL);
1056  omega_std_config.Ellipticity = cpl_table_get_double(ps.zptbl, "ELLIPTICITY", 0, NULL);
1057 
1058  qclist = cpl_propertylist_new();
1059  cpl_propertylist_update_double(qclist, "ESO QC ZEROPOINT", omega_std_config.ZP) ;
1060  cpl_propertylist_set_comment(qclist, "ESO QC ZEROPOINT", "zp with flux in ADU/sec");
1061  cpl_propertylist_update_double(qclist, "ESO QC ZEROPOINT ERR", omega_std_config.ZPerr) ;
1062  cpl_propertylist_set_comment(qclist, "ESO QC ZEROPOINT ERR", "zp error");
1063  /*QC parameters for zeropoints calculated for electrons and not ADUs*/
1064  cpl_propertylist_update_double(qclist, "ESO QC ZEROPOINT_ELECTRON", omega_std_config.ZP+(2.5*log10(gain))) ;
1065  cpl_propertylist_set_comment(qclist, "ESO QC ZEROPOINT_ELECTRON", "zp with flux in e-/sec");
1066  cpl_propertylist_update_double(qclist, "ESO QC ZEROPOINT_ELECTRON ERR", omega_std_config.ZPerr) ;
1067  cpl_propertylist_set_comment(qclist, "ESO QC ZEROPOINT_ELECTRON ERR", "zp error");
1068 
1069  cpl_propertylist_update_double(qclist, "ESO QC EXTINCTION", omega_std_config.Extinction) ;
1070  cpl_propertylist_set_comment(qclist, "ESO QC EXTINCTION", "calculated extinction");
1071  cpl_propertylist_update_double(qclist, "ESO QC EXTINCTION ERR", omega_std_config.Exterr) ;
1072  cpl_propertylist_set_comment(qclist, "ESO QC EXTINCTION ERR", "calculated extinction error");
1073  cpl_propertylist_update_int(qclist, "ESO QC STD MATCHES", omega_std_config.nmatches);
1074  cpl_propertylist_set_comment(qclist, "ESO QC STD MATCHES", "number matches between USNOA2 cat and stars");
1075  cpl_propertylist_update_double(qclist, "ESO QC STD RATIO MATCHES", omega_std_config.mratio);
1076  cpl_propertylist_set_comment(qclist, "ESO QC STD RATIO MATCHES", "ratio USNOA2 matches/detected stars");
1077  cpl_propertylist_update_double(qclist, "ESO QC STD SEEING", omega_std_config.Seeing);
1078  cpl_propertylist_set_comment(qclist, "ESO QC STD SEEING", "calculated seeing of standard field");
1079  cpl_propertylist_update_double(qclist, "ESO QC STD ELLIPTICITY", omega_std_config.Ellipticity);
1080  cpl_propertylist_set_comment(qclist, "ESO QC STD ELLIPTICITY", "calculated ellipticity of standard field");
1081  cpl_propertylist_update_int(qclist, "ESO QC STD NUMBER STARS", omega_std_config.nstars);
1082  cpl_propertylist_set_comment(qclist, "ESO QC STD NUMBER STARS", "number of std stars used for ZP");
1083 
1084  /* Save ZP table */
1085  if(isfirst){
1086  ps.zname = cpl_sprintf("%s_%s.fits", INSTRUME,ZP_PROCATG);
1087  zpframe = omega_product_frame(ps.zname, ZP_PROCATG, CPL_FRAME_TYPE_IMAGE);
1088  }
1089  cpl_msg_info(cpl_func,"Saving ZP table");
1090  if((omega_save_table(ps.zptbl,set,pars,alist,qclist,ps.zname,RECIPE,
1091  zpframe,NULL,isfirst)) == -1){
1092  cpl_msg_error(cpl_func,"Cannot save photometric table");
1093  freeplist(qclist);
1094  freeplist(alist);
1095  cpl_free(maskname); maskname=NULL;
1096  omega_std_tidy(0);
1097  return -1;
1098  }
1099 
1100  freetable(ps.zptbl);
1101  freeplist(qclist);
1102  freeplist(alist);
1103  } /* go and work on next extension */
1104 
1105  /*Clean up */
1106  cpl_free(maskname); maskname=NULL;
1107  omega_std_tidy(0);
1108 
1109  return 0;
1110 
1111 }
1112 
1124 omega_fits *omega_std_process(cpl_frameset *stdlist,cpl_parameterlist *pars, int ext)
1125 {
1126 
1127  int i = 0;
1128  int nraw = 0;
1129  const char *smoothed = "omega_smoothed_std.fits";
1130  const char *smoothed_weight = "omega_smoothed_std_weight.fits";
1131  double xshift=0.,yshift=0.;
1132  cpl_image *trim=NULL, *mask_img=NULL, *image=NULL, *combmap=NULL;
1133  cpl_image *back = NULL;
1134  cpl_image *reduced = NULL;
1135  cpl_image *sumwght = NULL;
1136  cpl_mask *satu_map=NULL,*bpm_map=NULL;
1137  cpl_mask *satellite= NULL;
1138  cpl_mask *cosmic=NULL;
1139  cpl_propertylist *plist=NULL, *astrolist=NULL, *wcslist=NULL;
1140  cpl_frame *frame=NULL;
1141  omega_fits *stdfits = NULL;
1142  omega_fits **sfits = NULL;
1143 
1144 
1145  if(cpl_image_get_mean(ps.mflat) < 0.1){
1146  cpl_msg_error(cpl_func,"Master Flat image is NULL");
1147  return NULL;
1148  }
1149 
1150  if(cpl_image_get_min(ps.mflat) <= DBL_EPSILON){
1151  cpl_msg_warning(cpl_func,"Some pixel values of the Master Flat are "
1152  "smaller or equal to %g.", DBL_EPSILON);
1153  cpl_msg_warning(cpl_func,"Thresholding image to a minimum of %g ",
1154  DBL_EPSILON);
1155  cpl_image_threshold(ps.mflat, DBL_EPSILON, DBL_MAX,
1156  DBL_EPSILON, DBL_MAX);
1157  }
1158 
1159  /* Load omega_fits structure */
1160  nraw = cpl_frameset_get_size(stdlist);
1161  sfits = omega_fits_load_list(stdlist,CPL_TYPE_FLOAT,ext);
1162 
1163  for(i = 0; i < nraw; i++){
1164  /* Trim and overscan correct */
1165  if((trim = omega_trim_oscan_correct(sfits[i], omega_std_config.oc)) == NULL){
1166  cpl_msg_error(cpl_func,"Unable to trim image %d",i);
1167  freelfits(sfits,nraw);
1168  return NULL;
1169  }
1170 
1171  /* Subtract the bias */
1172  omega_biascor(trim, ps.mbias);
1173 
1174  /* Divide by the flat */
1175  if(omega_flatcor(trim, ps.mflat, NULL) != 0){
1176  cpl_msg_error(cpl_func,"Error in flat correction");
1177  freeimage(trim);
1178  freelfits(sfits,nraw);
1179  return NULL;
1180  }
1181 
1182  /* Create BPM+SATURATION mask */
1183  satu_map = omega_saturated_map(trim, omega_std_config.oc, pars);
1184  bpm_map = cpl_mask_threshold_image_create(ps.bpm, 0.5, 1.5) ;
1185  if(satu_map != NULL){
1186 // cpl_mask_and(bpm_map, satu_map);
1187  cpl_mask_or(bpm_map, satu_map);
1188  freemask(satu_map);
1189  }
1190  mask_img = cpl_image_new_from_mask(bpm_map);
1191  cpl_image_save(mask_img,"bpmsatu.fits",CPL_BPP_16_SIGNED,NULL,CPL_IO_CREATE);
1192  /*Add the bad pixel mask to the image*/
1193  cpl_image_reject_from_mask(trim, bpm_map);
1194  freemask(bpm_map);
1195 
1196  /* Get background */
1197  back = omega_background(trim, pars);
1198 
1199  if(back == NULL)
1200  cpl_msg_debug(cpl_func,"Unable to create background image");
1201 
1202  /* Detect cosmic rays */
1203  image = cpl_image_subtract_create(trim, back);
1204  cosmic = omega_cosmic_rays(image,ps.mflat,ps.illum,mask_img,pars);
1205 
1206  /* Subtract background from std */
1207  if(omega_std_config.bckg == 1){
1208  freeimage(trim);
1209  trim = cpl_image_duplicate(image);
1210  }
1211  freeimage(image);
1212  freeimage(back);
1213 
1214 
1215  /* Detect satellite tracks in background subtracted image */
1216  satellite = detsat(trim, pars);
1217 
1218 
1219  /* Create combination map (BPM,saturated,cosmic,satellite) */
1220  combmap = create_weightframe(ps.mflat,mask_img,cosmic,satellite);
1221  freemask(satellite);
1222  freemask(cosmic);
1223  freeimage(mask_img);
1224 
1225  if((ps.illum != NULL) && (combmap != NULL))
1226  cpl_image_divide(combmap, ps.illum);
1227 
1228  /* Multiply stds by their weights */
1229  cpl_image_multiply(trim, combmap);
1230 
1231  if(i == 0){
1232  reduced = cpl_image_duplicate(trim);
1233  sumwght = cpl_image_duplicate(combmap);
1234  }
1235  else{
1236  cpl_image_add(reduced, trim);
1237  cpl_image_add(sumwght, combmap);
1238  }
1239  freeimage(trim);
1240  freeimage(combmap);
1241 
1242  /* Go to next image */
1243 
1244  }
1245 
1246  freelfits(sfits,nraw);
1247 
1248  /* Weighted average of STDs */
1249  if(cpl_image_divide(reduced, sumwght) != CPL_ERROR_NONE){
1250  cpl_msg_error(cpl_func,"Cannot create weighted average of images. %s", cpl_error_get_message());
1251  freeimage(sumwght);
1252  return NULL;
1253  }
1254 
1255 
1256  /* Correct coordinates after trimming */
1257  frame = cpl_frameset_get_first(stdlist);
1258  plist = cpl_propertylist_load(cpl_frame_get_filename(frame),0);
1259  astrolist = cpl_propertylist_load(cpl_frame_get_filename(frame),ext);
1260  omega_shift_refpix(frame, ext, astrolist);
1261 
1262  /* Use pattern matching to detect stars */
1263  /* Smooth image before creating catalogue */
1264  image = omega_smooth_image(reduced, 1);
1265 
1266  /* Save star as intermediate product */
1267  cpl_propertylist_save(plist, smoothed, CPL_IO_CREATE);
1268  cpl_image_save(image, smoothed, BITPIX, astrolist, CPL_IO_EXTEND);
1269 
1270  /* Save star weight as intermediate product */
1271  cpl_propertylist_save(plist, smoothed_weight, CPL_IO_CREATE);
1272  cpl_image_save(sumwght, smoothed_weight, BITPIX, astrolist, CPL_IO_EXTEND);
1273 
1274  freeimage(image);
1275  freeimage(sumwght);
1276 
1277  /* Calculate WCS distortion */
1278  wcslist = omega_match_points(smoothed, smoothed_weight, ps.usnoa2, pars, ext,
1279  &omega_std_config.nmatches, &omega_std_config.mratio);
1280 
1281  omega_get_wcsshift(astrolist, wcslist, &xshift, &yshift);
1282 
1283 
1284  if(wcslist == NULL || fabs(xshift)> omega_std_config.MaxWcsShift ||
1285  fabs(yshift)>omega_std_config.MaxWcsShift){
1286  cpl_msg_warning(cpl_func,"Unable to refine WCS for image");
1287  cpl_msg_warning(cpl_func,"Taking original WCS coordinates");
1288  wcslist = cpl_propertylist_duplicate(astrolist);
1289  cpl_propertylist_update_int (wcslist, "ESO QC STD PPM FAILURE", 0);
1290  cpl_propertylist_set_comment(wcslist, "ESO QC STD PPM FAILURE", "PPM failure if ZERO");
1291  xshift=0.;
1292  yshift=0.;
1293  }
1294  else{
1295  cpl_propertylist_update_int (wcslist, "ESO QC STD PPM FAILURE", 1);
1296  cpl_propertylist_set_comment(wcslist, "ESO QC STD PPM FAILURE", "PPM failure if ZERO");
1297  }
1298 
1299  cpl_propertylist_update_double (astrolist, "ESO QC DELTAX SHIFT", xshift);
1300  cpl_propertylist_set_comment(astrolist, "ESO QC DELTAX SHIFT", "WCS shift in x");
1301  cpl_propertylist_update_double (astrolist, "ESO QC DELTAY SHIFT", yshift);
1302  cpl_propertylist_set_comment(astrolist, "ESO QC DELTAY SHIFT", "WCS shift in y");
1303 
1304  /* Append WCS header to extension header */
1305  if(omega_pfits_update_header(astrolist, wcslist) != 0)
1306  cpl_msg_debug(cpl_func,"Cannot append WCS header to extension header");
1307 
1308 
1309  /* Wrap product into omega fits structure using 1st frame headers */
1310  stdfits = omega_fits_wrap(reduced,NULL,plist,astrolist);
1311 
1312  freeplist(plist);
1313  freeplist(astrolist);
1314  freeplist(wcslist);
1315 
1316  return stdfits;
1317 }
1318 
1319 
1320 int omega_std_retrieve_input_param(const cpl_parameterlist *pars)
1321 {
1322 
1323  const cpl_parameter *par = NULL;
1324  cpl_errorstate prestate = cpl_errorstate_get();
1325 
1326  par = cpl_parameterlist_find_const(pars, "omega.omega_standard_star.ExtensionNumber") ;
1327  omega_std_config.extnum = cpl_parameter_get_int(par) ;
1328  par = cpl_parameterlist_find_const(pars, "omega.omega_standard_star.OverscanMethod") ;
1329  omega_std_config.oc = cpl_parameter_get_int(par) ;
1330  par = cpl_parameterlist_find_const(pars, "omega.omega_standard_star.BackRestore");
1331  omega_std_config.bckg = cpl_parameter_get_bool(par) ;
1332  par = cpl_parameterlist_find_const(pars, "omega.omega_standard_star.PAF");
1333  omega_std_config.paf = cpl_parameter_get_bool(par) ;
1334  par = cpl_parameterlist_find_const(pars, "omega.omega_standard_star.MaxWcsShift") ;
1335  omega_std_config.MaxWcsShift = cpl_parameter_get_double(par) ;
1336 
1337  if(!cpl_errorstate_is_equal(prestate)){
1338  cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
1339  return -1;
1340  }
1341 
1342  return 0;
1343 }
1344 
1345 static int omega_std_load_calib(int ext)
1346 {
1347 
1348  /* Load mandatory calibration frames */
1349  /* master bias */
1350  ps.mbias = cpl_image_load(cpl_frame_get_filename(ps.mbiasfr), CPL_TYPE_FLOAT, 0, ext);
1351  if(ps.mbias == NULL){
1352  cpl_msg_error(cpl_func,"Cannot load Master Bias. %s", cpl_error_get_message());
1353  return -1;
1354  }
1355  /* master flat */
1356  ps.mflat = cpl_image_load(cpl_frame_get_filename(ps.mflatfr),CPL_TYPE_FLOAT,0,ext);
1357  if (ps.mflat == NULL){
1358  cpl_msg_error(cpl_func,"Cannot load Master Flat. %s",cpl_error_get_message());
1359  return -1;
1360  }
1361 
1362  /* bad pixels map */
1363  ps.bpm = cpl_image_load(cpl_frame_get_filename(ps.bpmfr), CPL_TYPE_INT, 0, ext);
1364  if(ps.bpm == NULL){
1365  cpl_msg_error(cpl_func, "Cannot load BPM. %s", cpl_error_get_message());
1366  return -1;
1367  }
1368 
1369  /* illumination map */
1370  if(ps.illumfr != NULL)
1371  ps.illum = cpl_image_load(cpl_frame_get_filename(ps.illumfr),CPL_TYPE_FLOAT,0,ext);
1372 
1373  return 0;
1374 }
1375 
1376 /* Initialize the pointers */
1377 static void omega_std_init(void) {
1378  ps.stdlist = NULL;
1379  ps.labels = NULL;
1380  ps.bpmfr = NULL;
1381  ps.extfr = NULL;
1382  ps.monitfr = NULL;
1383  ps.stdfr = NULL;
1384  ps.usnoa2 = NULL;
1385  ps.reffr = NULL;
1386  ps.illumfr = NULL;
1387  ps.mbiasfr = NULL;
1388  ps.mflatfr = NULL;
1389  ps.mbias = NULL;
1390  ps.mflat = NULL;
1391  ps.colfr = NULL;
1392  ps.stdfits = NULL;
1393  ps.zptbl = NULL;
1394  ps.photbl = NULL;
1395  ps.sname = NULL;
1396  ps.pname = NULL;
1397  ps.zname = NULL;
1398 }
1399 
1400 /* Free any allocated memory */
1401 static void omega_std_tidy(int level) {
1402  freeimage(ps.mbias);
1403  freeimage(ps.bpm);
1404  freeimage(ps.illum);
1405  freeimage(ps.mflat);
1406  if(level == 1)
1407  return;
1408 
1409  freeframeset(ps.stdlist);
1410  freefits(ps.stdfits);
1411  freetable(ps.extratbl);
1412  freetable(ps.zptbl);
1413  freetable(ps.photbl);
1414  freespace(ps.labels);
1415  freespace(ps.sname);
1416  freespace(ps.pname);
1417  freespace(ps.zname);
1418 }
1419