VIRCAM Pipeline  1.3.3
vircam_detector_noise.c
1 /* $Id: vircam_detector_noise.c,v 1.57 2012-01-16 12:32:18 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
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: jim $
23  * $Date: 2012-01-16 12:32:18 $
24  * $Revision: 1.57 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 /* Includes */
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <stdio.h>
35 #include <cpl.h>
36 #include <math.h>
37 #include <string.h>
38 
39 #include "vircam_utils.h"
40 #include "vircam_mask.h"
41 #include "vircam_dfs.h"
42 #include "vircam_stats.h"
43 #include "vircam_pfits.h"
44 #include "vircam_paf.h"
45 
46 /* Function prototypes */
47 
48 static int vircam_detector_noise_create(cpl_plugin *) ;
49 static int vircam_detector_noise_exec(cpl_plugin *) ;
50 static int vircam_detector_noise_destroy(cpl_plugin *) ;
51 static int vircam_detector_noise(cpl_parameterlist *, cpl_frameset *) ;
52 static int vircam_detector_noise_save(cpl_frameset *framelist,
53  cpl_parameterlist *parlist);
54 static void vircam_detector_noise_init(void);
55 static void vircam_detector_noise_tidy(void);
56 
57 /* Static global variables */
58 
59 static struct {
60 
61  /* Input */
62 
63  float thresh;
64  int extenum;
65 
66  /* Output */
67 
68  float gain;
69  float readnoise;
70  float counts;
71  float lampflux;
72 } vircam_detector_noise_config ;
73 
74 static struct {
75  cpl_size *labels;
76  cpl_frameset *darklist;
77  cpl_frameset *domelist;
78  cpl_frame *inherit;
79  cpl_image *darkim1;
80  cpl_image *darkim2;
81  cpl_image *domeim1;
82  cpl_image *domeim2;
83  vir_mask *master_mask;
84  cpl_propertylist *ph;
85  cpl_propertylist *eh;
86  cpl_propertylist *phupaf;
87 } ps;
88 
89 static cpl_frame *product_frame = NULL;
90 static int isfirst;
91 static int dummy;
92 
93 #define BUZZ_OFF {vircam_detector_noise_tidy(); return(-1);}
94 
95 static char vircam_detector_noise_description[] =
96 "vircam_detector_noise -- VIRCAM readnoise and gain recipe.\n\n"
97 "Measures the read noise and gain of a chip using two dome flat exposures\n"
98 "and two dark exposures. The flats should have the same illumination.\n"
99 "All four frames should have the same exposure time. If the SOF\n"
100 "contains more than two files of a given type, the others are ignored.\n\n"
101 "The program requires the following files in the SOF:\n\n"
102 " Tag Description\n"
103 " -----------------------------------------------------------------------\n"
104 " %-21s A list of two raw dark images\n"
105 " %-21s A list of two raw dome flat image\n"
106 " %-21s Optional master bad pixel map or\n"
107 " %-21s Optional master confidence map\n"
108 "\n";
109 
175 /* Function code */
176 
177 /*---------------------------------------------------------------------------*/
185 /*---------------------------------------------------------------------------*/
186 
187 int cpl_plugin_get_info(cpl_pluginlist *list) {
188  cpl_recipe *recipe = cpl_calloc(1,sizeof(*recipe));
189  cpl_plugin *plugin = &recipe->interface;
190  char alldesc[SZ_ALLDESC];
191  (void)snprintf(alldesc,SZ_ALLDESC,vircam_detector_noise_description,
192  VIRCAM_NOISE_DARK_RAW,VIRCAM_NOISE_FLAT_RAW,VIRCAM_CAL_BPM,
193  VIRCAM_CAL_CONF);
194 
195  cpl_plugin_init(plugin,
196  CPL_PLUGIN_API,
197  VIRCAM_BINARY_VERSION,
198  CPL_PLUGIN_TYPE_RECIPE,
199  "vircam_detector_noise",
200  "VIRCAM recipe to determine readout noise and gain",
201  alldesc,
202  "Jim Lewis",
203  "jrl@ast.cam.ac.uk",
205  vircam_detector_noise_create,
206  vircam_detector_noise_exec,
207  vircam_detector_noise_destroy);
208 
209  cpl_pluginlist_append(list,plugin);
210 
211  return(0);
212 }
213 
214 
215 /*---------------------------------------------------------------------------*/
224 /*---------------------------------------------------------------------------*/
225 
226 static int vircam_detector_noise_create(cpl_plugin *plugin) {
227  cpl_recipe *recipe;
228  cpl_parameter *p;
229 
230  /* Get the recipe out of the plugin */
231 
232  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
233  recipe = (cpl_recipe *)plugin;
234  else
235  return(-1);
236 
237  /* Create the parameters list in the cpl_recipe object */
238 
239  recipe->parameters = cpl_parameterlist_new();
240 
241  /* Fill in the rejection threshold parameter */
242 
243  p = cpl_parameter_new_value("vircam.vircam_detector_noise.thresh",
244  CPL_TYPE_DOUBLE,
245  "Rejection threshold in sigma above background", "vircam.vircam_detector_noise",5.0);
246  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"thresh");
247  cpl_parameterlist_append(recipe->parameters,p);
248 
249  /* Extension number of input frames to use */
250 
251  p = cpl_parameter_new_range("vircam.vircam_detector_noise.extenum",
252  CPL_TYPE_INT,
253  "Extension number to be done, 0 == all",
254  "vircam.vircam_detector_noise",
255  1,0,16);
256  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ext");
257  cpl_parameterlist_append(recipe->parameters,p);
258 
259  /* Get out of here */
260 
261  return(0);
262 }
263 
264 /*---------------------------------------------------------------------------*/
270 /*---------------------------------------------------------------------------*/
271 
272 static int vircam_detector_noise_destroy(cpl_plugin *plugin) {
273  cpl_recipe *recipe ;
274 
275  /* Get the recipe out of the plugin */
276 
277  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
278  recipe = (cpl_recipe *)plugin;
279  else
280  return(-1);
281 
282  cpl_parameterlist_delete(recipe->parameters);
283  return(0);
284 }
285 
286 /*---------------------------------------------------------------------------*/
292 /*---------------------------------------------------------------------------*/
293 
294 static int vircam_detector_noise_exec(cpl_plugin *plugin) {
295  cpl_recipe *recipe;
296 
297  /* Get the recipe out of the plugin */
298 
299  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
300  recipe = (cpl_recipe *)plugin;
301  else
302  return(-1);
303 
304  return(vircam_detector_noise(recipe->parameters,recipe->frames));
305 }
306 
307 /*---------------------------------------------------------------------------*/
314 /*---------------------------------------------------------------------------*/
315 
316 static int vircam_detector_noise(cpl_parameterlist *parlist,
317  cpl_frameset *framelist) {
318  const char *fctid="vircam_detector_noise";
319  cpl_parameter *p;
320  int j,jst,jfn,retval,nx,ny,live;
321  cpl_size nlab;
322  long nptsdark;
323  float meandark1,meandome1,meandark2,meandome2,sigdark,lcut,hcut;
324  float meandarkdiff,sigdarkdiff,counts;
325  float meandomediff,sigdomediff,gain,readnoise,exptime;
326  cpl_frame *dark1,*dark2,*dome1,*dome2;
327  cpl_propertylist *plist;
328  unsigned char *bpm;
329 
330  /* Check validity of input frameset */
331 
332  if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
333  cpl_msg_error(fctid,"Input framelist NULL or has no input data");
334  return(-1);
335  }
336 
337  /* Check the files in the frameset */
338 
339  if (vircam_frameset_fexists(framelist) != VIR_OK) {
340  cpl_msg_error(fctid,"Input frameset is missing files. Check SOF");
341  return(-1);
342  }
343 
344  /* Initialise a few things */
345 
346  vircam_detector_noise_init();
347 
348  /* Get the parameters */
349 
350  p = cpl_parameterlist_find(parlist,"vircam.vircam_detector_noise.thresh");
351  vircam_detector_noise_config.thresh = (float)cpl_parameter_get_double(p);
352  p = cpl_parameterlist_find(parlist,"vircam.vircam_detector_noise.extenum");
353  vircam_detector_noise_config.extenum = cpl_parameter_get_int(p);
354 
355  /* Sort out raw from calib frames */
356 
357  if (vircam_dfs_set_groups(framelist) != VIR_OK) {
358  cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
359  vircam_detector_noise_tidy();
360  return(-1);
361  }
362 
363  /* Get dark and dome flat frames. Make sure there are at least 2 of each */
364 
365  if ((ps.labels = cpl_frameset_labelise(framelist,vircam_compare_tags,
366  &nlab)) == NULL) {
367  cpl_msg_error(fctid,"Cannot labelise the input frameset");
368  BUZZ_OFF
369  }
370  if ((ps.darklist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
371  VIRCAM_NOISE_DARK_RAW)) == NULL) {
372  cpl_msg_error(fctid,"Cannot find dark frames in input frameset");
373  BUZZ_OFF
374  }
375  if (cpl_frameset_get_size(ps.darklist) < 2) {
376  cpl_msg_error(fctid,"Dark frameset doesn't have enough frames");
377  BUZZ_OFF
378  }
379  if ((ps.domelist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
380  VIRCAM_NOISE_FLAT_RAW)) == NULL) {
381  cpl_msg_error(fctid,"Cannot find dome flat frames in input frameset");
382  BUZZ_OFF
383  }
384  if (cpl_frameset_get_size(ps.domelist) < 2) {
385  cpl_msg_error(fctid,"Dome flat frameset doesn't have enough frames");
386  BUZZ_OFF
387  }
388 
389  /* Check to see if there is a master bad pixel map. If there isn't one
390  then look for a confidence map */
391 
392  ps.master_mask = vircam_mask_define(framelist,ps.labels,nlab);
393 
394  /* Set up some convenience variables */
395 
396  dark1 = cpl_frameset_get_frame(ps.darklist,0);
397  dark2 = cpl_frameset_get_frame(ps.darklist,1);
398  dome1 = cpl_frameset_get_frame(ps.domelist,0);
399  dome2 = cpl_frameset_get_frame(ps.domelist,1);
400  ps.inherit = dome1;
401 
402  /* Get a propertylist for the primary */
403 
404  ps.ph = cpl_propertylist_load(cpl_frame_get_filename(dome1),0);
405  (void)vircam_pfits_get_exptime((const cpl_propertylist *)ps.ph,&exptime);
406 
407  /* Loop for each of the image extensions */
408 
409  vircam_exten_range(vircam_detector_noise_config.extenum,
410  (const cpl_frame *)dark1,&jst,&jfn);
411  if (jst == -1 || jfn == -1) {
412  cpl_msg_error(fctid,"Unable to continue");
413  vircam_detector_noise_tidy();
414  return(-1);
415  }
416  for (j = jst; j <= jfn; j++) {
417  cpl_msg_info(fctid,"Beginning work on extension %" CPL_SIZE_FORMAT,
418  (cpl_size)j);
419  isfirst = (j == jst);
420  vircam_detector_noise_config.readnoise = 0.0;
421  vircam_detector_noise_config.gain = 0.0;
422  vircam_detector_noise_config.counts = 0.0;
423  vircam_detector_noise_config.lampflux = 0.0;
424  dummy = 1;
425 
426  /* Get the full set of images */
427 
428  ps.darkim1 = cpl_image_load(cpl_frame_get_filename(dark1),
429  CPL_TYPE_FLOAT,0,(cpl_size)j);
430  ps.darkim2 = cpl_image_load(cpl_frame_get_filename(dark2),
431  CPL_TYPE_FLOAT,0,(cpl_size)j);
432  ps.domeim1 = cpl_image_load(cpl_frame_get_filename(dome1),
433  CPL_TYPE_FLOAT,0,(cpl_size)j);
434  ps.domeim2 = cpl_image_load(cpl_frame_get_filename(dome2),
435  CPL_TYPE_FLOAT,0,(cpl_size)j);
436  if (ps.darkim1 == NULL || ps.darkim2 == NULL || ps.domeim1 == NULL ||
437  ps.domeim2 == NULL) {
438  cpl_error_reset();
439  cpl_msg_error(fctid,
440  "NULL image input for extension %" CPL_SIZE_FORMAT,
441  (cpl_size)j);
442  retval = vircam_detector_noise_save(framelist,parlist);
443  freeimage(ps.darkim1);
444  freeimage(ps.darkim2);
445  freeimage(ps.domeim1);
446  freeimage(ps.domeim2);
447  continue;
448  }
449 
450  /* Get some an extension propertylist */
451 
452  ps.eh = cpl_propertylist_load(cpl_frame_get_filename(dome1),
453  (cpl_size)j);
454 
455  /* Check that the current detectors are live */
456 
457  plist = cpl_propertylist_load(cpl_frame_get_filename(dark1),
458  (cpl_size)j);
459  vircam_pfits_get_detlive(plist,&live);
460  if (! live) {
461  cpl_msg_warning(fctid,"First dark image detector not live");
462  retval = vircam_detector_noise_save(framelist,parlist);
463  cpl_propertylist_delete(plist);
464  freeimage(ps.darkim1);
465  freeimage(ps.darkim2);
466  freeimage(ps.domeim1);
467  freeimage(ps.domeim2);
468  freepropertylist(ps.eh);
469  continue;
470  }
471  cpl_propertylist_delete(plist);
472  plist = cpl_propertylist_load(cpl_frame_get_filename(dark2),
473  (cpl_size)j);
474  vircam_pfits_get_detlive(plist,&live);
475  if (! live) {
476  cpl_msg_warning(fctid,"Second dark image detector not live");
477  retval = vircam_detector_noise_save(framelist,parlist);
478  cpl_propertylist_delete(plist);
479  freeimage(ps.darkim1);
480  freeimage(ps.darkim2);
481  freeimage(ps.domeim1);
482  freeimage(ps.domeim2);
483  freepropertylist(ps.eh);
484  continue;
485  }
486  cpl_propertylist_delete(plist);
487  plist = cpl_propertylist_load(cpl_frame_get_filename(dome1),
488  (cpl_size)j);
489  vircam_pfits_get_detlive(plist,&live);
490  if (! live) {
491  cpl_msg_warning(fctid,"First dome image detector not live");
492  retval = vircam_detector_noise_save(framelist,parlist);
493  cpl_propertylist_delete(plist);
494  freeimage(ps.darkim1);
495  freeimage(ps.darkim2);
496  freeimage(ps.domeim1);
497  freeimage(ps.domeim2);
498  freepropertylist(ps.eh);
499  continue;
500  }
501  cpl_propertylist_delete(plist);
502  plist = cpl_propertylist_load(cpl_frame_get_filename(dome2),
503  (cpl_size)j);
504  vircam_pfits_get_detlive(plist,&live);
505  if (! live) {
506  cpl_msg_warning(fctid,"Second dome image detector not live");
507  retval = vircam_detector_noise_save(framelist,parlist);
508  cpl_propertylist_delete(plist);
509  freeimage(ps.darkim1);
510  freeimage(ps.darkim2);
511  freeimage(ps.domeim1);
512  freeimage(ps.domeim2);
513  freepropertylist(ps.eh);
514  continue;
515  }
516  cpl_propertylist_delete(plist);
517 
518  /* Get the data array sizes */
519 
520  nx = (int)cpl_image_get_size_x(ps.darkim1);
521  ny = (int)cpl_image_get_size_y(ps.darkim1);
522  nptsdark = (long)(nx*ny);
523 
524  /* Load the mask */
525 
526  if (vircam_mask_load(ps.master_mask,j,nx,ny) == VIR_FATAL) {
527  cpl_msg_info(fctid,
528  "Unable to load mask image %s[%" CPL_SIZE_FORMAT "]",
529  vircam_mask_get_filename(ps.master_mask),(cpl_size)j);
530  cpl_msg_info(fctid,"Forcing all pixels to be good from now on");
531  vircam_mask_force(ps.master_mask,nx,ny);
532  }
533  bpm = vircam_mask_get_data(ps.master_mask);
534 
535  /* Get the mean of the first dark and the first dome */
536 
537  vircam_medmad((float *)cpl_image_get_data(ps.darkim1),bpm,
538  nptsdark,&meandark1,&sigdark);
539  sigdark *= 1.48;
540  lcut = meandark1 - vircam_detector_noise_config.thresh*sigdark;
541  hcut = meandark1 + vircam_detector_noise_config.thresh*sigdark;
542  vircam_medmadcut((float *)cpl_image_get_data(ps.darkim1),bpm,
543  nptsdark,lcut,hcut,&meandark1,&sigdark);
544  vircam_medmad((float *)cpl_image_get_data(ps.domeim1),bpm,
545  nptsdark,&meandome1,&sigdark);
546  sigdark *= 1.48;
547  lcut = meandome1 - vircam_detector_noise_config.thresh*sigdark;
548  hcut = meandome1 + vircam_detector_noise_config.thresh*sigdark;
549  vircam_medmadcut((float *)cpl_image_get_data(ps.domeim1),bpm,
550  nptsdark,lcut,hcut,&meandome1,&sigdark);
551 
552  /* Get the mean of the second dark and the second dome */
553 
554  vircam_medmad((float *)cpl_image_get_data(ps.darkim2),bpm,
555  nptsdark,&meandark2,&sigdark);
556  sigdark *= 1.48;
557  lcut = meandark2 - vircam_detector_noise_config.thresh*sigdark;
558  hcut = meandark2 + vircam_detector_noise_config.thresh*sigdark;
559  vircam_medmadcut((float *)cpl_image_get_data(ps.darkim2),bpm,
560  nptsdark,lcut,hcut,&meandark2,&sigdark);
561  vircam_medmad((float *)cpl_image_get_data(ps.domeim2),bpm,
562  nptsdark,&meandome2,&sigdark);
563  sigdark *= 1.48;
564  lcut = meandome2 - vircam_detector_noise_config.thresh*sigdark;
565  hcut = meandome2 + vircam_detector_noise_config.thresh*sigdark;
566  vircam_medmadcut((float *)cpl_image_get_data(ps.domeim2),bpm,
567  nptsdark,lcut,hcut,&meandome2,&sigdark);
568 
569  /* Form a difference image with each the of the dark and dome pairs */
570 
571  cpl_image_subtract(ps.darkim1,ps.darkim2);
572  cpl_image_subtract(ps.domeim1,ps.domeim2);
573 
574  /* Now measure the mean and sigma of each of the difference images */
575 
576  vircam_medmad((float *)cpl_image_get_data(ps.darkim1),bpm,
577  nptsdark,&meandarkdiff,&sigdarkdiff);
578  sigdarkdiff *= 1.48;
579  lcut = meandarkdiff - vircam_detector_noise_config.thresh*sigdarkdiff;
580  hcut = meandarkdiff + vircam_detector_noise_config.thresh*sigdarkdiff;
581  vircam_medmadcut((float *)cpl_image_get_data(ps.darkim1),bpm,
582  nptsdark,lcut,hcut,&meandarkdiff,&sigdarkdiff);
583  sigdarkdiff *= 1.48;
584  vircam_medmad((float *)cpl_image_get_data(ps.domeim1),bpm,
585  nptsdark,&meandomediff,&sigdomediff);
586  sigdomediff *= 1.48;
587  lcut = meandomediff - vircam_detector_noise_config.thresh*sigdomediff;
588  hcut = meandomediff + vircam_detector_noise_config.thresh*sigdomediff;
589  vircam_medmadcut((float *)cpl_image_get_data(ps.domeim1),bpm,
590  nptsdark,lcut,hcut,&meandomediff,&sigdomediff);
591  sigdomediff *= 1.48;
592 
593  /* Work out gain */
594 
595  counts = (meandome1 + meandome2) - (meandark1 + meandark2);
596  vircam_detector_noise_config.counts = 0.5*counts;
597  vircam_detector_noise_config.lampflux = 0.5*counts/exptime;
598  gain = counts/(sigdomediff*sigdomediff - sigdarkdiff*sigdarkdiff);
599  vircam_detector_noise_config.gain = gain;
600 
601  /* Now the read noise */
602 
603  readnoise = gain*sigdarkdiff/sqrt(2.0);
604  vircam_detector_noise_config.readnoise = readnoise;
605  dummy = 0;
606 
607  /* Save the products */
608 
609  retval = vircam_detector_noise_save(framelist,parlist);
610  if (retval != 0) {
611  cpl_msg_error(fctid,"Error saving results");
612  BUZZ_OFF
613  }
614 
615  /* Tidy up */
616 
617  freeimage(ps.darkim1);
618  freeimage(ps.darkim2);
619  freeimage(ps.domeim1);
620  freeimage(ps.domeim2);
621  vircam_mask_clear(ps.master_mask);
622  freepropertylist(ps.eh);
623  }
624  vircam_detector_noise_tidy();
625  return(0);
626 }
627 
628 /*---------------------------------------------------------------------------*/
635 /*---------------------------------------------------------------------------*/
636 
637 static int vircam_detector_noise_save(cpl_frameset *framelist,
638  cpl_parameterlist *parlist) {
639  const char *fctid = "vircam_detector_noise_save";
640  const char *outpaf = "vircam_detector_noise";
641  const char *outfile = "detector_noise.fits";
642  const char *recipeid = "vircam_detector_noise";
643  cpl_propertylist *plist,*p;
644  cpl_table *o;
645 
646  /* If this is the first time through then create the output image */
647 
648  if (isfirst) {
649 
650  /* Create a new product frame object and define some tags */
651 
652  product_frame = cpl_frame_new();
653  cpl_frame_set_filename(product_frame,outfile);
654  cpl_frame_set_tag(product_frame,VIRCAM_PRO_READGAINFILE);
655  cpl_frame_set_type(product_frame,CPL_FRAME_TYPE_IMAGE);
656  cpl_frame_set_group(product_frame,CPL_FRAME_GROUP_PRODUCT);
657  cpl_frame_set_level(product_frame,CPL_FRAME_LEVEL_FINAL);
658 
659  /* Fiddle with the primary header */
660 
661  plist = cpl_propertylist_duplicate(ps.ph);
662  ps.phupaf = vircam_paf_phu_items(plist);
663  vircam_dfs_set_product_primary_header(plist,product_frame,framelist,
664  parlist,(char *)recipeid,
665  "PRO-1.15",ps.inherit,0);
666  vircam_paf_append(ps.phupaf,plist,"ESO PRO CATG");
667  vircam_paf_append(ps.phupaf,plist,"ESO INS FILT1 NAME");
668 
669  /* 'Save' the PHU image */
670 
671  if (cpl_image_save(NULL,outfile,CPL_TYPE_UCHAR,plist,
672  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
673  cpl_msg_error(fctid,"Cannot save product PHU");
674  cpl_frame_delete(product_frame);
675  cpl_propertylist_delete(plist);
676  return(-1);
677  }
678  cpl_propertylist_delete(plist);
679  cpl_frameset_insert(framelist,product_frame);
680  }
681 
682  /* Create results header */
683 
684  plist = cpl_propertylist_duplicate(ps.eh);
685 
686  /* Now add the new data... */
687 
688  cpl_propertylist_update_float(plist,"ESO QC READNOISE",
689  vircam_detector_noise_config.readnoise);
690  cpl_propertylist_set_comment(plist,"ESO QC READNOISE",
691  "[e-] Calculated detector readnoise");
692  cpl_propertylist_update_float(plist,"ESO QC CONAD",
693  vircam_detector_noise_config.gain);
694  cpl_propertylist_set_comment(plist,"ESO QC CONAD",
695  "[e-/ADU] Calculated detector gain");
696  cpl_propertylist_update_float(plist,"ESO QC COUNTS",
697  vircam_detector_noise_config.counts);
698  cpl_propertylist_set_comment(plist,"ESO QC COUNTS",
699  "[ADU] Dark corrected dome counts");
700  cpl_propertylist_update_float(plist,"ESO QC LAMPFLUX",
701  vircam_detector_noise_config.lampflux);
702  cpl_propertylist_set_comment(plist,"ESO QC LAMPFLUX",
703  "[ADU/sec] Dark corrected flux level");
704 
705  /* Now fiddle with the extension header */
706 
707  vircam_dfs_set_product_exten_header(plist,product_frame,framelist,
708  parlist,(char *)recipeid,
709  "PRO-1.15",ps.inherit);
710  if (dummy)
711  vircam_dummy_property(plist);
712 
713  /* Create the output table */
714 
715  o = cpl_table_new(1);
716  cpl_table_new_column(o,"EXTNAME",CPL_TYPE_STRING);
717  cpl_table_new_column(o,"READNOISE",CPL_TYPE_FLOAT);
718  cpl_table_new_column(o,"GAIN",CPL_TYPE_FLOAT);
719 
720  /* Write the values to the table */
721 
722  cpl_table_set_string(o,"EXTNAME",0,
723  cpl_propertylist_get_string(plist,"EXTNAME"));
724  cpl_table_set_float(o,"READNOISE",0,
725  vircam_detector_noise_config.readnoise);
726  cpl_table_set_float(o,"GAIN",0,vircam_detector_noise_config.gain);
727 
728  /* 'Save' the image */
729 
730  if (cpl_table_save(o,NULL,plist,outfile,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
731  cpl_msg_error(fctid,"Cannot save product");
732  cpl_propertylist_delete(plist);
733  cpl_frame_delete(product_frame);
734  freetable(o);
735  return(-1);
736  }
737  freetable(o);
738 
739  /* Write the PAF */
740 
741  p = vircam_paf_req_items(plist);
742  vircam_merge_propertylists(p,ps.phupaf);
743  if (vircam_paf_print((char *)outpaf,"VIRCAM/vircam_detector_noise",
744  "QC file",p) != VIR_OK)
745  cpl_msg_warning(fctid,"Unable to write PAF");
746  cpl_propertylist_delete(p);
747 
748  /* Tidy and exit */
749 
750  freepropertylist(plist);
751  return(0);
752 }
753 
754 /*---------------------------------------------------------------------------*/
758 /*---------------------------------------------------------------------------*/
759 
760 static void vircam_detector_noise_init(void) {
761  ps.labels = NULL;
762  ps.darklist = NULL;
763  ps.domelist = NULL;
764  ps.darkim1 = NULL;
765  ps.darkim2 = NULL;
766  ps.domeim1 = NULL;
767  ps.domeim2 = NULL;
768  ps.master_mask = NULL;
769  ps.inherit = NULL;
770  ps.ph = NULL;
771  ps.eh = NULL;
772  ps.phupaf = NULL;
773  return;
774 }
775 
776 /*---------------------------------------------------------------------------*/
780 /*---------------------------------------------------------------------------*/
781 
782 static void vircam_detector_noise_tidy(void) {
783  freespace(ps.labels);
784  freeframeset(ps.darklist);
785  freeframeset(ps.domelist);
786  freeimage(ps.darkim1);
787  freeimage(ps.darkim2);
788  freeimage(ps.domeim1);
789  freeimage(ps.domeim2);
790  freemask(ps.master_mask);
791  freepropertylist(ps.ph);
792  freepropertylist(ps.eh);
793  freepropertylist(ps.phupaf);
794  return;
795 }
796 
800 /*
801 
802 $Log: not supported by cvs2svn $
803 Revision 1.56 2012/01/15 17:40:09 jim
804 Minor modifications to take into accout the changes in cpl API for v6
805 
806 Revision 1.55 2010/12/09 13:19:19 jim
807 Fixed bug where reported flux was a factor of two too high
808 
809 Revision 1.54 2010/06/30 12:42:00 jim
810 A few fixes to stop compiler compaints
811 
812 Revision 1.53 2010/03/09 14:28:38 jim
813 Added new QC values COUNTS and LAMPFLUX
814 
815 Revision 1.52 2010/01/31 18:55:30 jim
816 Filter name written to PAF. QC GAIN changed to QC CONAD (in spite of the
817 dreadful name)
818 
819 Revision 1.51 2009/09/09 09:50:21 jim
820 Modified to try and get headers right
821 
822 Revision 1.50 2008/10/01 04:59:13 jim
823 Added call to vircam_frameset_fexists to check input frameset
824 
825 Revision 1.49 2008/09/30 11:33:23 jim
826 Added PRO CATG to pafs
827 
828 Revision 1.48 2007/10/25 18:39:22 jim
829 Altered to remove some lint messages
830 
831 Revision 1.47 2007/10/15 12:52:39 jim
832 Fixed little cockup which had duplicate entries in the ps structure
833 
834 Revision 1.46 2007/09/07 13:32:12 jim
835 uses a sorted framelist to ensure that the correct information is given
836 to the output product header
837 
838 Revision 1.45 2007/09/06 21:37:53 jim
839 fixed call to vircam_dfs_setup_product_ routines to use the full input
840 frameset
841 
842 Revision 1.44 2007/07/18 15:35:41 jim
843 Added better error handling for missing or corrupt mask extensions
844 
845 Revision 1.43 2007/07/09 13:21:55 jim
846 Modified to use new version of vircam_exten_range
847 
848 Revision 1.42 2007/06/13 08:11:27 jim
849 Modified docs to reflect changes in DFS tags
850 
851 Revision 1.41 2007/04/04 10:36:18 jim
852 Modified to use new dfs tags
853 
854 Revision 1.40 2007/03/29 12:19:38 jim
855 Little changes to improve documentation
856 
857 Revision 1.39 2007/03/06 12:30:17 jim
858 Now writes results to a table in addtion to a header and a paf.
859 
860 Revision 1.38 2007/03/01 12:41:49 jim
861 Modified slightly after code checking
862 
863 Revision 1.37 2007/02/25 06:26:35 jim
864 Plugged a few memory leaks
865 
866 Revision 1.36 2007/02/15 06:59:37 jim
867 Added ability to write QC paf files
868 
869 Revision 1.35 2007/02/07 10:12:39 jim
870 Removed calls to vircam_ndit_correct as this is now no longer necessary
871 
872 Revision 1.34 2007/02/06 13:11:12 jim
873 Fixed entry for PRO dictionary in cpl_dfs_set_product_header
874 
875 Revision 1.33 2007/02/06 12:38:59 jim
876 Creates a sorted version of the input frameset so that a dome flat is first
877 in the list. This is done so that the header of the output product comes
878 from one of the dome flats and so that you can see which filter it was done
879 with.
880 
881 Revision 1.32 2007/02/06 11:59:38 jim
882 Added call to vircam_medmadcut for a better estimate of dispersion
883 
884 Revision 1.31 2007/01/17 23:56:12 jim
885 Plugged possible memory leak
886 
887 Revision 1.30 2006/12/14 14:46:32 jim
888 Fixed typo
889 
890 Revision 1.29 2006/12/11 22:47:49 jim
891 Fixed QC header names
892 
893 Revision 1.28 2006/11/27 12:16:33 jim
894 Modified to change location in the header where the results are written
895 
896 Revision 1.27 2006/11/10 09:20:29 jim
897 Fixed _save routine so that an extension name is written out to the file
898 header
899 
900 Revision 1.26 2006/09/29 11:19:31 jim
901 changed aliases on parameter names
902 
903 Revision 1.25 2006/09/09 16:49:39 jim
904 Header comment update
905 
906 Revision 1.24 2006/09/08 09:17:27 jim
907 Modified to flag dummy results
908 
909 Revision 1.23 2006/09/04 23:02:14 jim
910 Modified to deal with det live issues. Also does a better job of dealing
911 with duff input
912 
913 Revision 1.22 2006/06/20 19:07:01 jim
914 Corrects for ndit != 1
915 
916 Revision 1.21 2006/06/15 09:58:58 jim
917 Minor changes to docs
918 
919 Revision 1.20 2006/06/13 21:27:10 jim
920 Changed output product to a MEF with null images and readnoise/gain estimates
921 in the header. I HATE this solution
922 
923 Revision 1.19 2006/06/09 11:26:25 jim
924 Small changes to keep lint happy
925 
926 Revision 1.18 2006/05/04 11:56:02 jim
927 changed filename extension in default output file
928 
929 Revision 1.17 2006/05/04 11:53:14 jim
930 Fixed the way the _save routine works to be more consistent with the
931 standard CPL way of doing things
932 
933 Revision 1.16 2006/04/27 09:46:01 jim
934 Modified DFS frame types to conform to new dictionary
935 
936 Revision 1.15 2006/03/22 14:02:51 jim
937 cosmetic changes to keep lint happy
938 
939 Revision 1.14 2006/03/22 12:13:51 jim
940 Modified to use new vircam_mask capability
941 
942 Revision 1.13 2006/03/15 10:43:40 jim
943 Fixed a few things
944 
945 Revision 1.12 2006/01/23 10:36:39 jim
946 Now allows a CPM or a BPM to be used as the mask
947 
948 Revision 1.11 2005/12/14 22:19:12 jim
949 fixed docs
950 
951 Revision 1.10 2005/12/09 09:47:58 jim
952 Many changes to add more documentation
953 
954 Revision 1.9 2005/12/02 10:45:37 jim
955 The tags used in the sof are now written to the description string in the
956 constructor. This is so that if they change in the vircam_dfs.h file, they
957 aren't then hardcopied into each of the recipes...
958 
959 Revision 1.8 2005/11/29 16:10:58 jim
960 Added clipping into stats for difference images
961 
962 Revision 1.7 2005/11/25 15:20:29 jim
963 Fixed bug in mathematical description
964 
965 Revision 1.6 2005/11/25 09:56:14 jim
966 Tidied up some more documentation
967 
968 Revision 1.5 2005/11/23 14:57:40 jim
969 A bit of tidying in response to splint messages
970 
971 Revision 1.4 2005/11/21 16:16:23 jim
972 Added some better garbage collection
973 
974 Revision 1.3 2005/11/07 13:14:18 jim
975 Added some error trapping and some docs
976 
977 Revision 1.2 2005/08/09 11:09:39 jim
978 Replaced dodgy call to cpl_framelist_delete with correct cpl_frameset_delete
979 
980 Revision 1.1.1.1 2005/08/05 08:29:09 jim
981 Initial import
982 
983 
984 */