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