OMEGA Pipeline Reference Manual  1.0.5
omega_darkcurrent.c
1 /* $Id: omega_darkcurrent.c,v 1.5 2012-08-30 07:46:52 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-30 07:46:52 $
24  * $Revision: 1.5 $
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 
36 #include "omega_recipe.h"
37 
38 /*----------------------------------------------------------------------------*/
59 /*----------------------------------------------------------------------------*/
62 /*-----------------------------------------------------------------------------
63  Functions prototypes
64  -----------------------------------------------------------------------------*/
65 
66 static int omega_darkcurrent_create(cpl_plugin *) ;
67 static int omega_darkcurrent_exec(cpl_plugin *) ;
68 static int omega_darkcurrent_destroy(cpl_plugin *) ;
69 static int omega_darkcurrent(cpl_frameset *set,cpl_parameterlist *pars) ;
70 
71 /*-----------------------------------------------------------------------------
72  Private Functions
73  -----------------------------------------------------------------------------*/
74 int omega_darkcurrent_combine(cpl_parameterlist *pars, int xn);
75 int omega_darkcurrent_save(cpl_image *image, cpl_frameset *set, cpl_parameterlist *parlist,
76  cpl_propertylist *qclist, cpl_type_bpp bitpix,
77  const char *outfile, cpl_frame *product_frame);
78 static void omega_darkcurrent_init(void);
79 static void omega_darkcurrent_tidy(void);
80 
81 /*-----------------------------------------------------------------------------
82  Static structures
83  -----------------------------------------------------------------------------*/
84 
85 static struct {
86  /* Inputs. Parameters */
87 /* double rej_sig;*/
88  int extnum;
89  int oc;
90  int paf;
91 
92  /* Outputs. QC parameters */
93  double dark_current;
94  double rate;
95 
96 }omega_darkcurrent_config;
97 
98 /* Input and Output */
99 static struct {
100  cpl_size *labels;
101  const cpl_frame *mbframe;
102  cpl_frameset *darklist;
103  omega_fits *firstdark;
104  cpl_propertylist *eh;
105 
106  /* Products */
107  cpl_image *mdark;
108 
109 } ps;
110 
111 
112 /* Static variables */
113 #define RECIPE "omega_darkcurrent"
114 
115 static int isfirst;
116 static int dummy;
117 
118 
119 /*----------------------------------------------------------------------------*/
127 /*----------------------------------------------------------------------------*/
128 int cpl_plugin_get_info(cpl_pluginlist * list)
129 {
130  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
131  cpl_plugin * plugin = &recipe->interface ;
132 
133  cpl_plugin_init(plugin,
134  CPL_PLUGIN_API,
135  OMEGA_BINARY_VERSION,
136  CPL_PLUGIN_TYPE_RECIPE,
137  "omega_darkcurrent",
138  "OMEGA - Measure the dark current and the particle event rate.(Calfile 531).",
139  "The raw dark frames are trimmed, overscan-corrected and"
140  "debiased. The dark current is calculated by median averaging"
141  "three reduced dark frames and iteratively rejecting outliers"
142  "from the result, and computing the mean of the remaining pixels.",
143  "Sandra Castro",
144  "scastro@eso.org",
146  omega_darkcurrent_create,
147  omega_darkcurrent_exec,
148  omega_darkcurrent_destroy) ;
149 
150  cpl_pluginlist_append(list, plugin) ;
151 
152  return 0;
153 }
154 
155 
156 /*----------------------------------------------------------------------------*/
165 /*----------------------------------------------------------------------------*/
166 static int omega_darkcurrent_create(cpl_plugin * plugin)
167 {
168  cpl_recipe * recipe;
169  cpl_parameter * p ;
170  char *path = NULL;
171 
172  /* Do not create the recipe if an error code is already set */
173  if (cpl_error_get_code() != CPL_ERROR_NONE) {
174  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
175  cpl_func, __LINE__, cpl_error_get_where());
176  return (int)cpl_error_get_code();
177  }
178 
179  if (plugin == NULL) {
180  cpl_msg_error(cpl_func, "Null plugin");
181  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
182  }
183 
184  /* Verify plugin type */
185  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
186  cpl_msg_error(cpl_func, "Plugin is not a recipe");
187  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
188  }
189 
190  /* Get the recipe */
191  recipe = (cpl_recipe *)plugin;
192 
193  /* Create the parameters list in the cpl_recipe object */
194  recipe->parameters = cpl_parameterlist_new() ;
195  if (recipe->parameters == NULL) {
196  cpl_msg_error(cpl_func, "Parameter list allocation failed");
197  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
198  }
199 
200  /* Fill the parameters list */
201  p = cpl_parameter_new_value("omega.omega_darkcurrent.ExtensionNumber",
202  CPL_TYPE_INT,
203  "FITS extension number to load (1 to 32). (-1 = all)",
204  "omega_darkcurrent",
205  -1) ;
206 
207  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"ext") ;
208  cpl_parameterlist_append(recipe->parameters, p) ;
209 
210 
211  p = cpl_parameter_new_range("omega.omega_darkcurrent.OverscanMethod",
212  CPL_TYPE_INT,
213  "Overscan Correction Method",
214  "omega_darkcurrent",
215  6, 0, 6);
216  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"oc-meth") ;
217  cpl_parameterlist_append(recipe->parameters, p) ;
218 
219  p = cpl_parameter_new_value("omega.omega_darkcurrent.PAF",
220  CPL_TYPE_BOOL,
221  "Boolean value to create PAF files. 1(Yes), 0(No)",
222  "omega_darkcurrent",
223  1) ;
224 
225  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "paf") ;
226  cpl_parameterlist_append(recipe->parameters, p) ;
227 
228  p = cpl_parameter_new_value("omega.omega_darkcurrent.RejThre",
229  CPL_TYPE_DOUBLE,
230  "The threshold rejecting outlying pixels",
231  "omega_darkcurrent",
232  5.0) ;
233 
234  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"rej-thre") ;
235  cpl_parameterlist_append(recipe->parameters, p) ;
236 
237  p = cpl_parameter_new_value("omega.omega_darkcurrent.DetThre",
238  CPL_TYPE_DOUBLE,
239  "The detection threshold for cosmic ray event ",
240  "omega_darkcurrent",
241  6.0) ;
242 
243  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"det-thre") ;
244  cpl_parameterlist_append(recipe->parameters, p) ;
245 
246 
247  p = cpl_parameter_new_value("omega.omega_darkcurrent.MaxIter",
248  CPL_TYPE_INT,
249  "The maximum number of iterations",
250  "omega_darkcurrent",
251  3) ;
252 
253  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"niter") ;
254  cpl_parameterlist_append(recipe->parameters, p) ;
255 
256  p = cpl_parameter_new_value("omega.omega_darkcurrent.MaxCurrent",
257  CPL_TYPE_DOUBLE,
258  "The maximum dark current in ADU/pixel/hour",
259  "omega_darkcurrent",
260  5.0) ;
261 
262  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "maxcur") ;
263  cpl_parameterlist_append(recipe->parameters, p) ;
264 
265 
266  p = cpl_parameter_new_value("omega.omega_darkcurrent.MaxDiffCurrent",
267  CPL_TYPE_DOUBLE,
268  "The maximum difference of dark current between previous ??",
269  "omega_darkcurrent",
270  0.2) ;
271 
272  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "maxdifcur") ;
273  cpl_parameterlist_append(recipe->parameters, p) ;
274 
275 /* ------------------ Sextractor parameters ------------------------- */
276  path = cpl_sprintf("%s", OMEGA_BIN_PATH);
277  p = cpl_parameter_new_value("omega.omega_darkcurrent.BinPath",
278  CPL_TYPE_STRING,
279  "Path to any external executable program.",
280  "omega.BinPath",
281  path);
282 
283  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "bin-path");
284  cpl_parameterlist_append(recipe->parameters, p);
285  cpl_free(path);
286 
287  path = cpl_sprintf("%s/omega.cosmic.sex", OMEGA_CONFIG_PATH);
288  p = cpl_parameter_new_value("omega.omega_darkcurrent.SexCosmic",
289  CPL_TYPE_STRING,
290  "Path to Sextractor cosmic detection mode config file.",
291  "omega.Sextractor",
292  path);
293 
294  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-cosmic");
295  cpl_parameterlist_append(recipe->parameters, p);
296  cpl_free(path);
297 
298  path = cpl_sprintf("%s/omega.conv", OMEGA_CONFIG_PATH);
299  p = cpl_parameter_new_value("omega.omega_darkcurrent.SexConv",
300  CPL_TYPE_STRING,
301  "Path to Sextractor convolution mask file.",
302  "omega.Sextractor",
303  path);
304 
305  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-conv");
306  cpl_parameterlist_append(recipe->parameters, p);
307  cpl_free(path);
308 
309  path = cpl_sprintf("%s/omega.param", OMEGA_CONFIG_PATH);
310  p = cpl_parameter_new_value("omega.omega_darkcurrent.SexParam",
311  CPL_TYPE_STRING,
312  "Path to Sextractor parameters file.",
313  "omega.Sextractor",
314  path);
315 
316  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"sex-param");
317  cpl_parameterlist_append(recipe->parameters, p);
318  cpl_free(path);
319 
320  path = cpl_sprintf("%s/omega.nnw", OMEGA_CONFIG_PATH);
321  p = cpl_parameter_new_value("omega.omega_darkcurrent.SexNnw",
322  CPL_TYPE_STRING,
323  "Path to Sextractor neural network config file.",
324  "omega.Sextractor",
325  path);
326 
327  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sex-nnw");
328  cpl_parameterlist_append(recipe->parameters, p);
329  cpl_free(path);
330 
331 
332  /* Return */
333  return 0;
334 }
335 
336 /*----------------------------------------------------------------------------*/
342 /*----------------------------------------------------------------------------*/
343 static int omega_darkcurrent_exec(cpl_plugin * plugin)
344 {
345 
346  cpl_recipe * recipe;
347  int recipe_status;
348 
349  /* Return immediately if an error code is already set */
350  if (cpl_error_get_code() != CPL_ERROR_NONE) {
351  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
352  cpl_func, __LINE__, cpl_error_get_where());
353  return (int)cpl_error_get_code();
354  }
355 
356  if (plugin == NULL) {
357  cpl_msg_error(cpl_func, "Null plugin");
358  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
359  }
360 
361  /* Verify plugin type */
362  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
363  cpl_msg_error(cpl_func, "Plugin is not a recipe");
364  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
365  }
366 
367  /* Get the recipe */
368  recipe = (cpl_recipe *)plugin;
369 
370  /* Verify parameter and frame lists */
371  if (recipe->parameters == NULL) {
372  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
373  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
374  }
375  if (recipe->frames == NULL) {
376  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
377  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
378  }
379 
380  /* Invoke the recipe */
381  recipe_status = omega_darkcurrent(recipe->frames, recipe->parameters);
382 
383  /* Ensure DFS-compliance of the products */
384  if (cpl_dfs_update_product_header(recipe->frames)) {
385  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
386  }
387 
388 
389  return recipe_status;
390 }
391 
392 /*----------------------------------------------------------------------------*/
398 /*----------------------------------------------------------------------------*/
399 static int omega_darkcurrent_destroy(cpl_plugin * plugin)
400 {
401  cpl_recipe * recipe;
402 
403  if (plugin == NULL) {
404  cpl_msg_error(cpl_func, "Null plugin");
405  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
406  }
407 
408  /* Verify plugin type */
409  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
410  cpl_msg_error(cpl_func, "Plugin is not a recipe");
411  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
412  }
413 
414  /* Get the recipe */
415  recipe = (cpl_recipe *)plugin;
416 
417  cpl_parameterlist_delete(recipe->parameters);
418 
419  return 0 ;
420 }
421 
422 
423 /*----------------------------------------------------------------------------*/
430 /*----------------------------------------------------------------------------*/
431 static int omega_darkcurrent(cpl_frameset *set, cpl_parameterlist *pars)
432 {
433 
434  int j,jst,jfn;
435  cpl_size nlab;
436  int ndark = 0;
437  int oscan1 = 0;
438  int status = 0;
439  float bias = BIAS;
440  char *outmdark = NULL;
441  const char *_id = "omega_darkcurrent";
442 
443  cpl_parameter *par = NULL;
444  cpl_frame *firstframe = NULL;
445  cpl_frame *prframe_mdark = NULL;
446  cpl_propertylist *qclist = NULL;
447  cpl_propertylist *alist = NULL;
448 
449 
450 
451  /*Start the recipe */
452 
453  if (pars == NULL) {
454  cpl_msg_error (_id, "Parameters list not found");
455  return -1;
456  }
457 
458  if (cpl_frameset_is_empty(set) == 1) {
459  cpl_msg_error (_id, "Frameset not found");
460  return -1;
461  }
462 
463 /* Retrieve input parameters */
464  par = cpl_parameterlist_find(pars, "omega.omega_darkcurrent.ExtensionNumber") ;
465  omega_darkcurrent_config.extnum = cpl_parameter_get_int(par) ;
466 
467  par = cpl_parameterlist_find(pars, "omega.omega_darkcurrent.OverscanMethod") ;
468  omega_darkcurrent_config.oc = cpl_parameter_get_int(par) ;
469 
470  par = cpl_parameterlist_find(pars, "omega.omega_darkcurrent.PAF");
471  omega_darkcurrent_config.paf = cpl_parameter_get_bool(par);
472 
473 
474 
475 /* Identify the RAW and CALIB frames in the input frameset */
476  if (oc_dfs_set_groups(set)) {
477  cpl_msg_error(_id, "Cannot identify RAW and CALIB frames") ;
478  return -1 ;
479  }
480 
481  /*Initialized things*/
482  omega_darkcurrent_init();
483 
484 /* Verify the frameset contents */
485  if ((ps.labels = cpl_frameset_labelise(set,omega_compare_tags,
486  &nlab)) == NULL) {
487  cpl_msg_error(_id,"Cannot labelise the input frameset");
488  omega_darkcurrent_tidy();
489  return -1;
490  }
491  if ((ps.darklist = omega_frameset_subgroup(set,ps.labels,nlab,
492  DARK_RAW)) == NULL) {
493  cpl_msg_error(_id,"Cannot find bias frames in input frameset");
494  omega_darkcurrent_tidy();
495  return -1;
496  }
497 
498  ndark = cpl_frameset_count_tags (set, DARK_RAW);
499  if (ndark < 3) {
500  cpl_msg_error (_id, "Need at least 3 (%s) frames to run this recipe", DARK_RAW);
501  omega_darkcurrent_tidy();
502  return -1;
503  }
504 
505  cpl_msg_info (_id,"There are %d %s frames in frame set",ndark, DARK_RAW);
506 
507  /* Get first frame from frame set */
508  firstframe = cpl_frameset_get_first(ps.darklist);
509 
510 
511  /* Check for calibration frames */
512  /* Master Bias */
513  ps.mbframe = cpl_frameset_find_const(set, OMEGA_CALIB_BIAS);
514  if (ps.mbframe == NULL) {
515  cpl_msg_info(_id,"A Master Bias is not present in frame set. Using default value %f", bias);
516  }
517  else{
518  cpl_msg_info(_id,"Using %s %s",OMEGA_CALIB_BIAS, cpl_frame_get_filename(ps.mbframe));
519  }
520 
521  /* Loop for each of the image extensions */
522  omega_exten_range(omega_darkcurrent_config.extnum,&jst,&jfn);
523  if(omega_darkcurrent_config.extnum == 0){
524  cpl_msg_error(cpl_func,"Unsupported extension request, %d",omega_darkcurrent_config.extnum);
525  omega_darkcurrent_tidy();
526  return -1;
527  }
528 
529  /* Create output names for the products */
530  for (j = jst; j <= jfn; j++) {
531 
532  isfirst = (j == jst);
533  cpl_msg_info(_id,"Beginning work on extension %d",j);
534  omega_darkcurrent_config.dark_current = 0.0;
535  omega_darkcurrent_config.rate = 0;
536 
537  /* Check overscan correction method consistency if oc mode == 0*/
538 
539  if(omega_darkcurrent_config.oc==0){
540  if(ps.mbframe != NULL){
541  oscan1 = omega_pfits_get_overscan(ps.mbframe, j);
542  if(oscan1 != omega_darkcurrent_config.oc) {
543  cpl_msg_warning (_id, "Overscan correction mode for Master Bias (oc = %d) differs from "
544  "the one used here (oc = %d)", oscan1, omega_darkcurrent_config.oc);
545  }
546  }
547  }
548 
549  ps.firstdark = omega_fits_load(firstframe,CPL_TYPE_FLOAT,j);
550  ps.eh = omega_fits_get_ehu(ps.firstdark);
551 
552  /* Call the combining routine */
553  status = omega_darkcurrent_combine(pars, j);
554  if(status == 1){
555  cpl_msg_warning(_id, "Image detector is not live");
556  /* Save dummy product */
557  freefits(ps.firstdark);
558  ps.eh = NULL;
559  continue;
560  }
561  else if(status == -1){
562  cpl_msg_error(_id,"Cannot combine images");
563  freespace(outmdark);
564  omega_darkcurrent_tidy();
565  return -1;
566  }
567 
568  status = 0;
569 
570  /* Save the products */
571  /* Save the MEAN DARK product */
572  qclist = cpl_propertylist_new();
573  cpl_propertylist_append_double(qclist, "ESO QC DARK CURRENT",
574  omega_darkcurrent_config.dark_current) ;
575  cpl_propertylist_set_comment(qclist, "ESO QC DARK CURRENT",
576  "Dark current") ;
577  cpl_propertylist_append_double(qclist, "ESO QC PARTICLE RATE",
578  omega_darkcurrent_config.rate) ;
579  cpl_propertylist_set_comment(qclist, "ESO QC PARTICLE RATE",
580  "Value of particle rate" ) ;
581 
582  if(isfirst){
583  outmdark = cpl_sprintf("%s_%s.fits", INSTRUME,DARK_PROCATG);
584  prframe_mdark = omega_product_frame(outmdark, DARK_PROCATG, CPL_FRAME_TYPE_IMAGE);
585  }
586 
587  alist = cpl_propertylist_new();
588  cpl_propertylist_append_string(alist, "EXTNAME",
589  cpl_propertylist_get_string(ps.eh, "EXTNAME"));
590  cpl_propertylist_set_comment(alist,"EXTNAME", "Extension name");
591 
592  cpl_propertylist_copy_property_regexp(alist, ps.eh, WCS_KEYS, 0);
593 
594  if(omega_save_image(ps.mdark,set,pars,alist,qclist,CPL_BPP_IEEE_FLOAT,outmdark,
595  RECIPE,prframe_mdark,NULL,isfirst) == -1){
596  cpl_msg_error(_id,"Cannot save product %s", DARK_PROCATG);
597  freeplist(qclist);
598  freeplist(alist);
599  freespace(outmdark);
600  omega_darkcurrent_tidy();
601  return -1;;
602  }
603 
604  freeplist(qclist);
605  freeplist(alist);
606  freeimage(ps.mdark);
607  freefits(ps.firstdark);
608  ps.firstdark = NULL;
609  ps.eh = NULL;
610 
611  } /* work on next extension */
612 
613 
614  freespace(outmdark);
615  omega_darkcurrent_tidy();
616 
617 
618  return 0;
619 }
620 
621 /*----------------------------------------------------------------------------*/
630 /*----------------------------------------------------------------------------*/
631 int omega_darkcurrent_combine(cpl_parameterlist *pars, int xn)
632 {
633 
634  int count = 0;
635  int i = 0;
636  int maxiter = 0;
637  int ndark = 0;
638  int live = 0;
639  float bias = BIAS;
640  double dethres = 3.0;
641  double exptime = 0.0;
642  double rate = 0.0;
643  double rejt = 5.0;
644  double detector_size_x=1.;
645  double detector_size_y=1.;
646  double detector_size=1.;
647 
648  const char *cmd = NULL;
649  const char *cosmiccat = "OMEGA_cosmicrays.fits";
650  const char *cosmic_conf = NULL;
651  const char *_id = "";
652  const char *path = NULL;
653  const char *sex_conv = NULL;
654  const char *sex_nnw = NULL;
655  const char *sex_par = NULL;
656  const char *temp1739 = "OMEGA_temp001739.fits";
657 
658  const cpl_frame *darkfr = NULL;
659  cpl_image *mbias = NULL, *trim_raw = NULL;
660  cpl_imagelist *ilist = NULL;
661  cpl_stats *stats = NULL;
662  cpl_parameter *par = NULL;
663  cpl_propertylist *mplist = NULL, *xplist = NULL;
664 
665 
666  par = cpl_parameterlist_find(pars, "omega.omega_darkcurrent.MaxIter") ;
667  maxiter = cpl_parameter_get_int(par) ;
668 
669  par = cpl_parameterlist_find(pars, "omega.omega_darkcurrent.RejThre") ;
670  rejt = cpl_parameter_get_double(par) ;
671 
672  par = cpl_parameterlist_find(pars, "omega.omega_darkcurrent.DetThre") ;
673  dethres = cpl_parameter_get_double(par) ;
674 
675  par = cpl_parameterlist_find(pars, "omega.omega_darkcurrent.BinPath");
676  path = cpl_parameter_get_string(par) ;
677 
678  par = cpl_parameterlist_find(pars,"omega.omega_darkcurrent.SexCosmic" );
679  cosmic_conf = cpl_parameter_get_string(par) ;
680 
681  par = cpl_parameterlist_find(pars,"omega.omega_darkcurrent.SexConv" );
682  sex_conv = cpl_parameter_get_string(par) ;
683 
684  par = cpl_parameterlist_find(pars,"omega.omega_darkcurrent.SexParam" );
685  sex_par = cpl_parameter_get_string(par) ;
686 
687  par = cpl_parameterlist_find(pars,"omega.omega_darkcurrent.SexNnw" );
688  sex_nnw = cpl_parameter_get_string(par) ;
689 
690  ndark = cpl_frameset_get_size(ps.darklist);
691  darkfr = cpl_frameset_get_first_const(ps.darklist);
692 
693  /* Check that this detector is live*/
694  omega_pfits_get_detlive(ps.eh,&live);
695  if (! live) {
696  return 1;
697  }
698 
699  /* Load master bias image */
700  if(ps.mbframe != NULL){
701  mbias = cpl_image_load(cpl_frame_get_filename(ps.mbframe), CPL_TYPE_FLOAT,0,xn);
702  if (mbias == NULL) {
703  cpl_msg_warning(_id,"Cannot load image %s", OMEGA_CALIB_BIAS);
704  }
705  }
706 
707  ilist = cpl_imagelist_new();
708  cpl_msg_info (_id,"Doing trim and overscan correction on images");
709 
710  /* Loop through all images in frame list */
711  /* Loop through raw dark list and trim each image*/
712 
713  for (i=0; i< ndark; i++)
714  {
715 
716  trim_raw = TrimOscanCorrect(darkfr, omega_darkcurrent_config.oc, xn);
717  if(trim_raw == NULL){
718  cpl_msg_error(_id,"Cannot trim image");
719  freeilist(ilist);
720  return -1;
721  }
722 
723  if(omega_darkcurrent_config.oc==0){
724  if (mbias != NULL){
725  cpl_msg_info(cpl_func,"Subtracting bias frame");
726  cpl_image_subtract(trim_raw, mbias);
727  }
728  else
729  cpl_image_subtract_scalar(trim_raw, bias);
730  }
731 
732  cpl_imagelist_set(ilist, trim_raw, i);
733  darkfr = cpl_frameset_get_next_const(ps.darklist);
734  if (darkfr == NULL)
735  break;
736 
737  }
738 
739  freeimage(mbias);
740  if (ilist == NULL) {
741  cpl_msg_error(_id,"Error in image list <%s>",cpl_error_get_message());
742  freeimage(trim_raw);
743  return -1;
744  }
745 
746  cpl_msg_info (_id,"Computing the median of all images...");
747  ps.mdark = cpl_imagelist_collapse_median_create(ilist);
748 
749  if (ps.mdark == NULL) {
750  cpl_msg_error (_id,"Cannot take median of list <%s>",cpl_error_get_message());
751  freeilist(ilist);
752  return -1;
753  }
754 
755  cpl_msg_info(_id,"Estimating the RMS using %d maximum iterations",maxiter);
756  cpl_msg_info(_id,"Rejection threshold is %g (sigma)",rejt);
757 
758 
759  /*Calculate statistics iteratively*/
760  stats = omega_iter_stat(ps.mdark,rejt,maxiter);
761  if(stats == NULL){
762  cpl_msg_warning(_id,"Cannot calculate statistics iteratively");
763  }
764 
765  darkfr = cpl_frameset_get_first(ps.darklist);
766  mplist = cpl_propertylist_load_regexp(cpl_frame_get_filename(darkfr), 0, "EXPTIME", 0);
767  xplist = cpl_propertylist_load_regexp(cpl_frame_get_filename(darkfr), xn, "EXPTIME", 0);
768  exptime = omega_pfits_get_exptime(xplist);
769  if (exptime == 0.0){
770  exptime = omega_pfits_get_exptime(mplist);
771  }
772 
773  omega_darkcurrent_config.dark_current = cpl_stats_get_mean(stats) / exptime*3600.0;
774  freeplist(mplist);
775  freeplist(xplist);
776 
777  freestats(stats);
778 
779  /*Calculate the particle event rate*/
780  rate = 0.0;
781  for(i=0; i < ndark; i++){
782 
783  cpl_image_save(cpl_imagelist_get(ilist, i),temp1739,BITPIX,NULL,CPL_IO_DEFAULT);
784 
785  /*
786  * Run Sextractor on a cosmic detection mode
787  */
788 
789  cmd = cpl_sprintf("%s/sex %s -c %s -PARAMETERS_NAME %s -FILTER_NAME %s -STARNNW_NAME %s "
790  "-DETECT_THRESH %g "
791  "-CHECKIMAGE_NAME chkimage.fits "
792  "-CATALOG_TYPE FITS_1.0 "
793  "-CATALOG_NAME %s",
794  path,
795  temp1739,
796  cosmic_conf,
797  sex_par,
798  sex_conv,
799  sex_nnw,
800  dethres,
801  cosmiccat);
802 
803  if (system(cmd) != 0) {
804  cpl_free((char *)cmd);
805  freeilist(ilist);
806  cpl_msg_error("","%s Failed to run Sextractor", _id);
807  return -1;
808  }
809 
810  cpl_free((char *)cmd);
811 
812  mplist = cpl_propertylist_load_regexp(cosmiccat, 1, "NAXIS2", 0);
813  if(mplist == NULL){
814  cpl_msg_error(_id,"Cannot load header for %s",cosmiccat);
815  freeilist(ilist);
816  return -1;
817  }
818 
819  count = cpl_propertylist_get_int(mplist,"NAXIS2");
820  /* cpl_msg_info(_id,"Detected %d cosmic ray events",count);*/
821 
822  rate += count;
823  freeplist(mplist);
824  }
825  /*Detector size in cm^2 assuming 15mue/pixel */
826 
827  detector_size_x=cpl_image_get_size_x(cpl_imagelist_get(ilist,0));
828  detector_size_y=cpl_image_get_size_y(cpl_imagelist_get(ilist,0));
829  detector_size=detector_size_x * detector_size_y * 0.0015 * 0.0015;
830 
831  rate = rate/ndark;
832  rate = rate/exptime*3600.0;
833  if(detector_size>0){
834  rate = rate/detector_size;
835  }
836  omega_darkcurrent_config.rate = rate;
837 
838  freeilist(ilist);
839 
840 
841  return 0;
842 }
843 
857 /*----------------------------------------------------------------------------*/
872 int omega_darkcurrent_save(cpl_image *image, cpl_frameset *set, cpl_parameterlist *parlist,
873  cpl_propertylist *qclist, cpl_type_bpp bitpix,
874  const char *outfile, cpl_frame *product_frame)
875 
876 {
877 
878  const char *fctid = "omega_darkcurrent_save";
879  cpl_propertylist *plist = NULL;
880 
881  /* If it is the first time, setup initial frame */
882  if (isfirst) {
883 
884  /* Create a new product frame object and define some tags */
885  plist = cpl_propertylist_new();
886 
887  /* Add DataFlow keywords in primary header */
888  if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
889  RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
890 
891  cpl_msg_warning(fctid, "Problem in the main header of product DFS-compliance") ;
892  }
893 
894  /* Once CPL recalculates these values, the following
895  * line should be removed
896  */
897  cpl_propertylist_erase_regexp(plist,REM_PRIM_KEYS,0);
898 
899  /* Save the empty primary unit */
900  if (cpl_propertylist_save(plist,outfile,CPL_IO_DEFAULT) != CPL_ERROR_NONE){
901  cpl_msg_error(fctid,"Cannot save product PHU");
902  freeplist(plist);
903  return 1;
904  }
905 
906  freeplist(plist);
907  cpl_frameset_insert(set,product_frame);
908  }
909 
910  /* Setup the extension */
911  plist = cpl_propertylist_duplicate(ps.eh);
912 
913 
914  /* Add DRS keywords */
915  cpl_propertylist_append_int(plist, "ESO DRS OVERSCAN METHOD", omega_darkcurrent_config.oc);
916  cpl_propertylist_set_comment(plist, "ESO DRS OVERSCAN METHOD", "overscan correction method");
917 
918  /* Add DataFlow keywords in extension header */
919  if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
920  RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
921 
922  cpl_msg_warning(fctid, "Problem in the extension header of product DFS-compliance") ;
923  }
924 
925  /*Remove undesired keywords from extension header*/
926  cpl_propertylist_erase_regexp(plist, REM_EXT_KEYS, 0);
927 
928 
929  /* Append QC list to the extension header */
930  cpl_propertylist_append(plist, qclist);
931 
932  /* Save the product */
933  if (cpl_image_save(image,outfile,bitpix,plist,
934  CPL_IO_EXTEND) != CPL_ERROR_NONE) {
935  cpl_msg_error(fctid,"Cannot save product. %s", cpl_error_get_message());
936  freeplist(plist);
937  return -1;
938  }
939 
940 
941  /* Save the paf file */
942  if(omega_darkcurrent_config.paf){
943  int xtnum = omega_fits_get_extnum(ps.firstdark);
944  char *prefix = omega_get_root_name(outfile);
945  char *outpaf = cpl_sprintf("%s_%d.paf",prefix,xtnum);
946  const char pafcopy[] = "^(DATE-OBS|ARCFILE|ESO TPL ID|ESO DET WIN1 DIT1|MJD-OBS|EXTNAME|ESO PRO CATG)$";
947  cpl_frame *fframe = cpl_frameset_get_first(set);
948  cpl_propertylist *mlist = cpl_propertylist_load_regexp(cpl_frame_get_filename(fframe),0,pafcopy, 0);
949  cpl_propertylist_copy_property_regexp(qclist, mlist, pafcopy, 0);
950  if (cpl_propertylist_copy_property_regexp(qclist, plist,
951  pafcopy, 0) != CPL_ERROR_NONE){
952 
953  cpl_msg_warning(fctid,"Some mandatory keywords are missing in PAF file");
954  }
955 
956  cpl_dfs_save_paf(INSTRUME, RECIPE, qclist, outpaf);
957  cpl_free(outpaf);
958  freeplist(mlist);
959  }
960 
961  freeplist(plist);
962 
963  return 0;
964 }
965 
966 /* Initialize the pointers */
967 static void omega_darkcurrent_init(void) {
968  ps.labels = NULL;
969  ps.darklist = NULL;
970  ps.mdark = NULL;
971  ps.mbframe = NULL;
972  ps.eh = NULL;
973  ps.firstdark = NULL;
974 }
975 
976 /* Free any allocated memory */
977 static void omega_darkcurrent_tidy(void) {
978  freespace(ps.labels);
979  freeframeset(ps.darklist);
980  freeimage(ps.mdark);
981  freefits(ps.firstdark);
982 }
983