irplib_mkmaster.c

00001 /* $Id: irplib_mkmaster.c,v 1.5 2012/01/12 14:29:41 amodigli Exp $
00002  *
00003  * This file is part of the irplib package
00004  * Copyright (C) 2002,2003 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., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: amodigli $
00023  * $Date: 2012/01/12 14:29:41 $
00024  * $Revision: 1.5 $
00025  * $Name: uves-5_0_0 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <math.h>
00037 #include <string.h>
00038 #include "irplib_mkmaster.h"
00039 
00040 /*----------------------------------------------------------------------------*/
00044 /*----------------------------------------------------------------------------*/
00045 
00047 /*---------------------------------------------------------------------------*/
00054 /*---------------------------------------------------------------------------*/
00055 
00056 /*-------------------------------------------------------------------------*/
00068 /*--------------------------------------------------------------------------*/
00069 static cpl_vector * 
00070 irplib_imagelist_get_clean_mean_levels(const cpl_imagelist* iml, 
00071                                        const double kappa, 
00072                                        const int nclip,
00073                                        const double tolerance)
00074 {
00075 
00076    const cpl_image* img=NULL;
00077    int size=0;
00078    int i=0;
00079    cpl_vector* levels=NULL;
00080    double* pval=NULL;
00081    double mean=0;
00082    double stdev=0;
00083 
00084 
00085    cpl_error_ensure(iml != NULL, CPL_ERROR_NULL_INPUT, return(levels),
00086                     "Null input image list");
00087    cpl_error_ensure(kappa >= 0, CPL_ERROR_ILLEGAL_INPUT, return(levels), 
00088                     "Must be kappa>0");
00089 
00090    size=cpl_imagelist_get_size(iml);
00091    levels=cpl_vector_new(size);
00092    pval=cpl_vector_get_data(levels);
00093 
00094    for(i=0;i<size;i++) {
00095       img=cpl_imagelist_get_const(iml,i);
00096       irplib_ksigma_clip(img,1,1,
00097                          cpl_image_get_size_x(img),
00098                          cpl_image_get_size_y(img),
00099                          nclip,kappa,tolerance,&mean,&stdev);
00100       cpl_msg_info(cpl_func,"Ima %d mean level: %g",i+1,mean);
00101       pval[i]=mean;
00102    }
00103 
00104 
00105    return levels;
00106 }
00107 
00108 /*-------------------------------------------------------------------------*/
00116 /*--------------------------------------------------------------------------*/
00117 static cpl_error_code
00118 irplib_imagelist_subtract_values(cpl_imagelist** iml, cpl_vector* values)
00119 {
00120 
00121    cpl_image* img=NULL;
00122    int size=0;
00123    int i=0;
00124    double* pval=NULL;
00125   
00126    size=cpl_imagelist_get_size(*iml);
00127    pval=cpl_vector_get_data(values);
00128 
00129    for(i=0;i<size;i++) {
00130       img=cpl_imagelist_get(*iml,i);
00131       cpl_image_subtract_scalar(img,pval[i]);
00132       cpl_imagelist_set(*iml,img,i);
00133    }
00134 
00135    return cpl_error_get_code();
00136 }
00137 
00138 /*---------------------------------------------------------------------------*/
00151 /*---------------------------------------------------------------------------*/
00152 static double 
00153 irplib_vector_ksigma(cpl_vector *values,
00154                      const double klow, const double khigh, int kiter)
00155 {
00156    cpl_vector *accepted;
00157    double  mean  = 0.0;
00158    double  sigma = 0.0;
00159    double *data  = cpl_vector_get_data(values);
00160    int     n     = cpl_vector_get_size(values);
00161    int     ngood = n;
00162    int     count = 0;
00163    int     i;
00164  
00165    /*
00166     * At first iteration the mean is taken as the median, and the
00167     * standard deviation relative to this value is computed.
00168     */
00169 
00170    mean = cpl_vector_get_median(values);
00171 
00172    for (i = 0; i < n; i++) {
00173       sigma += (mean - data[i]) * (mean - data[i]);
00174    }
00175    sigma = sqrt(sigma / (n - 1));
00176 
00177    while (kiter) {
00178       count = 0;
00179       for (i = 0; i < ngood; i++) {
00180          if (data[i]-mean < khigh*sigma && mean-data[i] < klow*sigma) {
00181             data[count] = data[i];
00182             ++count;
00183          }
00184       }
00185 
00186       if (count == 0) // This cannot happen at first iteration.
00187          break;      // So we can break: we have already computed a mean.
00188 
00189       /*
00190        * The mean must be computed even if no element was rejected
00191        * (count == ngood), because at first iteration median instead
00192        * of mean was computed.
00193        */
00194 
00195       accepted = cpl_vector_wrap(count, data);
00196       mean = cpl_vector_get_mean(accepted);
00197       if(count>1) {
00198          sigma = cpl_vector_get_stdev(accepted);
00199       }
00200       cpl_vector_unwrap(accepted);
00201 
00202       if (count == ngood) {
00203          break;
00204       }
00205       ngood = count;
00206       --kiter;
00207    }
00208 
00209    return mean;
00210 }
00211 
00212 
00231 static cpl_image *
00232 irplib_imagelist_ksigma_stack(const cpl_imagelist *imlist, 
00233                               double klow, double khigh, int kiter)
00234 {
00235    int         ni, nx, ny, npix;
00236    cpl_image  *out_ima=NULL;
00237    cpl_imagelist  *loc_iml=NULL;
00238    double      *pout_ima=NULL;
00239    cpl_image  *image=NULL;
00240    const double     **data=NULL;
00241    double     *med=NULL;
00242    cpl_vector *time_line=NULL;
00243   
00244    double     *ptime_line=NULL;
00245    int         i, j;
00246    double mean_of_medians=0;
00247 
00248    cpl_error_ensure(imlist != NULL, CPL_ERROR_NULL_INPUT, return(out_ima),
00249                     "Null input image list");
00250 
00251    ni         = cpl_imagelist_get_size(imlist);
00252    loc_iml        = cpl_imagelist_duplicate(imlist);
00253    image      = cpl_imagelist_get(loc_iml, 0);
00254    nx         = cpl_image_get_size_x(image);
00255    ny         = cpl_image_get_size_y(image);
00256    npix       = nx * ny;
00257 
00258    out_ima    = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00259    pout_ima   = cpl_image_get_data_double(out_ima);
00260 
00261    time_line  = cpl_vector_new(ni);
00262    
00263    ptime_line = cpl_vector_get_data(time_line);
00264 
00265    data = cpl_calloc(sizeof(double *), ni);
00266    med  = cpl_calloc(sizeof(double), ni);
00267 
00268    for (i = 0; i < ni; i++) {
00269       image = cpl_imagelist_get(loc_iml, i);
00270       med[i]=cpl_image_get_median(image);
00271       cpl_image_subtract_scalar(image,med[i]);
00272       data[i] = cpl_image_get_data_double(image);
00273       mean_of_medians+=med[i];
00274    }
00275    mean_of_medians/=ni;
00276 
00277    for (i = 0; i < npix; i++) {
00278       for (j = 0; j < ni; j++) {
00279          ptime_line[j] = data[j][i];
00280       }
00281       pout_ima[i] = irplib_vector_ksigma(time_line, klow, khigh, kiter); 
00282    }
00283  
00284    cpl_image_add_scalar(out_ima,mean_of_medians);
00285 
00286  
00287    cpl_free(data);
00288    cpl_free(med);
00289    cpl_vector_delete(time_line);
00290    cpl_imagelist_delete(loc_iml);
00291 
00292    return out_ima;
00293 
00294 } 
00295 
00296 
00297 
00298 
00299 /*-------------------------------------------------------------------------*/
00311 /*--------------------------------------------------------------------------*/
00312 cpl_image*
00313 irplib_mkmaster_mean(cpl_imagelist* images,const double kappa, const int nclip, const double tolerance,const double klow,const double khigh,const int niter)
00314 {
00315 
00316    cpl_image* master=NULL;
00317    cpl_vector* levels=NULL;
00318    double mean=0;
00319    cpl_imagelist* iml=NULL;
00320 
00321    cpl_msg_info(cpl_func,"method mean");
00322    iml=cpl_imagelist_duplicate(images);
00323    levels=irplib_imagelist_get_clean_mean_levels(iml,kappa,nclip,tolerance);
00324    mean=cpl_vector_get_mean(levels);
00325    cpl_msg_info(cpl_func,"Master mean level: %g",mean);
00326 
00327    irplib_imagelist_subtract_values(&iml,levels);
00328 
00329    master = irplib_imagelist_ksigma_stack(iml,klow,khigh,niter);
00330    cpl_image_add_scalar(master,mean);
00331 
00332    cpl_vector_delete(levels);
00333    cpl_imagelist_delete(iml);
00334    return master;
00335 
00336 }
00337 
00338 /*-------------------------------------------------------------------------*/
00350 /*--------------------------------------------------------------------------*/
00351 cpl_image* 
00352 irplib_mkmaster_median(cpl_imagelist* images,const double kappa, const int nclip, const double tolerance)
00353 {
00354 
00355    cpl_image* master=NULL;
00356    cpl_vector* levels=NULL;
00357    double mean=0;
00358    cpl_imagelist* iml=NULL;
00359 
00360    cpl_msg_info(cpl_func,"method median");
00361    iml=cpl_imagelist_duplicate(images);
00362    levels=irplib_imagelist_get_clean_mean_levels(iml,kappa,nclip,tolerance);
00363 
00364    mean=cpl_vector_get_mean(levels);
00365    cpl_msg_info(cpl_func,"Master mean level: %g",mean);
00366    irplib_imagelist_subtract_values(&iml,levels);
00367        
00368    master = cpl_imagelist_collapse_median_create(iml);
00369 
00370    cpl_image_add_scalar(master,mean);
00371 
00372    cpl_vector_delete(levels);
00373    cpl_imagelist_delete(iml);
00374 
00375    return master;
00376 
00377 }
00378 
00379 /* Work in progress */
00380 static cpl_error_code
00381 irplib_mkmaster_dark_qc(const cpl_imagelist* raw_images,
00382     cpl_imagelist* preproc_images,
00383     const cpl_parameterlist* parameters,
00384      const int pr_num_x, const int pr_num_y,
00385     const int pr_box_sx, const int pr_box_sy, const char* recipe_id,
00386     cpl_table* qclog) {
00387 
00388    cpl_ensure_code(qclog !=NULL, CPL_ERROR_NULL_INPUT);
00389    cpl_ensure_code(recipe_id !=NULL, CPL_ERROR_NULL_INPUT);
00390    cpl_ensure_code(parameters !=NULL, CPL_ERROR_NULL_INPUT);
00391 
00392   int i = 0;
00393   cpl_image* current_dark = 0;
00394   if (pr_num_x != 0 && pr_num_y != 0 && pr_box_sx != 0 && pr_box_sy != 0) {
00395     for (i = 0; i < cpl_imagelist_get_size(raw_images); i++) {
00396       current_dark = cpl_image_duplicate(
00397           cpl_imagelist_get_const(preproc_images, i));
00398       cpl_msg_info(cpl_func, "Calculating QC parameters on raw dark frame %d",
00399           i);
00400       /* Here To be defined more general way to qc-log */
00401        /* UVES specific stuff: may be this function should not be put in irplib
00402       irplib_mdark_region_qc(current_dark, parameters, raw_images, recipe_id,qclog);
00403        */    
00404     }
00405   }
00406   return cpl_error_get_code();
00407 }
00408 
00409 /*-------------------------------------------------------------------------*/
00419 /*-------------------------------------------------------------------------*/
00420 static double
00421 irplib_head_get_exptime(const cpl_propertylist * plist) {
00422   double result = 0; /* Conversion from electrons to ADUs */
00423 
00424   result=cpl_propertylist_get_double(plist, "EXPTIME");
00425   cpl_ensure_code(result >= 0, CPL_ERROR_ILLEGAL_OUTPUT);
00426 
00427   return result;
00428 }
00429 
00430 /*-------------------------------------------------------------------------*/
00438 /*-------------------------------------------------------------------------*/
00439 static cpl_error_code
00440 irplib_head_set_exptime(cpl_propertylist *plist, double exptime)
00441 {
00442    cpl_propertylist_update_double(plist, "EXPTIME", exptime);
00443    cpl_propertylist_set_comment(plist, "EXPTIME", "Total integration time");
00444 
00445     return cpl_error_get_code();
00446 }
00447 
00448 static cpl_imagelist*
00449 irplib_mkmaster_dark_fill_imagelist(const cpl_imagelist* raw_images,
00450     cpl_propertylist** raw_headers, const cpl_image* master_bias,
00451     double* mean_exptime) {
00452   /* First process each input image and store the results in a
00453    new image list */
00454 
00455   cpl_imagelist* preproc_images = NULL;
00456   int i = 0;
00457   cpl_image* current_dark = NULL;
00458   double min_exptime = 0;
00459   double max_exptime = 0;
00460 
00461   preproc_images = cpl_imagelist_new();
00462   for (i = 0; i < cpl_imagelist_get_size(raw_images); i++) {
00463     double exposure_time = 0.0;
00464     const cpl_propertylist *current_header;
00465 
00466     current_dark = cpl_image_duplicate(cpl_imagelist_get_const(raw_images, i));
00467     current_header = raw_headers[i];
00468 
00469     /* Subtract master bias */
00470     if (master_bias != NULL) {
00471       cpl_msg_info(cpl_func, "Subtracting master bias");
00472       cpl_image_subtract(current_dark, master_bias);
00473     } else {
00474       cpl_msg_info(cpl_func, "Skipping bias subtraction");
00475     }
00476 
00477     exposure_time = irplib_head_get_exptime(current_header);
00478 
00479     /* Initialize/update min/max exposure time*/
00480     if (i == 0 || exposure_time < min_exptime) {
00481       min_exptime = exposure_time;
00482     }
00483     if (i == 0 || exposure_time > max_exptime) {
00484       max_exptime = exposure_time;
00485     }
00486 
00487     /* Do not normalize to unit exposure time */
00488     /*        If this is uncommented, then remember to also calculate the
00489      correct master dark exposure time below.
00490      irplib_msg("Normalizing from %f s to unit exposure time", exposure_time);
00491      check( cpl_image_divide_scalar(current_dark, exposure_time),
00492      "Error normalizing dark frame");   */
00493 
00494     /* Append to imagelist */
00495     cpl_imagelist_set(preproc_images, current_dark, i);
00496 
00497     /* Don't deallocate the image. It will be deallocated when
00498      the image list is deallocated */
00499     current_dark = NULL;
00500   }
00501 
00502 
00503   /* Check exposure times */
00504    cpl_msg_info(cpl_func,
00505        "Exposure times range from %e s to %e s (%e %% variation)", min_exptime,
00506        max_exptime, 100 * (max_exptime - min_exptime) / min_exptime);
00507 
00508    if ((max_exptime - min_exptime) / min_exptime > .001) {
00509      cpl_msg_warning(cpl_func, "Exposure times differ by %e %%",
00510          100 * (max_exptime - min_exptime) / min_exptime);
00511    }
00512 
00513    /* compute correct exposure time */
00514    *mean_exptime=0.5 * (max_exptime + min_exptime);
00515   return preproc_images;
00516 }
00517 
00518 
00519 cpl_image *
00520 irplib_mdark_process_chip(const cpl_imagelist *raw_images,
00521     cpl_propertylist **raw_headers, const cpl_image *master_bias,
00522     cpl_propertylist *mdark_header, const cpl_parameterlist *parameters,
00523     const char* recipe_id, cpl_table* qclog, const int do_qc,
00524     const char* STACK_METHOD, const double STACK_KLOW, const double STACK_KHIGH,
00525     const int STACK_NITER,
00526     const int pr_num_x, const int pr_num_y,
00527     const int pr_box_sx, const int pr_box_sy) {
00528   cpl_image *master_dark = NULL; /* Result */
00529   cpl_image *current_dark = NULL;
00530   cpl_imagelist *preproc_images = NULL;
00531   double mean_exptime = 0;
00532 
00533   /* First process each input image and store the results in a
00534    new image list */
00535   preproc_images = irplib_mkmaster_dark_fill_imagelist(raw_images, raw_headers,
00536       master_bias, &mean_exptime);
00537   if (do_qc) {
00538      /* Here we should compute QC but a a better way to log it is TBD  */
00539     irplib_mkmaster_dark_qc(raw_images, preproc_images, parameters, pr_num_x,
00540         pr_num_y, pr_box_sx, pr_box_sy, recipe_id, qclog);
00541      
00542   }
00543   /* Get median stack of input darks */
00544   if (strcmp(STACK_METHOD, "MEDIAN") == 0) {
00545     cpl_msg_info(cpl_func, "Calculating stack median");
00546     master_dark = cpl_imagelist_collapse_median_create(preproc_images);
00547   } else {
00548     cpl_msg_info(cpl_func, "Calculating stack mean");
00549     master_dark = irplib_imagelist_ksigma_stack(preproc_images, STACK_KLOW,
00550         STACK_KHIGH, STACK_NITER);
00551 
00552   }
00553   irplib_head_set_exptime(mdark_header, mean_exptime );
00554 
00555   cpl_image_delete(current_dark);
00556   cpl_imagelist_delete(preproc_images);
00557   if (cpl_error_get_code() != CPL_ERROR_NONE) {
00558     cpl_image_delete(master_dark);
00559   }
00560 
00561   return master_dark;
00562 }
00563 

Generated on 9 Mar 2012 for UVES Pipeline Reference Manual by  doxygen 1.6.1