visir_inputs.c

00001 /* $Id: visir_inputs.c,v 1.122 2009/03/12 08:23:47 llundin Exp $
00002  *
00003  * This file is part of the VISIR Pipeline
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: llundin $
00023  * $Date: 2009/03/12 08:23:47 $
00024  * $Revision: 1.122 $
00025  * $Name: visir-3_2_2 $
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 <float.h>
00039 #include <assert.h>
00040 
00041 #include <cpl.h>
00042 
00043 #include "visir_utils.h"
00044 #include "visir_pfits.h"
00045 #include "visir_parameter.h"
00046 #include "visir_pfits.h"
00047 #include "visir_spc_distortion.h"
00048 #include "visir_inputs.h"
00049 #include "irplib_plot.h"
00050 #include "irplib_framelist.h"
00051 
00052 /*-----------------------------------------------------------------------------
00053                                    Define
00054  -----------------------------------------------------------------------------*/
00055 
00056 /* The values range from 0 (or 1) to 2**16-1 (or 2**16) */
00057 #define VISIR_HCYCLE_BPM_THRESHOLD  65000.0
00058 
00059 #ifndef VISIR_DESTRIPE_DETECT
00060 #define VISIR_DESTRIPE_DETECT           (3.5 * 1.64)
00061 #endif
00062 
00063 #ifndef VISIR_DESTRIPE_DETECT_THRESHOLD
00064 #define VISIR_DESTRIPE_DETECT_THRESHOLD 1.3
00065 #endif
00066 
00067 
00068 /*-----------------------------------------------------------------------------
00069                                    Functions prototypes
00070  -----------------------------------------------------------------------------*/
00071 
00072 #include "visir_destripe.h"
00073 
00074 static cpl_image * visir_load_average(const char *,
00075                                       const cpl_propertylist *);
00076 static cpl_imagelist * visir_load_intermint(const irplib_framelist *, int);
00077 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *);
00078 static cpl_error_code visir_rem_glitch(cpl_image *);
00079 static cpl_error_code visir_rem_bad_images(cpl_imagelist *); 
00080 static cpl_error_code visir_offset_hcycle(cpl_image *);
00081 
00082 /*----------------------------------------------------------------------------*/
00086 /*----------------------------------------------------------------------------*/
00087 
00090 /*----------------------------------------------------------------------------*/
00173 /*----------------------------------------------------------------------------*/
00174 cpl_imagelist * visir_inputs_combine(const char * recipename,
00175                                      const cpl_parameterlist * parlist,
00176                                      const irplib_framelist * rawframes,
00177                                      const char      *   badpix,
00178                                      const char      *   flat,
00179                                      int             *   nodding_p,
00180                                      cpl_boolean         do_spc_fix,
00181                                      double              wlen,
00182                                      visir_spc_resol resol)
00183 {
00184     const char       * fnodpos;
00185     int                nfiles;
00186     cpl_imagelist    * in = NULL;
00187     cpl_image        * collapsed = NULL;
00188     cpl_image        * prev = NULL;
00189     cpl_vector       * nods_vec = NULL;
00190     double           * nods_data;
00191     int              * nod_pos = NULL;
00192     cpl_image       ** images = NULL;
00193     cpl_imagelist    * nodded = NULL;
00194     int                nnod;
00195     cpl_image        * flat_image = NULL;
00196     cpl_image        * bpm_im_int = NULL;
00197     cpl_mask         * bpm_im_bin = NULL;
00198     cpl_imagelist    * hcycle = NULL;
00199     cpl_boolean        no_rem;
00200     cpl_boolean        is_nodding = CPL_FALSE;
00201     int                i, j;
00202     cpl_boolean        auto_bpm, rem_glitch, rem_bad;
00203     int                ndestripe;
00204     cpl_boolean        morpho_destripe;
00205 
00206 
00207     skip_if (0);
00208     skip_if(recipename == NULL);
00209     skip_if(parlist    == NULL);
00210     skip_if(rawframes  == NULL);
00211     
00212     /* Get the number of files */
00213     nfiles = irplib_framelist_get_size(rawframes);
00214 
00215     /* There should be an even number of files */
00216     if (nfiles % 2) {
00217         if (nfiles == 1) {
00218             cpl_msg_error(cpl_func, "At least two files are required");
00219             skip_if (1);
00220         }
00221         cpl_msg_warning(cpl_func, "Expecting even number of files, "
00222                         "ignoring the last of %d files", nfiles);
00223         nfiles--;
00224     }
00225 
00226     nnod = nfiles/2;
00227 
00228     skip_if (nnod <= 0);
00229 
00230     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FRAME_TYPE,
00231                                        CPL_TYPE_STRING, CPL_FALSE, 0.0));
00232     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00233                                        CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00234     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00235                                        CPL_TYPE_INT, CPL_FALSE, 0.0));
00236     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00237                                        CPL_TYPE_INT, CPL_FALSE, 0.0));
00238 
00239 
00240     /* Retrieve input parameters */
00241     fnodpos = visir_parameterlist_get_string(parlist, recipename,
00242                                              VISIR_PARAM_NODPOS);
00243     skip_if (0);
00244 
00245     auto_bpm = visir_parameterlist_get_bool(parlist, recipename,
00246                                             VISIR_PARAM_AUTOBPM);
00247     skip_if (0);
00248 
00249     rem_glitch = visir_parameterlist_get_bool(parlist, recipename,
00250                                               VISIR_PARAM_GLITCH);
00251     skip_if (0);
00252 
00253     rem_bad = visir_parameterlist_get_bool(parlist, recipename,
00254                                            VISIR_PARAM_PURGE);
00255     skip_if (0);
00256 
00257     ndestripe = visir_parameterlist_get_int(parlist, recipename,
00258                                             VISIR_PARAM_STRIPITE);
00259     bug_if (0);
00260 
00261     morpho_destripe = ndestripe <= 0 ? CPL_FALSE :
00262         visir_parameterlist_get_bool(parlist, recipename,
00263                                      VISIR_PARAM_STRIPMOR);
00264     bug_if (0);
00265 
00266     no_rem = !rem_glitch && !rem_bad;
00267 
00268     /* Each file corresponds to a nodding position (object=1 or sky=-1) */
00269     /* Return nod_pos array if requested */
00270     nod_pos = nodding_p ? nodding_p : cpl_malloc(nfiles * sizeof(int));
00271     j = 0;
00272     if (fnodpos != NULL && strlen(fnodpos) > 0) {
00273         /* Get the nodding positions from the user-provided ascii file */
00274         nods_vec = cpl_vector_read(fnodpos);
00275         skip_if (cpl_vector_get_size(nods_vec) != nfiles);
00276         nods_data = cpl_vector_get_data(nods_vec);
00277         skip_if (0);
00278         for (i=0 ; i<nfiles ; i++) {
00279             if ((int)nods_data[i] == 0) {
00280                 nod_pos[i] = 1;
00281                 j++;
00282             } else if ((int)nods_data[i] == 1) {
00283                 nod_pos[i] = -1;
00284                 is_nodding = CPL_TRUE;
00285             } else {
00286                 cpl_msg_error(cpl_func, "Wrong values in line %d in %s", i+1,
00287                               fnodpos);
00288                 skip_if (1);
00289             }
00290         }
00291     } else {
00292         skip_if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_NODPOS,
00293                                             CPL_TYPE_STRING, CPL_FALSE, 0.0));
00294     }
00295 
00296     if (no_rem) cpl_msg_info(cpl_func, "No glitch removal and no purge of bad "
00297                              "frames requested: Using fast I/O method");
00298 
00299     /* Initialize the Bad Pixel Map */
00300     if (badpix != NULL) {
00301         /* The bpm is provided by the user */
00302         cpl_msg_info(cpl_func, "Loading bad pixel map from %s", badpix);
00303         /* Load the bad pixels image */
00304         bpm_im_int = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
00305         skip_if (0);
00306 
00307         /* Convert the map from integer to binary */
00308         bpm_im_bin = cpl_mask_threshold_image_create(bpm_im_int, -0.5, 0.5);
00309         cpl_image_delete(bpm_im_int);
00310         bpm_im_int = NULL;
00311         skip_if (cpl_mask_not(bpm_im_bin));
00312     }
00313 
00314     /* Initialize the flat field image */
00315     if (flat != NULL) {
00316         cpl_msg_info(cpl_func, "Divide the nodded images by the flatfield");
00317         /* Load the flat image */
00318         if ((flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00319             cpl_msg_error(cpl_func, "Cannot load the flat field %s", flat);
00320             skip_if (1);
00321         }
00322     }
00323  
00324     /* Get nodding position (if needed) and DIT from the header */
00325     nodded = cpl_imagelist_new();
00326     for (i=0; i < nfiles ; i++) {
00327         const char * file =
00328             cpl_frame_get_filename(irplib_framelist_get_const(rawframes, i));
00329         const cpl_propertylist * plist;
00330 
00331         double dit;
00332         double factor;
00333 
00334 
00335         plist = irplib_framelist_get_propertylist_const(rawframes, i);
00336         skip_if(plist == NULL);
00337 
00338         if (nods_vec == NULL) {
00339             const char * sval = visir_pfits_get_nodpos(plist);
00340             if (sval == NULL) {
00341                 cpl_msg_error(cpl_func, "Cannot get nodding pos for file %d",
00342                               i+1);
00343                 skip_if (1);
00344             }
00345             if (!strcmp(sval, "A")) {
00346                 nod_pos[i] = 1;
00347                 j++;
00348             } else {
00349                 nod_pos[i] = -1;
00350                 is_nodding = CPL_TRUE;
00351             }
00352         }
00353 
00354         /* Print the file name with its nodding position */
00355         cpl_msg_info(cpl_func, "File %02d: %s (%c)", i+1, file,
00356                      nod_pos[i]==1 ? '+' : '-');
00357 
00358         /* With nodding each pair must have exactly one object observation */
00359         if (is_nodding && (i & 1) == 1 && nod_pos[i] == nod_pos[i-1]) {
00360             cpl_msg_error(cpl_func, "Nodding pair (%d,%d) does not comprise an "
00361                           "on-object (A) and an off-object (B) image: %s", i-1,
00362                           i, nod_pos[i] == 1 ? "A" : "B");
00363         }
00364 
00365         /* Compute the normalization factor from the Detector Integration Time */
00366         dit = visir_pfits_get_dit(plist);
00367         skip_if (0);
00368 
00369         if (dit <= 0) {
00370             cpl_msg_error(cpl_func, "DIT in file %d is too small: %g", i+1, dit);
00371             skip_if (1);
00372         }
00373 
00374         factor = dit * nod_pos[i] * 2.0;
00375 
00376         if (i == 0 && badpix == NULL && auto_bpm) {
00377             /* Initialize the Bad Pixel Map using the hcycle */
00378 
00379             hcycle = visir_load_imagelist(rawframes, i, CPL_FALSE);
00380             skip_if (0);
00381 
00382             bpm_im_bin =
00383                 cpl_mask_threshold_image_create(cpl_imagelist_get(hcycle,0),
00384                                                 VISIR_HCYCLE_BPM_THRESHOLD,
00385                                                 DBL_MAX);
00386             cpl_imagelist_delete(hcycle);
00387             hcycle = NULL;
00388             skip_if (0);
00389         }
00390 
00391         if (no_rem) {
00392             collapsed = visir_load_average(file, plist);
00393         } else {
00394             if ((in = visir_load_intermint(rawframes, i)) == NULL) {
00395                 cpl_msg_error(cpl_func, "Cannot load the image set %d", i+1);
00396                 skip_if (1);
00397             }
00398 
00399 
00400             /* Convert the image lists from 'INTERM' to A-B' */
00401             skip_if (visir_imagelist_unpack_interm(in));
00402 
00403             /* Remove the glitch in each A-B image in each input cube
00404                if requested */
00405             if (rem_glitch) {
00406                 int jj;
00407                 for (jj=0 ; jj < cpl_imagelist_get_size(in); jj++) {
00408                     if (visir_rem_glitch(cpl_imagelist_get(in, jj))) {
00409                         cpl_msg_error(cpl_func,  "Cannot remove glitch in image "
00410                                       "%d in set %d", jj+1, i+1);
00411                         skip_if (1);
00412                     }
00413                 }
00414             }
00415 
00416             /* Remove the bad A-B images in each input file/cube if requested */
00417             if (rem_bad) {
00418                 cpl_msg_info(cpl_func, "Remove the bad A-B input images");
00419                 if (visir_rem_bad_images(in)) {
00420                     cpl_msg_error(cpl_func, "Cannot remove bad images in list "
00421                                   "%d", i+1);
00422                     skip_if (1);
00423                 }
00424             }
00425             /* Average each cube */
00426             collapsed = cpl_imagelist_collapse_create(in);
00427 
00428             cpl_imagelist_delete(in);
00429             in = NULL;
00430 
00431         }
00432 
00433         skip_if (0);
00434         /* Normalise to have ADU/s. */
00435         /* Also divide with 2 to achieve average of image pair */
00436         skip_if (cpl_image_divide_scalar(collapsed, 2*factor));
00437 
00438         /* Each pair of input files gives a nodded image in nodded */
00439         if (i & 1) {
00440             bug_if (cpl_image_add(prev, collapsed));
00441             cpl_image_delete(collapsed);
00442             collapsed = NULL;
00443 
00444             /* At this point prev is the image to be put into
00445                the list of nodded images */
00446 
00447             if (bpm_im_bin != NULL) {
00448                 /* Apply the bad pixels cleaning */
00449                 bug_if (cpl_image_reject_from_mask(prev, bpm_im_bin));
00450                 bug_if (cpl_detector_interpolate_rejected(prev));
00451             }
00452 
00453             if (ndestripe > 0)
00454                 skip_if(visir_destripe_image(prev, ndestripe,
00455                                              VISIR_DESTRIPE_DETECT,
00456                                              VISIR_DESTRIPE_DETECT_THRESHOLD,
00457                                              morpho_destripe));
00458 
00459             if (flat_image != NULL) {
00460                 /* Apply the flatfield correction */
00461                 skip_if (cpl_image_divide(prev, flat_image));
00462             }
00463 
00464             bug_if (cpl_imagelist_set(nodded, prev, i/2));
00465             prev = NULL;
00466         } else {
00467             prev = collapsed;
00468             collapsed = NULL;
00469         }
00470     }
00471 
00472     cpl_vector_delete(nods_vec);
00473     nods_vec = NULL;
00474 
00475     cpl_image_delete(flat_image);
00476     flat_image = NULL;
00477 
00478     cpl_mask_delete(bpm_im_bin);
00479     bpm_im_bin = NULL;
00480 
00481     if (nod_pos != nodding_p) cpl_free(nod_pos);
00482     nod_pos = NULL;
00483     
00484     if (is_nodding && j != nnod) {
00485         cpl_msg_error(cpl_func, "With nodding exactly half of the images "
00486                       "must be on-object, not %d of %d", j, 2*nnod);
00487         skip_if (1);
00488     }
00489 
00490     if (do_spc_fix) {
00491         const double ksi   = visir_parameterlist_get_double(parlist, recipename,
00492                                                           VISIR_PARAM_SPECSKEW);
00493         const double eps   = visir_parameterlist_get_double(parlist, recipename,
00494                                                             VISIR_PARAM_VERTARC);
00495         const double delta = visir_parameterlist_get_double(parlist, recipename,
00496                                                             VISIR_PARAM_HORIARC);
00497         const double phi   = visir_parameterlist_get_double(parlist, recipename,
00498                                                           VISIR_PARAM_SLITSKEW);
00499         const int doplot   = visir_parameterlist_get_int(parlist, recipename,
00500                                                          VISIR_PARAM_PLOT);
00501 
00502 
00503         skip_if (0);
00504 
00505         images = cpl_malloc(nnod * sizeof(cpl_image*));
00506 
00507         for (j = 0; j < nnod; j++) images[j] = cpl_imagelist_get(nodded, j);
00508 
00509         skip_if (visir_spc_det_fix(images, nnod, CPL_TRUE, wlen, resol,
00510                                    phi, ksi, eps, delta, doplot));
00511     }
00512 
00513     end_skip;
00514 
00515     cpl_free(images);
00516     cpl_imagelist_delete(in);
00517 
00518     if (nod_pos != nodding_p) cpl_free(nod_pos);
00519     cpl_vector_delete(nods_vec);
00520     cpl_image_delete(bpm_im_int);
00521     cpl_mask_delete(bpm_im_bin);
00522     cpl_image_delete(collapsed);
00523     cpl_image_delete(prev);
00524     if (cpl_error_get_code() && nodded != NULL) {
00525         cpl_imagelist_delete(nodded);
00526         nodded = NULL;
00527     }
00528 
00529     return nodded;
00530 }
00531 
00532 /*----------------------------------------------------------------------------*/
00579 /*----------------------------------------------------------------------------*/
00580 cpl_image ** visir_img_recombine(const char * recipename,
00581                                  const cpl_parameterlist * parlist,
00582                                  const irplib_framelist  * rawframes,
00583                                  const char        * badpix,
00584                                  const char        * flat,
00585                                  cpl_geom_combine    combine_mode,
00586                                  cpl_boolean       * pdid_resize,
00587                                  cpl_boolean         do_spc_fix,
00588                                  double              wlen,
00589                                  visir_spc_resol     resol)
00590 {
00591     int                     nfiles;
00592     int                 *   nod_pos = NULL;
00593     cpl_imagelist       *   nodded = NULL;
00594     int                     nnod;
00595     cpl_bivector        *   offsets_est = NULL;
00596     cpl_bivector        *   objs = NULL;
00597     cpl_image           **  combined = NULL;
00598     const cpl_vector    *   sigmas = NULL;
00599     double                  xoff, yoff;
00600     int                     i;
00601 
00602 
00603     bug_if (0);
00604 
00605     bug_if (recipename == NULL);
00606     bug_if (parlist    == NULL);
00607     bug_if (rawframes  == NULL);
00608     bug_if (pdid_resize  == NULL);
00609 
00610     /* Get the number of files */
00611     nfiles = irplib_framelist_get_size(rawframes);
00612 
00613     /* There should be an even number of files */
00614     if (nfiles % 2) {
00615         if (nfiles == 1) {
00616             cpl_msg_error(cpl_func, "At least two files are required");
00617             skip_if (1);
00618         }
00619         cpl_msg_warning(cpl_func, "Expecting even number of files, "
00620                         "ignoring the last of %d files", nfiles);
00621         nfiles--;
00622     }
00623 
00624     skip_if ( nfiles <= 0);
00625 
00626     /* Each file corresponds to a nodding position (object=1 or sky=-1) */
00627     nod_pos = cpl_malloc(nfiles * sizeof(int));
00628 
00629     /* Combine the input frames into the nodded images */
00630     cpl_msg_info(cpl_func, "Combining the input frames into the nodded images");
00631     nodded = visir_inputs_combine(recipename, parlist, rawframes, badpix, flat,
00632                                   nod_pos, do_spc_fix, wlen, resol);
00633 
00634     skip_if (nodded == NULL);
00635     nnod = cpl_imagelist_get_size(nodded);
00636 
00637     /* If only one nodded image, the work is finished */
00638     if (nnod == 1) {
00639 
00640         combined = cpl_malloc(2*sizeof(cpl_image*)); 
00641         combined[1] = NULL; /* In case the unset fails */
00642 
00643         combined[0] = cpl_imagelist_unset(nodded, 0);
00644         bug_if (combined[0] == NULL);
00645 
00646         combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
00647                                     cpl_image_get_size_y(combined[0]),
00648                                     CPL_TYPE_INT);
00649         bug_if (combined[1] == NULL);
00650 
00651         /* Set all pixel values to 1 */
00652         bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
00653 
00654         *pdid_resize = CPL_FALSE;
00655 
00656     } else {
00657         const double psigmas[] = {5, 2, 1, 0.5};
00658         const char * sval;
00659         const char * offsets;
00660         const char * objects;
00661         int sx, sy, mx, my;
00662         int rej_low, rej_high;
00663         cpl_boolean refine;
00664 
00665 
00666         refine = visir_parameterlist_get_bool(parlist, recipename,
00667                                               VISIR_PARAM_REFINE);
00668         skip_if (0);
00669 
00670         offsets = visir_parameterlist_get_string(parlist, recipename,
00671                                                  VISIR_PARAM_OFFSETS);
00672         skip_if (0);
00673 
00674         objects = visir_parameterlist_get_string(parlist, recipename,
00675                                                  VISIR_PARAM_OBJECTS);
00676         skip_if (0);
00677 
00678         sval = visir_parameterlist_get_string(parlist, recipename,
00679                                               VISIR_PARAM_XCORR);
00680         skip_if (0);
00681 
00682         skip_if (sscanf(sval, "%d %d %d %d", &sx, &sy, &mx, &my) != 4);
00683 
00684         sval = visir_parameterlist_get_string(parlist, recipename,
00685                                               VISIR_PARAM_REJECT);
00686         skip_if (0);
00687 
00688         skip_if (sscanf(sval, "%d %d", &rej_low, &rej_high) !=2 );
00689 
00690         /* Get the offsets estimation of each input file pair */
00691         cpl_msg_info(cpl_func, "Get the offsets estimation");
00692         if (offsets != NULL && strlen(offsets)) {
00693             /* A file has been provided on the command line */
00694             offsets_est = cpl_bivector_read(offsets);
00695             skip_if (offsets_est==NULL);
00696 
00697             if (cpl_bivector_get_size(offsets_est) != nnod) {
00698                 cpl_msg_error(cpl_func, "The offsets file %s must have %d "
00699                               "entries, not %d", offsets, nnod,
00700                               cpl_bivector_get_size(offsets_est));
00701                 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
00702                 skip_if (1);
00703             }
00704         } else {
00705             double * offsets_est_x;
00706             double * offsets_est_y;
00707             double   xoff0 = 0.0;  /* Avoid (false) uninit warning */
00708             double   yoff0 = 0.0;  /* Avoid (false) uninit warning */
00709             
00710             /* Get the offsets from the header */
00711             offsets_est = cpl_bivector_new(nnod);
00712             offsets_est_x = cpl_bivector_get_x_data(offsets_est);
00713             offsets_est_y = cpl_bivector_get_y_data(offsets_est);
00714 
00715             skip_if (0);
00716 
00717             offsets_est_x[0] = 0.0;
00718             offsets_est_y[0] = 0.0;
00719 
00720             for (i=0; i < nnod ; i++) {
00721                 const cpl_propertylist * plist;
00722 
00723                 /* Skip every other, non-object frame */ 
00724                 const int iframe = nod_pos[2*i] == 1 ? 2*i : 2*i+1;
00725 
00726                 plist = irplib_framelist_get_propertylist_const(rawframes,
00727                                                                 iframe);
00728                 skip_if(plist == NULL);
00729 
00730                 xoff = visir_pfits_get_cumoffsetx(plist);
00731                 yoff = visir_pfits_get_cumoffsety(plist);
00732 
00733                 skip_if (0);
00734 
00735                 if (i == 0) {
00736                     xoff0 = xoff;
00737                     yoff0 = yoff;
00738                 } else {
00739                     /* Subtract the first offset from all offsets */
00740                     offsets_est_x[i] = xoff0 - xoff;
00741                     offsets_est_y[i] = yoff0 - yoff;
00742                 }
00743             }
00744         }
00745         cpl_free(nod_pos);
00746         nod_pos = NULL;
00747     
00748         /* Read the provided objects file if provided
00749            - if a file has been provided on the command line */
00750         if (objects != NULL && strlen(objects) > 0 && 
00751             (objs = cpl_bivector_read(objects)) == NULL) {
00752             cpl_msg_error(cpl_func, "Could not read objects from %s", objects);
00753             skip_if (1);
00754         }
00755    
00756         cpl_msg_info(cpl_func, "Recombining the list of nodded images using "
00757                      "mode: %d (I=%d:U=%d:F=%d), rej-lo=%d, rej-hi=%d",
00758                      combine_mode, CPL_GEOM_INTERSECT, CPL_GEOM_UNION,
00759                      CPL_GEOM_FIRST, rej_low, rej_high);
00760 
00761         if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00762             cpl_msg_debug(cpl_func, "The offsets for the recombination:");
00763             cpl_bivector_dump(offsets_est, stdout);
00764         }
00765 
00766         sigmas = cpl_vector_wrap(4, (double*)psigmas); /* Not changed */
00767         combined = cpl_geom_img_offset_combine(nodded, offsets_est, refine,
00768                                                objs, sigmas, NULL, sx, sy,
00769                                                mx, my, rej_low, rej_high,
00770                                                combine_mode);
00771         if (combined == NULL) {
00772             cpl_msg_error(cpl_func, "Could not recombine the images");
00773             skip_if(1);
00774         }
00775 
00776         *pdid_resize = (cpl_boolean)(cpl_image_get_size_x(combined[0])
00777                 != cpl_image_get_size_x(cpl_imagelist_get_const(nodded, 0)) ||
00778                 cpl_image_get_size_y(combined[0])
00779                 != cpl_image_get_size_y(cpl_imagelist_get_const(nodded, 0)));
00780     }
00781 
00782     if (visir_parameterlist_get_int(parlist, recipename, VISIR_PARAM_PLOT) > 0)
00783         visir_image_plot("", "t 'The combined image'", "", combined[0]);
00784 
00785     end_skip;
00786 
00787     cpl_free(nod_pos);
00788     cpl_imagelist_delete(nodded);
00789     cpl_bivector_delete(offsets_est);
00790     cpl_bivector_delete(objs);
00791     cpl_vector_unwrap((cpl_vector*)sigmas);
00792 
00793     return combined;
00794 }
00795 
00796 /*----------------------------------------------------------------------------*/
00819 /*----------------------------------------------------------------------------*/
00820 cpl_imagelist * visir_load_hcycle(const irplib_framelist * rawframes, int pos)
00821 {
00822     return visir_load_imagelist(rawframes, pos, CPL_FALSE);
00823 }
00824 
00825 /*----------------------------------------------------------------------------*/
00836 /*----------------------------------------------------------------------------*/
00837 cpl_error_code visir_image_reject_hot(cpl_image * self, const char * bpmfile)
00838 {
00839 
00840     cpl_image  * im_bpm = NULL;
00841     cpl_mask   * bpm = NULL;
00842     const int upper = VISIR_HCYCLE_BPM_THRESHOLD;
00843 
00844 
00845     skip_if (0);
00846 
00847     skip_if (self == NULL);
00848 
00849     if (bpmfile == NULL) {
00850         bpm = cpl_mask_threshold_image_create(self, upper, DBL_MAX);
00851         skip_if (0);
00852     } else {
00853 
00854         /* The bpm is provided by the user */
00855         cpl_msg_info(cpl_func, "Clean user specified bad pixels");
00856         /* Load the bad pixel image */
00857         im_bpm = cpl_image_load(bpmfile, CPL_TYPE_INT, 0, 0);
00858         if (cpl_error_get_code()) {
00859             cpl_msg_error(cpl_func,"Cannot load the bad pixel map %s", bpmfile);
00860             skip_if (1);
00861         }
00862         /* Convert the map from integer to binary */
00863         bpm = cpl_mask_threshold_image_create(im_bpm, -0.5, 0.5);
00864         skip_if (0);
00865         cpl_image_delete(im_bpm);
00866         im_bpm = NULL;
00867 
00868         skip_if (cpl_mask_not(bpm));
00869     }
00870 
00871     skip_if (cpl_image_reject_from_mask(self, bpm));
00872 
00873     end_skip;
00874 
00875     cpl_image_delete(im_bpm);
00876     cpl_mask_delete(bpm);
00877 
00878     return cpl_error_get_code();
00879 
00880 }
00881 
00882 
00883 /*----------------------------------------------------------------------------*/
00890 /*----------------------------------------------------------------------------*/
00891 cpl_imagelist * visir_imagelist_load_last(const irplib_framelist * rawframes)
00892 {
00893     cpl_imagelist * self = NULL;
00894     int naxis3;
00895 
00896     /* Verify that NAXIS3 is the same in all files */
00897     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00898                                       CPL_TYPE_INT, CPL_TRUE, 0.0));
00899 
00900     naxis3 = visir_pfits_get_naxis3(irplib_framelist_get_propertylist_const(
00901                                                                       rawframes,
00902                                                                       0));
00903 
00904     /* Load the image set */
00905     self = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, naxis3-1,
00906                                            0);
00907 
00908     skip_if (self == NULL);
00909 
00910     end_skip;
00911 
00912     return self;
00913 
00914 }
00915 
00916 
00917 /*----------------------------------------------------------------------------*/
00927 /*----------------------------------------------------------------------------*/
00928 cpl_imagelist * visir_load_imagelist(const irplib_framelist * rawframes,
00929                                      int pos, cpl_boolean is_interm)
00930 {
00931     cpl_errorstate cleanstate = cpl_errorstate_get();
00932     cpl_imagelist    * self = NULL;
00933     cpl_image        * image = NULL;
00934     const char       * file = NULL;
00935     const cpl_propertylist * plist;
00936     int                nchop, naxis3;
00937 
00938 
00939     /* Check the error code */
00940     skip_if (0);
00941 
00942     skip_if (rawframes == NULL);
00943 
00944     file = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
00945     skip_if (file == NULL);
00946 
00947     /* First check if there is no chopping */
00948     plist = irplib_framelist_get_propertylist_const(rawframes, pos);
00949     skip_if (plist == NULL);
00950 
00951     naxis3 = visir_pfits_get_naxis3(plist);
00952     nchop = visir_pfits_get_chop_ncycles(plist);
00953 
00954     skip_if (0);
00955 
00956     if (nchop == 0 && naxis3 == 1 && is_interm) {
00957         self = cpl_imagelist_load(file, CPL_TYPE_FLOAT, 0);
00958     } else {
00959         const char   * sval;
00960         /* If nchop == 1 (and naxis3 == 3) the data unit is both a valid CUBE1
00961            and a valid CUBE2; Set plane_step as if the frame type is CUBE2 */
00962         const int      plane_step = (naxis3 == 2 * nchop + 1) ? 2 : 1;
00963         const cpl_type pixel_type = CPL_TYPE_FLOAT;
00964         int            nsize;
00965         int            iplane;
00966         int            i;
00967 
00968 
00969         if (nchop <= 0) {
00970             cpl_msg_error(cpl_func, "CHOP NCYCLES in %s is non-positive (and "
00971                           "NAXIS3=%d): %d", file, naxis3, nchop);
00972             visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
00973             skip_if (1);
00974         }
00975 
00976         if (plane_step == 1 && naxis3 != nchop+2) {
00977             cpl_msg_error(cpl_func, "NAXIS3=%d and CHOP NCYCLES=%d in %s is "
00978                           "not a valid VISIR INTERM+Half-Cycle format", naxis3,
00979                           nchop, file);
00980             visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
00981             skip_if (1);
00982         }
00983 
00984         if (plane_step == 1 && nchop > 1)
00985             cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
00986                           "Cycle frame (old CUBE1-format)", file, nchop);
00987 
00988         /* Check the data format */
00989         sval = visir_pfits_get_frame_type(plist);
00990         if (sval == NULL) {
00991             /* Has warned about missing frame type card */
00992             visir_error_reset("Could not get FITS key");
00993             /* Don't know whether or not to expect CUBE1 or CUBE2 */
00994         } else if (strlen(sval) == 0) {
00995             /* Don't know whether or not to expect CUBE1 or CUBE2 */
00996         } else if (plane_step == 1) {
00997             if (strcmp(sval, "CUBE2")==0)
00998                 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
00999                                 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01000                                 " the frame type is really CUBE1",  file,
01001                                 naxis3, nchop);
01002         } else if (nchop > 1) {
01003             /* if nchop == 1 format can be CUBE1 or CUBE2 */
01004             if (strcmp(sval, "CUBE1")==0)
01005                 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01006                                 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01007                                 " the frame type is really CUBE2",  file,
01008                                 naxis3, nchop);
01009         } 
01010 
01011         self = cpl_imagelist_new();
01012 
01013         if (plane_step == 1) {
01014             /* All INTERM frames are in the first part of the cube */
01015             iplane = is_interm ? 0 : nchop;
01016             /* - followed by a single Half-cycle image */
01017             nsize  = is_interm ? nchop : 1;
01018         } else {
01019             /* Each INTERM frame follows the Half-cycle frame */
01020             iplane = is_interm ? 1 : 0;
01021             nsize  = nchop;
01022         }
01023 
01024         for (i=0 ; i < nsize; i++, iplane += plane_step) {
01025 
01026             image = cpl_image_load(file, pixel_type, iplane, 0);
01027             skip_if (image == NULL);
01028 
01029             skip_if (!is_interm && visir_offset_hcycle(image));
01030 
01031             skip_if (cpl_imagelist_set(self, image, i));
01032 
01033             image = NULL;
01034         }
01035 
01036         skip_if (i < nsize);
01037     }
01038 
01039     end_skip;
01040 
01041     if (cpl_error_get_code()) {
01042         if (file != NULL) cpl_msg_warning(cpl_func, "Could not load the %s "
01043                                           "frame(s) from: %s",
01044                                           is_interm ? "INTERM" : "Half-Cycle",
01045                                           file);
01046         cpl_image_delete(image);
01047         cpl_imagelist_delete(self);
01048         self = NULL;
01049     }
01050 
01051     return self;
01052 }
01053 
01054 
01057 /*----------------------------------------------------------------------------*/
01081 /*----------------------------------------------------------------------------*/
01082 static cpl_imagelist * visir_load_intermint(const irplib_framelist * rawframes,
01083                                             int pos)
01084 {
01085     return visir_load_imagelist(rawframes, pos, CPL_TRUE);
01086 
01087 }
01088 
01089 /*----------------------------------------------------------------------------*/
01098 /*----------------------------------------------------------------------------*/
01099 static cpl_image * visir_load_average(const char * file,
01100                                       const cpl_propertylist * plist)
01101 {
01102     cpl_errorstate cleanstate = cpl_errorstate_get();
01103     cpl_image        * self = NULL;
01104     int                nchop, naxis3;
01105 
01106 
01107     skip_if (0);
01108     skip_if (file   == NULL);
01109     skip_if (plist == NULL);
01110 
01111     naxis3 = visir_pfits_get_naxis3(plist);
01112     nchop = visir_pfits_get_chop_ncycles(plist);
01113 
01114     skip_if (0);
01115 
01116     if (nchop == 0 && naxis3 == 1) {
01117         self = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
01118     } else {
01119         const char   * sval;
01120         /* If nchop == 1 (and naxis3 == 3) the data unit is both a valid CUBE1
01121            and a valid CUBE2; Set plane_offset as if the frame type is CUBE2 */
01122         const int      plane_offset = (naxis3 == 2 * nchop + 1) ? 2 : 3;
01123 
01124 
01125         if (nchop <= 0) {
01126             cpl_msg_error(cpl_func, "CHOP NCYCLES in %s is non-positive (and "
01127                           "NAXIS3=%d): %d", file, naxis3, nchop);
01128             visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01129             skip_if (1);
01130         }
01131 
01132         if (plane_offset == 3 && naxis3 != nchop+2) {
01133             cpl_msg_error(cpl_func, "NAXIS3=%d and CHOP NCYCLES=%d in %s is "
01134                           "not a valid VISIR INTERM+Half-Cycle format", naxis3,
01135                           nchop, file);
01136             visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01137             skip_if (1);
01138         }
01139 
01140         if (plane_offset == 3 && nchop > 1)
01141             cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01142                           "Cycle frame (old CUBE1-format)", file, nchop);
01143 
01144         /* Check the data format */
01145         sval = visir_pfits_get_frame_type(plist);
01146         if (sval == NULL) {
01147             /* Has warned about missing frame type card */
01148             visir_error_reset("Could not get FITS key");
01149             /* Don't know whether or not to expect CUBE1 or CUBE2 */
01150         } else if (strlen(sval) == 0) {
01151             /* Don't know whether or not to expect CUBE1 or CUBE2 */
01152         } else if (plane_offset == 3) {
01153             if (strcmp(sval, "CUBE2")==0)
01154                 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
01155                                 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01156                                 " the frame type is really CUBE1",  file,
01157                                 naxis3, nchop);
01158         } else if (nchop > 1) {
01159             /* if nchop == 1 format can be CUBE1 or CUBE2 */
01160             if (strcmp(sval, "CUBE1")==0)
01161                 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01162                                 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01163                                 " the frame type is really CUBE2",  file,
01164                                 naxis3, nchop);
01165         } 
01166 
01167         /* Load last INTERM frame */
01168         self = cpl_image_load(file, CPL_TYPE_FLOAT, naxis3-plane_offset, 0);
01169 
01170     }
01171 
01172     skip_if (0);
01173 
01174     end_skip;
01175 
01176     if (cpl_error_get_code()) {
01177         cpl_msg_warning(cpl_func, "Could not load the last INTERM frame from: "
01178                         "%s", file ? file : "<NULL>");
01179         cpl_image_delete(self);
01180         self = NULL;
01181     }
01182 
01183     return self;
01184 }
01185 
01186 /*----------------------------------------------------------------------------*/
01209 /*----------------------------------------------------------------------------*/
01210 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist * self) 
01211 {
01212     cpl_image * iprev;
01213     cpl_image * image;
01214     const int   n = cpl_imagelist_get_size(self);
01215     int         i;
01216 
01217 
01218     skip_if (0);
01219 
01220     if (n == 1) return CPL_ERROR_NONE;
01221 
01222     iprev = cpl_imagelist_get(self, n - 1);
01223 
01224     skip_if (0);
01225 
01226     skip_if (cpl_image_multiply_scalar(iprev, n));
01227 
01228     /* Loop on the images - with first and last iteration peeled off */
01229     for (i = n-1 ; i > 1 ; i--, iprev = image) {
01230         image = cpl_imagelist_get(self, i-1);
01231 
01232         skip_if (0);
01233 
01234         skip_if (cpl_image_multiply_scalar(image, i));
01235 
01236         skip_if (cpl_image_subtract(iprev, image));
01237 
01238     }
01239 
01240     image = cpl_imagelist_get(self, 0);
01241 
01242     skip_if (0);
01243 
01244     skip_if (cpl_image_subtract(iprev, image));
01245 
01246     end_skip;
01247 
01248     return cpl_error_get_code();
01249 }
01250 
01251 /*----------------------------------------------------------------------------*/
01264 /*----------------------------------------------------------------------------*/
01265 static cpl_error_code visir_rem_glitch(cpl_image * glitchy) 
01266 {
01267     cpl_image   *   med_filt = NULL;
01268     cpl_mask    *   bpm = NULL;
01269     cpl_matrix  *   kernel = NULL;
01270     double          mean, stdev;
01271     double          low_thresh, high_thresh;
01272     const int       nx = cpl_image_get_size_x(glitchy);
01273     const int       ny = cpl_image_get_size_y(glitchy);
01274     int             i;
01275 
01276     /* Some heuristic constants */
01277     double          factor1 = 3.0;
01278     double          factor2 = 10.0;
01279     const int       niterations = 5;
01280     const double    median_corr = 1.5;
01281 
01282 
01283     skip_if (0);
01284 
01285     /* Create the filtering kernel */
01286     kernel = cpl_matrix_new(3, 3);
01287     skip_if (cpl_matrix_fill(kernel, 1.0));
01288     
01289     /* Apply a 3x3 median filter to the input image  */
01290     med_filt = cpl_image_filter_median(glitchy, kernel);
01291     cpl_matrix_delete(kernel);
01292     kernel = NULL;
01293 
01294     /* Noise is glitchy - med_filt */
01295     skip_if (cpl_image_subtract(glitchy, med_filt));
01296 
01297     /* niterations iterations */
01298     for (i=0 ; i < niterations ; i++) {
01299         /* Compute mean and stdev */
01300         mean = cpl_image_get_mean(glitchy);
01301         stdev = cpl_image_get_stdev(glitchy);
01302         
01303         skip_if (0);
01304 
01305         /* Set the thresholds */
01306         low_thresh  = mean - factor1 * stdev;
01307         high_thresh = mean + factor1 * stdev;
01308 
01309         /* Identify where mean-factor1*stdev < glitchy < mean+factor1*stdev */
01310         bpm = cpl_mask_threshold_image_create(glitchy,low_thresh,high_thresh);
01311         skip_if (cpl_mask_not(bpm));
01312         skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01313         cpl_mask_delete(bpm);
01314         bpm = NULL;
01315 
01316         /* Test the number of bad pixels */
01317         skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01318     }
01319 
01320     /* Last iteration */
01321     /* Compute mean and stdev */
01322     mean = cpl_image_get_mean(glitchy);
01323     stdev = cpl_image_get_stdev(glitchy) * median_corr;
01324 
01325     skip_if (0);
01326 
01327     low_thresh  = mean - factor2 * stdev;
01328     high_thresh = mean + factor2 * stdev;
01329 
01330     bpm = cpl_mask_threshold_image_create(glitchy, low_thresh, high_thresh);
01331     skip_if (cpl_mask_not(bpm));
01332     skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01333     cpl_mask_delete(bpm);
01334     bpm = NULL;
01335 
01336     /* Test the number of bad pixels */
01337     skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01338     
01339     /* Set the bad pixels to 0 */
01340     skip_if (cpl_image_fill_rejected(glitchy, 0.0));
01341     skip_if (cpl_image_accept_all(glitchy));
01342 
01343     /* Reconstruct the corrected image */
01344     skip_if (cpl_image_add(glitchy, med_filt));
01345 
01346     end_skip;
01347 
01348     cpl_image_delete(med_filt);
01349     cpl_mask_delete(bpm);
01350     cpl_matrix_delete(kernel);
01351     
01352     return cpl_error_get_code();
01353 }
01354 
01355 /*----------------------------------------------------------------------------*/
01366 /*----------------------------------------------------------------------------*/
01367 static cpl_error_code visir_rem_bad_images(cpl_imagelist * in) 
01368 {
01369     cpl_vector * medians = NULL;
01370     cpl_vector * stdevs = NULL;
01371     cpl_vector * selection = NULL;
01372     double       mean_medians, mean_stdevs, stdev_medians, stdev_stdevs;
01373     const double threshold = 3;
01374     const int    nima = cpl_imagelist_get_size(in);
01375     int          i;
01376 
01377 
01378     /* This will catch a NULL input */
01379     skip_if (0);
01380 
01381     if (nima <= 3) return CPL_ERROR_NONE;
01382     
01383     /* Create medians and stdevs arrays */
01384     medians = cpl_vector_new(nima);
01385     stdevs = cpl_vector_new(nima);
01386 
01387     /* Compute the statistics */
01388     for (i=0 ; i < nima ; i++) {
01389         cpl_stats * stats = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
01390                                             CPL_STATS_STDEV | CPL_STATS_MEDIAN);
01391 
01392         cpl_vector_set(medians, i, cpl_stats_get_median(stats));
01393         cpl_vector_set(stdevs,  i, cpl_stats_get_stdev(stats));
01394         cpl_stats_delete(stats); /* :-( */
01395     }
01396 
01397     skip_if( 0);
01398 
01399     /* Get the stats on these arrays */
01400     mean_medians  = cpl_vector_get_mean(medians);
01401     stdev_medians = cpl_vector_get_stdev(medians);
01402     mean_stdevs   = cpl_vector_get_mean(stdevs);
01403     stdev_stdevs  = cpl_vector_get_stdev(stdevs);
01404 
01405     skip_if (cpl_vector_subtract_scalar(medians, mean_medians));
01406     skip_if (cpl_vector_subtract_scalar(stdevs,  mean_stdevs));
01407 
01408     stdev_medians *= threshold;
01409     stdev_stdevs  *= threshold;
01410 
01411     /* Create the selection vector */
01412     selection = cpl_vector_new(nima);
01413     skip_if( cpl_vector_fill(selection, 0)); /* Flag all as good */
01414     for (i=0 ; i < nima ; i++) {
01415         if (fabs(cpl_vector_get(medians, i)) <= stdev_medians &&
01416             fabs(cpl_vector_get(stdevs,  i)) <= stdev_stdevs) continue;
01417 
01418         cpl_vector_set(selection, i, -1);
01419         cpl_msg_info(cpl_func, "Image %d of %d rejected: median=%g, stdev=%g",
01420                      i+1, nima, stdev_medians, stdev_stdevs);
01421     }
01422 
01423     /* Purge the bad images in the images set */
01424     cpl_imagelist_erase(in, selection);
01425 
01426     end_skip;
01427 
01428     cpl_vector_delete(medians);
01429     cpl_vector_delete(stdevs);
01430     
01431     cpl_vector_delete(selection);
01432 
01433     return CPL_ERROR_NONE;
01434 
01435 }
01436 
01437 /*----------------------------------------------------------------------------*/
01446 /*----------------------------------------------------------------------------*/
01447 static cpl_error_code visir_offset_hcycle(cpl_image * hcycle) 
01448 {
01449     double minval;
01450 
01451 
01452     skip_if (0);
01453 
01454     skip_if (cpl_image_add_scalar(hcycle, VISIR_HCYCLE_OFFSET));
01455 
01456     minval = cpl_image_get_min(hcycle);
01457 
01458     /* It seems that the offset really is VISIR_HCYCLE_OFFSET-1, warn if not */
01459     if (minval < 1) cpl_msg_warning(cpl_func, "HCycle pixel minval: %g", minval);
01460 
01461     end_skip;
01462 
01463     return CPL_ERROR_NONE;
01464 }
01465 
01466 #include "visir_destripe.c"

Generated on Fri Jul 3 11:15:23 2009 for VISIR Pipeline Reference Manual by  doxygen 1.5.8