vircam_detector_noise.c

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

Generated on Wed Apr 10 04:01:55 2013 for VIRCAM Pipeline by  doxygen 1.5.1