OMEGA Pipeline Reference Manual  1.0.5
omega_science.c
1 /* $Id: omega_science.c,v 1.39 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.39 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 
33 #include "omega_recipe.h"
34 
35 #include "omega_coadd.h"
36 #include "omega_catalog.h"
37 #include "omega_background.h"
38 #include "omega_cosmic.h"
39 #include "omega_photometry.h"
40 #include "omega_science.h"
41 #include "omega_satellites.h"
42 #include "omega_wcscor.h"
91 /*-----------------------------------------------------------------------------
92  Functions prototypes
93  -----------------------------------------------------------------------------*/
94 
95 static int omega_science_create(cpl_plugin *) ;
96 static int omega_science_exec(cpl_plugin *) ;
97 static int omega_science_destroy(cpl_plugin *) ;
98 static int omega_science(cpl_frameset *,cpl_parameterlist *);
99 
100 /*-----------------------------------------------------------------------------
101  Private Functions
102  -----------------------------------------------------------------------------*/
103 
104 static int omega_science_retrieve_input_param(const cpl_parameterlist *parlist);
105 static int omega_science_load_calib();
106 static void omega_science_init(void);
107 static void omega_science_tidy(int level);
108 static cpl_error_code omega_correct_crpix_union(cpl_propertylist *xlist,
109  cpl_bivector *offsets);
110 
111 
117 static struct {
118  int extnum;
119  int oc;
120  int sub_back;
121  int mode;
122 
123 }omega_science_config;
124 
130 static struct {
131  int nmatches;
132  int nstars;
133  double mratio;
134  float ZP;
135  float ZPerr;
136 // float Extinction;
137 // float Exterr;
138  double Seeing;
139 
140 }omega_sci_qc;
141 
142 /*
143  * Input and Ouput
144  */
145 static struct {
146 
147  /* Calib frames */
148  const cpl_frame *bpmfr;
149  const cpl_frame *fringesfr;
150  const cpl_frame *illumfr;
151  const cpl_frame *mbiasfr;
152  const cpl_frame *mflatfr;
153  const cpl_frame *nskyfr;
154  const cpl_frame *usnoa2;
155  const cpl_frame *photomfr;
156 
157  cpl_size *labels;
158  cpl_frameset *scilist;
159  cpl_propertylist *ph;
160  cpl_propertylist *eh;
161  omega_fits *scifits;
162  cpl_image *mbias;
163  cpl_image *mflat;
164  cpl_image *bpm;
165  cpl_image *illum;
166  cpl_image *fringes;
167  cpl_image *nsky;
168  cpl_table *photom;
169 
170  /* Products */
171  char *proname;
172  char *confname;
173  char *catname;
174  omega_fits *sfits;
175  cpl_image **combined;
176  cpl_table *catalogue;
177  cpl_propertylist *qclist;
178  cpl_propertylist *plist;
179 }ps;
180 
181 
182 /* Static variables */
183 #define RECIPE "omega_science"
184 
185 
186 /*----------------------------------------------------------------------------*/
194 /*----------------------------------------------------------------------------*/
195 int cpl_plugin_get_info(cpl_pluginlist * list)
196 {
197  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
198  cpl_plugin * plugin = &recipe->interface ;
199 
200  cpl_plugin_init(plugin,
201  CPL_PLUGIN_API,
202  OMEGA_BINARY_VERSION,
203  CPL_PLUGIN_TYPE_RECIPE,
204  "omega_science",
205  "OMEGA - This recipe is used to reduce science observations.",
206  "The recipe assumes that the data is for a single CCD. \n"
207  "The following operations are performed: \n\n"
208  " 1. Trim and overscan correct; \n"
209  " 2. Subtract the bias and divide by the flat field; \n"
210  " 3. Correct for fringing, illumination and the background, if requested; \n"
211  " 4. Extract the zero point from the data and calculate the extinction \n"
212  " value and save both in the header and in one table. \n\n"
213  " ------------------------------------------------------------------------ \n\n"
214  " Mandatory inputs : \n\n"
215  " : a raw standard star frame \n"
216  " : a master bias frame (Calfile 541) \n"
217  " : a master flat field (Calfile 546) \n\n"
218  " : a master USNOA2 table \n"
219  " : a standard stars catalog table \n\n"
220  " Optional inputs : \n\n"
221  " : fringe map (Calfile 545) \n"
222  " : bad pixels map (Calfile 522+535) \n"
223  " : illumination correction frame (Calfile 548) \n\n"
224  " The recipe will save the extinction and zero point values in one table.",
225  "Sandra Castro / Armin Gabasch",
226  "scastro@eso.org",
228  omega_science_create,
229  omega_science_exec,
230  omega_science_destroy) ;
231 
232  cpl_pluginlist_append(list, plugin) ;
233 
234  return 0;
235 }
236 
237 /*----------------------------------------------------------------------------*/
246 /*----------------------------------------------------------------------------*/
247 static int omega_science_create(cpl_plugin * plugin)
248 {
249  cpl_recipe * recipe;
250  cpl_parameter * p ;
251  char *path = NULL;
252 
253  /* Do not create the recipe if an error code is already set */
254  if (cpl_error_get_code() != CPL_ERROR_NONE) {
255  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
256  cpl_func, __LINE__, cpl_error_get_where());
257  return (int)cpl_error_get_code();
258  }
259 
260  if (plugin == NULL) {
261  cpl_msg_error(cpl_func, "Null plugin");
262  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
263  }
264 
265  /* Verify plugin type */
266  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
267  cpl_msg_error(cpl_func, "Plugin is not a recipe");
268  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
269  }
270 
271  /* Get the recipe */
272  recipe = (cpl_recipe *)plugin;
273 
274  /* Create the parameters list in the cpl_recipe object */
275  recipe->parameters = cpl_parameterlist_new() ;
276  if (recipe->parameters == NULL) {
277  cpl_msg_error(cpl_func, "Parameter list allocation failed");
278  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
279  }
280 
281  /* Fill the parameters list */
282 
283  /* --------------- General parameters ---------------------------*/
284  p = cpl_parameter_new_value("omega.omega_science.ExtensionNumber",
285  CPL_TYPE_INT,
286  "FITS extension number to load (1 to 32). (-1 == all)",
287  "omega_science",
288  -1) ;
289 
290  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"ext") ;
291  cpl_parameterlist_append(recipe->parameters, p) ;
292 
293  p = cpl_parameter_new_range("omega.omega_science.OverscanMethod",
294  CPL_TYPE_INT,
295  "Overscan Correction Method",
296  "overscan",
297  0, 0, 6);
298  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"oc-meth") ;
299  cpl_parameterlist_append(recipe->parameters, p) ;
300 
301  /* --------------- Saturated pixels parameters ---------------------------*/
302 
303  p = cpl_parameter_new_value("omega.omega_science.LowThreSatuPixel",
304  CPL_TYPE_DOUBLE,
305  "Low threshold for calculating the saturated pixels map.",
306  "omega_science",
307  -500.0) ;
308 
309  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "lt-satu") ;
310  cpl_parameterlist_append(recipe->parameters, p) ;
311 
312  p = cpl_parameter_new_value("omega.omega_science.HighThreSatuPixel",
313  CPL_TYPE_DOUBLE,
314  "High threshold for calculating the saturated pixels map.",
315  "omega_science",
316  60000.0) ;
317 
318  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "ht-satu") ;
319  cpl_parameterlist_append(recipe->parameters, p) ;
320 
321  /* --------------- Satellite detection parameters ---------------------------*/
322  p = cpl_parameter_new_value("omega.omega_science.DetectionThreSatellite",
323  CPL_TYPE_DOUBLE,
324  "Minimum SNR for pixels to contribute to Hough map.",
325  "omega.Hough",
326  4.0) ;
327 
328  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "det-sate") ;
329  cpl_parameterlist_append(recipe->parameters, p) ;
330 
331  p = cpl_parameter_new_value("omega.omega_science.HoughThreshold",
332  CPL_TYPE_DOUBLE,
333  "Threshold for satellite tracks in Hough image.",
334  "omega.Hough",
335  400.0) ;
336 
337  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "hough-thre") ;
338  cpl_parameterlist_append(recipe->parameters, p) ;
339 
340 
341  /* --------------- Fringing parameters ---------------------------*/
342  p = cpl_parameter_new_value("omega.omega_science.SigmaFringeScaling",
343  CPL_TYPE_DOUBLE,
344  "Sigma threshold in image data for scaling estimate (fringes only)",
345  "omega_science",
346  5.0) ;
347 
348  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sigma-fringes") ;
349  cpl_parameterlist_append(recipe->parameters, p) ;
350 
351  p = cpl_parameter_new_value("omega.omega_science.LowThreFringe",
352  CPL_TYPE_DOUBLE,
353  "Lower bound of fringes to include in scaling (fringes only)",
354  "omega_science",
355  1.5) ;
356 
357  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "lfringes") ;
358  cpl_parameterlist_append(recipe->parameters, p) ;
359 
360  p = cpl_parameter_new_value("omega.omega_science.HighThreFringe",
361  CPL_TYPE_DOUBLE,
362  "Higher bound of fringes to include in scaling (fringes only)",
363  "omega_science",
364  5.0) ;
365 
366  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "hfringes") ;
367  cpl_parameterlist_append(recipe->parameters, p) ;
368 
369 
370  /* ----------------- Background parameters ---------------------------*/
371  p = cpl_parameter_new_value("omega.omega_science.SubtractBackground",
372  CPL_TYPE_BOOL,
373  "Boolean value to subtract background or not. 1(TRUE), 0(FALSE)",
374  "omega_science",
375  1) ;
376 
377  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sub-back") ;
378  cpl_parameterlist_append(recipe->parameters, p) ;
379 
380  p = cpl_parameter_new_value("omega.omega_science.BackThreshold",
381  CPL_TYPE_DOUBLE,
382  "Detection threshold for background in image (Sextractor DETECT_THRESH)",
383  "omega_science",
384  1000.) ;
385 
386  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "backthre") ;
387  cpl_parameterlist_append(recipe->parameters, p) ;
388 
389 
390  /* ------------------ PATH to external executable programs --------------*/
391  path = cpl_sprintf("%s", OMEGA_BIN_PATH);
392  p = cpl_parameter_new_value("omega.omega_science.BinPath",
393  CPL_TYPE_STRING,
394  "Path to any external executable program.",
395  "omega.BinPath",
396  path);
397 
398  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "bin-path");
399  cpl_parameterlist_append(recipe->parameters, p);
400  cpl_free(path);
401 
402  /* ------------------ Sextractor parameters ------------------------- */
403  path = cpl_sprintf("%s/omega.sex", OMEGA_CONFIG_PATH);
404  p = cpl_parameter_new_value("omega.omega_science.SexConfig",
405  CPL_TYPE_STRING,
406  "Path to Sextractor config file.",
407  "omega.sextractor",
408  path);
409 
410  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-config");
411  cpl_parameterlist_append(recipe->parameters, p);
412  cpl_free(path);
413 
414 
415  path = cpl_sprintf("%s/omega.conv", OMEGA_CONFIG_PATH);
416  p = cpl_parameter_new_value("omega.omega_science.SexConv",
417  CPL_TYPE_STRING,
418  "Path to Sextractor convolution mask file.",
419  "omega.sextractor",
420  path);
421 
422  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-conv");
423  cpl_parameterlist_append(recipe->parameters, p);
424  cpl_free(path);
425 
426 
427  path = cpl_sprintf("%s/omega.param", OMEGA_CONFIG_PATH);
428  p = cpl_parameter_new_value("omega.omega_science.SexParam",
429  CPL_TYPE_STRING,
430  "Path to Sextractor parameters file.",
431  "omega.sextractor",
432  path);
433 
434  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-param");
435  cpl_parameterlist_append(recipe->parameters, p);
436  cpl_free(path);
437 
438  path = cpl_sprintf("%s/omega.nnw", OMEGA_CONFIG_PATH);
439  p = cpl_parameter_new_value("omega.omega_science.SexNnw",
440  CPL_TYPE_STRING,
441  "Path to Sextractor neural network config file.",
442  "omega.sextractor",
443  path);
444 
445  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-nnw");
446  cpl_parameterlist_append(recipe->parameters, p);
447  cpl_free(path);
448 
449  p = cpl_parameter_new_value("omega.omega_science.SexDetThreshold",
450  CPL_TYPE_DOUBLE,
451  "Detection threshold for Sextractor sources.",
452  "omega.sextractor",
453  1.5);
454 
455  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-dthre");
456  cpl_parameterlist_append(recipe->parameters, p);
457 
458 
459  /* ------- Cosmic rays detection parameters for Sextractor ------------*/
460  path = cpl_sprintf("%s/omega.cosmic.sex", OMEGA_CONFIG_PATH);
461  p = cpl_parameter_new_value("omega.omega_science.SexCosmic",
462  CPL_TYPE_STRING,
463  "Path to Sextractor cosmic detection mode config file.",
464  "omega.Sextractor",
465  path);
466 
467  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-cosmic");
468  cpl_parameterlist_append(recipe->parameters, p);
469  cpl_free(path);
470 
471  path = cpl_sprintf("%s/omega.cosmic.param", OMEGA_CONFIG_PATH);
472  p = cpl_parameter_new_value("omega.omega_science.SexCosmicParam",
473  CPL_TYPE_STRING,
474  "Path to Sextractor cosmic parameters file.",
475  "omega.Sextractor",
476  path);
477 
478  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"sex-cosmic-param");
479  cpl_parameterlist_append(recipe->parameters, p);
480  cpl_free(path);
481 
482  path = cpl_sprintf("%s/cosmic.ret", OMEGA_CONFIG_PATH);
483  p = cpl_parameter_new_value("omega.omega_science.SexCosmicFilt",
484  CPL_TYPE_STRING,
485  "Path to Sextractor filter mask for cosmic detection mode.",
486  "omega.Sextractor",
487  path);
488 
489  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-cosfilt");
490  cpl_parameterlist_append(recipe->parameters, p);
491  cpl_free(path);
492 
493  p = cpl_parameter_new_value("omega.omega_science.SexCosmicDet",
494  CPL_TYPE_DOUBLE,
495  "Detection threshold for detecting cosmic rays in Sextractor",
496  "omega.Sextractor",
497  5.0) ;
498 
499  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-cosmic-det") ;
500  cpl_parameterlist_append(recipe->parameters, p) ;
501 
502 
503  /* ------------------ Astrometric parameters ------------------------- */
504  p = cpl_parameter_new_value("omega.omega_science.AstromDetThre",
505  CPL_TYPE_DOUBLE,
506  "Sextractor threshold to detect stars for astrometric correction.",
507  "omega.Astrom",
508  10.0) ;
509 
510  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "astrom-thre") ;
511  cpl_parameterlist_append(recipe->parameters, p) ;
512 
513  p = cpl_parameter_new_enum("omega.omega_science.PlateSolution",
514  CPL_TYPE_INT,
515  "Number of constant plate fits to do for the astrometry solution.",
516  "omega.Astrom",
517  4,2,4,6);
518 
519  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "platesol");
520  cpl_parameterlist_append(recipe->parameters, p);
521 
522  p = cpl_parameter_new_value("omega.omega_science.NumIterations",
523  CPL_TYPE_INT,
524  "Number of iterations for the plate solution fitting.",
525  "omega.Astrom",
526  3);
527 
528  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "niter");
529  cpl_parameterlist_append(recipe->parameters, p);
530 
531 
532  p = cpl_parameter_new_range("omega.omega_science.SextractorFlagLimit",
533  CPL_TYPE_INT,
534  "Sextractor FLAG upper limit to preselect good sources for the "
535  "astrometric correction computation.", "omega.Astrom",
536  256, 0, 256);
537  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"SextractorFlagLimit") ;
538  cpl_parameterlist_append(recipe->parameters, p) ;
539 
540  p = cpl_parameter_new_range("omega.omega_science.SextractorClassStar",
541  CPL_TYPE_DOUBLE,
542  "Sextractor CLASS_STAR lower limit to preselect starlike objects "
543  "for the astrometric correction computation.", "omega.Astrom",
544  0.0, 0.0, 1.0);
545  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"SextractorClassStar") ;
546  cpl_parameterlist_append(recipe->parameters, p) ;
547 
548 
549 
550  /* ------------------ Photometric parameters ------------------------- */
551  p = cpl_parameter_new_value("omega.omega_science.PhotomDetThre",
552  CPL_TYPE_DOUBLE,
553  "Sextractor threshold to detect stars for photometric correction.",
554  "omega.Photom",
555  10.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_science.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_science.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_science.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_science.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_science.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_science.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_science.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  /* Stacking parameters */
633  p = cpl_parameter_new_value("omega.omega_science.xcorr",
634  CPL_TYPE_STRING,
635  "String of four values meaning: x,y search area and "
636  "x,y measurement area, needed for cross-correlation "
637  "when stacking images",
638  "omega.Stack",
639  "20,20,20,20");
640 
641  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcorr");
642  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
643  cpl_parameterlist_append(recipe->parameters, p);
644 
645  p = cpl_parameter_new_value("omega.omega_science.CombMode",
646  CPL_TYPE_STRING,
647  "Combination mode to use when stacking images. "
648  "union,intersect or first",
649  "omega.Stack",
650  "union");
651 
652  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "comb-mode");
653  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
654  cpl_parameterlist_append(recipe->parameters, p);
655 
656  p = cpl_parameter_new_value("omega.omega_science.StackRej",
657  CPL_TYPE_STRING,
658  "Number of low and high values to reject when stacking",
659  "omega.Stack",
660  "0,0");
661 
662  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "stack-rej");
663  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
664  cpl_parameterlist_append(recipe->parameters, p);
665 
666  /* Catalogue creation */
667  p = cpl_parameter_new_value("omega.omega_science.CatThre",
668  CPL_TYPE_DOUBLE,
669  "Sextractor threshold to detect sources in stack image",
670  "omega.Sextractor",
671  3.0) ;
672 
673  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "cat-thre") ;
674  cpl_parameterlist_append(recipe->parameters, p) ;
675 
676 
677 
678  p = cpl_parameter_new_value("omega.omega_science.mag_zpt_no_std_table",
679  CPL_TYPE_DOUBLE,
680  "Zeropoint used if the standard star zeropoint table is empty ",
681  "omega.Sextractor",
682  0.0) ;
683  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "mag_zpt_no_std_table") ;
684  cpl_parameterlist_append(recipe->parameters, p) ;
685 
686 
687 
688  p = cpl_parameter_new_value("omega.omega_science.mag_zpt_err_no_std_table",
689  CPL_TYPE_DOUBLE,
690  "Zeropoint error used if the standard star zeropoint table is empty ",
691  "omega.Sextractor",
692  1.0) ;
693  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "mag_zpt_err_no_std_table") ;
694  cpl_parameterlist_append(recipe->parameters, p) ;
695 
696 
697 
698  p = cpl_parameter_new_value("omega.omega_science.ext_no_std_table",
699  CPL_TYPE_DOUBLE,
700  "extinction used if the standard star zeropoint table is empty",
701  "omega.Sextractor",
702  1.0) ;
703  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "ext_no_std_table") ;
704  cpl_parameterlist_append(recipe->parameters, p) ;
705 
706 
707  /* Return */
708  return 0;
709 }
710 
711 /*----------------------------------------------------------------------------*/
717 /*----------------------------------------------------------------------------*/
718 static int omega_science_exec(cpl_plugin * plugin)
719 {
720  cpl_recipe * recipe;
721  int recipe_status;
722 
723  /* Return immediately if an error code is already set */
724  if (cpl_error_get_code() != CPL_ERROR_NONE) {
725  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
726  cpl_func, __LINE__, cpl_error_get_where());
727  return (int)cpl_error_get_code();
728  }
729 
730  if (plugin == NULL) {
731  cpl_msg_error(cpl_func, "Null plugin");
732  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
733  }
734 
735  /* Verify plugin type */
736  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
737  cpl_msg_error(cpl_func, "Plugin is not a recipe");
738  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
739  }
740 
741  /* Get the recipe */
742  recipe = (cpl_recipe *)plugin;
743 
744  /* Verify parameter and frame lists */
745  if (recipe->parameters == NULL) {
746  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
747  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
748  }
749  if (recipe->frames == NULL) {
750  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
751  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
752  }
753 
754  /* Invoke the recipe */
755  recipe_status = omega_science(recipe->frames, recipe->parameters);
756 
757  /* Ensure DFS-compliance of the products */
758  if (cpl_dfs_update_product_header(recipe->frames)) {
759  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
760  }
761 
762  return recipe_status;
763 
764 }
765 
766 /*----------------------------------------------------------------------------*/
772 /*----------------------------------------------------------------------------*/
773 static int omega_science_destroy(cpl_plugin * plugin)
774 {
775  cpl_recipe * recipe;
776 
777  if (plugin == NULL) {
778  cpl_msg_error(cpl_func, "Null plugin");
779  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
780  }
781 
782  /* Verify plugin type */
783  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
784  cpl_msg_error(cpl_func, "Plugin is not a recipe");
785  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
786  }
787 
788  /* Get the recipe */
789  recipe = (cpl_recipe *)plugin;
790 
791  cpl_parameterlist_delete(recipe->parameters) ;
792 
793  return 0 ;
794 }
795 
796 /*----------------------------------------------------------------------------*/
806 /*----------------------------------------------------------------------------*/
807 static int omega_science(cpl_frameset *set, cpl_parameterlist *pars)
808 {
809  int j,jst,jfn,i,n_ext;
810  cpl_size nlab;
811  int nraw = 0;
812  int refine = 0;
813  static int isfirst = 0;
814  cpl_size *plabels = NULL;
815  int has_fringes = 0;
816  double pixscalex = 0.0;
817  double pixscaley = 0.0;
818  double Seeing = 0.0;
819  double ellipticity = 0.0;
820  double zeropoint_final=0.0;
821  const char *smoothed = "omega_stacksmooth.fits";
822  const char *smoothed_weight = "omega_stacksmooth_weight.fits";
823  const char *tag = NULL;
824  const char *tag_mask = NULL;
825  const char * maskname= NULL;
826 
827  cpl_image *smooth;
828  cpl_image *image_simple_mask=NULL;
829  cpl_frame *sciframe;
830  cpl_frame *firstframe=NULL;
831  cpl_frame *product_frame=NULL ;
832  cpl_frame *product_frame_mask=NULL ;
833  cpl_frame *conf_frame;
834  cpl_frame *catframe;
835  cpl_frameset *proset=NULL;
836  cpl_frameset *proset_mask=NULL;
837  cpl_bivector *offsets=NULL;
838  cpl_propertylist *plist, *xlist, *alist;
839  cpl_propertylist *plist_dummy=NULL;
840  cpl_propertylist *flist;
841  cpl_propertylist *qclist=NULL;
842  cpl_parameter *par = NULL;
843  const char *sval = NULL;
844 
845 
846  /*Start the recipe */
847 
848  if (pars == NULL) {
849  cpl_msg_error (cpl_func, "Parameters list not found");
850  return -1;
851  }
852 
853  if (cpl_frameset_is_empty(set) == 1) {
854  cpl_msg_error (cpl_func, "Frameset not found");
855  return -1;
856  }
857 
858  /* Retrieve input parameters and initiates specific parameters lists*/
859  if(omega_science_retrieve_input_param(pars) != 0){
860  cpl_msg_error(cpl_func,"Cannot retrieve input parameters. %s", cpl_error_get_message());
861  return -1;
862  }
863 
864  /* Identify the RAW and CALIB frames in the input frameset */
865  if (oc_dfs_set_groups(set)) {
866  cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames") ;
867  return -1 ;
868  }
869 
870  /*Initialized things*/
871  omega_science_init();
872  omega_sci_qc.Seeing = 0.0;
873  omega_sci_qc.mratio = 0.0;
874  omega_sci_qc.nmatches = 0;
875  omega_sci_qc.nstars = 0;
876 
877  /* Verify the frameset contents. */
878  if ((ps.labels = cpl_frameset_labelise(set,omega_compare_tags,
879  &nlab)) == NULL) {
880  cpl_msg_error(cpl_func,"Cannot labelise the input frameset");
881  omega_science_tidy(0);
882  return -1;
883  }
884 
885  omega_science_config.mode = 0;
886 
887  if ((ps.scilist = omega_frameset_subgroup(set,ps.labels,nlab,
888  STARE_RAW)) != NULL) {
889  omega_science_config.mode = 1;
890  refine = 0;
891  tag = STARE_RAW;
892  }
893  else if ((ps.scilist = omega_frameset_subgroup(set,ps.labels,nlab,
894  JITTER_RAW)) != NULL) {
895  omega_science_config.mode = 2;
896  refine = 0;
897  tag = JITTER_RAW;
898  }
899  else if ((ps.scilist = omega_frameset_subgroup(set,ps.labels,nlab,
900  DITHER_RAW)) != NULL) {
901  omega_science_config.mode = 3;
902  refine = 0;
903  tag = DITHER_RAW;
904  }
905  else if ((ps.scilist = omega_frameset_subgroup(set,ps.labels,nlab,
906  OFFSET_RAW)) != NULL) {
907  omega_science_config.mode = 4;
908  refine = 0;
909  tag = OFFSET_RAW;
910  }
911  else {
912  cpl_msg_error(cpl_func,"Cannot find science frames in input frameset");
913  omega_science_tidy(0);
914  return -1;
915  }
916 
917  nraw = cpl_frameset_get_size(ps.scilist);
918  cpl_msg_info(cpl_func,"There are %d %s frames in frame set",nraw,tag);
919 
920  /* Check for mandatory calibration frames */
921  /* Master Bias */
922  ps.mbiasfr = cpl_frameset_find_const(set, OMEGA_CALIB_BIAS);
923  if (ps.mbiasfr == NULL) {
924  cpl_msg_error(cpl_func,"Cannot find %s frame in frame set", OMEGA_CALIB_BIAS);
925  omega_science_tidy(0);
926  }
927  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_BIAS, cpl_frame_get_filename(ps.mbiasfr));
928 
929  /* Master Flat */
930  ps.mflatfr = cpl_frameset_find_const(set, OMEGA_CALIB_FLAT);
931  if(ps.mflatfr == NULL) {
932  cpl_msg_error(cpl_func,"Cannot find %s frame in frame set", OMEGA_CALIB_FLAT);
933  omega_science_tidy(0);
934  return -1;
935  }
936  cpl_msg_info(cpl_func,"Using %s %s", OMEGA_CALIB_FLAT, cpl_frame_get_filename(ps.mflatfr));
937 
938  /* Photometric table */
939  ps.photomfr = cpl_frameset_find (set,OMEGA_CALIB_ZP);
940  if(ps.photomfr == NULL) {
941  cpl_msg_warning(cpl_func,"Cannot find %s in frame set", OMEGA_CALIB_ZP);
942  //omega_science_tidy(0);
943  //return -1;
944  }
945  else{
946  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_ZP,cpl_frame_get_filename(ps.photomfr));
947  }
948  /* USNOA2 master table */
949  ps.usnoa2 = cpl_frameset_find (set, OMEGA_USNOA2);
950  if (ps.usnoa2 == NULL) {
951  cpl_msg_error(cpl_func,"Cannot find %s frame in frame set",OMEGA_USNOA2);
952  omega_science_tidy(0);
953  return -1;
954  }
955  cpl_msg_info(cpl_func,"Using %s %s", OMEGA_USNOA2, cpl_frame_get_filename(ps.usnoa2));
956 
957  /* Bad Pixels Map */
958  ps.bpmfr = cpl_frameset_find (set,OMEGA_CALIB_BPM);
959  if(ps.bpmfr == NULL) {
960  cpl_msg_error(cpl_func,"Cannot find %s in frame set", OMEGA_CALIB_BPM);
961  omega_science_tidy(0);
962  return -1;
963  }
964  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_BPM,cpl_frame_get_filename(ps.bpmfr));
965 
966  /* Optional Calibration frames */
967  /* Illumination frame */
968  ps.illumfr = cpl_frameset_find(set, OMEGA_CALIB_ILLUM);
969  if(ps.illumfr != NULL)
970  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_ILLUM,cpl_frame_get_filename(ps.illumfr));
971 
972  /*Night sky flat */
973 /* ps.nskyfr = cpl_frameset_find(set, OMEGA_CALIB_NSKY);
974  if(ps.nskyfr != NULL)
975  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_NSKY,cpl_frame_get_filename(ps.nskyfr));
976 */
977  /* Fringe flat */
978 /* ps.fringesfr = cpl_frameset_find(set,OMEGA_CALIB_FRINGE);
979  if(ps.fringesfr != NULL)
980  cpl_msg_info(cpl_func,"Using %s %s",OMEGA_CALIB_FRINGE,cpl_frame_get_filename(ps.fringesfr));*/
981 
982 
983  sciframe = cpl_frameset_find(set,tag);
984  /* Check which image extension(s) to load */
985  omega_extensions(sciframe,omega_science_config.extnum,&jst,&jfn);
986  if(omega_science_config.extnum == 0){
987  cpl_msg_error(cpl_func,"Unsupported extension request, %d",omega_science_config.extnum);
988  omega_science_tidy(0);
989  return -1;
990  }
991 
992 
993  /* Loop over all science frames */
994  for(i=0; i < nraw; i++){
995  cpl_msg_info(cpl_func,"Working on %s",cpl_frame_get_filename(sciframe));
996 
997  /* Loop through extensions to reduce simple images */
998  /* CHANGE LATER ************************************ */
999 
1000  for (j = jst; j <= jfn; j++) {
1001  isfirst = (j == jst);
1002 
1003  cpl_msg_indent_more();
1004  cpl_msg_info(cpl_func,".....Working on extension %d.....",j);
1005  cpl_msg_indent_less();
1006 
1007  /* Load calibration frames */
1008  if(omega_science_load_calib(j) != 0){
1009  cpl_msg_error(cpl_func,"Cannot load calibration frame(s)");
1010  omega_science_tidy(0);
1011  return -1;
1012  }
1013 
1014  /* Load omega_fits structure for this extension */
1015  ps.scifits = omega_fits_load(sciframe, CPL_TYPE_FLOAT, j);
1016 
1017  /* Call processing routine. Mark file as dummy if unsuccessful */
1018  ps.sfits = omega_jitter_process(ps.scifits,ps.mbias,ps.mflat,ps.bpm,ps.photom,
1019  ps.usnoa2,ps.illum,ps.fringes,ps.nsky, &zeropoint_final ,pars, j);
1020 
1021  if(ps.sfits == NULL){
1022  cpl_msg_error(cpl_func,"Unable to reduce image");
1023  omega_science_tidy(0);
1024  return -1;
1025  }
1026 
1027  /* Free some space */
1028  omega_science_tidy(1);
1029 
1030  /* Save this extension with updated extension header!!! */
1031  /* NOTE: Should these products have the same PROCATG? */
1032  if(isfirst){
1033  tag = NULL;
1034  if(omega_science_config.mode == 1) {
1035  ps.proname = cpl_sprintf("%s_%s_%d.fits", INSTRUME,SIMPLE_STARE,i);
1036  product_frame = omega_product_frame(ps.proname, SIMPLE_STARE, CPL_FRAME_TYPE_IMAGE);
1037  tag = SIMPLE_STARE;
1038  }
1039  if(omega_science_config.mode == 2){
1040  ps.proname = cpl_sprintf("%s_%s_%d.fits", INSTRUME,SIMPLE_JITTER,i);
1041  product_frame = omega_product_frame(ps.proname, SIMPLE_JITTER, CPL_FRAME_TYPE_IMAGE);
1042  tag = SIMPLE_JITTER;
1043  }
1044  if(omega_science_config.mode == 3){
1045  ps.proname = cpl_sprintf("%s_%s_%d.fits", INSTRUME,SIMPLE_DITHER,i);
1046  product_frame = omega_product_frame(ps.proname, SIMPLE_DITHER, CPL_FRAME_TYPE_IMAGE);
1047  tag = SIMPLE_DITHER;
1048  }
1049  if(omega_science_config.mode == 4){
1050  ps.proname = cpl_sprintf("%s_%s_%d.fits", INSTRUME,SIMPLE_OFFSET,i);
1051  product_frame = omega_product_frame(ps.proname, SIMPLE_OFFSET, CPL_FRAME_TYPE_IMAGE);
1052  tag = SIMPLE_OFFSET;
1053  }
1054  maskname=cpl_sprintf("%s_%s_%d.fits", INSTRUME,SIMPLE_MASK,i);
1055  product_frame_mask = omega_product_frame(maskname, SIMPLE_MASK, CPL_FRAME_TYPE_IMAGE);
1056  tag_mask=SIMPLE_MASK;
1057  }
1058 
1059  cpl_msg_info(cpl_func,"Saving SIMPLE image");
1060  if(omega_save_fits(ps.sfits,set,pars,NULL,CPL_BPP_IEEE_FLOAT,ps.proname,RECIPE,
1061  product_frame,sciframe,isfirst) == -1){
1062  cpl_msg_error(cpl_func,"Cannot save SIMPLE image. %s",cpl_error_get_message());
1063  cpl_free(maskname);
1064  omega_science_tidy(0);
1065  return -1;
1066  }
1067 
1068  /*Extracting the mask file from the image*/
1069  image_simple_mask=cpl_image_new_from_mask(cpl_image_get_bpm(ps.sfits->image));
1070  cpl_image_delete(ps.sfits->image); ps.sfits->image=NULL;
1071  ps.sfits->image=image_simple_mask;
1072 
1073  cpl_msg_info(cpl_func,"Saving SIMPLE MASK file");
1074  if(omega_save_fits(ps.sfits,set,pars,NULL,CPL_BPP_8_UNSIGNED,maskname,RECIPE,
1075  product_frame_mask,sciframe,isfirst) == -1){
1076  cpl_msg_error(cpl_func,"Cannot save SIMPLE image. %s",cpl_error_get_message());
1077  cpl_free(maskname);
1078  omega_science_tidy(0);
1079  return -1;
1080  }
1081 
1082 
1083  freefits(ps.sfits);
1084  }
1085 
1086  sciframe = cpl_frameset_find(set, NULL);
1087 
1088  freespace(ps.proname);
1089  cpl_free(maskname);
1090  product_frame = NULL;
1091  product_frame_mask= NULL;
1092  }
1093 
1094  /* Labelise simple products */
1095  if ((plabels = cpl_frameset_labelise(set,omega_compare_tags,
1096  &nlab)) == NULL) {
1097  cpl_msg_error(cpl_func,"Cannot labelise the output frameset");
1098  omega_science_tidy(0);
1099  return -1;
1100  }
1101 
1102  /* Extract simple products into a new frameset */
1103  if ((proset = omega_frameset_subgroup(set,plabels,nlab,
1104  tag)) == NULL) {
1105  cpl_msg_error(cpl_func,"Cannot create simple frameset");
1106  freespace(plabels);
1107  omega_science_tidy(0);
1108  return -1;
1109  }
1110 
1111  /* Extract simple mask products into a new frameset */
1112  if ((proset_mask = omega_frameset_subgroup(set,plabels,nlab,
1113  tag_mask)) == NULL) {
1114  cpl_msg_error(cpl_func,"Cannot create simple mask frameset");
1115  freespace(plabels);
1116  omega_science_tidy(0);
1117  return -1;
1118  }
1119 
1120 
1121  freespace(plabels);
1122 
1123  /* Get telescope offsets (in pixels) from headers */
1124 
1125 
1126 /*
1127  if((offsets = omega_tel_offsets(proset, omega_science_config.mode)) == NULL){
1128  cpl_msg_error(cpl_func,"Unable to get telescope offsets for mode=%d",omega_science_config.mode);
1129  freeframeset(proset);
1130  omega_science_tidy(0);
1131  return -1;
1132  }
1133 */
1134 
1135 /*
1136  offsets=omega_get_offsets_from_wcs(proset, cpl_frameset_get_first(proset),
1137  omega_science_config.extnum);
1138 */
1139 
1140 // cpl_bivector_dump(offsets,stdout);
1141 
1142  /* Loop over extensions again to create stack */
1143  /* Check if only one extension was requested */
1144  firstframe = cpl_frameset_get_first(proset);
1145  n_ext = cpl_fits_count_extensions(cpl_frame_get_filename(firstframe));
1146 
1147  /* Get filter information */
1148  plist = cpl_propertylist_load_regexp(cpl_frame_get_filename(firstframe),0,"ESO INS FILT",0);
1149  flist = omega_pfits_get_filter_info(plist);
1150  has_fringes = cpl_propertylist_get_int(flist, "HAS_FRINGES");
1151  freeplist(plist);
1152  freeplist(flist);
1153 
1154 
1155  cpl_msg_info(cpl_func,"Creating stack image and catalogue");
1156  for(j = 1; j <= n_ext; j++){
1157  isfirst = (j == 1);
1158 
1159  offsets=omega_get_offsets_from_wcs(proset, firstframe, j);
1160 
1161 
1162  cpl_msg_indent_more();
1163  cpl_msg_info(cpl_func,"....... Image in position %d .......",j);
1164  cpl_msg_indent_less();
1165 
1166  plist = cpl_propertylist_load(cpl_frame_get_filename(firstframe),j);
1167  omega_get_pixelscale(plist, &pixscalex, &pixscaley);
1168  freeplist(plist);
1169 
1170  /*This is a workaround as the current cpl version 5.1 has a bug:
1171  * Even if there is only one image in the sof (i.e. the relative shift
1172  * is zero), cpl_geom_img_offset_combine() interpolates the bad pixels
1173  * dilating one bad pixel to 16 bad pixels */
1174  if(cpl_frameset_get_size(proset)==1){
1175  ps.combined = cpl_malloc(2*sizeof(cpl_image *));
1176  ps.combined[0]=cpl_image_load(cpl_frame_get_filename(cpl_frameset_get_first(proset)),CPL_TYPE_FLOAT,0,j);
1177  ps.combined[1]=cpl_image_load(cpl_frame_get_filename(cpl_frameset_get_first(proset_mask)),CPL_TYPE_INT,0,j);
1178  cpl_image_threshold(ps.combined[1],0.5,0.6,1,0);
1179  }
1180  else{
1181  /* Create stack and confidence map */
1182  ps.combined = omega_jitter_stack(proset, proset_mask, offsets, refine, pars, j);
1183  }
1184 
1185  if(ps.combined == NULL){
1186  cpl_msg_error(cpl_func,"Unable to create stack image. %s", cpl_error_get_message());
1187  freebivector(offsets);
1188  freeframeset(proset);
1189  freeframeset(proset_mask);
1190  omega_science_tidy(0);
1191  return -1;
1192  }
1193 
1194  /* Create night sky flat and correct stack frame */
1195  if(cpl_frameset_get_size(proset) >= 3){
1196  cpl_imagelist *ilist = cpl_imagelist_load_frameset(proset, CPL_TYPE_FLOAT,1,j);
1197  if((ps.nsky = omega_nsky_create(ilist, NULL,
1198  cpl_frameset_get_size(proset))) != NULL){
1199  cpl_image_divide(ps.combined[0],ps.nsky);
1200  }
1201 
1202  /* Correct for fringes if filter requires it */
1203  if(has_fringes == 1){
1204  cpl_msg_info(cpl_func,"Applying fringing correction");
1205  ps.bpm = cpl_image_load(cpl_frame_get_filename(ps.bpmfr),CPL_TYPE_FLOAT,0,j);
1206  ps.fringes = cpl_image_subtract_scalar_create(ps.nsky, 1.0);
1207  if(ps.fringes != NULL)
1208  omega_fringecor(ps.combined[0],ps.fringes,ps.bpm,pars);
1209 
1210  freeimage(ps.fringes);
1211  freeimage(ps.bpm);
1212  }
1213  freeilist(ilist);
1214  freeimage(ps.nsky);
1215  }
1216 
1217  /* Refine WCS for stack ?? */
1218  smooth = omega_smooth_image(ps.combined[0], 1);
1219 
1220  if(cpl_detector_interpolate_rejected(smooth) != CPL_ERROR_NONE)
1221  cpl_msg_debug(cpl_func,"Cannot clean rejected pixels. %s",
1222  cpl_error_get_message());
1223 
1224  xlist = cpl_propertylist_load(cpl_frame_get_filename(firstframe),j);
1225 
1226  /* Get filter information */
1227  plist_dummy = cpl_propertylist_load_regexp(
1228  cpl_frame_get_filename(firstframe),0,"ESO INS FILT",0);
1229  cpl_propertylist_copy_property_regexp(xlist,plist_dummy,"ESO INS FILT",0);
1230  freeplist(plist_dummy);
1231 
1232 
1233 
1234 
1235  /*Adjust CRPIX according to the CombMode used*/
1236  par = cpl_parameterlist_find(pars, "omega.omega_science.CombMode");
1237  sval = cpl_parameter_get_string(par);
1238  if (!strcmp(sval, "union")){
1239  omega_correct_crpix_union(xlist, offsets);
1240  }
1241 
1242  alist = cpl_propertylist_new();
1243  cpl_propertylist_append_string(alist, "EXTNAME",
1244  cpl_propertylist_get_string(xlist, "EXTNAME"));
1245  cpl_propertylist_set_comment(alist,"EXTNAME", "Extension name");
1246 
1247 
1248  cpl_propertylist_save(xlist,smoothed,CPL_IO_CREATE);
1249  cpl_image_save(smooth,smoothed,BITPIX,xlist,CPL_IO_EXTEND);
1250 
1251  cpl_propertylist_save(xlist,smoothed_weight,CPL_IO_CREATE);
1252  cpl_image_save(ps.combined[1],smoothed_weight,BITPIX,xlist,CPL_IO_EXTEND);
1253 
1254 
1255  cpl_msg_info(cpl_func,"Refining WCS for stack image");
1256  ps.plist = omega_match_points(smoothed, smoothed_weight, ps.usnoa2, pars, j,
1257  &omega_sci_qc.nmatches, &omega_sci_qc.mratio);
1258  if(ps.plist == NULL){
1259  cpl_msg_warning(cpl_func,"Unable to refine WCS for stack image");
1260  ps.plist = cpl_propertylist_duplicate(xlist);
1261  }
1262 
1263  freeimage(smooth);
1264  freeplist(xlist);
1265 
1266  ps.qclist = cpl_propertylist_new();
1267  cpl_propertylist_update_int(ps.qclist, "ESO QC SCI MATCHES", omega_sci_qc.nmatches);
1268  cpl_propertylist_set_comment(ps.qclist, "ESO QC SCI MATCHES",
1269  "number matches between USNOA2 cat and stars");
1270  cpl_propertylist_update_double(ps.qclist, "ESO QC SCI RATIO MATCHES", omega_sci_qc.mratio);
1271  cpl_propertylist_set_comment(ps.qclist, "ESO QC SCI RATIO MATCHES",
1272  "ratio USNOA2 matches/detected stars");
1273 
1274  /* Save stack and confidence map */
1275  if(isfirst){
1276  ps.proname = cpl_sprintf("%s_%s.fits", INSTRUME,STACK_PROCATG);
1277  ps.confname = cpl_sprintf("%s_%s.fits", INSTRUME,CONF_PROCATG);
1278  product_frame = omega_product_frame(ps.proname, STACK_PROCATG, CPL_FRAME_TYPE_IMAGE);
1279  conf_frame = omega_product_frame(ps.confname,CONF_PROCATG, CPL_FRAME_TYPE_IMAGE);
1280  }
1281 
1282  cpl_msg_info(cpl_func,"Saving stack and confidence map");
1283 
1284  if(!cpl_propertylist_has(ps.plist,"EXTNAME")){
1285  cpl_propertylist_copy_property(ps.plist,alist,"EXTNAME");
1286  }
1287  if(omega_save_image(ps.combined[0],set,pars,ps.plist,ps.qclist,CPL_BPP_IEEE_FLOAT,
1288  ps.proname,RECIPE,product_frame,NULL,isfirst) == -1){
1289  cpl_msg_error(cpl_func,"Cannot save product. %s", cpl_error_get_message());
1290  freebivector(offsets);
1291  freeframeset(proset);
1292  freeframeset(proset_mask);
1293  freeplist(alist);
1294  omega_science_tidy(0);
1295  return -1;
1296  }
1297 
1298  if(omega_save_image(ps.combined[1],set,pars,alist,NULL,CPL_BPP_16_SIGNED,
1299  ps.confname,RECIPE,conf_frame,NULL,isfirst) == -1){
1300  cpl_msg_error(cpl_func,"Cannot save product. %s", cpl_error_get_message());
1301  freebivector(offsets);
1302  freeframeset(proset);
1303  freeframeset(proset_mask);
1304  freeplist(alist);
1305  omega_science_tidy(0);
1306  return -1;
1307  }
1308 
1309  freeplist(ps.qclist);
1310  freeplist(ps.plist);
1311  if(ps.combined!=NULL) {
1312  freeimage(ps.combined[0]);
1313  freeimage(ps.combined[1]);
1314  freespace(ps.combined);
1315  }
1316 
1317  /* Create catalogue from stack */
1318  ps.catalogue = omega_science_catalogue(ps.proname, ps.confname, zeropoint_final, pars);
1319  if(ps.catalogue == NULL){
1320  cpl_msg_error(cpl_func,"Unable to create catalogue of stack. %s", cpl_error_get_message());
1321  freeplist(alist);
1322  freebivector(offsets);
1323  freeframeset(proset);
1324  freeframeset(proset_mask);
1325  omega_science_tidy(0);
1326  return -1;
1327  }
1328 
1329  if(omega_basic_param(ps.catalogue, pixscalex, &Seeing, &ellipticity) == -1){
1330  cpl_msg_warning(cpl_func,"Cannot find stars with CLASS_STAR near 1 to calculate seeing");
1331  }
1332 
1333 
1334  qclist = cpl_propertylist_new();
1335  cpl_propertylist_update_double(qclist, "ESO QC SCI SEEING", Seeing);
1336  cpl_propertylist_set_comment(qclist, "ESO QC SCI SEEING", "calculated seeing of science field");
1337  cpl_propertylist_update_double(qclist, "ESO QC SCI ELLIPTICITY", ellipticity);
1338  cpl_propertylist_set_comment(qclist, "ESO QC SCI ELLIPTICITY", "calculated ellipticity of science field");
1339 
1340 
1341  /* Save catalogue */
1342  if(isfirst){
1343  ps.catname = cpl_sprintf("%s_%s.fits", INSTRUME,CAT_PROCATG);
1344  catframe = omega_product_frame(ps.catname, CAT_PROCATG, CPL_FRAME_TYPE_TABLE);
1345  }
1346  cpl_msg_info(cpl_func,"Saving catalogue");
1347  if(omega_save_table(ps.catalogue,set,pars,alist,qclist,ps.catname,RECIPE,
1348  catframe,NULL,isfirst) == -1){
1349  freebivector(offsets);
1350  freeframeset(proset);
1351  freeframeset(proset_mask);
1352  freeplist(alist);
1353  freeplist(qclist);
1354  omega_science_tidy(0);
1355  return -1;
1356  }
1357 
1358  freetable(ps.catalogue);
1359  freebivector(offsets);
1360  freeplist(alist);
1361  freeplist(qclist);
1362  } /* next extension */
1363 
1364  cpl_msg_info(cpl_func,"Cleaning up");
1365  //freebivector(offsets);
1366  freeframeset(proset);
1367  freeframeset(proset_mask);
1368  freeplist(alist);
1369  freeplist(qclist);
1370  omega_science_tidy(0);
1371 
1372  return 0;
1373 
1374 }
1375 
1376 
1377 
1378 static int omega_science_retrieve_input_param(const cpl_parameterlist * parlist)
1379 {
1380 
1381  const cpl_parameter *par = NULL;
1382  cpl_errorstate prestate = cpl_errorstate_get();
1383 
1384  /* Load common parameters */
1385  par = cpl_parameterlist_find_const(parlist, "omega.omega_science.ExtensionNumber") ;
1386  omega_science_config.extnum = cpl_parameter_get_int(par) ;
1387  par = cpl_parameterlist_find_const(parlist, "omega.omega_science.OverscanMethod") ;
1388  omega_science_config.oc = cpl_parameter_get_int(par) ;
1389 
1390  if(!cpl_errorstate_is_equal(prestate)){
1391  cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
1392  return -1;
1393  }
1394 
1395  return 0;
1396 }
1397 
1398 static int omega_science_load_calib(int ext)
1399 {
1400 
1401  /* Load mandatory calibration frames */
1402  /* master bias */
1403  ps.mbias = cpl_image_load(cpl_frame_get_filename(ps.mbiasfr), CPL_TYPE_FLOAT, 0, ext);
1404  if(ps.mbias == NULL){
1405  cpl_msg_error(cpl_func,"Cannot load Master Bias. %s", cpl_error_get_message());
1406  return -1;
1407  }
1408  /* master flat */
1409  ps.mflat = cpl_image_load(cpl_frame_get_filename(ps.mflatfr),CPL_TYPE_FLOAT,0,ext);
1410  if (ps.mflat == NULL){
1411  cpl_msg_error(cpl_func,"Cannot load Master Flat. %s",cpl_error_get_message());
1412  return -1;
1413  }
1414 
1415  /* bad pixels map */
1416  ps.bpm = cpl_image_load(cpl_frame_get_filename(ps.bpmfr), CPL_TYPE_INT, 0, ext);
1417  if(ps.bpm == NULL){
1418  cpl_msg_error(cpl_func, "Cannot load BPM. %s", cpl_error_get_message());
1419  return -1;
1420  }
1421 
1422  /* Photometric table */
1423  ps.photom = cpl_table_load(cpl_frame_get_filename(ps.photomfr),ext,0);
1424  if(ps.photom == NULL){
1425  cpl_msg_warning(cpl_func,"Cannot load the zeropoint table. %s",cpl_error_get_message());
1426  cpl_msg_warning(cpl_func,"Using values defined in the recipe parameter");
1427  }
1428 
1429  /* Load optional calibration frames */
1430  /* night sky flat */
1431 /* if(ps.nskyfr != NULL)
1432  ps.nsky = cpl_image_load(cpl_frame_get_filename(ps.nskyfr), CPL_TYPE_FLOAT,0,ext);
1433 */
1434  /* illumination map */
1435  if(ps.illumfr != NULL)
1436  ps.illum = cpl_image_load(cpl_frame_get_filename(ps.illumfr),CPL_TYPE_FLOAT,0,ext);
1437 
1438  /* fringes map */
1439 /* if(ps.fringesfr != NULL)
1440  ps.fringes = cpl_image_load(cpl_frame_get_filename(ps.fringesfr), CPL_TYPE_FLOAT,0, ext);*/
1441 
1442  return 0;
1443 }
1444 
1445 static cpl_error_code omega_correct_crpix_union(cpl_propertylist *xlist,
1446  cpl_bivector *offsets){
1447 
1448  cpl_vector * offset_x=NULL;
1449  cpl_vector * offset_y=NULL;
1450  double crpix1=0.;
1451  double crpix2=0.;
1452 
1453  offset_x=cpl_bivector_get_x(offsets);
1454  offset_y=cpl_bivector_get_y(offsets);
1455 
1456 
1457  if (cpl_vector_get_max(offset_x)-cpl_vector_get_min(offset_x) > 3000 ||
1458  cpl_vector_get_max(offset_y)-cpl_vector_get_min(offset_y) > 6000){
1459  /* FIXME: The combination method <union> is overruled in omega_jitter_stack
1460  * and therefore the wcs adjustment is not needed - dirty solution! */
1461  return cpl_error_get_code();
1462  }
1463 
1464 
1465  if(cpl_propertylist_has(xlist, "CRPIX1") &&
1466  cpl_propertylist_has(xlist, "CRPIX2")){
1467  crpix1=cpl_propertylist_get_double(xlist, "CRPIX1");
1468  crpix2=cpl_propertylist_get_double(xlist, "CRPIX2");
1469 
1470  cpl_propertylist_update_double(xlist,"CRPIX1",
1471  crpix1-cpl_vector_get_min(offset_x));
1472 
1473  cpl_propertylist_update_double(xlist,"CRPIX2",
1474  crpix2-cpl_vector_get_min(offset_y));
1475 
1476  }
1477 
1478  return cpl_error_get_code();
1479 
1480 
1481 }
1482 
1483 /* Initialize the pointers */
1484 static void omega_science_init(void) {
1485  ps.bpmfr = NULL;
1486  ps.fringesfr = NULL;
1487  ps.usnoa2 = NULL;
1488  ps.nskyfr = NULL;
1489  ps.illumfr = NULL;
1490  ps.mbiasfr = NULL;
1491  ps.mflatfr = NULL;
1492  ps.photomfr = NULL;
1493  ps.ph = NULL;
1494  ps.eh = NULL;
1495  ps.scifits = NULL;
1496  ps.sfits = NULL;
1497  ps.combined = NULL;
1498  ps.catalogue = NULL;
1499  ps.scilist = NULL;
1500  ps.labels = NULL;
1501  ps.mbias = NULL;
1502  ps.mflat = NULL;
1503  ps.bpm = NULL;
1504  ps.photom = NULL;
1505  ps.proname = NULL;
1506  ps.confname = NULL;
1507  ps.catname = NULL;
1508  ps.nsky = NULL;
1509  ps.illum = NULL;
1510  ps.fringes = NULL;
1511  ps.qclist = NULL;
1512  ps.plist = NULL;
1513 }
1514 
1515 /*
1516  * Free any allocated memory
1517  */
1518 static void omega_science_tidy(int level) {
1519  freeimage(ps.mbias);
1520  freeimage(ps.mflat);
1521  freeimage(ps.bpm);
1522  freeimage(ps.illum);
1523  freetable(ps.photom);
1524  freefits(ps.scifits);
1525  freeframeset(ps.scilist);
1526  if(level == 1)
1527  return;
1528 
1529  freeimage(ps.fringes);
1530  freeimage(ps.nsky);
1531  freefits(ps.sfits);
1532  if(ps.combined!=NULL) {
1533  freeimage(ps.combined[0]);
1534  freeimage(ps.combined[1]);
1535  freespace(ps.combined);
1536  }
1537  freetable(ps.catalogue);
1538  freeimage(ps.mflat);
1539  freespace(ps.labels);
1540  freespace(ps.proname);
1541  freespace(ps.confname);
1542  freespace(ps.catname);
1543  freeplist(ps.qclist);
1544  freeplist(ps.plist);
1545 }
1546