vircam_detector_noise.c

00001 /* $Id: vircam_detector_noise.c,v 1.55 2010/12/09 13:19:19 jim Exp $
00002  *
00003  * This file is part of the VIRCAM Pipeline
00004  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: jim $
00023  * $Date: 2010/12/09 13:19:19 $
00024  * $Revision: 1.55 $
00025  * $Name: v1-1-0 $
00026  */
00027 
00028 /* Includes */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033 
00034 #include <stdio.h>
00035 #include <cpl.h>
00036 #include <math.h>
00037 #include <string.h>
00038 
00039 #include "vircam_utils.h"
00040 #include "vircam_mask.h"
00041 #include "vircam_dfs.h"
00042 #include "vircam_stats.h"
00043 #include "vircam_pfits.h"
00044 #include "vircam_paf.h"
00045 
00046 /* Function prototypes */
00047 
00048 static int vircam_detector_noise_create(cpl_plugin *) ;
00049 static int vircam_detector_noise_exec(cpl_plugin *) ;
00050 static int vircam_detector_noise_destroy(cpl_plugin *) ;
00051 static int vircam_detector_noise(cpl_parameterlist *, cpl_frameset *) ;
00052 static int vircam_detector_noise_save(cpl_frameset *framelist, 
00053                                       cpl_parameterlist *parlist);
00054 static void vircam_detector_noise_init(void);
00055 static void vircam_detector_noise_tidy(void);
00056 
00057 /* Static global variables */
00058 
00059 static struct {
00060 
00061     /* Input */
00062 
00063     float       thresh;
00064     int         extenum;
00065 
00066     /* Output */
00067 
00068     float       gain;
00069     float       readnoise;
00070     float       counts;
00071     float       lampflux;
00072 } vircam_detector_noise_config ;
00073 
00074 static struct {
00075     int              *labels;
00076     cpl_frameset     *darklist;
00077     cpl_frameset     *domelist;
00078     cpl_frame        *inherit;
00079     cpl_image        *darkim1;
00080     cpl_image        *darkim2;
00081     cpl_image        *domeim1;
00082     cpl_image        *domeim2;
00083     vir_mask         *master_mask;
00084     cpl_propertylist *ph;
00085     cpl_propertylist *eh;
00086     cpl_propertylist *phupaf;
00087 } ps;
00088 
00089 static cpl_frame *product_frame = NULL;
00090 static int isfirst;
00091 static int dummy;
00092 
00093 #define BUZZ_OFF {vircam_detector_noise_tidy(); return(-1);}
00094 
00095 static char vircam_detector_noise_description[] =
00096 "vircam_detector_noise -- VIRCAM readnoise and gain recipe.\n\n"
00097 "Measures the read noise and gain of a chip using two dome flat exposures\n"
00098 "and two dark exposures. The flats should have the same illumination.\n"
00099 "All four frames should have the same exposure time. If the SOF\n"
00100 "contains more than two files of a given type, the others are ignored.\n\n"
00101 "The program requires the following files in the SOF:\n\n"
00102 "    Tag                   Description\n"
00103 "    -----------------------------------------------------------------------\n"
00104 "    %-21s A list of two raw dark images\n"
00105 "    %-21s A list of two raw dome flat image\n"
00106 "    %-21s Optional master bad pixel map or\n"
00107 "    %-21s Optional master confidence map\n"
00108 "\n";
00109 
00175 /* Function code */
00176 
00177 /*---------------------------------------------------------------------------*/
00185 /*---------------------------------------------------------------------------*/
00186 
00187 int cpl_plugin_get_info(cpl_pluginlist *list) {
00188     cpl_recipe  *recipe = cpl_calloc(1,sizeof(*recipe));
00189     cpl_plugin  *plugin = &recipe->interface;
00190     char alldesc[SZ_ALLDESC];
00191     (void)snprintf(alldesc,SZ_ALLDESC,vircam_detector_noise_description,
00192                    VIRCAM_NOISE_DARK_RAW,VIRCAM_NOISE_FLAT_RAW,VIRCAM_CAL_BPM,
00193                    VIRCAM_CAL_CONF);
00194 
00195     cpl_plugin_init(plugin,
00196                     CPL_PLUGIN_API,
00197                     VIRCAM_BINARY_VERSION,
00198                     CPL_PLUGIN_TYPE_RECIPE,
00199                     "vircam_detector_noise",
00200                     "VIRCAM recipe to determine readout noise and gain",
00201                     alldesc,
00202                     "Jim Lewis",
00203                     "jrl@ast.cam.ac.uk",
00204                     vircam_get_license(),
00205                     vircam_detector_noise_create,
00206                     vircam_detector_noise_exec,
00207                     vircam_detector_noise_destroy);
00208 
00209     cpl_pluginlist_append(list,plugin);
00210 
00211     return(0);
00212 }
00213 
00214 
00215 /*---------------------------------------------------------------------------*/
00224 /*---------------------------------------------------------------------------*/
00225 
00226 static int vircam_detector_noise_create(cpl_plugin *plugin) {
00227     cpl_recipe      *recipe;
00228     cpl_parameter   *p;
00229 
00230     /* Get the recipe out of the plugin */
00231 
00232     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00233         recipe = (cpl_recipe *)plugin;
00234     else
00235         return(-1);
00236 
00237     /* Create the parameters list in the cpl_recipe object */
00238 
00239     recipe->parameters = cpl_parameterlist_new();
00240 
00241     /* Fill in the rejection threshold parameter */
00242 
00243     p = cpl_parameter_new_value("vircam.vircam_detector_noise.thresh",
00244                                 CPL_TYPE_DOUBLE,
00245                                 "Rejection threshold in sigma above background",                                "vircam.vircam_detector_noise",5.0);
00246     cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"thresh");
00247     cpl_parameterlist_append(recipe->parameters,p);
00248 
00249     /* Extension number of input frames to use */
00250 
00251     p = cpl_parameter_new_range("vircam.vircam_detector_noise.extenum",
00252                                 CPL_TYPE_INT,
00253                                 "Extension number to be done, 0 == all",
00254                                 "vircam.vircam_detector_noise",
00255                                 1,0,16);
00256     cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ext");
00257     cpl_parameterlist_append(recipe->parameters,p);
00258 
00259     /* Get out of here */
00260 
00261     return(0);
00262 }
00263 
00264 /*---------------------------------------------------------------------------*/
00270 /*---------------------------------------------------------------------------*/
00271 
00272 static int vircam_detector_noise_destroy(cpl_plugin *plugin) {
00273     cpl_recipe *recipe ;
00274 
00275     /* Get the recipe out of the plugin */
00276 
00277     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00278         recipe = (cpl_recipe *)plugin;
00279     else
00280         return(-1);
00281 
00282     cpl_parameterlist_delete(recipe->parameters);
00283     return(0);
00284 }
00285 
00286 /*---------------------------------------------------------------------------*/
00292 /*---------------------------------------------------------------------------*/
00293 
00294 static int vircam_detector_noise_exec(cpl_plugin *plugin) {
00295     cpl_recipe  *recipe;
00296 
00297     /* Get the recipe out of the plugin */
00298 
00299     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00300         recipe = (cpl_recipe *)plugin;
00301     else
00302         return(-1);
00303 
00304     return(vircam_detector_noise(recipe->parameters,recipe->frames));
00305 }
00306 
00307 /*---------------------------------------------------------------------------*/
00314 /*---------------------------------------------------------------------------*/
00315 
00316 static int vircam_detector_noise(cpl_parameterlist *parlist,
00317                                  cpl_frameset *framelist) {
00318     const char *fctid="vircam_detector_noise";
00319     cpl_parameter *p;
00320     int nlab,j,jst,jfn,retval,nx,ny,live;
00321     long nptsdark;
00322     float meandark1,meandome1,meandark2,meandome2,sigdark,lcut,hcut;
00323     float meandarkdiff,sigdarkdiff,counts;
00324     float meandomediff,sigdomediff,gain,readnoise,exptime;
00325     cpl_frame *dark1,*dark2,*dome1,*dome2;
00326     cpl_propertylist *plist;
00327     unsigned char *bpm;
00328 
00329     /* Check validity of input frameset */
00330 
00331     if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
00332         cpl_msg_error(fctid,"Input framelist NULL or has no input data\n");
00333         return(-1);
00334     }
00335 
00336     /* Check the files in the frameset */
00337 
00338     if (vircam_frameset_fexists(framelist) != VIR_OK) {
00339         cpl_msg_error(fctid,"Input frameset is missing files. Check SOF");
00340         return(-1);
00341     }
00342 
00343     /* Initialise a few things */
00344 
00345     vircam_detector_noise_init();
00346 
00347     /* Get the parameters */
00348 
00349     p = cpl_parameterlist_find(parlist,"vircam.vircam_detector_noise.thresh");
00350     vircam_detector_noise_config.thresh = (float)cpl_parameter_get_double(p);
00351     p = cpl_parameterlist_find(parlist,"vircam.vircam_detector_noise.extenum");
00352     vircam_detector_noise_config.extenum = cpl_parameter_get_int(p);
00353 
00354     /* Sort out raw from calib frames */
00355 
00356     if (vircam_dfs_set_groups(framelist) != VIR_OK) {
00357         cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
00358         vircam_detector_noise_tidy();
00359         return(-1);
00360     }
00361 
00362     /* Get dark and dome flat frames. Make sure there are at least 2 of each */
00363 
00364     if ((ps.labels = cpl_frameset_labelise(framelist,vircam_compare_tags,
00365                                            &nlab)) == NULL) {
00366         cpl_msg_error(fctid,"Cannot labelise the input frameset");
00367         BUZZ_OFF
00368     }
00369     if ((ps.darklist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
00370                                                 VIRCAM_NOISE_DARK_RAW)) == NULL) {
00371         cpl_msg_error(fctid,"Cannot find dark frames in input frameset");
00372         BUZZ_OFF
00373     }
00374     if (cpl_frameset_get_size(ps.darklist) < 2) {
00375         cpl_msg_error(fctid,"Dark frameset doesn't have enough frames");
00376         BUZZ_OFF
00377     }
00378     if ((ps.domelist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
00379                                                 VIRCAM_NOISE_FLAT_RAW)) == NULL) {
00380         cpl_msg_error(fctid,"Cannot find dome flat frames in input frameset");
00381         BUZZ_OFF
00382     }
00383     if (cpl_frameset_get_size(ps.domelist) < 2) {
00384         cpl_msg_error(fctid,"Dome flat frameset doesn't have enough frames");
00385         BUZZ_OFF
00386     }
00387 
00388     /* Check to see if there is a master bad pixel map. If there isn't one 
00389        then look for a confidence map */
00390 
00391     ps.master_mask = vircam_mask_define(framelist,ps.labels,nlab);
00392 
00393     /* Set up some convenience variables */
00394 
00395     dark1 = cpl_frameset_get_frame(ps.darklist,0);
00396     dark2 = cpl_frameset_get_frame(ps.darklist,1);
00397     dome1 = cpl_frameset_get_frame(ps.domelist,0);
00398     dome2 = cpl_frameset_get_frame(ps.domelist,1);
00399     ps.inherit = dome1;
00400     
00401     /* Get a propertylist for the primary */
00402 
00403     ps.ph = cpl_propertylist_load(cpl_frame_get_filename(dome1),0);
00404     (void)vircam_pfits_get_exptime((const cpl_propertylist *)ps.ph,&exptime);
00405 
00406     /* Loop for each of the image extensions */
00407 
00408     vircam_exten_range(vircam_detector_noise_config.extenum,
00409                        (const cpl_frame *)dark1,&jst,&jfn);
00410     if (jst == -1 || jfn == -1) {
00411         cpl_msg_error(fctid,"Unable to continue");
00412         vircam_detector_noise_tidy();
00413         return(-1);
00414     }
00415     for (j = jst; j <= jfn; j++) {
00416         cpl_msg_info(fctid,"Beginning work on extension %d",j);
00417         isfirst = (j == jst);
00418         vircam_detector_noise_config.readnoise = 0.0;
00419         vircam_detector_noise_config.gain = 0.0;
00420         vircam_detector_noise_config.counts = 0.0;
00421         vircam_detector_noise_config.lampflux = 0.0;
00422         dummy = 1;
00423 
00424         /* Get the full set of images */
00425 
00426         ps.darkim1 = cpl_image_load(cpl_frame_get_filename(dark1),
00427                                     CPL_TYPE_FLOAT,0,j);
00428         ps.darkim2 = cpl_image_load(cpl_frame_get_filename(dark2),
00429                                     CPL_TYPE_FLOAT,0,j);
00430         ps.domeim1 = cpl_image_load(cpl_frame_get_filename(dome1),
00431                                     CPL_TYPE_FLOAT,0,j);
00432         ps.domeim2 = cpl_image_load(cpl_frame_get_filename(dome2),
00433                                     CPL_TYPE_FLOAT,0,j);
00434         if (ps.darkim1 == NULL || ps.darkim2 == NULL || ps.domeim1 == NULL ||
00435             ps.domeim2 == NULL) {
00436             cpl_error_reset();
00437             cpl_msg_error(fctid,"NULL image input for extension %d",j);
00438             retval = vircam_detector_noise_save(framelist,parlist);
00439             freeimage(ps.darkim1);
00440             freeimage(ps.darkim2);
00441             freeimage(ps.domeim1);
00442             freeimage(ps.domeim2);
00443             continue;
00444         }
00445 
00446         /* Get some an extension propertylist */
00447 
00448         ps.eh = cpl_propertylist_load(cpl_frame_get_filename(dome1),j);
00449 
00450         /* Check that the current detectors are live */
00451 
00452         plist = cpl_propertylist_load(cpl_frame_get_filename(dark1),j);
00453         vircam_pfits_get_detlive(plist,&live);
00454         if (! live) {
00455             cpl_msg_warning(fctid,"First dark image detector not live");
00456             retval = vircam_detector_noise_save(framelist,parlist);
00457             cpl_propertylist_delete(plist);
00458             freeimage(ps.darkim1);
00459             freeimage(ps.darkim2);
00460             freeimage(ps.domeim1);
00461             freeimage(ps.domeim2);
00462             freepropertylist(ps.eh);
00463             continue;
00464         }
00465         cpl_propertylist_delete(plist);
00466         plist = cpl_propertylist_load(cpl_frame_get_filename(dark2),j);
00467         vircam_pfits_get_detlive(plist,&live);
00468         if (! live) {
00469             cpl_msg_warning(fctid,"Second dark image detector not live");
00470             retval = vircam_detector_noise_save(framelist,parlist);
00471             cpl_propertylist_delete(plist);
00472             freeimage(ps.darkim1);
00473             freeimage(ps.darkim2);
00474             freeimage(ps.domeim1);
00475             freeimage(ps.domeim2);
00476             freepropertylist(ps.eh);
00477             continue;
00478         }
00479         cpl_propertylist_delete(plist);
00480         plist = cpl_propertylist_load(cpl_frame_get_filename(dome1),j);
00481         vircam_pfits_get_detlive(plist,&live);
00482         if (! live) {
00483             cpl_msg_warning(fctid,"First dome image detector not live");
00484             retval = vircam_detector_noise_save(framelist,parlist);
00485             cpl_propertylist_delete(plist);
00486             freeimage(ps.darkim1);
00487             freeimage(ps.darkim2);
00488             freeimage(ps.domeim1);
00489             freeimage(ps.domeim2);
00490             freepropertylist(ps.eh);
00491             continue;
00492         }
00493         cpl_propertylist_delete(plist);
00494         plist = cpl_propertylist_load(cpl_frame_get_filename(dome2),j);
00495         vircam_pfits_get_detlive(plist,&live);
00496         if (! live) {
00497             cpl_msg_warning(fctid,"Second dome image detector not live");
00498             retval = vircam_detector_noise_save(framelist,parlist);
00499             cpl_propertylist_delete(plist);
00500             freeimage(ps.darkim1);
00501             freeimage(ps.darkim2);
00502             freeimage(ps.domeim1);
00503             freeimage(ps.domeim2);
00504             freepropertylist(ps.eh);
00505             continue;
00506         }
00507         cpl_propertylist_delete(plist);
00508 
00509         /* Get the data array sizes */
00510 
00511         nx = cpl_image_get_size_x(ps.darkim1);
00512         ny = cpl_image_get_size_y(ps.darkim1);
00513         nptsdark = (long)(nx*ny);
00514 
00515         /* Load the mask */
00516 
00517         if (vircam_mask_load(ps.master_mask,j,nx,ny) == VIR_FATAL) {
00518             cpl_msg_info(fctid,"Unable to load mask image %s[%d]",
00519                          vircam_mask_get_filename(ps.master_mask),j);
00520             cpl_msg_info(fctid,"Forcing all pixels to be good from now on");
00521             vircam_mask_force(ps.master_mask,nx,ny);
00522         }
00523         bpm = vircam_mask_get_data(ps.master_mask);
00524 
00525         /* Get the mean of the first dark and the first dome */
00526 
00527         vircam_medmad((float *)cpl_image_get_data(ps.darkim1),bpm,
00528                                nptsdark,&meandark1,&sigdark);
00529         sigdark *= 1.48;
00530         lcut = meandark1 - vircam_detector_noise_config.thresh*sigdark;
00531         hcut = meandark1 + vircam_detector_noise_config.thresh*sigdark;
00532         vircam_medmadcut((float *)cpl_image_get_data(ps.darkim1),bpm,
00533                          nptsdark,lcut,hcut,&meandark1,&sigdark);
00534         vircam_medmad((float *)cpl_image_get_data(ps.domeim1),bpm,
00535                                nptsdark,&meandome1,&sigdark);
00536         sigdark *= 1.48;
00537         lcut = meandome1 - vircam_detector_noise_config.thresh*sigdark;
00538         hcut = meandome1 + vircam_detector_noise_config.thresh*sigdark;
00539         vircam_medmadcut((float *)cpl_image_get_data(ps.domeim1),bpm,
00540                          nptsdark,lcut,hcut,&meandome1,&sigdark);
00541 
00542         /* Get the mean of the second dark and the second dome */
00543 
00544         vircam_medmad((float *)cpl_image_get_data(ps.darkim2),bpm,
00545                                nptsdark,&meandark2,&sigdark);
00546         sigdark *= 1.48;
00547         lcut = meandark2 - vircam_detector_noise_config.thresh*sigdark;
00548         hcut = meandark2 + vircam_detector_noise_config.thresh*sigdark;
00549         vircam_medmadcut((float *)cpl_image_get_data(ps.darkim2),bpm,
00550                          nptsdark,lcut,hcut,&meandark2,&sigdark);
00551         vircam_medmad((float *)cpl_image_get_data(ps.domeim2),bpm,
00552                                nptsdark,&meandome2,&sigdark);
00553         sigdark *= 1.48;
00554         lcut = meandome2 - vircam_detector_noise_config.thresh*sigdark;
00555         hcut = meandome2 + vircam_detector_noise_config.thresh*sigdark;
00556         vircam_medmadcut((float *)cpl_image_get_data(ps.domeim2),bpm,
00557                          nptsdark,lcut,hcut,&meandome2,&sigdark);
00558 
00559         /* Form a difference image with each the of the dark and dome pairs */
00560 
00561         cpl_image_subtract(ps.darkim1,ps.darkim2);
00562         cpl_image_subtract(ps.domeim1,ps.domeim2);
00563 
00564         /* Now measure the mean and sigma of each of the difference images */
00565     
00566         vircam_medmad((float *)cpl_image_get_data(ps.darkim1),bpm,
00567                                nptsdark,&meandarkdiff,&sigdarkdiff);
00568         sigdarkdiff *= 1.48;
00569         lcut = meandarkdiff - vircam_detector_noise_config.thresh*sigdarkdiff;
00570         hcut = meandarkdiff + vircam_detector_noise_config.thresh*sigdarkdiff;
00571         vircam_medmadcut((float *)cpl_image_get_data(ps.darkim1),bpm,
00572                          nptsdark,lcut,hcut,&meandarkdiff,&sigdarkdiff);
00573         sigdarkdiff *= 1.48;
00574         vircam_medmad((float *)cpl_image_get_data(ps.domeim1),bpm,
00575                                nptsdark,&meandomediff,&sigdomediff);
00576         sigdomediff *= 1.48;
00577         lcut = meandomediff - vircam_detector_noise_config.thresh*sigdomediff;
00578         hcut = meandomediff + vircam_detector_noise_config.thresh*sigdomediff;
00579         vircam_medmadcut((float *)cpl_image_get_data(ps.domeim1),bpm,
00580                          nptsdark,lcut,hcut,&meandomediff,&sigdomediff);
00581         sigdomediff *= 1.48;
00582 
00583         /* Work out gain */
00584 
00585         counts = (meandome1 + meandome2) - (meandark1 + meandark2);
00586         vircam_detector_noise_config.counts = 0.5*counts;
00587         vircam_detector_noise_config.lampflux = 0.5*counts/exptime;
00588         gain = counts/(sigdomediff*sigdomediff - sigdarkdiff*sigdarkdiff);
00589         vircam_detector_noise_config.gain = gain;
00590 
00591         /* Now the read noise */
00592 
00593         readnoise = gain*sigdarkdiff/sqrt(2.0);
00594         vircam_detector_noise_config.readnoise = readnoise;
00595         dummy = 0;
00596     
00597         /* Save the products */
00598 
00599         retval = vircam_detector_noise_save(framelist,parlist);
00600         if (retval != 0) {
00601             cpl_msg_error(fctid,"Error saving results");
00602             BUZZ_OFF
00603         }
00604 
00605         /* Tidy up */
00606 
00607         freeimage(ps.darkim1);
00608         freeimage(ps.darkim2);
00609         freeimage(ps.domeim1);
00610         freeimage(ps.domeim2);
00611         vircam_mask_clear(ps.master_mask);
00612         freepropertylist(ps.eh);
00613     }
00614     vircam_detector_noise_tidy();
00615     return(0);
00616 }
00617 
00618 /*---------------------------------------------------------------------------*/
00625 /*---------------------------------------------------------------------------*/
00626 
00627 static int vircam_detector_noise_save(cpl_frameset *framelist, 
00628                                       cpl_parameterlist *parlist) {
00629     const char *fctid = "vircam_detector_noise_save";
00630     const char *outpaf = "vircam_detector_noise";
00631     const char *outfile = "detector_noise.fits";
00632     const char *recipeid = "vircam_detector_noise";
00633     cpl_propertylist *plist,*p;
00634     cpl_table *o;
00635 
00636     /* If this is the first time through then create the output image */
00637     
00638     if (isfirst) {
00639 
00640         /* Create a new product frame object and define some tags */
00641 
00642         product_frame = cpl_frame_new();
00643         cpl_frame_set_filename(product_frame,outfile);
00644         cpl_frame_set_tag(product_frame,VIRCAM_PRO_READGAINFILE);
00645         cpl_frame_set_type(product_frame,CPL_FRAME_TYPE_IMAGE);
00646         cpl_frame_set_group(product_frame,CPL_FRAME_GROUP_PRODUCT);
00647         cpl_frame_set_level(product_frame,CPL_FRAME_LEVEL_FINAL);
00648 
00649         /* Fiddle with the primary header */
00650 
00651         plist = cpl_propertylist_duplicate(ps.ph);
00652         ps.phupaf = vircam_paf_phu_items(plist);
00653         vircam_dfs_set_product_primary_header(plist,product_frame,framelist,
00654                                               parlist,(char *)recipeid,
00655                                               "PRO-1.15",ps.inherit,0);
00656         vircam_paf_append(ps.phupaf,plist,"ESO PRO CATG");
00657         vircam_paf_append(ps.phupaf,plist,"ESO INS FILT1 NAME");
00658 
00659         /* 'Save' the PHU image */
00660 
00661         if (cpl_image_save(NULL,outfile,CPL_BPP_8_UNSIGNED,plist,
00662                            CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00663             cpl_msg_error(fctid,"Cannot save product PHU");
00664             cpl_frame_delete(product_frame);
00665             cpl_propertylist_delete(plist);
00666             return(-1);
00667         }
00668         cpl_propertylist_delete(plist);
00669         cpl_frameset_insert(framelist,product_frame);
00670     }
00671 
00672     /* Create results header */
00673 
00674     plist = cpl_propertylist_duplicate(ps.eh);
00675 
00676     /* Now add the new data... */
00677 
00678     cpl_propertylist_update_float(plist,"ESO QC READNOISE",
00679                                   vircam_detector_noise_config.readnoise);
00680     cpl_propertylist_set_comment(plist,"ESO QC READNOISE",
00681                                  "[e-] Calculated detector readnoise");
00682     cpl_propertylist_update_float(plist,"ESO QC CONAD",
00683                                   vircam_detector_noise_config.gain);
00684     cpl_propertylist_set_comment(plist,"ESO QC CONAD",
00685                                  "[e-/ADU] Calculated detector gain");
00686     cpl_propertylist_update_float(plist,"ESO QC COUNTS",
00687                                   vircam_detector_noise_config.counts);
00688     cpl_propertylist_set_comment(plist,"ESO QC COUNTS",
00689                                  "[ADU] Dark corrected dome counts");
00690     cpl_propertylist_update_float(plist,"ESO QC LAMPFLUX",
00691                                   vircam_detector_noise_config.lampflux);
00692     cpl_propertylist_set_comment(plist,"ESO QC LAMPFLUX",
00693                                  "[ADU/sec] Dark corrected flux level");
00694 
00695     /* Now fiddle with the extension header */
00696 
00697     vircam_dfs_set_product_exten_header(plist,product_frame,framelist,
00698                                         parlist,(char *)recipeid,
00699                                         "PRO-1.15",ps.inherit);
00700     if (dummy)
00701         vircam_dummy_property(plist);
00702 
00703     /* Create the output table */
00704 
00705     o = cpl_table_new(1);
00706     cpl_table_new_column(o,"EXTNAME",CPL_TYPE_STRING);
00707     cpl_table_new_column(o,"READNOISE",CPL_TYPE_FLOAT);
00708     cpl_table_new_column(o,"GAIN",CPL_TYPE_FLOAT);
00709 
00710     /* Write the values to the table */
00711 
00712     cpl_table_set_string(o,"EXTNAME",0,
00713                          cpl_propertylist_get_string(plist,"EXTNAME"));
00714     cpl_table_set_float(o,"READNOISE",0,
00715                         vircam_detector_noise_config.readnoise);
00716     cpl_table_set_float(o,"GAIN",0,vircam_detector_noise_config.gain);
00717 
00718     /* 'Save' the image */
00719 
00720     if (cpl_table_save(o,NULL,plist,outfile,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00721         cpl_msg_error(fctid,"Cannot save product");
00722         cpl_propertylist_delete(plist);
00723         cpl_frame_delete(product_frame);
00724         freetable(o);
00725         return(-1);
00726     }
00727     freetable(o);
00728 
00729     /* Write the PAF */
00730 
00731     p = vircam_paf_req_items(plist);
00732     vircam_merge_propertylists(p,ps.phupaf);
00733     if (vircam_paf_print((char *)outpaf,"VIRCAM/vircam_detector_noise",
00734                          "QC file",p) != VIR_OK)
00735         cpl_msg_warning(fctid,"Unable to write PAF\n");
00736     cpl_propertylist_delete(p);
00737 
00738     /* Tidy and exit */
00739 
00740     freepropertylist(plist);
00741     return(0);
00742 }
00743 
00744 /*---------------------------------------------------------------------------*/
00748 /*---------------------------------------------------------------------------*/
00749 
00750 static void vircam_detector_noise_init(void) {
00751     ps.labels = NULL;
00752     ps.darklist = NULL;
00753     ps.domelist = NULL;
00754     ps.darkim1 = NULL;
00755     ps.darkim2 = NULL;
00756     ps.domeim1 = NULL;
00757     ps.domeim2 = NULL;
00758     ps.master_mask = NULL;
00759     ps.inherit = NULL;
00760     ps.ph = NULL;
00761     ps.eh = NULL;
00762     ps.phupaf = NULL;
00763     return;
00764 }
00765 
00766 /*---------------------------------------------------------------------------*/
00770 /*---------------------------------------------------------------------------*/
00771 
00772 static void vircam_detector_noise_tidy(void) {
00773     freespace(ps.labels);
00774     freeframeset(ps.darklist);
00775     freeframeset(ps.domelist);
00776     freeimage(ps.darkim1);
00777     freeimage(ps.darkim2);
00778     freeimage(ps.domeim1);
00779     freeimage(ps.domeim2);
00780     freemask(ps.master_mask);
00781     freepropertylist(ps.ph);
00782     freepropertylist(ps.eh);
00783     freepropertylist(ps.phupaf);
00784     return;
00785 }
00786 
00790 /*
00791 
00792 $Log: vircam_detector_noise.c,v $
00793 Revision 1.55  2010/12/09 13:19:19  jim
00794 Fixed bug where reported flux was a factor of two too high
00795 
00796 Revision 1.54  2010/06/30 12:42:00  jim
00797 A few fixes to stop compiler compaints
00798 
00799 Revision 1.53  2010/03/09 14:28:38  jim
00800 Added new QC values COUNTS and LAMPFLUX
00801 
00802 Revision 1.52  2010/01/31 18:55:30  jim
00803 Filter name written to PAF. QC GAIN changed to QC CONAD (in spite of the
00804 dreadful name)
00805 
00806 Revision 1.51  2009/09/09 09:50:21  jim
00807 Modified to try and get headers right
00808 
00809 Revision 1.50  2008/10/01 04:59:13  jim
00810 Added call to vircam_frameset_fexists to check input frameset
00811 
00812 Revision 1.49  2008/09/30 11:33:23  jim
00813 Added PRO CATG to pafs
00814 
00815 Revision 1.48  2007/10/25 18:39:22  jim
00816 Altered to remove some lint messages
00817 
00818 Revision 1.47  2007/10/15 12:52:39  jim
00819 Fixed little cockup which had duplicate entries in the ps structure
00820 
00821 Revision 1.46  2007/09/07 13:32:12  jim
00822 uses a sorted framelist to ensure that the correct information is given
00823 to the output product header
00824 
00825 Revision 1.45  2007/09/06 21:37:53  jim
00826 fixed call to vircam_dfs_setup_product_ routines to use the full input
00827 frameset
00828 
00829 Revision 1.44  2007/07/18 15:35:41  jim
00830 Added better error handling for missing or corrupt mask extensions
00831 
00832 Revision 1.43  2007/07/09 13:21:55  jim
00833 Modified to use new version of vircam_exten_range
00834 
00835 Revision 1.42  2007/06/13 08:11:27  jim
00836 Modified docs to reflect changes in DFS tags
00837 
00838 Revision 1.41  2007/04/04 10:36:18  jim
00839 Modified to use new dfs tags
00840 
00841 Revision 1.40  2007/03/29 12:19:38  jim
00842 Little changes to improve documentation
00843 
00844 Revision 1.39  2007/03/06 12:30:17  jim
00845 Now writes results to a table in addtion to a header and a paf.
00846 
00847 Revision 1.38  2007/03/01 12:41:49  jim
00848 Modified slightly after code checking
00849 
00850 Revision 1.37  2007/02/25 06:26:35  jim
00851 Plugged a few memory leaks
00852 
00853 Revision 1.36  2007/02/15 06:59:37  jim
00854 Added ability to write QC paf files
00855 
00856 Revision 1.35  2007/02/07 10:12:39  jim
00857 Removed calls to vircam_ndit_correct as this is now no longer necessary
00858 
00859 Revision 1.34  2007/02/06 13:11:12  jim
00860 Fixed entry for PRO dictionary in cpl_dfs_set_product_header
00861 
00862 Revision 1.33  2007/02/06 12:38:59  jim
00863 Creates a sorted version of the input frameset so that a dome flat is first
00864 in the list. This is done so that the header of the output product comes
00865 from one of the dome flats and so that you can see which filter it was done
00866 with.
00867 
00868 Revision 1.32  2007/02/06 11:59:38  jim
00869 Added call to vircam_medmadcut for a better estimate of dispersion
00870 
00871 Revision 1.31  2007/01/17 23:56:12  jim
00872 Plugged possible memory leak
00873 
00874 Revision 1.30  2006/12/14 14:46:32  jim
00875 Fixed typo
00876 
00877 Revision 1.29  2006/12/11 22:47:49  jim
00878 Fixed QC header names
00879 
00880 Revision 1.28  2006/11/27 12:16:33  jim
00881 Modified to change location in the header where the results are written
00882 
00883 Revision 1.27  2006/11/10 09:20:29  jim
00884 Fixed _save routine so that an extension name is written out to the file
00885 header
00886 
00887 Revision 1.26  2006/09/29 11:19:31  jim
00888 changed aliases on parameter names
00889 
00890 Revision 1.25  2006/09/09 16:49:39  jim
00891 Header comment update
00892 
00893 Revision 1.24  2006/09/08 09:17:27  jim
00894 Modified to flag dummy results
00895 
00896 Revision 1.23  2006/09/04 23:02:14  jim
00897 Modified to deal with det live issues. Also does a better job of dealing
00898 with duff input
00899 
00900 Revision 1.22  2006/06/20 19:07:01  jim
00901 Corrects for ndit != 1
00902 
00903 Revision 1.21  2006/06/15 09:58:58  jim
00904 Minor changes to docs
00905 
00906 Revision 1.20  2006/06/13 21:27:10  jim
00907 Changed output product to a MEF with null images and readnoise/gain estimates
00908 in the header. I HATE this solution
00909 
00910 Revision 1.19  2006/06/09 11:26:25  jim
00911 Small changes to keep lint happy
00912 
00913 Revision 1.18  2006/05/04 11:56:02  jim
00914 changed filename extension in default output file
00915 
00916 Revision 1.17  2006/05/04 11:53:14  jim
00917 Fixed the way the _save routine works to be more consistent with the
00918 standard CPL way of doing things
00919 
00920 Revision 1.16  2006/04/27 09:46:01  jim
00921 Modified DFS frame types to conform to new dictionary
00922 
00923 Revision 1.15  2006/03/22 14:02:51  jim
00924 cosmetic changes to keep lint happy
00925 
00926 Revision 1.14  2006/03/22 12:13:51  jim
00927 Modified to use new vircam_mask capability
00928 
00929 Revision 1.13  2006/03/15 10:43:40  jim
00930 Fixed a few things
00931 
00932 Revision 1.12  2006/01/23 10:36:39  jim
00933 Now allows a CPM or a BPM to be used as the mask
00934 
00935 Revision 1.11  2005/12/14 22:19:12  jim
00936 fixed docs
00937 
00938 Revision 1.10  2005/12/09 09:47:58  jim
00939 Many changes to add more documentation
00940 
00941 Revision 1.9  2005/12/02 10:45:37  jim
00942 The tags used in the sof are now written to the description string in the
00943 constructor. This is so that if they change in the vircam_dfs.h file, they
00944 aren't then hardcopied into each of the recipes...
00945 
00946 Revision 1.8  2005/11/29 16:10:58  jim
00947 Added clipping into stats for difference images
00948 
00949 Revision 1.7  2005/11/25 15:20:29  jim
00950 Fixed bug in mathematical description
00951 
00952 Revision 1.6  2005/11/25 09:56:14  jim
00953 Tidied up some more documentation
00954 
00955 Revision 1.5  2005/11/23 14:57:40  jim
00956 A bit of tidying in response to splint messages
00957 
00958 Revision 1.4  2005/11/21 16:16:23  jim
00959 Added some better garbage collection
00960 
00961 Revision 1.3  2005/11/07 13:14:18  jim
00962 Added some error trapping and some docs
00963 
00964 Revision 1.2  2005/08/09 11:09:39  jim
00965 Replaced dodgy call to cpl_framelist_delete with correct cpl_frameset_delete
00966 
00967 Revision 1.1.1.1  2005/08/05 08:29:09  jim
00968 Initial import
00969 
00970 
00971 */

Generated on 7 Feb 2011 for VIRCAM Pipeline by  doxygen 1.6.1