vircam_reset_combine.c

00001 /* $Id: vircam_reset_combine.c,v 1.50 2007/10/19 09:25:09 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/19 09:25:09 $
00024  * $Revision: 1.50 $
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 
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     int              *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 nlab,j,jst,jfn,retval,status,i,live,nx,ny;
00439     cpl_parameter *p;
00440     vir_fits *ff;
00441 
00442     /* Check validity of input frameset */
00443 
00444     if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
00445         cpl_msg_error(fctid,"Input framelist NULL or has no input data\n");
00446         return(-1);
00447     }
00448 
00449     /* Initialise a few things */
00450 
00451     vircam_reset_combine_init();
00452     we_expect |= MEANRESET;
00453 
00454     /* Get the parameters */
00455 
00456     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.combtype");
00457     vircam_reset_combine_config.combtype = cpl_parameter_get_int(p);
00458     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.scaletype");
00459     vircam_reset_combine_config.scaletype = cpl_parameter_get_int(p);
00460     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.xrej");
00461     vircam_reset_combine_config.xrej = cpl_parameter_get_bool(p);
00462     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.thresh");
00463     vircam_reset_combine_config.thresh = (float)cpl_parameter_get_double(p);
00464     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.ncells");
00465     vircam_reset_combine_config.ncells = cpl_parameter_get_int(p);
00466     p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.extenum");
00467     vircam_reset_combine_config.extenum = cpl_parameter_get_int(p);
00468 
00469     /* Sort out raw from calib frames */
00470 
00471     if (vircam_dfs_set_groups(framelist) != VIR_OK) {
00472         cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
00473         return(-1);
00474     }
00475 
00476     /* Get the reset frames */
00477 
00478     if ((ps.labels = cpl_frameset_labelise(framelist,vircam_compare_tags,
00479                                            &nlab)) == NULL) {
00480         cpl_msg_error(fctid,"Cannot labelise the input frames");
00481         return(-1);
00482     }
00483     if ((ps.resetlist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
00484                                                  VIRCAM_RESET_RAW)) == NULL) {
00485         cpl_msg_error(fctid,"Cannot find reset frames in input frameset");
00486         return(-1);
00487     }
00488     ps.nresets = cpl_frameset_get_size(ps.resetlist);
00489         
00490     /* Check to see if there is a master reset frame */
00491 
00492     if ((ps.master_reset = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00493                                                       VIRCAM_REF_RESET)) == NULL) 
00494         cpl_msg_info(fctid,"No master reset found -- no difference image will be formed");
00495     else
00496         we_expect |= DIFFIMG;
00497         
00498     /* Check to see if there is a master bad pixel map. If there isn't one 
00499        then look for a confidence map */
00500 
00501     ps.master_mask = vircam_mask_define(framelist,ps.labels,nlab);
00502 
00503     /* Check to see if there is a channel table */
00504 
00505     if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00506                                                  VIRCAM_CAL_CHANTAB)) == NULL) {
00507         if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00508                                                      VIRCAM_CAL_CHANTAB_INIT)) == NULL) 
00509             cpl_msg_info(fctid,"No channel table found -- no difference image stats will be done");
00510     } else if (we_expect & DIFFIMG) 
00511             we_expect |= STATS_TAB;
00512 
00513     /* Now, how many image extensions do we want to do? If the extension
00514        number is zero, then we loop for all possible extensions. If it
00515        isn't then we just do the extension specified */
00516 
00517     vircam_exten_range(vircam_reset_combine_config.extenum,
00518                        (const cpl_frame *)cpl_frameset_get_frame(ps.resetlist,0),
00519                        &jst,&jfn);
00520     if (jst == -1 || jfn == -1) {
00521         cpl_msg_error(fctid,"Unable to continue");
00522         vircam_reset_combine_tidy(2);
00523         return(-1);
00524     }
00525 
00526     /* Get some space for the good frames */
00527 
00528     ps.good = cpl_malloc(ps.nresets*sizeof(vir_fits *));
00529 
00530     /* Now loop for all the extension... */
00531 
00532     for (j = jst; j <= jfn; j++) {
00533         status = VIR_OK;
00534         we_get = 0;
00535         isfirst = (j == jst);
00536 
00537         /* Load up the images. If they won't load the signal a major error */
00538 
00539         ps.resets = vircam_fits_load_list(ps.resetlist,CPL_TYPE_FLOAT,j);
00540         if (ps.resets == NULL) {
00541             cpl_msg_info(fctid,"Extension %d resets wouldn't load",j);
00542             retval = vircam_reset_combine_lastbit(j,framelist,parlist);
00543             if (retval != 0)
00544                 return(-1);
00545             continue;
00546         }
00547 
00548         /* Are any of these reset images good? */
00549 
00550         ps.ngood = 0;
00551         for (i = 0; i < ps.nresets; i++) {
00552             ff = ps.resets[i];
00553             vircam_pfits_get_detlive(vircam_fits_get_ehu(ff),&live);
00554             if (! live) {
00555                 cpl_msg_info(fctid,"Detector flagged dead %s",
00556                              vircam_fits_get_fullname(ff));
00557                 vircam_fits_set_error(ff,VIR_FATAL);
00558             } else {
00559                 ps.good[ps.ngood] = ff;
00560                 ps.ngood += 1;
00561             }
00562         }
00563 
00564         /* If there are no good images, then signal that wee need to 
00565            create some dummy products and move on */
00566 
00567         if (ps.ngood == 0) {
00568             cpl_msg_info(fctid,"All images flagged bad for this extension");
00569             retval = vircam_reset_combine_lastbit(j,framelist,parlist);
00570             if (retval != 0)
00571                 return(-1);
00572             continue;
00573         }
00574 
00575         /* Load the mask */
00576 
00577         nx = cpl_image_get_size_x(vircam_fits_get_image(ps.good[0]));
00578         ny = cpl_image_get_size_y(vircam_fits_get_image(ps.good[0]));
00579         if (vircam_mask_load(ps.master_mask,j,nx,ny) == VIR_FATAL) {
00580             cpl_msg_info(fctid,"Unable to load mask image %s[%d]",
00581                          vircam_mask_get_filename(ps.master_mask),j);
00582             cpl_msg_info(fctid,"Forcing all pixels to be good from now on");
00583             vircam_mask_force(ps.master_mask,nx,ny);
00584         }
00585 
00586         /* Call the combine module. If it fails then signal that
00587            all products will be dummies */
00588 
00589         cpl_msg_info(fctid,"Doing combination for extension %d\n",j);
00590         (void)vircam_imcombine(ps.good,ps.ngood,
00591                                vircam_reset_combine_config.combtype,
00592                                vircam_reset_combine_config.scaletype,
00593                                vircam_reset_combine_config.xrej,
00594                                vircam_reset_combine_config.thresh,
00595                                &(ps.outimage),&(ps.rejmask),
00596                                &(ps.rejplus),&(ps.drs),&status);
00597         if (status == VIR_OK) {
00598             we_get |= MEANRESET;
00599             vircam_reset_combine_normal(j);
00600         }
00601 
00602         /* Create any dummies and save products */
00603 
00604         retval = vircam_reset_combine_lastbit(j,framelist,parlist);
00605         if (retval != 0)
00606             return(-1);
00607     }
00608     vircam_reset_combine_tidy(2);
00609     return(0);
00610 }
00611 
00612 /*---------------------------------------------------------------------------*/
00619 /*---------------------------------------------------------------------------*/
00620 
00621 static int vircam_reset_combine_save(cpl_frameset *framelist, 
00622                                      cpl_parameterlist *parlist) {
00623     cpl_propertylist *plist,*elist,*p,*pafprop;
00624     int status;
00625     const char *fctid = "vircam_reset_combine_save";
00626     const char *outfile = "resetcomb.fits";
00627     const char *outdiff = "resetdiff.fits";
00628     const char *outdimst = "resetdifftab.fits";
00629     const char *outfilepaf = "resetcomb";
00630     const char *outdiffpaf = "resetdiff";
00631     const char *recipeid = "vircam_reset_combine";
00632 
00633     /* If we need to make a PHU then do that now based on the first frame
00634        in the input frame list */
00635 
00636     if (isfirst) {
00637 
00638         /* Create a new product frame object and define some tags */
00639 
00640         product_frame_mean_reset = cpl_frame_new();
00641         cpl_frame_set_filename(product_frame_mean_reset,outfile);
00642         cpl_frame_set_tag(product_frame_mean_reset,VIRCAM_PRO_RESET);
00643         cpl_frame_set_type(product_frame_mean_reset,CPL_FRAME_TYPE_IMAGE);
00644         cpl_frame_set_group(product_frame_mean_reset,CPL_FRAME_GROUP_PRODUCT);
00645         cpl_frame_set_level(product_frame_mean_reset,CPL_FRAME_LEVEL_FINAL);
00646 
00647         /* Set up product phu */
00648 
00649         plist = vircam_fits_get_phu(ps.resets[0]);
00650         ps.phupaf = vircam_paf_phu_items(plist);
00651         vircam_dfs_set_product_primary_header(plist,product_frame_mean_reset,
00652                                               framelist,parlist,
00653                                               (char *)recipeid,
00654                                               "PRO-1.15");
00655 
00656         /* 'Save' the PHU image */                       
00657 
00658         if (cpl_image_save(NULL,outfile,CPL_BPP_8_UNSIGNED,plist,
00659                            CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00660             cpl_msg_error(fctid,"Cannot save product PHU");
00661             cpl_frame_delete(product_frame_mean_reset);
00662             return(-1);
00663         }
00664         cpl_frameset_insert(framelist,product_frame_mean_reset);
00665 
00666         /* Create a new product frame object for the difference image */
00667 
00668         if (we_expect & DIFFIMG) {
00669             product_frame_diffimg = cpl_frame_new();
00670             cpl_frame_set_filename(product_frame_diffimg,outdiff);
00671             cpl_frame_set_tag(product_frame_diffimg,
00672                               VIRCAM_PRO_DIFFIMG_RESET);
00673             cpl_frame_set_type(product_frame_diffimg,CPL_FRAME_TYPE_IMAGE);
00674             cpl_frame_set_group(product_frame_diffimg,CPL_FRAME_GROUP_PRODUCT);
00675             cpl_frame_set_level(product_frame_diffimg,CPL_FRAME_LEVEL_FINAL);
00676 
00677             /* Set up product phu */
00678 
00679             plist = vircam_fits_get_phu(ps.resets[0]);
00680             vircam_dfs_set_product_primary_header(plist,product_frame_diffimg,
00681                                                   framelist,parlist,
00682                                                   (char *)recipeid,
00683                                                   "PRO-1.15");
00684             /* 'Save' the PHU image */                   
00685 
00686             if (cpl_image_save(NULL,outdiff,CPL_BPP_8_UNSIGNED,plist,
00687                                CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00688                 cpl_msg_error(fctid,"Cannot save product PHU");
00689                 cpl_frame_delete(product_frame_diffimg);
00690                 return(-1);
00691             }
00692             cpl_frameset_insert(framelist,product_frame_diffimg);
00693         }
00694 
00695         /* Create a new product frame object for the difference image stats 
00696            table */
00697 
00698         if (we_expect & STATS_TAB) {
00699             product_frame_diffimg_stats = cpl_frame_new();
00700             cpl_frame_set_filename(product_frame_diffimg_stats,outdimst);
00701             cpl_frame_set_tag(product_frame_diffimg_stats,
00702                               VIRCAM_PRO_DIFFIMG_RESET_STATS);
00703             cpl_frame_set_type(product_frame_diffimg_stats,
00704                                CPL_FRAME_TYPE_TABLE);
00705             cpl_frame_set_group(product_frame_diffimg_stats,
00706                                 CPL_FRAME_GROUP_PRODUCT);
00707             cpl_frame_set_level(product_frame_diffimg_stats,
00708                                 CPL_FRAME_LEVEL_FINAL);
00709 
00710             /* Set up product phu */
00711 
00712             plist = vircam_fits_get_phu(ps.resets[0]);
00713             vircam_dfs_set_product_primary_header(plist,
00714                                                   product_frame_diffimg_stats,
00715                                                   framelist,parlist,
00716                                                   (char *)recipeid,
00717                                                   "PRO-1.15");
00718 
00719             /* Fiddle with the extension header */
00720 
00721             elist = vircam_fits_get_ehu(ps.resets[0]);
00722             p = cpl_propertylist_duplicate(elist);
00723             vircam_merge_propertylists(p,ps.drs);
00724             if (! (we_get & STATS_TAB))
00725                 vircam_dummy_property(p);
00726             vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
00727                                                 framelist,parlist,
00728                                                 (char *)recipeid,
00729                                                 "PRO-1.15");
00730             status = VIR_OK;
00731             vircam_removewcs(p,&status);
00732             if (cpl_table_save(ps.diffimstats,plist,p,outdimst,
00733                                CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00734                 cpl_msg_error(fctid,"Cannot save product table extension");
00735                 cpl_propertylist_delete(p);
00736                 return(-1);
00737             }
00738             cpl_propertylist_delete(p);
00739             cpl_frameset_insert(framelist,product_frame_diffimg_stats);
00740         }
00741     }
00742 
00743     /* Get the extension property list */ 
00744 
00745     plist = vircam_fits_get_ehu(ps.resets[0]);
00746 
00747     /* Fiddle with the header now */
00748 
00749     vircam_merge_propertylists(plist,ps.drs);
00750     p = cpl_propertylist_duplicate(plist);
00751     if (! (we_get & MEANRESET))
00752         vircam_dummy_property(p);
00753     vircam_dfs_set_product_exten_header(p,product_frame_mean_reset,framelist,
00754                                         parlist,(char *)recipeid,
00755                                         "PRO-1.15");
00756 
00757     /* Now save the reset image extension */
00758 
00759     cpl_propertylist_update_float(p,"ESO QC RESETMED",
00760                                   vircam_reset_combine_config.resetmed);
00761     cpl_propertylist_set_comment(p,"ESO QC RESETMED",
00762                                  "Median of mean reset frame");
00763     cpl_propertylist_update_float(p,"ESO QC RESETRMS",
00764                                   vircam_reset_combine_config.resetrms);
00765     cpl_propertylist_set_comment(p,"ESO QC RESETRMS",
00766                                  "RMS of mean reset frame");
00767     if (cpl_image_save(ps.outimage,outfile,CPL_BPP_IEEE_FLOAT,p,
00768                        CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00769         cpl_msg_error(fctid,"Cannot save product image extension");
00770         cpl_propertylist_delete(p);
00771         return(-1);
00772     }
00773 
00774     /* Write out PAF for mean image */
00775 
00776     pafprop = vircam_paf_req_items(p);
00777     vircam_merge_propertylists(pafprop,ps.phupaf);
00778     if (vircam_paf_print((char *)outfilepaf,"VIRCAM/vircam_reset_combine",
00779                          "QC file",pafprop) != VIR_OK)
00780         cpl_msg_warning(fctid,"Unable to save PAF for mean reset");
00781     cpl_propertylist_delete(pafprop);
00782     cpl_propertylist_delete(p);
00783 
00784     /* Now save the reset difference image extension */
00785 
00786     if (we_expect & DIFFIMG) {
00787         p = cpl_propertylist_duplicate(plist);
00788         if (! (we_get & DIFFIMG))
00789             vircam_dummy_property(p);
00790         cpl_propertylist_update_float(p,"ESO QC RESETDIFF_MED",
00791                                       vircam_reset_combine_config.resetdiff_med);
00792         cpl_propertylist_set_comment(p,"ESO QC RESETDIFF_MED",
00793                                      "Median value of difference image");
00794         cpl_propertylist_update_float(p,"ESO QC RESETDIFF_RMS",
00795                                       vircam_reset_combine_config.resetdiff_rms);
00796         cpl_propertylist_set_comment(p,"ESO QC RESETDIFF_RMS",
00797                                      "RMS value of difference image");
00798         vircam_dfs_set_product_exten_header(p,product_frame_diffimg,
00799                                             framelist,parlist,
00800                                             (char *)recipeid,
00801                                             "PRO-1.15");
00802         if (cpl_image_save(ps.diffimg,outdiff,CPL_BPP_IEEE_FLOAT,p,
00803                            CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00804             cpl_propertylist_delete(p);
00805             cpl_msg_error(fctid,"Cannot save product image extension");
00806             return(-1);
00807         }
00808         /* Write out PAF for difference image */
00809 
00810         pafprop = vircam_paf_req_items(p);
00811         vircam_merge_propertylists(pafprop,ps.phupaf);
00812         if (vircam_paf_print((char *)outdiffpaf,"VIRCAM/vircam_reset_combine",
00813                              "QC file",pafprop) != VIR_OK)
00814             cpl_msg_warning(fctid,"Unable to save PAF for difference image");
00815         cpl_propertylist_delete(pafprop);
00816         cpl_propertylist_delete(p);
00817     }
00818 
00819     /* Now any further difference image stats tables */
00820 
00821     if (! isfirst && (we_expect & STATS_TAB)) {
00822         p = cpl_propertylist_duplicate(plist);
00823         if (! (we_get & STATS_TAB))
00824             vircam_dummy_property(p);
00825         vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
00826                                             framelist,parlist,
00827                                             (char *)recipeid,
00828                                             "PRO-1.15");
00829         status = VIR_OK;
00830         vircam_removewcs(p,&status);
00831         if (cpl_table_save(ps.diffimstats,NULL,p,outdimst,CPL_IO_EXTEND)
00832                            != CPL_ERROR_NONE) {
00833             cpl_msg_error(fctid,"Cannot save product table extension");
00834             cpl_propertylist_delete(p);
00835             return(-1);
00836         }       
00837         cpl_propertylist_delete(p);
00838     }
00839 
00840     return(0);
00841 }
00842 
00843 /*---------------------------------------------------------------------------*/
00847 /*---------------------------------------------------------------------------*/
00848 
00849 static void vircam_reset_combine_dummy_products(void) {
00850 
00851     /* See if you even need to be here */
00852 
00853     if (we_get == we_expect)
00854         return;
00855 
00856     /* First an output combined reset frame */
00857 
00858     if (! (we_get & MEANRESET)) {
00859         ps.outimage = vircam_dummy_image(ps.resets[0]);
00860 
00861         /* Set up the QC parameters */
00862 
00863         vircam_reset_combine_config.resetmed = 0.0;
00864         vircam_reset_combine_config.resetrms = 0.0;
00865     }
00866 
00867     /* Do the difference image */
00868 
00869     if ((we_expect & DIFFIMG) && ! (we_get & DIFFIMG)) {
00870         vircam_reset_combine_config.resetdiff_med = 0.0;
00871         vircam_reset_combine_config.resetdiff_rms = 0.0;
00872 
00873         /* Is a difference image required? If so then let's have it... */
00874 
00875         ps.diffimg = vircam_dummy_image(ps.resets[0]);
00876     }
00877 
00878     /* If a difference image stats table is required, then do that now */
00879 
00880     if ((we_expect & STATS_TAB) && ! (we_get & STATS_TAB)) 
00881         ps.diffimstats = vircam_create_diffimg_stats(0);
00882 
00883 
00884     return;
00885 }
00886 
00887 /*---------------------------------------------------------------------------*/
00892 /*---------------------------------------------------------------------------*/
00893 
00894 static void vircam_reset_combine_normal(int jext) {
00895     int nx,ny,ncells;
00896     long npi;
00897     unsigned char *bpm;
00898     float med,sig,*idata,grms,gdiff;
00899     const char *fctid="vircam_reset_combine_normal";
00900     cpl_table *ctable;
00901     cpl_propertylist *p;
00902 
00903     /* Load up the bad pixel mask */
00904 
00905     nx = cpl_image_get_size_x(ps.outimage);
00906     ny = cpl_image_get_size_y(ps.outimage);
00907     npi = nx*ny;
00908     bpm = vircam_mask_get_data(ps.master_mask);
00909 
00910     /* Work out the RMS of the mean reset frame */
00911 
00912     idata = cpl_image_get_data(ps.outimage);
00913     vircam_medmad(idata,bpm,npi,&med,&sig);
00914     sig *= 1.48;
00915     vircam_reset_combine_config.resetmed = med;
00916     vircam_reset_combine_config.resetrms = sig;
00917 
00918     /* Load up the master reset */
00919 
00920     if (ps.master_reset != NULL) {
00921         ps.mrimage = vircam_fits_load(ps.master_reset,CPL_TYPE_FLOAT,jext);
00922         if (ps.mrimage == NULL) 
00923             cpl_msg_info(fctid,"Master reset extension %d won't load",jext);
00924         else if (vircam_is_dummy(vircam_fits_get_ehu(ps.mrimage))) {
00925             cpl_msg_info(fctid,"Master reset extension %d is a dummy!",jext);
00926             freefits(ps.mrimage);
00927         }
00928     } else 
00929         ps.mrimage = NULL;
00930 
00931     /* Load up the channel table */
00932 
00933     if (ps.chantab != NULL) {
00934         ctable = cpl_table_load(cpl_frame_get_filename(ps.chantab),jext,0);
00935         if (ctable == NULL) {
00936             cpl_error_reset();
00937             cpl_msg_info(fctid,"Channel table extension %d won't load",jext);
00938         } else if (vircam_chantab_verify(ctable) != VIR_OK) {
00939             cpl_msg_info(fctid,"Channel table extension %d has errors",jext);
00940             freetable(ctable);
00941         } else { 
00942             p = cpl_propertylist_load(cpl_frame_get_filename(ps.chantab),jext);
00943             if (vircam_is_dummy(p)) {
00944                 cpl_msg_info(fctid,"Channel table extensions %d is a dummy",
00945                              jext);
00946                 freetable(ctable);
00947             }
00948             freepropertylist(p);
00949         }
00950     } else 
00951         ctable = NULL;
00952 
00953     /* Form the difference image. NB: the difference image routine
00954        copes if the input mean image and or the channel tables are
00955        null. Thus if either or both are null because of a failure
00956        to load then the routine will do as much as it can and return
00957        allowing you to fill in the rest with dummy products */
00958 
00959     vircam_reset_combine_config.resetdiff_med = 0.0;
00960     vircam_reset_combine_config.resetdiff_rms = 0.0;
00961     ncells = vircam_reset_combine_config.ncells;
00962     vircam_difference_image(vircam_fits_get_image(ps.mrimage),
00963                             ps.outimage,bpm,ctable,ncells,1,
00964                             &gdiff,&grms,&(ps.diffimg),
00965                             &(ps.diffimstats));
00966     vircam_mask_clear(ps.master_mask);
00967     vircam_reset_combine_config.resetdiff_med = gdiff;
00968     vircam_reset_combine_config.resetdiff_rms = grms;
00969     freetable(ctable);
00970     if (ps.diffimg != NULL)
00971         we_get |= DIFFIMG;
00972     if (ps.diffimstats != NULL)
00973         we_get |= STATS_TAB;
00974     return;
00975 }
00976 
00977 /*---------------------------------------------------------------------------*/
00985 /*---------------------------------------------------------------------------*/
00986 
00987 static int vircam_reset_combine_lastbit(int jext, cpl_frameset *framelist,
00988                                         cpl_parameterlist *parlist) {
00989     int retval;
00990     const char *fctid="vircam_reset_combine_lastbit";
00991 
00992     /* Make whatever dummy products you need */
00993 
00994     vircam_reset_combine_dummy_products();
00995 
00996     /* Save everything */
00997 
00998     cpl_msg_info(fctid,"Saving products for extension %d",jext);
00999     retval = vircam_reset_combine_save(framelist,parlist);
01000     if (retval != 0) {
01001         vircam_reset_combine_tidy(2);
01002         return(-1);
01003     }
01004 
01005     /* Free some stuff up */
01006 
01007     vircam_reset_combine_tidy(1);
01008     return(0);
01009 }
01010 
01011 /*---------------------------------------------------------------------------*/
01015 /*---------------------------------------------------------------------------*/
01016 
01017 static void vircam_reset_combine_init(void) {
01018     ps.labels = NULL;
01019     ps.resetlist = NULL;
01020     ps.resets = NULL;
01021     ps.nresets = 0;
01022     ps.good = NULL;
01023     ps.master_reset = NULL;
01024     ps.master_mask = NULL;
01025     ps.chantab = NULL;
01026     ps.outimage = NULL;
01027     ps.drs = NULL;
01028     ps.rejmask = NULL;
01029     ps.rejplus = NULL;
01030     ps.mrimage = NULL;
01031     ps.diffimg = NULL;
01032     ps.diffimstats = NULL;
01033     ps.phupaf = NULL;
01034 }
01035 
01036 /*---------------------------------------------------------------------------*/
01040 /*---------------------------------------------------------------------------*/
01041 
01042 static void vircam_reset_combine_tidy(int level) {
01043     freeimage(ps.outimage);
01044     freefitslist(ps.resets,ps.nresets);
01045     freespace(ps.rejmask);
01046     freespace(ps.rejplus);
01047     freepropertylist(ps.drs);
01048     freefits(ps.mrimage);
01049     freeimage(ps.diffimg);
01050     freetable(ps.diffimstats);
01051     if (level == 1)
01052         return;
01053     freespace(ps.labels);
01054     freeframeset(ps.resetlist);
01055     freeframe(ps.master_reset);
01056     freemask(ps.master_mask);
01057     freeframe(ps.chantab);
01058     freespace(ps.good);
01059     freepropertylist(ps.phupaf);
01060 }
01061 
01064 /*
01065 
01066 $Log: vircam_reset_combine.c,v $
01067 Revision 1.50  2007/10/19 09:25:09  jim
01068 Fixed problems with missing includes
01069 
01070 Revision 1.49  2007/10/15 12:53:26  jim
01071 Modified for compatibiliity with cpl_4.0
01072 
01073 Revision 1.48  2007/07/18 15:35:42  jim
01074 Added better error handling for missing or corrupt mask extensions
01075 
01076 Revision 1.47  2007/07/09 13:21:56  jim
01077 Modified to use new version of vircam_exten_range
01078 
01079 Revision 1.46  2007/04/04 10:36:18  jim
01080 Modified to use new dfs tags
01081 
01082 Revision 1.45  2007/03/29 12:19:39  jim
01083 Little changes to improve documentation
01084 
01085 Revision 1.44  2007/03/02 12:37:16  jim
01086 Removed WCS stuff from table headers
01087 
01088 Revision 1.43  2007/03/01 12:41:49  jim
01089 Modified slightly after code checking
01090 
01091 Revision 1.42  2007/02/25 06:27:41  jim
01092 plugged a few memory leaks
01093 
01094 Revision 1.41  2007/02/19 10:03:02  jim
01095 Fixed small memory leak
01096 
01097 Revision 1.40  2007/02/15 11:54:09  jim
01098 Modified to make a distinction between initial channel table and one that
01099 has the proper linearity information
01100 
01101 Revision 1.39  2007/02/15 06:59:38  jim
01102 Added ability to write QC paf files
01103 
01104 Revision 1.38  2007/02/06 13:11:12  jim
01105 Fixed entry for PRO dictionary in cpl_dfs_set_product_header
01106 
01107 Revision 1.37  2007/02/05 14:14:05  jim
01108 Input master frame is now tagged as REFERENCE. QC removed from stats table
01109 headers
01110 
01111 Revision 1.36  2007/01/09 11:39:02  jim
01112 Moved free for ps.good in tidy routine to the correct place
01113 
01114 Revision 1.35  2007/01/08 19:09:11  jim
01115 Fixed memory leak
01116 
01117 Revision 1.34  2006/12/13 13:19:52  jim
01118 Fixed problem with bad sigma estimate
01119 
01120 Revision 1.33  2006/12/08 11:39:27  jim
01121 Fixed bug where we_expect didn't check to see if the difference image was
01122 being produced before deciding whether or not a table would be produced.
01123 
01124 Revision 1.32  2006/11/27 12:15:08  jim
01125 changed calls to cpl_propertylist_append to cpl_propertylist_update
01126 
01127 Revision 1.31  2006/09/29 11:19:31  jim
01128 changed aliases on parameter names
01129 
01130 Revision 1.30  2006/09/09 16:49:40  jim
01131 Header comment update
01132 
01133 Revision 1.29  2006/08/27 20:30:02  jim
01134 Major mods to structure of the main processing routine to deal with missing
01135 and dummy frames. Deals better with lower level failures too
01136 
01137 Revision 1.28  2006/06/15 09:58:58  jim
01138 Minor changes to docs
01139 
01140 Revision 1.27  2006/06/09 11:26:25  jim
01141 Small changes to keep lint happy
01142 
01143 Revision 1.26  2006/06/06 13:01:40  jim
01144 Fixed so that the QC parameters go into the correct headers
01145 
01146 Revision 1.25  2006/05/17 14:43:58  jim
01147 Fixed problem in save routine which messed up the PRO CATG keywords
01148 
01149 Revision 1.24  2006/05/16 13:58:47  jim
01150 Fixed memory leaks that occur from not closing images at the end of
01151 the image extension loop
01152 
01153 Revision 1.23  2006/05/09 09:27:06  jim
01154 removed unecessary call to cpl_propertylist_delete
01155 
01156 Revision 1.22  2006/05/04 11:53:15  jim
01157 Fixed the way the _save routine works to be more consistent with the
01158 standard CPL way of doing things
01159 
01160 Revision 1.21  2006/04/27 09:46:01  jim
01161 Modified DFS frame types to conform to new dictionary
01162 
01163 Revision 1.20  2006/04/25 13:45:57  jim
01164 Fixed to adhere to new calling sequence for vircam_dfs routines
01165 
01166 Revision 1.19  2006/03/23 21:18:46  jim
01167 Minor changes mainly to comment headers
01168 
01169 Revision 1.18  2006/03/22 12:13:52  jim
01170 Modified to use new vircam_mask capability
01171 
01172 Revision 1.17  2006/03/15 10:43:40  jim
01173 Fixed a few things
01174 
01175 Revision 1.16  2006/03/08 14:32:35  jim
01176 Lots of little mods
01177 
01178 Revision 1.15  2006/03/03 14:29:06  jim
01179 Now calls routines with vir_fits.
01180 
01181 Revision 1.13  2006/02/22 10:01:38  jim
01182 Modified to use new version of vircam_imcombine
01183 
01184 Revision 1.12  2006/02/18 11:50:43  jim
01185 Modified the way the dfs product keywords are written using the vircam
01186 routines, rather than the cpl routine that doesn't understand image
01187 extensions
01188 
01189 Revision 1.11  2006/01/23 10:37:21  jim
01190 Now allows either a BPM or a CPM to be used as a mask
01191 
01192 Revision 1.10  2005/12/14 22:19:12  jim
01193 fixed docs
01194 
01195 Revision 1.9  2005/12/09 09:47:58  jim
01196 Many changes to add more documentation
01197 
01198 Revision 1.8  2005/12/02 10:45:38  jim
01199 The tags used in the sof are now written to the description string in the
01200 constructor. This is so that if they change in the vircam_dfs.h file, they
01201 aren't then hardcopied into each of the recipes...
01202 
01203 Revision 1.7  2005/12/01 16:25:48  jim
01204 Made the routine a bit more forgiving if certain master calibration files
01205 were missing. Now does as much as it can with the info it has
01206 
01207 Revision 1.6  2005/11/25 09:56:14  jim
01208 Tidied up some more documentation
01209 
01210 Revision 1.5  2005/11/23 14:57:40  jim
01211 A bit of tidying in response to splint messages
01212 
01213 Revision 1.4  2005/11/08 12:47:44  jim
01214 Made garbage collection a little better
01215 
01216 Revision 1.3  2005/11/07 13:13:43  jim
01217 Added some docs and calls to vircam_getnpts
01218 
01219 Revision 1.2  2005/11/03 15:16:28  jim
01220 Lots of changes mainly to strengthen error reporting
01221 
01222 Revision 1.1  2005/09/29 08:58:25  jim
01223 new routine
01224 
01225 
01226 
01227 */
01228 
01229 

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