vircam_reset_combine.c

00001 /* $Id: vircam_reset_combine.c,v 1.60 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.60 $
00025  * $Name: vcam-1_3_2 $
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 
00038 #include "vircam_utils.h"
00039 #include "vircam_mask.h"
00040 #include "vircam_dfs.h"
00041 #include "vircam_mods.h"
00042 #include "vircam_stats.h"
00043 #include "vircam_fits.h"
00044 #include "vircam_pfits.h"
00045 #include "vircam_channel.h"
00046 #include "vircam_paf.h"
00047 #include "vircam_wcsutils.h"
00048 
00049 /* Define values for the bit mask that flags dummy results */
00050 
00051 #define MEANRESET    1
00052 #define DIFFIMG      2
00053 #define STATS_TAB    4
00054 
00055 /* Function prototypes */
00056 
00057 static int vircam_reset_combine_create(cpl_plugin *) ;
00058 static int vircam_reset_combine_exec(cpl_plugin *) ;
00059 static int vircam_reset_combine_destroy(cpl_plugin *) ;
00060 static int vircam_reset_combine(cpl_parameterlist *, cpl_frameset *) ;
00061 static int vircam_reset_combine_save(cpl_frameset *framelist, 
00062                                      cpl_parameterlist *parlist);
00063 static void vircam_reset_combine_dummy_products(void);
00064 static void vircam_reset_combine_normal(int jext);
00065 static int vircam_reset_combine_lastbit(int jext, cpl_frameset *framelist,
00066                                         cpl_parameterlist *parlist);
00067 static void vircam_reset_combine_init(void);
00068 static void vircam_reset_combine_tidy(int level);
00069 
00070 /* Static global variables */
00071 
00072 static struct {
00073 
00074     /* Input */
00075 
00076     int         combtype;
00077     int         scaletype;
00078     int         xrej;
00079     float       thresh;
00080     int         ncells;
00081     int         extenum;
00082 
00083     /* Output */
00084 
00085     float       resetmed;
00086     float       resetrms;
00087     float       resetdiff_med;
00088     float       resetdiff_rms;
00089 
00090 } vircam_reset_combine_config ;
00091 
00092 static struct {
00093     cpl_size         *labels;
00094     cpl_frameset     *resetlist;
00095     vir_fits         **resets;
00096     int              nresets;
00097     vir_fits         **good;
00098     int              ngood;
00099     cpl_frame        *master_reset;
00100     vir_mask         *master_mask;
00101     cpl_frame        *chantab;
00102     cpl_image        *outimage;
00103     cpl_propertylist *drs;
00104     unsigned char    *rejmask;
00105     unsigned char    *rejplus;
00106     vir_fits         *mrimage;
00107     cpl_image        *diffimg;
00108     cpl_table        *diffimstats;
00109     cpl_propertylist *phupaf;
00110 } ps;
00111 
00112 static int isfirst;
00113 static cpl_frame *product_frame_mean_reset = NULL;
00114 static cpl_frame *product_frame_diffimg = NULL;
00115 static cpl_frame *product_frame_diffimg_stats = NULL;
00116 static int we_expect;
00117 static int we_get;
00118 
00119 static char vircam_reset_combine_description[] =
00120 "vircam_reset_combine -- VIRCAM reset combine recipe.\n\n"
00121 "Combine a list of reset frames into a mean reset frame. Optionally compare \n"
00122 "the output frame to a master reset frame\n\n"
00123 "The program requires the following files in the SOF:\n\n"
00124 "    Tag                   Description\n"
00125 "    -----------------------------------------------------------------------\n"
00126 "    %-21s A list of raw reset images\n"
00127 "    %-21s Optional reference reset frame\n"
00128 "    %-21s Optional master bad pixel map or\n"
00129 "    %-21s Optional master confidence map\n"
00130 "    %-21s Optional channel table or\n"
00131 "    %-21s Optional initial channel table\n"
00132 "\n"
00133 "If no master reset frame is made available, then no comparison will be done\n"
00134 "This means there will be no output difference image. If a master reset is\n"
00135 "available, but no channel table is, then a difference image will be formed\n"
00136 "but no stats will be written."
00137 "\n";
00138 
00253 /* Function code */
00254 
00255 /*---------------------------------------------------------------------------*/
00263 /*---------------------------------------------------------------------------*/
00264 
00265 int cpl_plugin_get_info(cpl_pluginlist *list) {
00266     cpl_recipe  *recipe = cpl_calloc(1,sizeof(*recipe));
00267     cpl_plugin  *plugin = &recipe->interface;
00268     char alldesc[SZ_ALLDESC];
00269     (void)snprintf(alldesc,SZ_ALLDESC,vircam_reset_combine_description,
00270                    VIRCAM_RESET_RAW,VIRCAM_REF_RESET,VIRCAM_CAL_BPM,
00271                    VIRCAM_CAL_CONF,VIRCAM_CAL_CHANTAB,VIRCAM_CAL_CHANTAB_INIT);
00272 
00273     cpl_plugin_init(plugin,
00274                     CPL_PLUGIN_API,
00275                     VIRCAM_BINARY_VERSION,
00276                     CPL_PLUGIN_TYPE_RECIPE,
00277                     "vircam_reset_combine",
00278                     "VIRCAM reset combination recipe",
00279                     alldesc,
00280                     "Jim Lewis",
00281                     "jrl@ast.cam.ac.uk",
00282                     vircam_get_license(),
00283                     vircam_reset_combine_create,
00284                     vircam_reset_combine_exec,
00285                     vircam_reset_combine_destroy);
00286 
00287     cpl_pluginlist_append(list,plugin);
00288 
00289     return(0);
00290 }
00291 
00292 /*---------------------------------------------------------------------------*/
00301 /*---------------------------------------------------------------------------*/
00302 
00303 static int vircam_reset_combine_create(cpl_plugin *plugin) {
00304     cpl_recipe      *recipe;
00305     cpl_parameter   *p;
00306 
00307     /* Get the recipe out of the plugin */
00308 
00309     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00310         recipe = (cpl_recipe *)plugin;
00311     else 
00312         return(-1);
00313 
00314     /* Create the parameters list in the cpl_recipe object */
00315 
00316     recipe->parameters = cpl_parameterlist_new();
00317 
00318     /* Fill in the parameters. First the combination type */
00319 
00320     p = cpl_parameter_new_range("vircam.vircam_reset_combine.combtype",
00321                                 CPL_TYPE_INT,
00322                                 "1 == Median,\n 2 == Mean",
00323                                 "vircam.vircam_reset_combine",
00324                                 1,1,2);
00325     cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"combtype");
00326     cpl_parameterlist_append(recipe->parameters,p);
00327 
00328     /* The requested scaling */
00329 
00330     p = cpl_parameter_new_range("vircam.vircam_reset_combine.scaletype",
00331                                 CPL_TYPE_INT,
00332                                 "0 == none,\n 1 == additive offset,\n 2 == multiplicative offset,\n 3 == exposure time scaling + additive offset",
00333                                 "vircam.vircam_reset_combine",
00334                                 1,0,3);
00335     cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"scaletype");
00336     cpl_parameterlist_append(recipe->parameters,p);
00337     
00338     /* Extra rejection cycle */
00339 
00340     p = cpl_parameter_new_value("vircam.vircam_reset_combine.xrej",
00341                                 CPL_TYPE_BOOL,
00342                                 "True if using extra rejection cycle",
00343                                 "vircam.vircam_reset_combine",
00344                                 TRUE);
00345     cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"xrej");
00346     cpl_parameterlist_append(recipe->parameters,p);
00347 
00348     /* Rejection threshold */
00349 
00350     p = cpl_parameter_new_value("vircam.vircam_reset_combine.thresh",
00351                                 CPL_TYPE_DOUBLE,
00352                                 "Rejection threshold in sigma above background",
00353                                 "vircam.vircam_reset_combine",5.0);
00354     cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"thresh");
00355     cpl_parameterlist_append(recipe->parameters,p);
00356 
00357     /* How many cells to divide each data channel */
00358 
00359     p = cpl_parameter_new_enum("vircam.vircam_reset_combine.ncells",
00360                                CPL_TYPE_INT,
00361                                "Number of cells for data channel stats",
00362                                "vircam.vircam_reset_combine",8,7,1,2,4,8,
00363                                16,32,64);
00364     cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ncells");
00365     cpl_parameterlist_append(recipe->parameters,p);
00366 
00367     /* Extension number of input frames to use */
00368 
00369     p = cpl_parameter_new_range("vircam.vircam_reset_combine.extenum",
00370                                 CPL_TYPE_INT,
00371                                 "Extension number to be done, 0 == all",
00372                                 "vircam.vircam_reset_combine",
00373                                 1,0,16);
00374     cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ext");
00375     cpl_parameterlist_append(recipe->parameters,p);
00376         
00377     /* Get out of here */
00378 
00379     return(0);
00380 }
00381     
00382     
00383 /*---------------------------------------------------------------------------*/
00389 /*---------------------------------------------------------------------------*/
00390 
00391 static int vircam_reset_combine_exec(cpl_plugin *plugin) {
00392     cpl_recipe  *recipe;
00393 
00394     /* Get the recipe out of the plugin */
00395 
00396     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00397         recipe = (cpl_recipe *)plugin;
00398     else 
00399         return(-1);
00400 
00401     return(vircam_reset_combine(recipe->parameters,recipe->frames));
00402 }
00403                                 
00404 /*---------------------------------------------------------------------------*/
00410 /*---------------------------------------------------------------------------*/
00411 
00412 static int vircam_reset_combine_destroy(cpl_plugin *plugin) {
00413     cpl_recipe *recipe ;
00414 
00415     /* Get the recipe out of the plugin */
00416 
00417     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00418         recipe = (cpl_recipe *)plugin;
00419     else 
00420         return(-1);
00421 
00422     cpl_parameterlist_delete(recipe->parameters);
00423     return(0);
00424 }
00425 
00426 /*---------------------------------------------------------------------------*/
00433 /*---------------------------------------------------------------------------*/
00434 
00435 static int vircam_reset_combine(cpl_parameterlist *parlist, 
00436                                 cpl_frameset *framelist) {
00437     const char *fctid="vircam_reset_combine";
00438     int j,jst,jfn,retval,status,i,live,nx,ny;
00439     cpl_size nlab;
00440     cpl_parameter *p;
00441     vir_fits *ff;
00442 
00443     /* Check validity of input frameset */
00444 
00445     if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
00446         cpl_msg_error(fctid,"Input framelist NULL or has no input data");
00447         return(-1);
00448     }
00449 
00450     /* Check the files in the frameset */
00451 
00452     if (vircam_frameset_fexists(framelist) != VIR_OK) {
00453         cpl_msg_error(fctid,"Input frameset is missing files. Check SOF");
00454         return(-1);
00455     }
00456 
00457     /* Initialise a few things */
00458 
00459     vircam_reset_combine_init();
00460     we_expect |= MEANRESET;
00461 
00462     /* Get the parameters */
00463 
00464     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.combtype");
00465     vircam_reset_combine_config.combtype = cpl_parameter_get_int(p);
00466     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.scaletype");
00467     vircam_reset_combine_config.scaletype = cpl_parameter_get_int(p);
00468     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.xrej");
00469     vircam_reset_combine_config.xrej = cpl_parameter_get_bool(p);
00470     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.thresh");
00471     vircam_reset_combine_config.thresh = (float)cpl_parameter_get_double(p);
00472     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.ncells");
00473     vircam_reset_combine_config.ncells = cpl_parameter_get_int(p);
00474     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.extenum");
00475     vircam_reset_combine_config.extenum = cpl_parameter_get_int(p);
00476 
00477     /* Sort out raw from calib frames */
00478 
00479     if (vircam_dfs_set_groups(framelist) != VIR_OK) {
00480         cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
00481         return(-1);
00482     }
00483 
00484     /* Get the reset frames */
00485 
00486     if ((ps.labels = cpl_frameset_labelise(framelist,vircam_compare_tags,
00487                                            &nlab)) == NULL) {
00488         cpl_msg_error(fctid,"Cannot labelise the input frames");
00489         return(-1);
00490     }
00491     if ((ps.resetlist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
00492                                                  VIRCAM_RESET_RAW)) == NULL) {
00493         cpl_msg_error(fctid,"Cannot find reset frames in input frameset");
00494         return(-1);
00495     }
00496     ps.nresets = cpl_frameset_get_size(ps.resetlist);
00497         
00498     /* Check to see if there is a master reset frame */
00499 
00500     if ((ps.master_reset = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00501                                                       VIRCAM_REF_RESET)) == NULL) 
00502         cpl_msg_info(fctid,"No master reset found -- no difference image will be formed");
00503     else
00504         we_expect |= DIFFIMG;
00505         
00506     /* Check to see if there is a master bad pixel map. If there isn't one 
00507        then look for a confidence map */
00508 
00509     ps.master_mask = vircam_mask_define(framelist,ps.labels,nlab);
00510 
00511     /* Check to see if there is a channel table */
00512 
00513     if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00514                                                  VIRCAM_CAL_CHANTAB)) == NULL) {
00515         if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00516                                                      VIRCAM_CAL_CHANTAB_INIT)) == NULL) 
00517             cpl_msg_info(fctid,"No channel table found -- no difference image stats will be done");
00518     } else if (we_expect & DIFFIMG) 
00519             we_expect |= STATS_TAB;
00520 
00521     /* Now, how many image extensions do we want to do? If the extension
00522        number is zero, then we loop for all possible extensions. If it
00523        isn't then we just do the extension specified */
00524 
00525     vircam_exten_range(vircam_reset_combine_config.extenum,
00526                        (const cpl_frame *)cpl_frameset_get_frame(ps.resetlist,0),
00527                        &jst,&jfn);
00528     if (jst == -1 || jfn == -1) {
00529         cpl_msg_error(fctid,"Unable to continue");
00530         vircam_reset_combine_tidy(2);
00531         return(-1);
00532     }
00533 
00534     /* Get some space for the good frames */
00535 
00536     ps.good = cpl_malloc(ps.nresets*sizeof(vir_fits *));
00537 
00538     /* Now loop for all the extension... */
00539 
00540     for (j = jst; j <= jfn; j++) {
00541         status = VIR_OK;
00542         we_get = 0;
00543         isfirst = (j == jst);
00544 
00545         /* Load up the images. If they won't load the signal a major error */
00546 
00547         ps.resets = vircam_fits_load_list(ps.resetlist,CPL_TYPE_FLOAT,j);
00548         if (ps.resets == NULL) {
00549             cpl_msg_info(fctid,
00550                          "Extension %" CPL_SIZE_FORMAT " resets wouldn't load",
00551                          (cpl_size)j);
00552             retval = vircam_reset_combine_lastbit(j,framelist,parlist);
00553             if (retval != 0)
00554                 return(-1);
00555             continue;
00556         }
00557 
00558         /* Are any of these reset images good? */
00559 
00560         ps.ngood = 0;
00561         for (i = 0; i < ps.nresets; i++) {
00562             ff = ps.resets[i];
00563             vircam_pfits_get_detlive(vircam_fits_get_ehu(ff),&live);
00564             if (! live) {
00565                 cpl_msg_info(fctid,"Detector flagged dead %s",
00566                              vircam_fits_get_fullname(ff));
00567                 vircam_fits_set_error(ff,VIR_FATAL);
00568             } else {
00569                 ps.good[ps.ngood] = ff;
00570                 ps.ngood += 1;
00571             }
00572         }
00573 
00574         /* If there are no good images, then signal that wee need to 
00575            create some dummy products and move on */
00576 
00577         if (ps.ngood == 0) {
00578             cpl_msg_info(fctid,"All images flagged bad for this extension");
00579             retval = vircam_reset_combine_lastbit(j,framelist,parlist);
00580             if (retval != 0)
00581                 return(-1);
00582             continue;
00583         }
00584 
00585         /* Load the mask */
00586 
00587         nx = (int)cpl_image_get_size_x(vircam_fits_get_image(ps.good[0]));
00588         ny = (int)cpl_image_get_size_y(vircam_fits_get_image(ps.good[0]));
00589         if (vircam_mask_load(ps.master_mask,j,nx,ny) == VIR_FATAL) {
00590             cpl_msg_info(fctid,
00591                          "Unable to load mask image %s[%" CPL_SIZE_FORMAT "]",
00592                          vircam_mask_get_filename(ps.master_mask),
00593                          (cpl_size)j);
00594             cpl_msg_info(fctid,"Forcing all pixels to be good from now on");
00595             vircam_mask_force(ps.master_mask,nx,ny);
00596         }
00597 
00598         /* Call the combine module. If it fails then signal that
00599            all products will be dummies */
00600 
00601         cpl_msg_info(fctid,"Doing combination for extension %" CPL_SIZE_FORMAT,
00602                      (cpl_size)j);
00603         (void)vircam_imcombine(ps.good,ps.ngood,
00604                                vircam_reset_combine_config.combtype,
00605                                vircam_reset_combine_config.scaletype,
00606                                vircam_reset_combine_config.xrej,
00607                                vircam_reset_combine_config.thresh,
00608                                &(ps.outimage),&(ps.rejmask),
00609                                &(ps.rejplus),&(ps.drs),&status);
00610         if (status == VIR_OK) {
00611             we_get |= MEANRESET;
00612             vircam_reset_combine_normal(j);
00613         }
00614 
00615         /* Create any dummies and save products */
00616 
00617         retval = vircam_reset_combine_lastbit(j,framelist,parlist);
00618         if (retval != 0)
00619             return(-1);
00620     }
00621     vircam_reset_combine_tidy(2);
00622     return(0);
00623 }
00624 
00625 /*---------------------------------------------------------------------------*/
00632 /*---------------------------------------------------------------------------*/
00633 
00634 static int vircam_reset_combine_save(cpl_frameset *framelist, 
00635                                      cpl_parameterlist *parlist) {
00636     cpl_propertylist *plist,*elist,*p,*pafprop;
00637     int status;
00638     const char *fctid = "vircam_reset_combine_save";
00639     const char *outfile = "resetcomb.fits";
00640     const char *outdiff = "resetdiff.fits";
00641     const char *outdimst = "resetdifftab.fits";
00642     const char *outfilepaf = "resetcomb";
00643     const char *outdiffpaf = "resetdiff";
00644     const char *recipeid = "vircam_reset_combine";
00645 
00646     /* If we need to make a PHU then do that now based on the first frame
00647        in the input frame list */
00648 
00649     if (isfirst) {
00650 
00651         /* Create a new product frame object and define some tags */
00652 
00653         product_frame_mean_reset = cpl_frame_new();
00654         cpl_frame_set_filename(product_frame_mean_reset,outfile);
00655         cpl_frame_set_tag(product_frame_mean_reset,VIRCAM_PRO_RESET);
00656         cpl_frame_set_type(product_frame_mean_reset,CPL_FRAME_TYPE_IMAGE);
00657         cpl_frame_set_group(product_frame_mean_reset,CPL_FRAME_GROUP_PRODUCT);
00658         cpl_frame_set_level(product_frame_mean_reset,CPL_FRAME_LEVEL_FINAL);
00659 
00660         /* Set up product phu */
00661 
00662         plist = vircam_fits_get_phu(ps.resets[0]);
00663         ps.phupaf = vircam_paf_phu_items(plist);
00664         if (ps.master_reset != NULL) {
00665             cpl_propertylist_update_string(ps.phupaf,"REF_RESET",
00666                                            cpl_frame_get_filename(ps.master_reset));
00667             cpl_propertylist_set_comment(ps.phupaf,"REF_RESET",
00668                                          "Reference reset used");
00669         }
00670         vircam_dfs_set_product_primary_header(plist,product_frame_mean_reset,
00671                                               framelist,parlist,
00672                                               (char *)recipeid,
00673                                               "PRO-1.15",NULL,0);
00674 
00675         /* 'Save' the PHU image */                       
00676 
00677         if (cpl_image_save(NULL,outfile,CPL_TYPE_UCHAR,plist,
00678                            CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00679             cpl_msg_error(fctid,"Cannot save product PHU");
00680             cpl_frame_delete(product_frame_mean_reset);
00681             return(-1);
00682         }
00683         cpl_frameset_insert(framelist,product_frame_mean_reset);
00684 
00685         /* Create a new product frame object for the difference image */
00686 
00687         if (we_expect & DIFFIMG) {
00688             product_frame_diffimg = cpl_frame_new();
00689             cpl_frame_set_filename(product_frame_diffimg,outdiff);
00690             cpl_frame_set_tag(product_frame_diffimg,
00691                               VIRCAM_PRO_DIFFIMG_RESET);
00692             cpl_frame_set_type(product_frame_diffimg,CPL_FRAME_TYPE_IMAGE);
00693             cpl_frame_set_group(product_frame_diffimg,CPL_FRAME_GROUP_PRODUCT);
00694             cpl_frame_set_level(product_frame_diffimg,CPL_FRAME_LEVEL_FINAL);
00695 
00696             /* Set up product phu */
00697 
00698             plist = vircam_fits_get_phu(ps.resets[0]);
00699             vircam_dfs_set_product_primary_header(plist,product_frame_diffimg,
00700                                                   framelist,parlist,
00701                                                   (char *)recipeid,
00702                                                   "PRO-1.15",NULL,0);
00703             /* 'Save' the PHU image */                   
00704 
00705             if (cpl_image_save(NULL,outdiff,CPL_TYPE_UCHAR,plist,
00706                                CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00707                 cpl_msg_error(fctid,"Cannot save product PHU");
00708                 cpl_frame_delete(product_frame_diffimg);
00709                 return(-1);
00710             }
00711             cpl_frameset_insert(framelist,product_frame_diffimg);
00712         }
00713 
00714         /* Create a new product frame object for the difference image stats 
00715            table */
00716 
00717         if (we_expect & STATS_TAB) {
00718             product_frame_diffimg_stats = cpl_frame_new();
00719             cpl_frame_set_filename(product_frame_diffimg_stats,outdimst);
00720             cpl_frame_set_tag(product_frame_diffimg_stats,
00721                               VIRCAM_PRO_DIFFIMG_RESET_STATS);
00722             cpl_frame_set_type(product_frame_diffimg_stats,
00723                                CPL_FRAME_TYPE_TABLE);
00724             cpl_frame_set_group(product_frame_diffimg_stats,
00725                                 CPL_FRAME_GROUP_PRODUCT);
00726             cpl_frame_set_level(product_frame_diffimg_stats,
00727                                 CPL_FRAME_LEVEL_FINAL);
00728 
00729             /* Set up product phu */
00730 
00731             plist = vircam_fits_get_phu(ps.resets[0]);
00732             vircam_dfs_set_product_primary_header(plist,
00733                                                   product_frame_diffimg_stats,
00734                                                   framelist,parlist,
00735                                                   (char *)recipeid,
00736                                                   "PRO-1.15",NULL,0);
00737 
00738             /* Fiddle with the extension header */
00739 
00740             elist = vircam_fits_get_ehu(ps.resets[0]);
00741             p = cpl_propertylist_duplicate(elist);
00742             vircam_merge_propertylists(p,ps.drs);
00743             if (! (we_get & STATS_TAB))
00744                 vircam_dummy_property(p);
00745             vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
00746                                                 framelist,parlist,
00747                                                 (char *)recipeid,
00748                                                 "PRO-1.15",NULL);
00749             status = VIR_OK;
00750             vircam_removewcs(p,&status);
00751             if (cpl_table_save(ps.diffimstats,plist,p,outdimst,
00752                                CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00753                 cpl_msg_error(fctid,"Cannot save product table extension");
00754                 cpl_propertylist_delete(p);
00755                 return(-1);
00756             }
00757             cpl_propertylist_delete(p);
00758             cpl_frameset_insert(framelist,product_frame_diffimg_stats);
00759         }
00760     }
00761 
00762     /* Get the extension property list */ 
00763 
00764     plist = vircam_fits_get_ehu(ps.resets[0]);
00765     cpl_propertylist_update_int(plist,"ESO PRO DATANCOM",ps.ngood);
00766 
00767     /* Fiddle with the header now */
00768 
00769     vircam_merge_propertylists(plist,ps.drs);
00770     p = cpl_propertylist_duplicate(plist);
00771     if (! (we_get & MEANRESET))
00772         vircam_dummy_property(p);
00773     vircam_dfs_set_product_exten_header(p,product_frame_mean_reset,framelist,
00774                                         parlist,(char *)recipeid,"PRO-1.15",
00775                                         NULL);
00776 
00777     /* Now save the reset image extension */
00778 
00779     cpl_propertylist_update_float(p,"ESO QC RESETMED",
00780                                   vircam_reset_combine_config.resetmed);
00781     cpl_propertylist_set_comment(p,"ESO QC RESETMED",
00782                                  "Median of mean reset frame");
00783     cpl_propertylist_update_float(p,"ESO QC RESETRMS",
00784                                   vircam_reset_combine_config.resetrms);
00785     cpl_propertylist_set_comment(p,"ESO QC RESETRMS",
00786                                  "RMS of mean reset frame");
00787     if (cpl_image_save(ps.outimage,outfile,CPL_TYPE_FLOAT,p,
00788                        CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00789         cpl_msg_error(fctid,"Cannot save product image extension");
00790         cpl_propertylist_delete(p);
00791         return(-1);
00792     }
00793 
00794     /* Write out PAF for mean image */
00795 
00796     pafprop = vircam_paf_req_items(p);
00797     vircam_merge_propertylists(pafprop,ps.phupaf);
00798     vircam_paf_append(pafprop,p,"ESO PRO CATG");
00799     vircam_paf_append(pafprop,p,"ESO PRO DATANCOM");
00800     if (vircam_paf_print((char *)outfilepaf,"VIRCAM/vircam_reset_combine",
00801                          "QC file",pafprop) != VIR_OK)
00802         cpl_msg_warning(fctid,"Unable to save PAF for mean reset");
00803     cpl_propertylist_delete(pafprop);
00804     cpl_propertylist_delete(p);
00805 
00806     /* Now save the reset difference image extension */
00807 
00808     if (we_expect & DIFFIMG) {
00809         p = cpl_propertylist_duplicate(plist);
00810         if (! (we_get & DIFFIMG))
00811             vircam_dummy_property(p);
00812         cpl_propertylist_update_float(p,"ESO QC RESETDIFF_MED",
00813                                       vircam_reset_combine_config.resetdiff_med);
00814         cpl_propertylist_set_comment(p,"ESO QC RESETDIFF_MED",
00815                                      "Median value of difference image");
00816         cpl_propertylist_update_float(p,"ESO QC RESETDIFF_RMS",
00817                                       vircam_reset_combine_config.resetdiff_rms);
00818         cpl_propertylist_set_comment(p,"ESO QC RESETDIFF_RMS",
00819                                      "RMS value of difference image");
00820         vircam_dfs_set_product_exten_header(p,product_frame_diffimg,
00821                                             framelist,parlist,(char *)recipeid,
00822                                             "PRO-1.15",NULL);
00823         if (cpl_image_save(ps.diffimg,outdiff,CPL_TYPE_FLOAT,p,
00824                            CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00825             cpl_propertylist_delete(p);
00826             cpl_msg_error(fctid,"Cannot save product image extension");
00827             return(-1);
00828         }
00829         /* Write out PAF for difference image */
00830 
00831         pafprop = vircam_paf_req_items(p);
00832         vircam_merge_propertylists(pafprop,ps.phupaf);
00833         vircam_paf_append(pafprop,p,"ESO PRO CATG");
00834         if (vircam_paf_print((char *)outdiffpaf,"VIRCAM/vircam_reset_combine",
00835                              "QC file",pafprop) != VIR_OK)
00836             cpl_msg_warning(fctid,"Unable to save PAF for difference image");
00837         cpl_propertylist_delete(pafprop);
00838         cpl_propertylist_delete(p);
00839     }
00840 
00841     /* Now any further difference image stats tables */
00842 
00843     if (! isfirst && (we_expect & STATS_TAB)) {
00844         p = cpl_propertylist_duplicate(plist);
00845         if (! (we_get & STATS_TAB))
00846             vircam_dummy_property(p);
00847         vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
00848                                             framelist,parlist,(char *)recipeid,
00849                                             "PRO-1.15",NULL);
00850         status = VIR_OK;
00851         vircam_removewcs(p,&status);
00852         if (cpl_table_save(ps.diffimstats,NULL,p,outdimst,CPL_IO_EXTEND)
00853                            != CPL_ERROR_NONE) {
00854             cpl_msg_error(fctid,"Cannot save product table extension");
00855             cpl_propertylist_delete(p);
00856             return(-1);
00857         }       
00858         cpl_propertylist_delete(p);
00859     }
00860 
00861     return(0);
00862 }
00863 
00864 /*---------------------------------------------------------------------------*/
00868 /*---------------------------------------------------------------------------*/
00869 
00870 static void vircam_reset_combine_dummy_products(void) {
00871 
00872     /* See if you even need to be here */
00873 
00874     if (we_get == we_expect)
00875         return;
00876 
00877     /* First an output combined reset frame */
00878 
00879     if (! (we_get & MEANRESET)) {
00880         ps.outimage = vircam_dummy_image(ps.resets[0]);
00881 
00882         /* Set up the QC parameters */
00883 
00884         vircam_reset_combine_config.resetmed = 0.0;
00885         vircam_reset_combine_config.resetrms = 0.0;
00886     }
00887 
00888     /* Do the difference image */
00889 
00890     if ((we_expect & DIFFIMG) && ! (we_get & DIFFIMG)) {
00891         vircam_reset_combine_config.resetdiff_med = 0.0;
00892         vircam_reset_combine_config.resetdiff_rms = 0.0;
00893 
00894         /* Is a difference image required? If so then let's have it... */
00895 
00896         ps.diffimg = vircam_dummy_image(ps.resets[0]);
00897     }
00898 
00899     /* If a difference image stats table is required, then do that now */
00900 
00901     if ((we_expect & STATS_TAB) && ! (we_get & STATS_TAB)) 
00902         ps.diffimstats = vircam_create_diffimg_stats(0);
00903 
00904 
00905     return;
00906 }
00907 
00908 /*---------------------------------------------------------------------------*/
00913 /*---------------------------------------------------------------------------*/
00914 
00915 static void vircam_reset_combine_normal(int jext) {
00916     int nx,ny,ncells;
00917     long npi;
00918     unsigned char *bpm;
00919     float med,sig,*idata,grms,gdiff;
00920     const char *fctid="vircam_reset_combine_normal";
00921     cpl_table *ctable;
00922     cpl_propertylist *p;
00923 
00924     /* Load up the bad pixel mask */
00925 
00926     nx = (int)cpl_image_get_size_x(ps.outimage);
00927     ny = (int)cpl_image_get_size_y(ps.outimage);
00928     npi = nx*ny;
00929     bpm = vircam_mask_get_data(ps.master_mask);
00930 
00931     /* Work out the RMS of the mean reset frame */
00932 
00933     idata = cpl_image_get_data(ps.outimage);
00934     vircam_medmad(idata,bpm,npi,&med,&sig);
00935     sig *= 1.48;
00936     vircam_reset_combine_config.resetmed = med;
00937     vircam_reset_combine_config.resetrms = sig;
00938 
00939     /* Load up the master reset */
00940 
00941     if (ps.master_reset != NULL) {
00942         ps.mrimage = vircam_fits_load(ps.master_reset,CPL_TYPE_FLOAT,jext);
00943         if (ps.mrimage == NULL) 
00944             cpl_msg_info(fctid,
00945                          "Master reset extension %" CPL_SIZE_FORMAT " won't load",
00946                          (cpl_size)jext);
00947         else if (vircam_is_dummy(vircam_fits_get_ehu(ps.mrimage))) {
00948             cpl_msg_info(fctid,
00949                          "Master reset extension %" CPL_SIZE_FORMAT " is a dummy!",
00950                          (cpl_size)jext);
00951             freefits(ps.mrimage);
00952         }
00953     } else 
00954         ps.mrimage = NULL;
00955 
00956     /* Load up the channel table */
00957 
00958     if (ps.chantab != NULL) {
00959         ctable = cpl_table_load(cpl_frame_get_filename(ps.chantab),jext,0);
00960         if (ctable == NULL) {
00961             cpl_error_reset();
00962             cpl_msg_info(fctid,
00963                          "Channel table extension %" CPL_SIZE_FORMAT " won't load",
00964                          (cpl_size)jext);
00965         } else if (vircam_chantab_verify(ctable) != VIR_OK) {
00966             cpl_msg_info(fctid,
00967                          "Channel table extension %" CPL_SIZE_FORMAT " has errors",
00968                          (cpl_size)jext);
00969             freetable(ctable);
00970         } else { 
00971             p = cpl_propertylist_load(cpl_frame_get_filename(ps.chantab),
00972                                       (cpl_size)jext);
00973             if (vircam_is_dummy(p)) {
00974                 cpl_msg_info(fctid,
00975                              "Channel table extensions %" CPL_SIZE_FORMAT " is a dummy",
00976                              (cpl_size)jext);
00977                 freetable(ctable);
00978             }
00979             freepropertylist(p);
00980         }
00981     } else 
00982         ctable = NULL;
00983 
00984     /* Form the difference image. NB: the difference image routine
00985        copes if the input mean image and or the channel tables are
00986        null. Thus if either or both are null because of a failure
00987        to load then the routine will do as much as it can and return
00988        allowing you to fill in the rest with dummy products */
00989 
00990     vircam_reset_combine_config.resetdiff_med = 0.0;
00991     vircam_reset_combine_config.resetdiff_rms = 0.0;
00992     ncells = vircam_reset_combine_config.ncells;
00993     vircam_difference_image(vircam_fits_get_image(ps.mrimage),
00994                             ps.outimage,bpm,ctable,ncells,1,
00995                             &gdiff,&grms,&(ps.diffimg),
00996                             &(ps.diffimstats));
00997     vircam_mask_clear(ps.master_mask);
00998     vircam_reset_combine_config.resetdiff_med = gdiff;
00999     vircam_reset_combine_config.resetdiff_rms = grms;
01000     freetable(ctable);
01001     if (ps.diffimg != NULL)
01002         we_get |= DIFFIMG;
01003     if (ps.diffimstats != NULL)
01004         we_get |= STATS_TAB;
01005     return;
01006 }
01007 
01008 /*---------------------------------------------------------------------------*/
01016 /*---------------------------------------------------------------------------*/
01017 
01018 static int vircam_reset_combine_lastbit(int jext, cpl_frameset *framelist,
01019                                         cpl_parameterlist *parlist) {
01020     int retval;
01021     const char *fctid="vircam_reset_combine_lastbit";
01022 
01023     /* Make whatever dummy products you need */
01024 
01025     vircam_reset_combine_dummy_products();
01026 
01027     /* Save everything */
01028 
01029     cpl_msg_info(fctid,
01030                  "Saving products for extension %" CPL_SIZE_FORMAT,
01031                  (cpl_size)jext);
01032     retval = vircam_reset_combine_save(framelist,parlist);
01033     if (retval != 0) {
01034         vircam_reset_combine_tidy(2);
01035         return(-1);
01036     }
01037 
01038     /* Free some stuff up */
01039 
01040     vircam_reset_combine_tidy(1);
01041     return(0);
01042 }
01043 
01044 /*---------------------------------------------------------------------------*/
01048 /*---------------------------------------------------------------------------*/
01049 
01050 static void vircam_reset_combine_init(void) {
01051     ps.labels = NULL;
01052     ps.resetlist = NULL;
01053     ps.resets = NULL;
01054     ps.nresets = 0;
01055     ps.good = NULL;
01056     ps.master_reset = NULL;
01057     ps.master_mask = NULL;
01058     ps.chantab = NULL;
01059     ps.outimage = NULL;
01060     ps.drs = NULL;
01061     ps.rejmask = NULL;
01062     ps.rejplus = NULL;
01063     ps.mrimage = NULL;
01064     ps.diffimg = NULL;
01065     ps.diffimstats = NULL;
01066     ps.phupaf = NULL;
01067 }
01068 
01069 /*---------------------------------------------------------------------------*/
01073 /*---------------------------------------------------------------------------*/
01074 
01075 static void vircam_reset_combine_tidy(int level) {
01076     freeimage(ps.outimage);
01077     freefitslist(ps.resets,ps.nresets);
01078     freespace(ps.rejmask);
01079     freespace(ps.rejplus);
01080     freepropertylist(ps.drs);
01081     freefits(ps.mrimage);
01082     freeimage(ps.diffimg);
01083     freetable(ps.diffimstats);
01084     if (level == 1)
01085         return;
01086     freespace(ps.labels);
01087     freeframeset(ps.resetlist);
01088     freeframe(ps.master_reset);
01089     freemask(ps.master_mask);
01090     freeframe(ps.chantab);
01091     freespace(ps.good);
01092     freepropertylist(ps.phupaf);
01093 }
01094 
01097 /*
01098 
01099 $Log: vircam_reset_combine.c,v $
01100 Revision 1.60  2012/01/16 12:32:18  jim
01101 A few more changes to fit in with cpl6
01102 
01103 Revision 1.59  2012/01/15 17:40:09  jim
01104 Minor modifications to take into accout the changes in cpl API for v6
01105 
01106 Revision 1.58  2010/03/21 06:48:21  jim
01107 Fixed bug where DATANCOM wasn't being updated in all products
01108 
01109 Revision 1.57  2010/03/09 14:27:40  jim
01110 Now updates ESO PRO DATANCOM to reflect the number of images used
01111 
01112 Revision 1.56  2010/02/05 09:42:22  jim
01113 Fixed call to non-existent cpl routine
01114 
01115 Revision 1.55  2010/01/31 18:54:01  jim
01116 Reference reset included in paf
01117 
01118 Revision 1.54  2009/09/09 09:50:21  jim
01119 Modified to try and get headers right
01120 
01121 Revision 1.53  2008/12/05 13:28:32  jim
01122 Fixed save routine so that the correct version of PRO CATG is written to the
01123 paf file
01124 
01125 Revision 1.52  2008/10/01 04:59:13  jim
01126 Added call to vircam_frameset_fexists to check input frameset
01127 
01128 Revision 1.51  2008/09/30 11:33:23  jim
01129 Added PRO CATG to pafs
01130 
01131 Revision 1.50  2007/10/19 09:25:09  jim
01132 Fixed problems with missing includes
01133 
01134 Revision 1.49  2007/10/15 12:53:26  jim
01135 Modified for compatibiliity with cpl_4.0
01136 
01137 Revision 1.48  2007/07/18 15:35:42  jim
01138 Added better error handling for missing or corrupt mask extensions
01139 
01140 Revision 1.47  2007/07/09 13:21:56  jim
01141 Modified to use new version of vircam_exten_range
01142 
01143 Revision 1.46  2007/04/04 10:36:18  jim
01144 Modified to use new dfs tags
01145 
01146 Revision 1.45  2007/03/29 12:19:39  jim
01147 Little changes to improve documentation
01148 
01149 Revision 1.44  2007/03/02 12:37:16  jim
01150 Removed WCS stuff from table headers
01151 
01152 Revision 1.43  2007/03/01 12:41:49  jim
01153 Modified slightly after code checking
01154 
01155 Revision 1.42  2007/02/25 06:27:41  jim
01156 plugged a few memory leaks
01157 
01158 Revision 1.41  2007/02/19 10:03:02  jim
01159 Fixed small memory leak
01160 
01161 Revision 1.40  2007/02/15 11:54:09  jim
01162 Modified to make a distinction between initial channel table and one that
01163 has the proper linearity information
01164 
01165 Revision 1.39  2007/02/15 06:59:38  jim
01166 Added ability to write QC paf files
01167 
01168 Revision 1.38  2007/02/06 13:11:12  jim
01169 Fixed entry for PRO dictionary in cpl_dfs_set_product_header
01170 
01171 Revision 1.37  2007/02/05 14:14:05  jim
01172 Input master frame is now tagged as REFERENCE. QC removed from stats table
01173 headers
01174 
01175 Revision 1.36  2007/01/09 11:39:02  jim
01176 Moved free for ps.good in tidy routine to the correct place
01177 
01178 Revision 1.35  2007/01/08 19:09:11  jim
01179 Fixed memory leak
01180 
01181 Revision 1.34  2006/12/13 13:19:52  jim
01182 Fixed problem with bad sigma estimate
01183 
01184 Revision 1.33  2006/12/08 11:39:27  jim
01185 Fixed bug where we_expect didn't check to see if the difference image was
01186 being produced before deciding whether or not a table would be produced.
01187 
01188 Revision 1.32  2006/11/27 12:15:08  jim
01189 changed calls to cpl_propertylist_append to cpl_propertylist_update
01190 
01191 Revision 1.31  2006/09/29 11:19:31  jim
01192 changed aliases on parameter names
01193 
01194 Revision 1.30  2006/09/09 16:49:40  jim
01195 Header comment update
01196 
01197 Revision 1.29  2006/08/27 20:30:02  jim
01198 Major mods to structure of the main processing routine to deal with missing
01199 and dummy frames. Deals better with lower level failures too
01200 
01201 Revision 1.28  2006/06/15 09:58:58  jim
01202 Minor changes to docs
01203 
01204 Revision 1.27  2006/06/09 11:26:25  jim
01205 Small changes to keep lint happy
01206 
01207 Revision 1.26  2006/06/06 13:01:40  jim
01208 Fixed so that the QC parameters go into the correct headers
01209 
01210 Revision 1.25  2006/05/17 14:43:58  jim
01211 Fixed problem in save routine which messed up the PRO CATG keywords
01212 
01213 Revision 1.24  2006/05/16 13:58:47  jim
01214 Fixed memory leaks that occur from not closing images at the end of
01215 the image extension loop
01216 
01217 Revision 1.23  2006/05/09 09:27:06  jim
01218 removed unecessary call to cpl_propertylist_delete
01219 
01220 Revision 1.22  2006/05/04 11:53:15  jim
01221 Fixed the way the _save routine works to be more consistent with the
01222 standard CPL way of doing things
01223 
01224 Revision 1.21  2006/04/27 09:46:01  jim
01225 Modified DFS frame types to conform to new dictionary
01226 
01227 Revision 1.20  2006/04/25 13:45:57  jim
01228 Fixed to adhere to new calling sequence for vircam_dfs routines
01229 
01230 Revision 1.19  2006/03/23 21:18:46  jim
01231 Minor changes mainly to comment headers
01232 
01233 Revision 1.18  2006/03/22 12:13:52  jim
01234 Modified to use new vircam_mask capability
01235 
01236 Revision 1.17  2006/03/15 10:43:40  jim
01237 Fixed a few things
01238 
01239 Revision 1.16  2006/03/08 14:32:35  jim
01240 Lots of little mods
01241 
01242 Revision 1.15  2006/03/03 14:29:06  jim
01243 Now calls routines with vir_fits.
01244 
01245 Revision 1.13  2006/02/22 10:01:38  jim
01246 Modified to use new version of vircam_imcombine
01247 
01248 Revision 1.12  2006/02/18 11:50:43  jim
01249 Modified the way the dfs product keywords are written using the vircam
01250 routines, rather than the cpl routine that doesn't understand image
01251 extensions
01252 
01253 Revision 1.11  2006/01/23 10:37:21  jim
01254 Now allows either a BPM or a CPM to be used as a mask
01255 
01256 Revision 1.10  2005/12/14 22:19:12  jim
01257 fixed docs
01258 
01259 Revision 1.9  2005/12/09 09:47:58  jim
01260 Many changes to add more documentation
01261 
01262 Revision 1.8  2005/12/02 10:45:38  jim
01263 The tags used in the sof are now written to the description string in the
01264 constructor. This is so that if they change in the vircam_dfs.h file, they
01265 aren't then hardcopied into each of the recipes...
01266 
01267 Revision 1.7  2005/12/01 16:25:48  jim
01268 Made the routine a bit more forgiving if certain master calibration files
01269 were missing. Now does as much as it can with the info it has
01270 
01271 Revision 1.6  2005/11/25 09:56:14  jim
01272 Tidied up some more documentation
01273 
01274 Revision 1.5  2005/11/23 14:57:40  jim
01275 A bit of tidying in response to splint messages
01276 
01277 Revision 1.4  2005/11/08 12:47:44  jim
01278 Made garbage collection a little better
01279 
01280 Revision 1.3  2005/11/07 13:13:43  jim
01281 Added some docs and calls to vircam_getnpts
01282 
01283 Revision 1.2  2005/11/03 15:16:28  jim
01284 Lots of changes mainly to strengthen error reporting
01285 
01286 Revision 1.1  2005/09/29 08:58:25  jim
01287 new routine
01288 
01289 
01290 
01291 */
01292 
01293 

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1