HAWKI Pipeline Reference Manual 1.8.6
hawki_step_compute_bkg.c
00001 /* $Id: hawki_step_compute_bkg.c,v 1.17 2011/10/24 10:42:43 cgarcia Exp $
00002  *
00003  * This file is part of the HAWKI Pipeline
00004  * Copyright (C) 2008 European Southern Observatory
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: cgarcia $
00023  * $Date: 2011/10/24 10:42:43 $
00024  * $Revision: 1.17 $
00025  * $Name: hawki-1_8_6 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <string.h>
00037 #include <math.h>
00038 #include <cpl.h>
00039 
00040 #include "hawki_utils.h"
00041 #include "hawki_distortion.h"
00042 #include "hawki_load.h"
00043 #include "hawki_save.h"
00044 #include "hawki_pfits.h"
00045 #include "hawki_dfs.h"
00046 #include "hawki_bkg.h"
00047 #include "hawki_calib.h"
00048 
00049 /*-----------------------------------------------------------------------------
00050                                 Structs
00051  -----------------------------------------------------------------------------*/
00052 
00053 static struct 
00054 {
00055     /* Configuration values */
00056     int      nmin_comb;
00057     int      nhalf_window;
00058     int      rejlow;
00059     int      rejhigh;
00060     
00061 } hawki_step_compute_bkg_config;
00062 
00063 /*-----------------------------------------------------------------------------
00064                             Functions prototypes
00065  -----------------------------------------------------------------------------*/
00066 
00067 static int hawki_step_compute_bkg_create(cpl_plugin *) ;
00068 static int hawki_step_compute_bkg_exec(cpl_plugin *) ;
00069 static int hawki_step_compute_bkg_destroy(cpl_plugin *) ;
00070 static int hawki_step_compute_bkg(cpl_parameterlist *, cpl_frameset *) ;
00071 
00072 static int hawki_step_compute_bkg_from_objects_qc_save
00073 (cpl_frameset        *  objframes,
00074  cpl_frameset        *  maskframes,
00075  cpl_frameset        *  offsetsframes,
00076  cpl_frameset        *  x_distortionframes,
00077  cpl_frameset        *  y_distortionframes,
00078  cpl_parameterlist   *  parlist, 
00079  cpl_frameset        *  recipe_framelist);
00080 static int hawki_step_compute_bkg_from_objects_median_save
00081 (cpl_frameset        *  objframes,
00082  cpl_parameterlist   *  recipe_parlist, 
00083  cpl_frameset        *  recipe_framelist);
00084 static int hawki_step_compute_bkg_from_sky_median_save
00085 (cpl_frameset        *  skyframes,
00086  cpl_parameterlist   *  recipe_parlist, 
00087  cpl_frameset        *  recipe_framelist);
00088 static int hawki_step_compute_bkg_interpolate_badpix
00089 (cpl_image           *  image);
00090 static int hawki_step_compute_bkg_from_objects_running_median_save
00091 (cpl_frameset        *  objframes,
00092  cpl_frameset        *  maskframes,
00093  cpl_frameset        *  offsetframes,
00094  cpl_frameset        *  x_distortionframes,
00095  cpl_frameset        *  y_distortionframes,
00096  cpl_parameterlist   *  recipe_parlist, 
00097  cpl_frameset        *  recipe_framelist);
00098 static int hawki_step_compute_bkg_from_running_median_nonmasked_save
00099 (const cpl_frameset  *  objframes,
00100  int                    nhalf_window,
00101  int                    rejlow,
00102  int                    rejhigh,
00103  cpl_frameset        *  recipe_framelist,
00104  cpl_parameterlist   *  recipe_parlist);
00105 static int hawki_step_compute_bkg_from_running_median_masked_save
00106 (const cpl_frameset  *  objframes,
00107  cpl_frame           *  maskframe,
00108  cpl_bivector        ** offsets,
00109  cpl_frame           *  x_distortionframe,
00110  cpl_frame           *  y_distortionframe,
00111  int                    nhalf_window,
00112  int                    rejlow,
00113  int                    rejhigh,
00114  cpl_frameset        *  recipe_framelist,
00115  cpl_parameterlist   *  recipe_parlist);
00116 
00117 
00118 int hawki_step_compute_bkg_retrieve_input_param
00119 (cpl_parameterlist  *  parlist);
00120 
00121 /*-----------------------------------------------------------------------------
00122                             Static variables
00123  -----------------------------------------------------------------------------*/
00124 
00125 static char hawki_step_compute_bkg_description[] =
00126 "hawki_step_compute_bkg -- hawki background computation utility.\n"
00127 "This recipe will create the associated background images\n"
00128 "for a given set of object images. If there are sky images, these will\n"
00129 "be used to compute the background, otherwise, the background is computed\n"
00130 "using a running mean on the object images. An optional mask can be supplied\n"
00131 "for the running mean.\n"
00132 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
00133 "obj_basic_cal-file.fits "HAWKI_CALPRO_BASICCALIBRATED" or\n"
00134 "sky_basic_cal-file.fits "HAWKI_CALPRO_SKY_BASICCALIBRATED" \n"
00135 "and optionally for object masking:\n"
00136 "object_mask-file.fits "HAWKI_CALPRO_OBJ_MASK" \n"
00137 "offsets.fits "HAWKI_CALPRO_OFFSETS" \n"
00138 "distortion_x.fits "HAWKI_CALPRO_DISTORTION_X" \n"
00139 "distortion_y.fits "HAWKI_CALPRO_DISTORTION_Y" \n";
00140 
00141 /*-----------------------------------------------------------------------------
00142                                 Functions code
00143  -----------------------------------------------------------------------------*/
00144 
00145 /*----------------------------------------------------------------------------*/
00153 /*----------------------------------------------------------------------------*/
00154 int cpl_plugin_get_info(cpl_pluginlist * list)
00155 {
00156     cpl_recipe  *   recipe = cpl_calloc(1, sizeof(*recipe)) ;
00157     cpl_plugin  *   plugin = &recipe->interface ;
00158 
00159     cpl_plugin_init(plugin,
00160                     CPL_PLUGIN_API,
00161                     HAWKI_BINARY_VERSION,
00162                     CPL_PLUGIN_TYPE_RECIPE,
00163                     "hawki_step_compute_bkg",
00164                     "Background computing utility",
00165                     hawki_step_compute_bkg_description,
00166                     "Cesar Enrique Garcia Dabo",
00167                     PACKAGE_BUGREPORT,  
00168                     hawki_get_license(),
00169                     hawki_step_compute_bkg_create,
00170                     hawki_step_compute_bkg_exec,
00171                     hawki_step_compute_bkg_destroy);
00172 
00173     cpl_pluginlist_append(list, plugin);
00174     
00175     return 0;
00176 }
00177 
00178 /*----------------------------------------------------------------------------*/
00187 /*----------------------------------------------------------------------------*/
00188 static int hawki_step_compute_bkg_create(cpl_plugin * plugin)
00189 {
00190     cpl_recipe      * recipe;
00191     cpl_parameter   * p; 
00192 
00193     /* Get the recipe out of the plugin */
00194     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00195         recipe = (cpl_recipe *)plugin ;
00196     else return -1 ;
00197 
00198     /* Create the parameters list in the cpl_recipe object */
00199     recipe->parameters = cpl_parameterlist_new() ;
00200     if (recipe->parameters == NULL)
00201         return 1;
00202 
00203     /* Fill the parameters list */
00204     /* --nmin_comb */
00205     p = cpl_parameter_new_value
00206             ("hawki.hawki_step_compute_bkg.nmin_comb",
00207              CPL_TYPE_INT,
00208              "Minimum number of jitter frames to use the running median",
00209              "hawki.hawki_step_compute_bkg",
00210              10) ;
00211     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nmin_comb") ;
00212     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00213     cpl_parameterlist_append(recipe->parameters, p) ;
00214 
00215     /* --nhalf_window */
00216     p = cpl_parameter_new_value
00217             ("hawki.hawki_step_compute_bkg.nhalf_window",
00218              CPL_TYPE_INT,
00219              "Number of images at both sides of the current ima to use for bkg in running median",
00220              "hawki.hawki_step_compute_bkg",
00221              7);
00222     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nhalf_window") ;
00223     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00224     cpl_parameterlist_append(recipe->parameters, p) ;
00225 
00226     /* --rejlow */
00227     p = cpl_parameter_new_value
00228             ("hawki.hawki_step_compute_bkg.rejlow",
00229              CPL_TYPE_INT,
00230              "The number of frames with low level to reject",
00231              "hawki.hawki_step_compute_bkg",
00232              2) ;
00233     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rejlow") ;
00234     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00235     cpl_parameterlist_append(recipe->parameters, p) ;
00236 
00237     /* --rejhigh */
00238     p = cpl_parameter_new_value
00239             ("hawki.hawki_step_compute_bkg.rejhigh",
00240              CPL_TYPE_INT,
00241              "The number of frames with high level to reject",
00242              "hawki.hawki_step_compute_bkg",
00243              2) ;
00244     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rejhigh") ;
00245     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ;
00246     cpl_parameterlist_append(recipe->parameters, p) ;
00247 
00248     /* Return */
00249     return 0;
00250 }
00251 
00252 /*----------------------------------------------------------------------------*/
00258 /*----------------------------------------------------------------------------*/
00259 static int hawki_step_compute_bkg_exec(cpl_plugin * plugin)
00260 {
00261     cpl_recipe  *   recipe ;
00262 
00263     /* Get the recipe out of the plugin */
00264     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00265         recipe = (cpl_recipe *)plugin ;
00266     else return -1 ;
00267 
00268     /* Issue a banner */
00269     hawki_print_banner();
00270 
00271     return hawki_step_compute_bkg(recipe->parameters, recipe->frames) ;
00272 }
00273 
00274 /*----------------------------------------------------------------------------*/
00280 /*----------------------------------------------------------------------------*/
00281 static int hawki_step_compute_bkg_destroy(cpl_plugin * plugin)
00282 {
00283     cpl_recipe  *   recipe ;
00284 
00285     /* Get the recipe out of the plugin */
00286     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00287         recipe = (cpl_recipe *)plugin ;
00288     else return -1 ;
00289 
00290     cpl_parameterlist_delete(recipe->parameters) ;
00291     return 0 ;
00292 }
00293 
00294 /*----------------------------------------------------------------------------*/
00301 /*----------------------------------------------------------------------------*/
00302 static int hawki_step_compute_bkg(
00303         cpl_parameterlist   *   parlist, 
00304         cpl_frameset        *   framelist)
00305 {
00306     cpl_frameset    *   objframes = NULL;
00307     cpl_frameset    *   skyframes;
00308     cpl_frameset    *   maskframes;
00309     cpl_frameset    *   x_distortionframes;
00310     cpl_frameset    *   y_distortionframes;
00311     cpl_frameset    *   offsetsframes = NULL;
00312 
00313     /* Get the recipe parameters */
00314     hawki_step_compute_bkg_retrieve_input_param(parlist);
00315 
00316     /* Identify the RAW and CALIB frames in the input frameset */
00317     if (hawki_dfs_set_groups(framelist)) 
00318     {
00319         cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00320         return -1 ;
00321     }
00322     
00323     /* Identifying objects and sky data frames */
00324     cpl_msg_info(__func__, "Identifying objects and sky data");
00325     objframes = hawki_extract_frameset
00326         (framelist, HAWKI_CALPRO_BASICCALIBRATED);
00327     skyframes = hawki_extract_frameset
00328         (framelist, HAWKI_CALPRO_SKY_BASICCALIBRATED);
00329     if (objframes == NULL && skyframes == NULL)
00330     {
00331         cpl_msg_error(__func__, "No object (%s) or sky (%s) frames provided",
00332                 HAWKI_CALPRO_BASICCALIBRATED, HAWKI_CALPRO_SKY_BASICCALIBRATED);
00333         return -1 ;
00334     }
00335     
00336     /* Retrieve the mask */
00337     maskframes = hawki_extract_frameset
00338         (framelist, HAWKI_CALPRO_OBJ_MASK);
00339     if(maskframes != NULL)
00340     {
00341         offsetsframes = hawki_extract_frameset
00342             (framelist, HAWKI_CALPRO_OFFSETS);
00343         x_distortionframes = hawki_extract_frameset
00344             (framelist, HAWKI_CALPRO_DISTORTION_X);
00345         y_distortionframes =  hawki_extract_frameset
00346             (framelist, HAWKI_CALPRO_DISTORTION_Y);
00347         if((x_distortionframes == NULL && y_distortionframes != NULL) ||
00348            (x_distortionframes != NULL && y_distortionframes == NULL))
00349         {
00350             cpl_msg_error(__func__, "One X-distortion frame (%s) and one Y-distortion (%s)"
00351                           "must be provided", HAWKI_CALPRO_DISTORTION_X, HAWKI_CALPRO_DISTORTION_Y);
00352             cpl_frameset_delete(skyframes);
00353             cpl_frameset_delete(maskframes);
00354             cpl_frameset_delete(x_distortionframes);
00355             cpl_frameset_delete(y_distortionframes);
00356             return -1 ;
00357         }
00358     }
00359     
00360     /* Compute the background */
00361     if(skyframes == NULL)
00362         hawki_step_compute_bkg_from_objects_qc_save
00363             (objframes,
00364              maskframes, offsetsframes, x_distortionframes, y_distortionframes,
00365              parlist, framelist);
00366     else
00367         hawki_step_compute_bkg_from_sky_median_save
00368             (skyframes, 
00369              parlist, framelist);
00370 
00371     /* Free resources */
00372     if(skyframes != NULL)
00373         cpl_frameset_delete(skyframes);
00374     if(objframes != NULL)
00375         cpl_frameset_delete(objframes);
00376     if(maskframes != NULL)
00377     {
00378         cpl_frameset_delete(maskframes);
00379         if(x_distortionframes != NULL)
00380             cpl_frameset_delete(x_distortionframes);
00381         if(y_distortionframes != NULL)
00382             cpl_frameset_delete(y_distortionframes);
00383         if(offsetsframes != NULL)
00384             cpl_frameset_delete(offsetsframes);
00385     }
00386     
00387     /* return */
00388     if (cpl_error_get_code()) return -1 ;
00389     else return 0 ;
00390 }
00391 
00392 /*----------------------------------------------------------------------------*/
00402 /*----------------------------------------------------------------------------*/
00403 static int hawki_step_compute_bkg_from_objects_qc_save
00404 (cpl_frameset        *  objframes,
00405  cpl_frameset        *  maskframes,
00406  cpl_frameset        *  offsetsframes,
00407  cpl_frameset        *  x_distortionframes,
00408  cpl_frameset        *  y_distortionframes,
00409  cpl_parameterlist   *  parlist, 
00410  cpl_frameset        *  recipe_framelist)
00411 {
00412     int nobjs;
00413     
00414     /* Select the algorithm based on the number of frames */
00415     nobjs = cpl_frameset_get_size(objframes);
00416     cpl_msg_info(__func__,"Number of object frames: %d",nobjs);
00417     if (hawki_step_compute_bkg_config.nmin_comb > nobjs)
00418     {
00419         /* TODO: Support for masks in this case?? */
00420         cpl_msg_info(__func__, 
00421                      "Number of obj frames min required for running median");
00422         cpl_msg_info(__func__, "Using simple median of object images");
00423         hawki_step_compute_bkg_from_objects_median_save
00424             (objframes, parlist, recipe_framelist);
00425     }
00426     else
00427     {
00428         cpl_msg_info(__func__, "Using running median of object images");
00429         hawki_step_compute_bkg_from_objects_running_median_save
00430             (objframes, maskframes, offsetsframes, 
00431              x_distortionframes, y_distortionframes,
00432              parlist, recipe_framelist);
00433     }
00434     if (cpl_error_get_code())
00435     {
00436         cpl_msg_error(__func__,
00437                       "HAWK-I pipeline could not recover from previous errors");
00438         return -1 ;
00439     }
00440     return 0;
00441 }
00442 
00443 /*----------------------------------------------------------------------------*/
00453 /*----------------------------------------------------------------------------*/
00454 static int hawki_step_compute_bkg_from_objects_median_save
00455 (cpl_frameset        *  objframes,
00456  cpl_parameterlist   *  recipe_parlist, 
00457  cpl_frameset        *  recipe_framelist)
00458 {
00459     cpl_imagelist    * bkg;
00460     const char       * recipe_name = "hawki_step_compute_bkg";
00461     
00462 
00463     /* Logging */
00464     cpl_msg_info(__func__,"Computing background from median of object images");
00465 
00466     /* Allocating for the background image */
00467     bkg = cpl_imagelist_new();
00468     
00469     /* Computing the background */
00470     if(hawki_bkg_from_objects_median(objframes, bkg) != 0)
00471     {
00472         cpl_msg_error(__func__,"Could not compute the median of objects");
00473         cpl_imagelist_delete(bkg);
00474         return -1;
00475     }
00476     
00477     /* Save the products */
00478     cpl_msg_info(__func__, "Saving the products") ;
00479     if(hawki_imagelist_save(recipe_framelist,
00480                             recipe_parlist,
00481                             objframes,
00482                             (const cpl_imagelist *)bkg,
00483                             recipe_name,
00484                             HAWKI_CALPRO_BKGIMAGE, 
00485                             HAWKI_PROTYPE_BKGIMAGE, 
00486                             NULL,
00487                             NULL,
00488                             "hawki_step_compute_bkg_01.fits") != CPL_ERROR_NONE)
00489     {
00490         cpl_msg_warning(__func__,"Some data could not be saved. "
00491                                  "Check permisions or disk space");
00492     }
00493 
00494     /* Free and return */
00495     cpl_imagelist_delete(bkg);
00496     return 0;
00497 }
00498 
00499 /*----------------------------------------------------------------------------*/
00509 /*----------------------------------------------------------------------------*/
00510 static int hawki_step_compute_bkg_from_sky_median_save
00511 (cpl_frameset        *  skyframes,
00512  cpl_parameterlist   *  recipe_parlist, 
00513  cpl_frameset        *  recipe_framelist)
00514 {
00515     cpl_imagelist    * bkg;
00516     const char       * recipe_name = "hawki_step_compute_bkg";
00517     
00518     /* Logging */
00519     cpl_msg_info(__func__,"Computing background from sky images");
00520 
00521     /* Allocating for the background image */
00522     bkg = cpl_imagelist_new();
00523     
00524     /* Computing the background */
00525     if(hawki_bkg_from_sky_median(skyframes, bkg)!= 0)
00526     {
00527         cpl_msg_error(__func__,"Could not compute the median of sky images");
00528         cpl_imagelist_delete(bkg);
00529         return -1;
00530     }
00531     
00532     /* Save the products */
00533     cpl_msg_info(__func__, "Saving the products") ;
00534     if(hawki_imagelist_save(recipe_framelist,
00535                             recipe_parlist,
00536                             skyframes,
00537                             (const cpl_imagelist *)bkg,
00538                             recipe_name,
00539                             HAWKI_CALPRO_BKGIMAGE, 
00540                             HAWKI_PROTYPE_BKGIMAGE, 
00541                             NULL,
00542                             NULL,
00543                             "hawki_step_compute_bkg_01.fits") != CPL_ERROR_NONE)
00544     {
00545         cpl_msg_warning(__func__,"Some data could not be saved. "
00546                                  "Check permisions or disk space");
00547     }
00548     
00549     /* Free and return */
00550     cpl_imagelist_delete(bkg);
00551     return 0;
00552 }
00553 
00554 static int hawki_step_compute_bkg_from_objects_running_median_save
00555 (cpl_frameset        *  objframes,
00556  cpl_frameset        *  maskframes,
00557  cpl_frameset        *  offsetframes,
00558  cpl_frameset        *  x_distortionframes,
00559  cpl_frameset        *  y_distortionframes,
00560  cpl_parameterlist   *  recipe_parlist, 
00561  cpl_frameset        *  recipe_framelist)
00562 {
00563 
00564     /* Logging */
00565     cpl_msg_info(__func__,"Computing background from running mean of objects");
00566     cpl_msg_indent_more();
00567 
00568     /* Actually calling the functions that computes all the background */
00569     if(maskframes == NULL)
00570     {
00571         cpl_msg_info(__func__,"Not using masked objects");
00572         if(hawki_step_compute_bkg_from_running_median_nonmasked_save
00573                 (objframes,
00574                  hawki_step_compute_bkg_config.nhalf_window,
00575                  hawki_step_compute_bkg_config.rejlow,
00576                  hawki_step_compute_bkg_config.rejhigh,
00577                  recipe_framelist,
00578                  recipe_parlist) !=0)
00579         {
00580             cpl_msg_error(__func__,"Could not compute objects running median");
00581             return -1;
00582         }
00583     }
00584     else
00585     {
00586         cpl_frame    *  maskframe;
00587         cpl_bivector ** offsets; /* Detector order */
00588         cpl_frame    *  x_distortionframe;
00589         cpl_frame    *  y_distortionframe;
00590         int             idet;
00591         
00592         cpl_msg_info(__func__,"Using masked objects");
00593 
00594         maskframe = cpl_frameset_get_first(maskframes);
00595         if(x_distortionframes == NULL && y_distortionframes == NULL )
00596         {
00597             x_distortionframe = NULL;
00598             y_distortionframe = NULL;
00599         }
00600         else
00601         {
00602             x_distortionframe = cpl_frameset_get_first(x_distortionframes);
00603             y_distortionframe = cpl_frameset_get_first(y_distortionframes);
00604         }
00605         
00606         /* Get the offsets */
00607         if(offsetframes == NULL)
00608         {
00609             cpl_bivector * offsets_all_chips;
00610 
00611             cpl_msg_info(__func__,"Using header nominal offsets");
00612             offsets_all_chips = hawki_get_header_tel_offsets(objframes); 
00613             if (offsets_all_chips == NULL) 
00614             {
00615                 cpl_msg_error(__func__, "Cannot load the header offsets");
00616                 return -1;
00617             }
00618             offsets = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_bivector *));
00619             for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet)
00620             {
00621                 offsets[idet] =  cpl_bivector_duplicate(offsets_all_chips);
00622                 /* Get the oposite offsets. This is to change from 
00623                  * telescope convention to cpl convention */
00624                 cpl_vector_multiply_scalar
00625                     (cpl_bivector_get_x(offsets[idet]), -1.0);
00626                 cpl_vector_multiply_scalar
00627                     (cpl_bivector_get_y(offsets[idet]), -1.0);
00628             }
00629             cpl_bivector_delete(offsets_all_chips);
00630         }
00631         else
00632         {
00633             cpl_msg_info(__func__,"Using refined offsets");
00634             offsets = hawki_load_refined_offsets
00635                 (cpl_frameset_get_first(offsetframes));
00636             if(offsets == NULL)
00637             {
00638                 cpl_msg_error(__func__, "Cannot load the refined offsets");
00639                 return -1;
00640             }
00641         }
00642            
00643         if(hawki_step_compute_bkg_from_running_median_masked_save
00644                 (objframes,
00645                  maskframe,
00646                  offsets,
00647                  x_distortionframe,
00648                  y_distortionframe,
00649                  hawki_step_compute_bkg_config.nhalf_window,
00650                  hawki_step_compute_bkg_config.rejlow,
00651                  hawki_step_compute_bkg_config.rejhigh,
00652                  recipe_framelist,
00653                  recipe_parlist) !=0)
00654         {
00655             cpl_msg_error(__func__,"Could not compute objects running median");
00656             for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet)
00657                 cpl_bivector_delete(offsets[idet]);
00658             cpl_free(offsets);
00659             cpl_msg_indent_less();
00660             return -1;
00661         }
00662         
00663         /* Free */
00664         for(idet = 0; idet < HAWKI_NB_DETECTORS; ++idet)
00665             cpl_bivector_delete(offsets[idet]);
00666         cpl_free(offsets);
00667     }
00668     cpl_msg_indent_less();
00669 
00670     
00671     /* Freeing and exit */
00672     return 0;
00673 }
00674 
00675 int hawki_step_compute_bkg_from_running_median_nonmasked_save
00676 (const cpl_frameset  *  objframes,
00677  int                    nhalf_window,
00678  int                    rejlow,
00679  int                    rejhigh,
00680  cpl_frameset        *  recipe_framelist,
00681  cpl_parameterlist   *  recipe_parlist)
00682 {
00683     int              iext;
00684     int              iobj;
00685     int              nobj;
00686     const char     * recipe_name = "hawki_step_compute_bkg";
00687     cpl_errorstate   error_prevstate = cpl_errorstate_get();
00688     
00689     /* Preparing the files to save */
00690     cpl_msg_info(__func__,"Preparing the output files");
00691     nobj = cpl_frameset_get_size(objframes); 
00692     for (iobj=0 ; iobj<nobj ; ++iobj)
00693     {
00694         cpl_frameset         * used_frameset;
00695         const cpl_frame      * target_frame;
00696         char filename[256];
00697         snprintf(filename, 256, "hawki_step_compute_bkg_%03d.fits", iobj + 1);
00698         target_frame = cpl_frameset_get_frame_const(objframes, iobj);
00699         used_frameset = cpl_frameset_new();
00700         cpl_frameset_insert(used_frameset, cpl_frame_duplicate(target_frame));
00701         hawki_main_header_save(recipe_framelist,
00702                                recipe_parlist,
00703                                used_frameset,
00704                                recipe_name,
00705                                HAWKI_CALPRO_BKGIMAGE, 
00706                                HAWKI_PROTYPE_BKGIMAGE, 
00707                                NULL,
00708                                filename);
00709         snprintf(filename, 256, "hawki_step_compute_bkg_bpm_%03d.fits", iobj + 1);
00710         hawki_main_header_save(recipe_framelist,
00711                                recipe_parlist,
00712                                used_frameset,
00713                                recipe_name,
00714                                HAWKI_CALPRO_BKGBPM, 
00715                                HAWKI_PROTYPE_BKGBPM, 
00716                                NULL,
00717                                filename);
00718         cpl_frameset_delete(used_frameset);
00719     }
00720     
00721     /* Loop on extensions */
00722     cpl_msg_indent_more();
00723     for(iext = 0; iext < HAWKI_NB_DETECTORS; ++iext)
00724     {
00725         cpl_imagelist * img_serie;
00726         cpl_vector    * medians;
00727         
00728         /* Info message */
00729         cpl_msg_info(__func__,"Working on extension %d", iext + 1);
00730         
00731         /* Loading the object frame */
00732         img_serie = hawki_load_extensions(objframes, iext + 1, CPL_TYPE_FLOAT);
00733         if(img_serie== NULL)
00734         {
00735             cpl_msg_error(__func__, "Error reading object image") ;
00736             return -1;
00737         }
00738         
00739         /* Pre-compute median value in each plane */
00740         medians = cpl_vector_new(nobj);
00741         for (iobj=0 ; iobj<nobj ; iobj++) 
00742         {
00743             cpl_vector_set
00744                 (medians, 
00745                  iobj,
00746                  cpl_image_get_median(cpl_imagelist_get(img_serie, iobj))) ;
00747         }
00748 
00749         cpl_msg_indent_more();
00750         for(iobj = 0 ; iobj < nobj ; ++iobj)
00751         {
00752             int             nx;
00753             int             ny;
00754             cpl_image     * this_bkg_image;
00755             cpl_image     * this_bkg_image_mask;
00756             char            filename[256];
00757 
00758             /* Info message */
00759             cpl_msg_info(__func__,"Computing bkg for image %d", iobj + 1);
00760 
00761             /* Creates the background image */
00762             nx = cpl_image_get_size_x(cpl_imagelist_get(img_serie, 0));
00763             ny = cpl_image_get_size_y(cpl_imagelist_get(img_serie, 0));
00764             this_bkg_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00765             
00766             /* Actually computing the running mean */ 
00767             if(hawki_bkg_from_running_mean_detector
00768                     (img_serie,
00769                      medians,
00770                      iobj,
00771                      nhalf_window,
00772                      rejlow,
00773                      rejhigh,
00774                      this_bkg_image) != 0)
00775              {
00776                 cpl_msg_error(__func__, "Cannot compute bkg");
00777                 cpl_vector_delete(medians);
00778                 cpl_imagelist_delete(img_serie);
00779                 cpl_image_delete(this_bkg_image);
00780                 return -1;
00781              }
00782             
00783             /* Save the extension bad pixel mask */
00784             this_bkg_image_mask = 
00785                 cpl_image_new_from_mask(cpl_image_get_bpm(this_bkg_image));
00786             snprintf(filename, 256, "hawki_step_compute_bkg_bpm_%03d.fits",iobj +1);
00787             hawki_image_ext_save
00788                 (objframes,
00789                  this_bkg_image_mask,
00790                  iext + 1,
00791                  NULL,
00792                  filename);
00793             
00794             /* Interpolate bad pixels */
00795             hawki_step_compute_bkg_interpolate_badpix(this_bkg_image);
00796 
00797             /* Save this extension */
00798             snprintf(filename, 256, "hawki_step_compute_bkg_%03d.fits",iobj +1);
00799             hawki_image_ext_save
00800                 (objframes,
00801                  this_bkg_image,
00802                  iext + 1,
00803                  NULL,
00804                  filename);
00805             
00806             /* Free */
00807             cpl_image_delete(this_bkg_image);
00808             cpl_image_delete(this_bkg_image_mask);
00809         }
00810         cpl_msg_indent_less();
00811         
00812         /* Freeing */
00813         cpl_vector_delete(medians);
00814         cpl_imagelist_delete(img_serie);
00815     }
00816     cpl_msg_indent_less();
00817     if(!cpl_errorstate_is_equal(error_prevstate))
00818     {
00819         cpl_msg_warning(__func__,"Probably some data could not be saved. "
00820                                  "Check permisions or disk space");
00821         cpl_errorstate_set(CPL_ERROR_NONE);
00822         return 1;
00823     }
00824     return 0;
00825 }
00826 
00827 int hawki_step_compute_bkg_from_running_median_masked_save
00828 (const cpl_frameset  *  objframes,
00829  cpl_frame           *  maskframe,
00830  cpl_bivector        ** offsets,
00831  cpl_frame           *  x_distortionframe,  
00832  cpl_frame           *  y_distortionframe,  
00833  int                    nhalf_window,
00834  int                    rejlow,
00835  int                    rejhigh,
00836  cpl_frameset        *  recipe_framelist,
00837  cpl_parameterlist   *  recipe_parlist)
00838 {
00839     int              iext;   /* 0 to HAWKI_NB_DETECTORS-1 */
00840     int              idet;  /* 1 to HAWKI_NB_DETECTORS */
00841     int              iobj;   /* 0 to obj-1 */
00842     int              nobj;
00843     const char     * recipe_name = "hawki_step_compute_bkg";
00844     cpl_errorstate   error_prevstate = cpl_errorstate_get();
00845     cpl_frameset   * calib_frameset; 
00846     
00847 
00848     //Add all the used frames
00849     calib_frameset = cpl_frameset_new();
00850     cpl_frameset_insert(calib_frameset, cpl_frame_duplicate(maskframe));
00851     if(x_distortionframe != NULL)
00852         cpl_frameset_insert(calib_frameset, cpl_frame_duplicate(x_distortionframe));
00853     if(y_distortionframe != NULL)
00854         cpl_frameset_insert(calib_frameset, cpl_frame_duplicate(y_distortionframe));
00855     
00856     /* Preparing the files to save */
00857     cpl_msg_info(__func__,"Preparing the final files");
00858     nobj = cpl_frameset_get_size(objframes); 
00859     for (iobj=0 ; iobj<nobj ; ++iobj)
00860     {
00861         cpl_frameset         * used_frameset;
00862         const cpl_frame      * target_frame;
00863         char filename[256];
00864         snprintf(filename, 256, "hawki_step_compute_bkg_%03d.fits", iobj + 1);
00865         target_frame = cpl_frameset_get_frame_const(objframes, iobj);
00866         used_frameset = cpl_frameset_duplicate(calib_frameset);
00867         cpl_frameset_insert(used_frameset, cpl_frame_duplicate(target_frame));
00868         cpl_frameset_insert(calib_frameset, cpl_frame_duplicate(maskframe));        
00869         hawki_main_header_save(recipe_framelist,
00870                                recipe_parlist,
00871                                used_frameset,
00872                                recipe_name,
00873                                HAWKI_CALPRO_BKGIMAGE, 
00874                                HAWKI_PROTYPE_BKGIMAGE, 
00875                                NULL,
00876                                filename);
00877         snprintf(filename, 256, "hawki_step_compute_bkg_bpm_%03d.fits", iobj + 1);
00878         hawki_main_header_save(recipe_framelist,
00879                                recipe_parlist,
00880                                used_frameset,
00881                                recipe_name,
00882                                HAWKI_CALPRO_BKGBPM, 
00883                                HAWKI_PROTYPE_BKGBPM, 
00884                                NULL,
00885                                filename);
00886         cpl_frameset_delete(used_frameset);
00887     }
00888     cpl_frameset_delete(calib_frameset);
00889     
00890     /* Loop on extensions */
00891     cpl_msg_indent_more();
00892     for(iext = 0; iext < HAWKI_NB_DETECTORS; ++iext)
00893     {
00894         cpl_imagelist    * img_serie;
00895         cpl_vector       * medians;
00896         cpl_image        * mask;
00897         hawki_distortion * inv_distortion = NULL;
00898         cpl_propertylist * prop_list; 
00899         cpl_image        * dist_x = NULL;
00900         cpl_image        * dist_y = NULL;
00901         double             mask_off_x;
00902         double             mask_off_y;
00903         
00904         cpl_msg_info(__func__,"Working on extension %d", iext + 1);
00905         cpl_msg_indent_more();
00906         
00907         /* Loading the object frames */
00908         img_serie = hawki_load_extensions(objframes, iext + 1, CPL_TYPE_FLOAT);
00909         if(img_serie== NULL)
00910         {
00911             cpl_msg_error(__func__, "Error reading object image") ;
00912             cpl_msg_indent_less();
00913             return -1;
00914         }
00915         nobj = cpl_imagelist_get_size(img_serie);
00916         
00917         /* Loading the mask frame */
00918         mask = hawki_load_frame_extension(maskframe, iext + 1, CPL_TYPE_FLOAT);
00919         if(mask == NULL)
00920         {
00921             cpl_msg_error(__func__, "Error reading mask image");
00922             cpl_msg_indent_less();
00923             cpl_msg_indent_less();
00924             return -1;
00925         }
00926         idet = 
00927             hawki_get_detector_from_ext(cpl_frame_get_filename(maskframe), iext+1);
00928         prop_list =
00929             cpl_propertylist_load(cpl_frame_get_filename(maskframe), iext + 1);
00930         mask_off_x = hawki_pfits_get_comb_cumoffsetx(prop_list);
00931         mask_off_y = hawki_pfits_get_comb_cumoffsety(prop_list);
00932         /* Change the offsets to cpl convention */
00933         mask_off_x *= -1; 
00934         mask_off_y *= -1; 
00935         if(!cpl_errorstate_is_equal(CPL_ERROR_NONE))
00936         {
00937             cpl_msg_error(__func__,"Could not get the offsets from mask file.\n"
00938                           "Keywords %s are missing","ESO QC COMBINED CUMOFFSET{X,Y}");
00939             cpl_imagelist_delete(img_serie);
00940             cpl_image_delete(mask);
00941             cpl_msg_indent_less();
00942             cpl_msg_indent_less();
00943             cpl_propertylist_delete(prop_list);
00944             return -1;
00945         }
00946         cpl_msg_info(__func__,"Mask offsets: %f %f", mask_off_x, mask_off_y);
00947 
00948         if(x_distortionframe != NULL && y_distortionframe != NULL)
00949         {
00950             int                nx;
00951             int                ny;
00952             
00953             /* Load the distortion */
00954             if ((inv_distortion = hawki_distortion_load
00955                     (x_distortionframe, y_distortionframe, idet)) == NULL)
00956             {
00957                 cpl_imagelist_delete(img_serie);
00958                 cpl_propertylist_delete(prop_list);
00959                 cpl_image_delete(mask);
00960                 cpl_msg_error(__func__,
00961                               "Cannot load distortion for chip %d",idet);
00962                 cpl_msg_indent_less();
00963                 cpl_msg_indent_less();
00964                 return -1 ;
00965             }
00966             /* Multiply distortion by -1, to get the inverse distortion */
00967             cpl_image_multiply_scalar(inv_distortion->dist_x, -1.);
00968             cpl_image_multiply_scalar(inv_distortion->dist_y, -1.);
00969             /* Create the distortion maps */
00970             nx = cpl_image_get_size_x(mask);
00971             ny = cpl_image_get_size_y(mask);
00972             dist_x = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00973             dist_y = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00974             if (hawki_distortion_create_maps_detector
00975                     (inv_distortion, dist_x, dist_y))
00976             {
00977                 cpl_msg_error(__func__, "Cannot create the distortion maps") ;
00978                 cpl_imagelist_delete(img_serie);
00979                 cpl_propertylist_delete(prop_list);
00980                 cpl_image_delete(mask);
00981                 cpl_image_delete(dist_x);
00982                 cpl_image_delete(dist_y);
00983                 hawki_distortion_delete(inv_distortion);
00984                 cpl_msg_indent_less();
00985                 cpl_msg_indent_less();
00986                 return -1;
00987             }
00988 
00989         }
00990         
00991         /* Creating a different mask for each object, using the offsets 
00992          * and the distortion (if applies) */
00993         cpl_msg_info(__func__,"Constructing the masks");
00994         for (iobj=0 ; iobj<nobj ; iobj++)
00995         {
00996             cpl_image  * mask_shifted;
00997             cpl_image  * mask_trim;
00998             cpl_mask   * mask_final;
00999             cpl_image  * target_image;
01000             cpl_vector * off_x;
01001             cpl_vector * off_y;
01002             
01003             /* Retrieve the offsets. Warning, it is in chip order */
01004             off_x = cpl_bivector_get_x(offsets[idet-1]);
01005             off_y = cpl_bivector_get_y(offsets[idet-1]);
01006             
01007             target_image = cpl_imagelist_get(img_serie, iobj);
01008             mask_shifted = cpl_image_duplicate(mask); 
01009             cpl_image_shift(mask_shifted,
01010                             -(int)(cpl_vector_get(off_x, iobj) - mask_off_x),
01011                             -(int)(cpl_vector_get(off_y, iobj) - mask_off_y));
01012             if(x_distortionframe != NULL && y_distortionframe != NULL)
01013             {
01014                 cpl_image * mask_distcorr;
01015 
01016                 /* Dedistort the mask */
01017                 mask_distcorr = hawki_distortion_correct_detector
01018                     (mask_shifted, dist_x, dist_y);
01019                 if(mask_distcorr == NULL)
01020                 {
01021                     cpl_msg_error(__func__, "Cannot correct the distortion") ;
01022                     cpl_image_delete(dist_x);
01023                     cpl_image_delete(dist_y);
01024                     cpl_image_delete(mask_shifted);
01025                     cpl_imagelist_delete(img_serie);
01026                     cpl_image_delete(mask);
01027                     cpl_propertylist_delete(prop_list);
01028                     hawki_distortion_delete(inv_distortion);
01029                     cpl_msg_indent_less();
01030                     cpl_msg_indent_less();
01031                     return -1 ;
01032                 }
01033                 mask_trim = cpl_image_extract
01034                     (mask_distcorr, 1, 1,
01035                      cpl_image_get_size_x(target_image),
01036                      cpl_image_get_size_y(target_image));
01037                 cpl_image_delete(mask_distcorr);
01038             }
01039             else
01040             {
01041                 mask_trim = cpl_image_extract
01042                     (mask_shifted, 1, 1,
01043                      cpl_image_get_size_x(target_image),
01044                      cpl_image_get_size_y(target_image));
01045             }
01046             mask_final = 
01047                 cpl_mask_threshold_image_create(mask_trim, 0.5, FLT_MAX);
01048             /* TODO: Add the current bpm to this mask? */
01049             cpl_image_reject_from_mask
01050                 (target_image, mask_final);
01051             cpl_image_delete(mask_shifted);
01052             cpl_image_delete(mask_trim);
01053             cpl_mask_delete(mask_final);
01054         }
01055         
01056         /* Pre-compute median value in each plane */
01057         cpl_msg_info(__func__,"Computing the medians");
01058         medians = cpl_vector_new(nobj);
01059         for (iobj=0 ; iobj<nobj ; iobj++)
01060         {
01061             cpl_vector_set
01062                 (medians, 
01063                  iobj,
01064                  cpl_image_get_median(cpl_imagelist_get(img_serie, iobj))) ;
01065         }
01066 
01067         /* Object loop to get the bkg */
01068         cpl_msg_info(__func__,"Computing backgrounds");
01069         cpl_msg_indent_more();
01070         for(iobj = 0 ; iobj < nobj ; ++iobj)
01071         {
01072             int             nx;
01073             int             ny;
01074             cpl_image     * this_bkg_image;
01075             cpl_image     * this_bkg_image_mask;
01076             char            filename[256];
01077 
01078             /* Creates the background image */
01079             cpl_msg_info(__func__,"Computing bkg for image %d", iobj + 1);
01080             nx = cpl_image_get_size_x(cpl_imagelist_get(img_serie, 0));
01081             ny = cpl_image_get_size_y(cpl_imagelist_get(img_serie, 0));
01082             this_bkg_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01083             
01084             /* Actually computing the running mean */ 
01085             if(hawki_bkg_from_running_mean_detector
01086                     (img_serie,
01087                      medians,
01088                      iobj,
01089                      nhalf_window,
01090                      rejlow,
01091                      rejhigh,
01092                      this_bkg_image) != 0)
01093             {
01094                 cpl_msg_error(__func__, "Cannot compute bkg");
01095                 cpl_image_delete(this_bkg_image);
01096                 cpl_vector_delete(medians);
01097                 cpl_imagelist_delete(img_serie);
01098                 cpl_image_delete(mask);
01099                 cpl_propertylist_delete(prop_list);
01100                 if(x_distortionframe != NULL && y_distortionframe != NULL)
01101                 {
01102                     hawki_distortion_delete(inv_distortion);
01103                     cpl_image_delete(dist_x);
01104                     cpl_image_delete(dist_y);
01105                 }
01106                 cpl_msg_indent_less();
01107                 cpl_msg_indent_less();
01108                 cpl_msg_indent_less();
01109                 return -1;
01110             }
01111             
01112             /* Save the extension bad pixel mask */
01113             this_bkg_image_mask = 
01114                 cpl_image_new_from_mask(cpl_image_get_bpm(this_bkg_image));
01115             snprintf(filename, 256, "hawki_step_compute_bkg_bpm_%03d.fits",iobj +1);
01116             hawki_image_ext_save
01117                 (objframes,
01118                  this_bkg_image_mask,
01119                  iext + 1,
01120                  NULL,
01121                  filename);
01122 
01123             /* Interpolate bad pixels */
01124             hawki_step_compute_bkg_interpolate_badpix(this_bkg_image);
01125 
01126             /* Save this extension */
01127             snprintf(filename, 256, "hawki_step_compute_bkg_%03d.fits",iobj +1);
01128             hawki_image_ext_save
01129                 (objframes,
01130                  this_bkg_image,
01131                  iext + 1,
01132                  NULL,
01133                  filename);
01134 
01135             /* Free */
01136             cpl_image_delete(this_bkg_image);
01137             cpl_image_delete(this_bkg_image_mask);
01138         }
01139         cpl_msg_indent_less();
01140 
01141         /* Freeing */
01142         cpl_vector_delete(medians);
01143         cpl_imagelist_delete(img_serie);
01144         cpl_image_delete(mask);
01145         cpl_propertylist_delete(prop_list);
01146         if(x_distortionframe != NULL && y_distortionframe != NULL)
01147         {
01148             hawki_distortion_delete(inv_distortion);
01149             cpl_image_delete(dist_x);
01150             cpl_image_delete(dist_y);
01151         }
01152         cpl_msg_indent_less();
01153     }
01154     cpl_msg_indent_less();
01155     if(!cpl_errorstate_is_equal(error_prevstate))
01156     {
01157         cpl_msg_warning(__func__,"Probably some data could not be saved. "
01158                                  "Check permissions or disk space");
01159         cpl_errorstate_set(CPL_ERROR_NONE);
01160         return 1;
01161     }
01162     return 0;
01163 }
01164 
01165 /*----------------------------------------------------------------------------*/
01171 /*----------------------------------------------------------------------------*/
01172 static int hawki_step_compute_bkg_interpolate_badpix
01173 (cpl_image           *  image)
01174 {
01175     int nbadpixels = cpl_image_count_rejected(image); 
01176     if(nbadpixels !=0)
01177         cpl_msg_info(__func__,"Number of pixels with no background available: %d ",
01178                      nbadpixels);
01179     if(cpl_image_count_rejected(image) > 0)
01180     {
01181         int ipix,npix;
01182         double median = cpl_image_get_median(image);
01183         const cpl_binary * bpm = cpl_mask_get_data_const
01184             (cpl_image_get_bpm(image));
01185         float * image_p = (float*)cpl_image_get_data(image);
01186         cpl_msg_warning(__func__,"Substituting pixels with no bkg with median of image %f",median);
01187         npix = cpl_image_get_size_x(image) * cpl_image_get_size_y(image);
01188         for(ipix = 0; ipix < npix; ipix++)
01189         {
01190             if (bpm[ipix])
01191             {
01192                 image_p[ipix] = median;
01193             }
01194         }
01195         //This cannot be used until DFS08929 is solved
01196         //cpl_detector_interpolate_rejected(image);
01197     }
01198     return 0;
01199 }
01200 
01201 int hawki_step_compute_bkg_retrieve_input_param
01202 (cpl_parameterlist  *  parlist)
01203 {
01204     cpl_parameter   *   par ;
01205 
01206     par = NULL ;
01207     par = cpl_parameterlist_find
01208         (parlist, "hawki.hawki_step_compute_bkg.nmin_comb");
01209     hawki_step_compute_bkg_config.nmin_comb = cpl_parameter_get_int(par);
01210 
01211     par = cpl_parameterlist_find
01212         (parlist, "hawki.hawki_step_compute_bkg.nhalf_window");
01213     hawki_step_compute_bkg_config.nhalf_window = cpl_parameter_get_int(par);
01214 
01215     par = cpl_parameterlist_find
01216         (parlist, "hawki.hawki_step_compute_bkg.rejlow");
01217     hawki_step_compute_bkg_config.rejlow = cpl_parameter_get_int(par);
01218 
01219     par = cpl_parameterlist_find
01220         (parlist, "hawki.hawki_step_compute_bkg.rejhigh");
01221     hawki_step_compute_bkg_config.rejhigh = cpl_parameter_get_int(par);
01222 
01223     return 0;
01224 }