vircam_detector_noise.c

00001 /* $Id: vircam_detector_noise.c,v 1.57 2012/01/16 12:32:18 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: 2012/01/16 12:32:18 $
00024  * $Revision: 1.57 $
00025  * $Name: vcam-1_3_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     cpl_size         *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 j,jst,jfn,retval,nx,ny,live;
00321     cpl_size nlab;
00322     long nptsdark;
00323     float meandark1,meandome1,meandark2,meandome2,sigdark,lcut,hcut;
00324     float meandarkdiff,sigdarkdiff,counts;
00325     float meandomediff,sigdomediff,gain,readnoise,exptime;
00326     cpl_frame *dark1,*dark2,*dome1,*dome2;
00327     cpl_propertylist *plist;
00328     unsigned char *bpm;
00329 
00330     /* Check validity of input frameset */
00331 
00332     if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
00333         cpl_msg_error(fctid,"Input framelist NULL or has no input data");
00334         return(-1);
00335     }
00336 
00337     /* Check the files in the frameset */
00338 
00339     if (vircam_frameset_fexists(framelist) != VIR_OK) {
00340         cpl_msg_error(fctid,"Input frameset is missing files. Check SOF");
00341         return(-1);
00342     }
00343 
00344     /* Initialise a few things */
00345 
00346     vircam_detector_noise_init();
00347 
00348     /* Get the parameters */
00349 
00350     p = cpl_parameterlist_find(parlist,"vircam.vircam_detector_noise.thresh");
00351     vircam_detector_noise_config.thresh = (float)cpl_parameter_get_double(p);
00352     p = cpl_parameterlist_find(parlist,"vircam.vircam_detector_noise.extenum");
00353     vircam_detector_noise_config.extenum = cpl_parameter_get_int(p);
00354 
00355     /* Sort out raw from calib frames */
00356 
00357     if (vircam_dfs_set_groups(framelist) != VIR_OK) {
00358         cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
00359         vircam_detector_noise_tidy();
00360         return(-1);
00361     }
00362 
00363     /* Get dark and dome flat frames. Make sure there are at least 2 of each */
00364 
00365     if ((ps.labels = cpl_frameset_labelise(framelist,vircam_compare_tags,
00366                                            &nlab)) == NULL) {
00367         cpl_msg_error(fctid,"Cannot labelise the input frameset");
00368         BUZZ_OFF
00369     }
00370     if ((ps.darklist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
00371                                                 VIRCAM_NOISE_DARK_RAW)) == NULL) {
00372         cpl_msg_error(fctid,"Cannot find dark frames in input frameset");
00373         BUZZ_OFF
00374     }
00375     if (cpl_frameset_get_size(ps.darklist) < 2) {
00376         cpl_msg_error(fctid,"Dark frameset doesn't have enough frames");
00377         BUZZ_OFF
00378     }
00379     if ((ps.domelist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
00380                                                 VIRCAM_NOISE_FLAT_RAW)) == NULL) {
00381         cpl_msg_error(fctid,"Cannot find dome flat frames in input frameset");
00382         BUZZ_OFF
00383     }
00384     if (cpl_frameset_get_size(ps.domelist) < 2) {
00385         cpl_msg_error(fctid,"Dome flat frameset doesn't have enough frames");
00386         BUZZ_OFF
00387     }
00388 
00389     /* Check to see if there is a master bad pixel map. If there isn't one 
00390        then look for a confidence map */
00391 
00392     ps.master_mask = vircam_mask_define(framelist,ps.labels,nlab);
00393 
00394     /* Set up some convenience variables */
00395 
00396     dark1 = cpl_frameset_get_frame(ps.darklist,0);
00397     dark2 = cpl_frameset_get_frame(ps.darklist,1);
00398     dome1 = cpl_frameset_get_frame(ps.domelist,0);
00399     dome2 = cpl_frameset_get_frame(ps.domelist,1);
00400     ps.inherit = dome1;
00401     
00402     /* Get a propertylist for the primary */
00403 
00404     ps.ph = cpl_propertylist_load(cpl_frame_get_filename(dome1),0);
00405     (void)vircam_pfits_get_exptime((const cpl_propertylist *)ps.ph,&exptime);
00406 
00407     /* Loop for each of the image extensions */
00408 
00409     vircam_exten_range(vircam_detector_noise_config.extenum,
00410                        (const cpl_frame *)dark1,&jst,&jfn);
00411     if (jst == -1 || jfn == -1) {
00412         cpl_msg_error(fctid,"Unable to continue");
00413         vircam_detector_noise_tidy();
00414         return(-1);
00415     }
00416     for (j = jst; j <= jfn; j++) {
00417         cpl_msg_info(fctid,"Beginning work on extension %" CPL_SIZE_FORMAT,
00418                      (cpl_size)j);
00419         isfirst = (j == jst);
00420         vircam_detector_noise_config.readnoise = 0.0;
00421         vircam_detector_noise_config.gain = 0.0;
00422         vircam_detector_noise_config.counts = 0.0;
00423         vircam_detector_noise_config.lampflux = 0.0;
00424         dummy = 1;
00425 
00426         /* Get the full set of images */
00427 
00428         ps.darkim1 = cpl_image_load(cpl_frame_get_filename(dark1),
00429                                     CPL_TYPE_FLOAT,0,(cpl_size)j);
00430         ps.darkim2 = cpl_image_load(cpl_frame_get_filename(dark2),
00431                                     CPL_TYPE_FLOAT,0,(cpl_size)j);
00432         ps.domeim1 = cpl_image_load(cpl_frame_get_filename(dome1),
00433                                     CPL_TYPE_FLOAT,0,(cpl_size)j);
00434         ps.domeim2 = cpl_image_load(cpl_frame_get_filename(dome2),
00435                                     CPL_TYPE_FLOAT,0,(cpl_size)j);
00436         if (ps.darkim1 == NULL || ps.darkim2 == NULL || ps.domeim1 == NULL ||
00437             ps.domeim2 == NULL) {
00438             cpl_error_reset();
00439             cpl_msg_error(fctid,
00440                           "NULL image input for extension %" CPL_SIZE_FORMAT,
00441                           (cpl_size)j);
00442             retval = vircam_detector_noise_save(framelist,parlist);
00443             freeimage(ps.darkim1);
00444             freeimage(ps.darkim2);
00445             freeimage(ps.domeim1);
00446             freeimage(ps.domeim2);
00447             continue;
00448         }
00449 
00450         /* Get some an extension propertylist */
00451 
00452         ps.eh = cpl_propertylist_load(cpl_frame_get_filename(dome1),
00453                                       (cpl_size)j);
00454 
00455         /* Check that the current detectors are live */
00456 
00457         plist = cpl_propertylist_load(cpl_frame_get_filename(dark1),
00458                                       (cpl_size)j);
00459         vircam_pfits_get_detlive(plist,&live);
00460         if (! live) {
00461             cpl_msg_warning(fctid,"First dark image detector not live");
00462             retval = vircam_detector_noise_save(framelist,parlist);
00463             cpl_propertylist_delete(plist);
00464             freeimage(ps.darkim1);
00465             freeimage(ps.darkim2);
00466             freeimage(ps.domeim1);
00467             freeimage(ps.domeim2);
00468             freepropertylist(ps.eh);
00469             continue;
00470         }
00471         cpl_propertylist_delete(plist);
00472         plist = cpl_propertylist_load(cpl_frame_get_filename(dark2),
00473                                       (cpl_size)j);
00474         vircam_pfits_get_detlive(plist,&live);
00475         if (! live) {
00476             cpl_msg_warning(fctid,"Second dark image detector not live");
00477             retval = vircam_detector_noise_save(framelist,parlist);
00478             cpl_propertylist_delete(plist);
00479             freeimage(ps.darkim1);
00480             freeimage(ps.darkim2);
00481             freeimage(ps.domeim1);
00482             freeimage(ps.domeim2);
00483             freepropertylist(ps.eh);
00484             continue;
00485         }
00486         cpl_propertylist_delete(plist);
00487         plist = cpl_propertylist_load(cpl_frame_get_filename(dome1),
00488                                       (cpl_size)j);
00489         vircam_pfits_get_detlive(plist,&live);
00490         if (! live) {
00491             cpl_msg_warning(fctid,"First dome image detector not live");
00492             retval = vircam_detector_noise_save(framelist,parlist);
00493             cpl_propertylist_delete(plist);
00494             freeimage(ps.darkim1);
00495             freeimage(ps.darkim2);
00496             freeimage(ps.domeim1);
00497             freeimage(ps.domeim2);
00498             freepropertylist(ps.eh);
00499             continue;
00500         }
00501         cpl_propertylist_delete(plist);
00502         plist = cpl_propertylist_load(cpl_frame_get_filename(dome2),
00503                                       (cpl_size)j);
00504         vircam_pfits_get_detlive(plist,&live);
00505         if (! live) {
00506             cpl_msg_warning(fctid,"Second dome image detector not live");
00507             retval = vircam_detector_noise_save(framelist,parlist);
00508             cpl_propertylist_delete(plist);
00509             freeimage(ps.darkim1);
00510             freeimage(ps.darkim2);
00511             freeimage(ps.domeim1);
00512             freeimage(ps.domeim2);
00513             freepropertylist(ps.eh);
00514             continue;
00515         }
00516         cpl_propertylist_delete(plist);
00517 
00518         /* Get the data array sizes */
00519 
00520         nx = (int)cpl_image_get_size_x(ps.darkim1);
00521         ny = (int)cpl_image_get_size_y(ps.darkim1);
00522         nptsdark = (long)(nx*ny);
00523 
00524         /* Load the mask */
00525 
00526         if (vircam_mask_load(ps.master_mask,j,nx,ny) == VIR_FATAL) {
00527             cpl_msg_info(fctid,
00528                          "Unable to load mask image %s[%" CPL_SIZE_FORMAT "]",
00529                          vircam_mask_get_filename(ps.master_mask),(cpl_size)j);
00530             cpl_msg_info(fctid,"Forcing all pixels to be good from now on");
00531             vircam_mask_force(ps.master_mask,nx,ny);
00532         }
00533         bpm = vircam_mask_get_data(ps.master_mask);
00534 
00535         /* Get the mean of the first dark and the first dome */
00536 
00537         vircam_medmad((float *)cpl_image_get_data(ps.darkim1),bpm,
00538                                nptsdark,&meandark1,&sigdark);
00539         sigdark *= 1.48;
00540         lcut = meandark1 - vircam_detector_noise_config.thresh*sigdark;
00541         hcut = meandark1 + vircam_detector_noise_config.thresh*sigdark;
00542         vircam_medmadcut((float *)cpl_image_get_data(ps.darkim1),bpm,
00543                          nptsdark,lcut,hcut,&meandark1,&sigdark);
00544         vircam_medmad((float *)cpl_image_get_data(ps.domeim1),bpm,
00545                                nptsdark,&meandome1,&sigdark);
00546         sigdark *= 1.48;
00547         lcut = meandome1 - vircam_detector_noise_config.thresh*sigdark;
00548         hcut = meandome1 + vircam_detector_noise_config.thresh*sigdark;
00549         vircam_medmadcut((float *)cpl_image_get_data(ps.domeim1),bpm,
00550                          nptsdark,lcut,hcut,&meandome1,&sigdark);
00551 
00552         /* Get the mean of the second dark and the second dome */
00553 
00554         vircam_medmad((float *)cpl_image_get_data(ps.darkim2),bpm,
00555                                nptsdark,&meandark2,&sigdark);
00556         sigdark *= 1.48;
00557         lcut = meandark2 - vircam_detector_noise_config.thresh*sigdark;
00558         hcut = meandark2 + vircam_detector_noise_config.thresh*sigdark;
00559         vircam_medmadcut((float *)cpl_image_get_data(ps.darkim2),bpm,
00560                          nptsdark,lcut,hcut,&meandark2,&sigdark);
00561         vircam_medmad((float *)cpl_image_get_data(ps.domeim2),bpm,
00562                                nptsdark,&meandome2,&sigdark);
00563         sigdark *= 1.48;
00564         lcut = meandome2 - vircam_detector_noise_config.thresh*sigdark;
00565         hcut = meandome2 + vircam_detector_noise_config.thresh*sigdark;
00566         vircam_medmadcut((float *)cpl_image_get_data(ps.domeim2),bpm,
00567                          nptsdark,lcut,hcut,&meandome2,&sigdark);
00568 
00569         /* Form a difference image with each the of the dark and dome pairs */
00570 
00571         cpl_image_subtract(ps.darkim1,ps.darkim2);
00572         cpl_image_subtract(ps.domeim1,ps.domeim2);
00573 
00574         /* Now measure the mean and sigma of each of the difference images */
00575     
00576         vircam_medmad((float *)cpl_image_get_data(ps.darkim1),bpm,
00577                                nptsdark,&meandarkdiff,&sigdarkdiff);
00578         sigdarkdiff *= 1.48;
00579         lcut = meandarkdiff - vircam_detector_noise_config.thresh*sigdarkdiff;
00580         hcut = meandarkdiff + vircam_detector_noise_config.thresh*sigdarkdiff;
00581         vircam_medmadcut((float *)cpl_image_get_data(ps.darkim1),bpm,
00582                          nptsdark,lcut,hcut,&meandarkdiff,&sigdarkdiff);
00583         sigdarkdiff *= 1.48;
00584         vircam_medmad((float *)cpl_image_get_data(ps.domeim1),bpm,
00585                                nptsdark,&meandomediff,&sigdomediff);
00586         sigdomediff *= 1.48;
00587         lcut = meandomediff - vircam_detector_noise_config.thresh*sigdomediff;
00588         hcut = meandomediff + vircam_detector_noise_config.thresh*sigdomediff;
00589         vircam_medmadcut((float *)cpl_image_get_data(ps.domeim1),bpm,
00590                          nptsdark,lcut,hcut,&meandomediff,&sigdomediff);
00591         sigdomediff *= 1.48;
00592 
00593         /* Work out gain */
00594 
00595         counts = (meandome1 + meandome2) - (meandark1 + meandark2);
00596         vircam_detector_noise_config.counts = 0.5*counts;
00597         vircam_detector_noise_config.lampflux = 0.5*counts/exptime;
00598         gain = counts/(sigdomediff*sigdomediff - sigdarkdiff*sigdarkdiff);
00599         vircam_detector_noise_config.gain = gain;
00600 
00601         /* Now the read noise */
00602 
00603         readnoise = gain*sigdarkdiff/sqrt(2.0);
00604         vircam_detector_noise_config.readnoise = readnoise;
00605         dummy = 0;
00606     
00607         /* Save the products */
00608 
00609         retval = vircam_detector_noise_save(framelist,parlist);
00610         if (retval != 0) {
00611             cpl_msg_error(fctid,"Error saving results");
00612             BUZZ_OFF
00613         }
00614 
00615         /* Tidy up */
00616 
00617         freeimage(ps.darkim1);
00618         freeimage(ps.darkim2);
00619         freeimage(ps.domeim1);
00620         freeimage(ps.domeim2);
00621         vircam_mask_clear(ps.master_mask);
00622         freepropertylist(ps.eh);
00623     }
00624     vircam_detector_noise_tidy();
00625     return(0);
00626 }
00627 
00628 /*---------------------------------------------------------------------------*/
00635 /*---------------------------------------------------------------------------*/
00636 
00637 static int vircam_detector_noise_save(cpl_frameset *framelist, 
00638                                       cpl_parameterlist *parlist) {
00639     const char *fctid = "vircam_detector_noise_save";
00640     const char *outpaf = "vircam_detector_noise";
00641     const char *outfile = "detector_noise.fits";
00642     const char *recipeid = "vircam_detector_noise";
00643     cpl_propertylist *plist,*p;
00644     cpl_table *o;
00645 
00646     /* If this is the first time through then create the output image */
00647     
00648     if (isfirst) {
00649 
00650         /* Create a new product frame object and define some tags */
00651 
00652         product_frame = cpl_frame_new();
00653         cpl_frame_set_filename(product_frame,outfile);
00654         cpl_frame_set_tag(product_frame,VIRCAM_PRO_READGAINFILE);
00655         cpl_frame_set_type(product_frame,CPL_FRAME_TYPE_IMAGE);
00656         cpl_frame_set_group(product_frame,CPL_FRAME_GROUP_PRODUCT);
00657         cpl_frame_set_level(product_frame,CPL_FRAME_LEVEL_FINAL);
00658 
00659         /* Fiddle with the primary header */
00660 
00661         plist = cpl_propertylist_duplicate(ps.ph);
00662         ps.phupaf = vircam_paf_phu_items(plist);
00663         vircam_dfs_set_product_primary_header(plist,product_frame,framelist,
00664                                               parlist,(char *)recipeid,
00665                                               "PRO-1.15",ps.inherit,0);
00666         vircam_paf_append(ps.phupaf,plist,"ESO PRO CATG");
00667         vircam_paf_append(ps.phupaf,plist,"ESO INS FILT1 NAME");
00668 
00669         /* 'Save' the PHU image */
00670 
00671         if (cpl_image_save(NULL,outfile,CPL_TYPE_UCHAR,plist,
00672                            CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00673             cpl_msg_error(fctid,"Cannot save product PHU");
00674             cpl_frame_delete(product_frame);
00675             cpl_propertylist_delete(plist);
00676             return(-1);
00677         }
00678         cpl_propertylist_delete(plist);
00679         cpl_frameset_insert(framelist,product_frame);
00680     }
00681 
00682     /* Create results header */
00683 
00684     plist = cpl_propertylist_duplicate(ps.eh);
00685 
00686     /* Now add the new data... */
00687 
00688     cpl_propertylist_update_float(plist,"ESO QC READNOISE",
00689                                   vircam_detector_noise_config.readnoise);
00690     cpl_propertylist_set_comment(plist,"ESO QC READNOISE",
00691                                  "[e-] Calculated detector readnoise");
00692     cpl_propertylist_update_float(plist,"ESO QC CONAD",
00693                                   vircam_detector_noise_config.gain);
00694     cpl_propertylist_set_comment(plist,"ESO QC CONAD",
00695                                  "[e-/ADU] Calculated detector gain");
00696     cpl_propertylist_update_float(plist,"ESO QC COUNTS",
00697                                   vircam_detector_noise_config.counts);
00698     cpl_propertylist_set_comment(plist,"ESO QC COUNTS",
00699                                  "[ADU] Dark corrected dome counts");
00700     cpl_propertylist_update_float(plist,"ESO QC LAMPFLUX",
00701                                   vircam_detector_noise_config.lampflux);
00702     cpl_propertylist_set_comment(plist,"ESO QC LAMPFLUX",
00703                                  "[ADU/sec] Dark corrected flux level");
00704 
00705     /* Now fiddle with the extension header */
00706 
00707     vircam_dfs_set_product_exten_header(plist,product_frame,framelist,
00708                                         parlist,(char *)recipeid,
00709                                         "PRO-1.15",ps.inherit);
00710     if (dummy)
00711         vircam_dummy_property(plist);
00712 
00713     /* Create the output table */
00714 
00715     o = cpl_table_new(1);
00716     cpl_table_new_column(o,"EXTNAME",CPL_TYPE_STRING);
00717     cpl_table_new_column(o,"READNOISE",CPL_TYPE_FLOAT);
00718     cpl_table_new_column(o,"GAIN",CPL_TYPE_FLOAT);
00719 
00720     /* Write the values to the table */
00721 
00722     cpl_table_set_string(o,"EXTNAME",0,
00723                          cpl_propertylist_get_string(plist,"EXTNAME"));
00724     cpl_table_set_float(o,"READNOISE",0,
00725                         vircam_detector_noise_config.readnoise);
00726     cpl_table_set_float(o,"GAIN",0,vircam_detector_noise_config.gain);
00727 
00728     /* 'Save' the image */
00729 
00730     if (cpl_table_save(o,NULL,plist,outfile,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00731         cpl_msg_error(fctid,"Cannot save product");
00732         cpl_propertylist_delete(plist);
00733         cpl_frame_delete(product_frame);
00734         freetable(o);
00735         return(-1);
00736     }
00737     freetable(o);
00738 
00739     /* Write the PAF */
00740 
00741     p = vircam_paf_req_items(plist);
00742     vircam_merge_propertylists(p,ps.phupaf);
00743     if (vircam_paf_print((char *)outpaf,"VIRCAM/vircam_detector_noise",
00744                          "QC file",p) != VIR_OK)
00745         cpl_msg_warning(fctid,"Unable to write PAF");
00746     cpl_propertylist_delete(p);
00747 
00748     /* Tidy and exit */
00749 
00750     freepropertylist(plist);
00751     return(0);
00752 }
00753 
00754 /*---------------------------------------------------------------------------*/
00758 /*---------------------------------------------------------------------------*/
00759 
00760 static void vircam_detector_noise_init(void) {
00761     ps.labels = NULL;
00762     ps.darklist = NULL;
00763     ps.domelist = NULL;
00764     ps.darkim1 = NULL;
00765     ps.darkim2 = NULL;
00766     ps.domeim1 = NULL;
00767     ps.domeim2 = NULL;
00768     ps.master_mask = NULL;
00769     ps.inherit = NULL;
00770     ps.ph = NULL;
00771     ps.eh = NULL;
00772     ps.phupaf = NULL;
00773     return;
00774 }
00775 
00776 /*---------------------------------------------------------------------------*/
00780 /*---------------------------------------------------------------------------*/
00781 
00782 static void vircam_detector_noise_tidy(void) {
00783     freespace(ps.labels);
00784     freeframeset(ps.darklist);
00785     freeframeset(ps.domelist);
00786     freeimage(ps.darkim1);
00787     freeimage(ps.darkim2);
00788     freeimage(ps.domeim1);
00789     freeimage(ps.domeim2);
00790     freemask(ps.master_mask);
00791     freepropertylist(ps.ph);
00792     freepropertylist(ps.eh);
00793     freepropertylist(ps.phupaf);
00794     return;
00795 }
00796 
00800 /*
00801 
00802 $Log: vircam_detector_noise.c,v $
00803 Revision 1.57  2012/01/16 12:32:18  jim
00804 A few more changes to fit in with cpl6
00805 
00806 Revision 1.56  2012/01/15 17:40:09  jim
00807 Minor modifications to take into accout the changes in cpl API for v6
00808 
00809 Revision 1.55  2010/12/09 13:19:19  jim
00810 Fixed bug where reported flux was a factor of two too high
00811 
00812 Revision 1.54  2010/06/30 12:42:00  jim
00813 A few fixes to stop compiler compaints
00814 
00815 Revision 1.53  2010/03/09 14:28:38  jim
00816 Added new QC values COUNTS and LAMPFLUX
00817 
00818 Revision 1.52  2010/01/31 18:55:30  jim
00819 Filter name written to PAF. QC GAIN changed to QC CONAD (in spite of the
00820 dreadful name)
00821 
00822 Revision 1.51  2009/09/09 09:50:21  jim
00823 Modified to try and get headers right
00824 
00825 Revision 1.50  2008/10/01 04:59:13  jim
00826 Added call to vircam_frameset_fexists to check input frameset
00827 
00828 Revision 1.49  2008/09/30 11:33:23  jim
00829 Added PRO CATG to pafs
00830 
00831 Revision 1.48  2007/10/25 18:39:22  jim
00832 Altered to remove some lint messages
00833 
00834 Revision 1.47  2007/10/15 12:52:39  jim
00835 Fixed little cockup which had duplicate entries in the ps structure
00836 
00837 Revision 1.46  2007/09/07 13:32:12  jim
00838 uses a sorted framelist to ensure that the correct information is given
00839 to the output product header
00840 
00841 Revision 1.45  2007/09/06 21:37:53  jim
00842 fixed call to vircam_dfs_setup_product_ routines to use the full input
00843 frameset
00844 
00845 Revision 1.44  2007/07/18 15:35:41  jim
00846 Added better error handling for missing or corrupt mask extensions
00847 
00848 Revision 1.43  2007/07/09 13:21:55  jim
00849 Modified to use new version of vircam_exten_range
00850 
00851 Revision 1.42  2007/06/13 08:11:27  jim
00852 Modified docs to reflect changes in DFS tags
00853 
00854 Revision 1.41  2007/04/04 10:36:18  jim
00855 Modified to use new dfs tags
00856 
00857 Revision 1.40  2007/03/29 12:19:38  jim
00858 Little changes to improve documentation
00859 
00860 Revision 1.39  2007/03/06 12:30:17  jim
00861 Now writes results to a table in addtion to a header and a paf.
00862 
00863 Revision 1.38  2007/03/01 12:41:49  jim
00864 Modified slightly after code checking
00865 
00866 Revision 1.37  2007/02/25 06:26:35  jim
00867 Plugged a few memory leaks
00868 
00869 Revision 1.36  2007/02/15 06:59:37  jim
00870 Added ability to write QC paf files
00871 
00872 Revision 1.35  2007/02/07 10:12:39  jim
00873 Removed calls to vircam_ndit_correct as this is now no longer necessary
00874 
00875 Revision 1.34  2007/02/06 13:11:12  jim
00876 Fixed entry for PRO dictionary in cpl_dfs_set_product_header
00877 
00878 Revision 1.33  2007/02/06 12:38:59  jim
00879 Creates a sorted version of the input frameset so that a dome flat is first
00880 in the list. This is done so that the header of the output product comes
00881 from one of the dome flats and so that you can see which filter it was done
00882 with.
00883 
00884 Revision 1.32  2007/02/06 11:59:38  jim
00885 Added call to vircam_medmadcut for a better estimate of dispersion
00886 
00887 Revision 1.31  2007/01/17 23:56:12  jim
00888 Plugged possible memory leak
00889 
00890 Revision 1.30  2006/12/14 14:46:32  jim
00891 Fixed typo
00892 
00893 Revision 1.29  2006/12/11 22:47:49  jim
00894 Fixed QC header names
00895 
00896 Revision 1.28  2006/11/27 12:16:33  jim
00897 Modified to change location in the header where the results are written
00898 
00899 Revision 1.27  2006/11/10 09:20:29  jim
00900 Fixed _save routine so that an extension name is written out to the file
00901 header
00902 
00903 Revision 1.26  2006/09/29 11:19:31  jim
00904 changed aliases on parameter names
00905 
00906 Revision 1.25  2006/09/09 16:49:39  jim
00907 Header comment update
00908 
00909 Revision 1.24  2006/09/08 09:17:27  jim
00910 Modified to flag dummy results
00911 
00912 Revision 1.23  2006/09/04 23:02:14  jim
00913 Modified to deal with det live issues. Also does a better job of dealing
00914 with duff input
00915 
00916 Revision 1.22  2006/06/20 19:07:01  jim
00917 Corrects for ndit != 1
00918 
00919 Revision 1.21  2006/06/15 09:58:58  jim
00920 Minor changes to docs
00921 
00922 Revision 1.20  2006/06/13 21:27:10  jim
00923 Changed output product to a MEF with null images and readnoise/gain estimates
00924 in the header. I HATE this solution
00925 
00926 Revision 1.19  2006/06/09 11:26:25  jim
00927 Small changes to keep lint happy
00928 
00929 Revision 1.18  2006/05/04 11:56:02  jim
00930 changed filename extension in default output file
00931 
00932 Revision 1.17  2006/05/04 11:53:14  jim
00933 Fixed the way the _save routine works to be more consistent with the
00934 standard CPL way of doing things
00935 
00936 Revision 1.16  2006/04/27 09:46:01  jim
00937 Modified DFS frame types to conform to new dictionary
00938 
00939 Revision 1.15  2006/03/22 14:02:51  jim
00940 cosmetic changes to keep lint happy
00941 
00942 Revision 1.14  2006/03/22 12:13:51  jim
00943 Modified to use new vircam_mask capability
00944 
00945 Revision 1.13  2006/03/15 10:43:40  jim
00946 Fixed a few things
00947 
00948 Revision 1.12  2006/01/23 10:36:39  jim
00949 Now allows a CPM or a BPM to be used as the mask
00950 
00951 Revision 1.11  2005/12/14 22:19:12  jim
00952 fixed docs
00953 
00954 Revision 1.10  2005/12/09 09:47:58  jim
00955 Many changes to add more documentation
00956 
00957 Revision 1.9  2005/12/02 10:45:37  jim
00958 The tags used in the sof are now written to the description string in the
00959 constructor. This is so that if they change in the vircam_dfs.h file, they
00960 aren't then hardcopied into each of the recipes...
00961 
00962 Revision 1.8  2005/11/29 16:10:58  jim
00963 Added clipping into stats for difference images
00964 
00965 Revision 1.7  2005/11/25 15:20:29  jim
00966 Fixed bug in mathematical description
00967 
00968 Revision 1.6  2005/11/25 09:56:14  jim
00969 Tidied up some more documentation
00970 
00971 Revision 1.5  2005/11/23 14:57:40  jim
00972 A bit of tidying in response to splint messages
00973 
00974 Revision 1.4  2005/11/21 16:16:23  jim
00975 Added some better garbage collection
00976 
00977 Revision 1.3  2005/11/07 13:14:18  jim
00978 Added some error trapping and some docs
00979 
00980 Revision 1.2  2005/08/09 11:09:39  jim
00981 Replaced dodgy call to cpl_framelist_delete with correct cpl_frameset_delete
00982 
00983 Revision 1.1.1.1  2005/08/05 08:29:09  jim
00984 Initial import
00985 
00986 
00987 */

Generated on 15 Mar 2012 for VIRCAM Pipeline by  doxygen 1.6.1