visir_inputs.c

00001 /* $Id: visir_inputs.c,v 1.129 2010/01/27 13:51:53 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: 2010/01/27 13:51:53 $
00024  * $Revision: 1.129 $
00025  * $Name: visir-3_3_1-public $
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_framelist.h"
00050 
00051 /*-----------------------------------------------------------------------------
00052                                    Define
00053  -----------------------------------------------------------------------------*/
00054 
00055 /* The values range from 0 (or 1) to 2**16-1 (or 2**16) */
00056 #define VISIR_HCYCLE_BPM_THRESHOLD  65000.0
00057 
00058 #ifndef VISIR_DESTRIPE_DETECT
00059 #define VISIR_DESTRIPE_DETECT           (3.5 * 1.64)
00060 #endif
00061 
00062 #ifndef VISIR_DESTRIPE_DETECT_THRESHOLD
00063 #define VISIR_DESTRIPE_DETECT_THRESHOLD 1.3
00064 #endif
00065 
00066 
00067 /*-----------------------------------------------------------------------------
00068                                    Functions prototypes
00069  -----------------------------------------------------------------------------*/
00070 
00071 #include "visir_destripe.h"
00072 
00073 static cpl_image * visir_load_average(const char *,
00074                                       const cpl_propertylist *);
00075 static cpl_imagelist * visir_load_intermint(const irplib_framelist *, int);
00076 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *);
00077 static cpl_error_code visir_rem_glitch(cpl_image *);
00078 static cpl_error_code visir_rem_bad_images(cpl_imagelist *); 
00079 static cpl_error_code visir_offset_hcycle(cpl_image *);
00080 
00081 /*----------------------------------------------------------------------------*/
00085 /*----------------------------------------------------------------------------*/
00086 
00089 /*----------------------------------------------------------------------------*/
00172 /*----------------------------------------------------------------------------*/
00173 cpl_imagelist * visir_inputs_combine(const char * recipename,
00174                                      const cpl_parameterlist * parlist,
00175                                      const irplib_framelist * rawframes,
00176                                      const char      *   badpix,
00177                                      const char      *   flat,
00178                                      int             *   nodding_p,
00179                                      cpl_boolean         do_spc_fix,
00180                                      double              wlen,
00181                                      visir_spc_resol resol)
00182 {
00183     const char       * fnodpos;
00184     int                nfiles;
00185     cpl_imagelist    * in = NULL;
00186     cpl_image        * collapsed = NULL;
00187     cpl_image        * prev = NULL;
00188     cpl_vector       * nods_vec = NULL;
00189     double           * nods_data;
00190     int              * nod_pos = NULL;
00191     cpl_image       ** images = NULL;
00192     cpl_imagelist    * nodded = NULL;
00193     int                nnod;
00194     cpl_image        * flat_image = NULL;
00195     cpl_image        * bpm_im_int = NULL;
00196     cpl_mask         * bpm_im_bin = NULL;
00197     cpl_imagelist    * hcycle = NULL;
00198     cpl_boolean        no_rem;
00199     cpl_boolean        is_nodding = CPL_FALSE;
00200     int                i, j;
00201     cpl_boolean        auto_bpm, rem_glitch, rem_bad;
00202     int                ndestripe;
00203     cpl_boolean        morpho_destripe;
00204 #ifdef _OPENMP
00205     double             tstart, tstop;
00206 #endif
00207     cpl_error_code     didfail = CPL_ERROR_NONE;
00208     cpl_errorstate     cleanstate = cpl_errorstate_get();
00209 
00210 
00211     skip_if (0);
00212     skip_if(recipename == NULL);
00213     skip_if(parlist    == NULL);
00214     skip_if(rawframes  == NULL);
00215     
00216     /* Get the number of files */
00217     nfiles = irplib_framelist_get_size(rawframes);
00218 
00219     /* There should be an even number of files */
00220     if (nfiles % 2) {
00221         if (nfiles == 1) {
00222             cpl_msg_error(cpl_func, "At least two files are required");
00223             skip_if (1);
00224         }
00225         cpl_msg_warning(cpl_func, "Expecting even number of files, "
00226                         "ignoring the last of %d files", nfiles);
00227         nfiles--;
00228     }
00229 
00230     nnod = nfiles/2;
00231 
00232     skip_if (nnod <= 0);
00233 
00234     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FRAME_TYPE,
00235                                        CPL_TYPE_STRING, CPL_FALSE, 0.0));
00236     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00237                                        CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00238     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00239                                        CPL_TYPE_INT, CPL_FALSE, 0.0));
00240     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00241                                        CPL_TYPE_INT, CPL_FALSE, 0.0));
00242 
00243 
00244     /* Retrieve input parameters */
00245     fnodpos = visir_parameterlist_get_string(parlist, recipename,
00246                                              VISIR_PARAM_NODPOS);
00247     skip_if (0);
00248 
00249     auto_bpm = visir_parameterlist_get_bool(parlist, recipename,
00250                                             VISIR_PARAM_AUTOBPM);
00251     skip_if (0);
00252 
00253     rem_glitch = visir_parameterlist_get_bool(parlist, recipename,
00254                                               VISIR_PARAM_GLITCH);
00255     skip_if (0);
00256 
00257     rem_bad = visir_parameterlist_get_bool(parlist, recipename,
00258                                            VISIR_PARAM_PURGE);
00259     skip_if (0);
00260 
00261     ndestripe = visir_parameterlist_get_int(parlist, recipename,
00262                                             VISIR_PARAM_STRIPITE);
00263     bug_if (0);
00264 
00265     morpho_destripe = ndestripe <= 0 ? CPL_FALSE :
00266         visir_parameterlist_get_bool(parlist, recipename,
00267                                      VISIR_PARAM_STRIPMOR);
00268     bug_if (0);
00269 
00270     no_rem = !rem_glitch && !rem_bad;
00271 
00272     /* Each file corresponds to a nodding position (object=1 or sky=-1) */
00273     /* Return nod_pos array if requested */
00274     nod_pos = nodding_p ? nodding_p : cpl_malloc(nfiles * sizeof(int));
00275     j = 0;
00276     if (fnodpos != NULL && strlen(fnodpos) > 0) {
00277         /* Get the nodding positions from the user-provided ascii file */
00278         nods_vec = cpl_vector_read(fnodpos);
00279         skip_if (cpl_vector_get_size(nods_vec) != nfiles);
00280         nods_data = cpl_vector_get_data(nods_vec);
00281         skip_if (0);
00282         for (i=0 ; i<nfiles ; i++) {
00283             if ((int)nods_data[i] == 0) {
00284                 nod_pos[i] = 1;
00285                 j++;
00286             } else if ((int)nods_data[i] == 1) {
00287                 nod_pos[i] = -1;
00288                 is_nodding = CPL_TRUE;
00289             } else {
00290                 cpl_msg_error(cpl_func, "Wrong values in line %d in %s", i+1,
00291                               fnodpos);
00292                 skip_if (1);
00293             }
00294         }
00295     } else {
00296         skip_if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_NODPOS,
00297                                             CPL_TYPE_STRING, CPL_FALSE, 0.0));
00298     }
00299 
00300     if (no_rem) cpl_msg_info(cpl_func, "No glitch removal and no purge of bad "
00301                              "frames requested: Using fast I/O method");
00302 
00303     /* Initialize the Bad Pixel Map */
00304     if (badpix != NULL) {
00305         /* The bpm is provided by the user */
00306         cpl_msg_info(cpl_func, "Loading bad pixel map from %s", badpix);
00307         /* Load the bad pixels image */
00308         bpm_im_int = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
00309         skip_if (0);
00310 
00311         /* Convert the map from integer to binary */
00312         bpm_im_bin = cpl_mask_threshold_image_create(bpm_im_int, -0.5, 0.5);
00313         cpl_image_delete(bpm_im_int);
00314         bpm_im_int = NULL;
00315         skip_if (cpl_mask_not(bpm_im_bin));
00316     } else if (auto_bpm) {
00317         /* Initialize the Bad Pixel Map using the hcycle */
00318 
00319         /* i == 0 */
00320         hcycle = visir_load_imagelist(rawframes, 0, CPL_FALSE);
00321         skip_if(0);
00322 
00323         bpm_im_bin =
00324             cpl_mask_threshold_image_create(cpl_imagelist_get(hcycle,0),
00325                                             VISIR_HCYCLE_BPM_THRESHOLD,
00326                                             DBL_MAX);
00327         cpl_imagelist_delete(hcycle);
00328         hcycle = NULL;
00329         skip_if(0);
00330     }
00331 
00332     /* Initialize the flat field image */
00333     if (flat != NULL) {
00334         cpl_msg_info(cpl_func, "Divide the nodded images by the flatfield");
00335         /* Load the flat image */
00336         if ((flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00337             cpl_msg_error(cpl_func, "Cannot load the flat field %s", flat);
00338             skip_if (1);
00339         }
00340     }
00341  
00342     /* Get nodding position (if needed) and DIT from the header */
00343     nodded = cpl_imagelist_new();
00344 
00345 #ifdef _OPENMP
00346     tstart = cpl_test_get_walltime();
00347 #endif
00348 
00349     /* Fill list with empty images of proper size and type */
00350 
00351     for (i=0; i < nfiles/2 ; i++) {
00352         /* FIXME: Use correct image size */
00353         cpl_image * empty = cpl_image_new(256, 256, CPL_TYPE_FLOAT);
00354 
00355         bug_if (cpl_imagelist_set(nodded, empty, i));
00356     }
00357 
00358 #ifdef _OPENMP
00359 #pragma omp parallel for private(i, prev, collapsed) schedule(static, 2)
00360 #endif
00361     for (i=0; i < nfiles ; i++) {
00362         const char * file =
00363             cpl_frame_get_filename(irplib_framelist_get_const(rawframes, i));
00364         const cpl_propertylist * plist;
00365 
00366         double dit;
00367         double factor;
00368 
00369 
00370         if (didfail) continue; /* FIXME: Verify with _OPENMP */
00371 
00372         plist = irplib_framelist_get_propertylist_const(rawframes, i);
00373         if (plist == NULL) {
00374             didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00375             irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00376             continue;
00377         }
00378 
00379         if (nods_vec == NULL) {
00380             const char * sval = visir_pfits_get_nodpos(plist);
00381             if (sval == NULL) {
00382                 cpl_msg_error(cpl_func, "Cannot get nodding pos for file %d",
00383                               i+1);
00384                 didfail = cpl_error_set(cpl_func, CPL_ERROR_UNSPECIFIED);
00385                 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00386                 continue;
00387             }
00388             if (!strcmp(sval, "A")) {
00389                 nod_pos[i] = 1;
00390                 j++;
00391             } else {
00392                 nod_pos[i] = -1;
00393                 is_nodding = CPL_TRUE;
00394             }
00395         }
00396 
00397         /* Print the file name with its nodding position */
00398         cpl_msg_info(cpl_func, "File %02d: %s (%c)", i+1, file,
00399                      nod_pos[i]==1 ? '+' : '-');
00400 
00401         /* With nodding each pair must have exactly one object observation */
00402         if (is_nodding && (i & 1) == 1 && nod_pos[i] == nod_pos[i-1]) {
00403             cpl_msg_error(cpl_func, "Nodding pair (%d,%d) does not comprise an "
00404                           "on-object (A) and an off-object (B) image: %s", i-1,
00405                           i, nod_pos[i] == 1 ? "A" : "B");
00406         }
00407 
00408         /* Compute the normalization factor from the Detector Integration Time */
00409         dit = visir_pfits_get_dit(plist);
00410         if (cpl_error_get_code()) {
00411             didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00412             irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00413             continue;
00414         }
00415 
00416         if (dit <= 0) {
00417             cpl_msg_error(cpl_func, "DIT in file %d is too small: %g", i+1, dit);
00418             didfail = cpl_error_set(cpl_func, CPL_ERROR_UNSPECIFIED);
00419             irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00420             continue;
00421         }
00422 
00423         factor = dit * nod_pos[i] * 2.0;
00424 
00425         if (no_rem){
00426             collapsed = visir_load_average(file, plist);
00427         } else {
00428             in = visir_load_intermint(rawframes, i);
00429             if (in == NULL) {
00430                 cpl_msg_error(cpl_func, "Cannot load the image set %d", i+1);
00431                 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00432                 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00433                 continue;
00434             }
00435 
00436 
00437             /* Convert the image lists from 'INTERM' to A-B' */
00438             if (visir_imagelist_unpack_interm(in)) {
00439                 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00440                 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00441                 continue;
00442             }
00443 
00444             /* Remove the glitch in each A-B image in each input cube
00445                if requested */
00446             if (rem_glitch) {
00447                 int jj;
00448                 for (jj=0 ; jj < cpl_imagelist_get_size(in); jj++) {
00449                     if (visir_rem_glitch(cpl_imagelist_get(in, jj))) {
00450                         cpl_msg_error(cpl_func,  "Cannot remove glitch in image "
00451                                       "%d in set %d", jj+1, i+1);
00452                         didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00453                         irplib_error_recover(cleanstate, "Failure for file %d",
00454                                              i+1);
00455                         continue;
00456                     }
00457                 }
00458             }
00459 
00460             /* Remove the bad A-B images in each input file/cube if requested */
00461             if (rem_bad) {
00462                 cpl_msg_info(cpl_func, "Remove the bad A-B input images");
00463                 if (visir_rem_bad_images(in)) {
00464                     cpl_msg_error(cpl_func, "Cannot remove bad images in list "
00465                                   "%d", i+1);
00466                     didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00467                     irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00468                     continue;
00469                 }
00470             }
00471             /* Average each cube */
00472             collapsed = cpl_imagelist_collapse_create(in);
00473 
00474             cpl_imagelist_delete(in);
00475             in = NULL;
00476 
00477         }
00478 
00479         if (cpl_error_get_code()) {
00480             didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00481             irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00482             continue;
00483         }
00484         /* Normalise to have ADU/s. */
00485         /* Also divide with 2 to achieve average of image pair */
00486         if (cpl_image_divide_scalar(collapsed, 2*factor)) {
00487             didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00488             irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00489             continue;
00490         }
00491 
00492         /* Each pair of input files gives a nodded image in nodded */
00493         if (i & 1) {
00494             if (cpl_image_add(prev, collapsed)) {
00495                 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00496                 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00497                 continue;
00498             }
00499             cpl_image_delete(collapsed);
00500             collapsed = NULL;
00501 
00502             /* At this point prev is the image to be put into
00503                the list of nodded images */
00504 
00505             if (bpm_im_bin != NULL) {
00506                 /* Apply the bad pixels cleaning */
00507                 if (cpl_image_reject_from_mask(prev, bpm_im_bin)) {
00508                     didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00509                     irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00510                     continue;
00511                 }
00512                 if (cpl_detector_interpolate_rejected(prev)) {
00513                     didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00514                     irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00515                     continue;
00516                 }
00517             }
00518 
00519             if (ndestripe > 0)
00520                 if(visir_destripe_image(prev, ndestripe,
00521                                              VISIR_DESTRIPE_DETECT,
00522                                              VISIR_DESTRIPE_DETECT_THRESHOLD,
00523                                         morpho_destripe)) {
00524                     didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00525                     irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00526                     continue;
00527                 }
00528 
00529             if (flat_image != NULL) {
00530                 /* Apply the flatfield correction */
00531                 if (cpl_image_divide(prev, flat_image)) {
00532                     didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00533                     irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00534                     continue;
00535                 }
00536             }
00537 
00538             if (cpl_imagelist_set(nodded, prev, i/2)) {
00539                 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00540                 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00541                 continue;
00542             }
00543             prev = NULL;
00544         } else {
00545             prev = collapsed;
00546             collapsed = NULL;
00547         }
00548     }
00549 
00550     skip_if(didfail);
00551 
00552 #ifdef _OPENMP
00553     tstop = cpl_test_get_walltime();
00554 
00555     cpl_msg_info(cpl_func, "Time to create %d nodded images [s]: %g", nnod,
00556                  tstop - tstart);
00557 #endif
00558 
00559     cpl_vector_delete(nods_vec);
00560     nods_vec = NULL;
00561 
00562     cpl_image_delete(flat_image);
00563     flat_image = NULL;
00564 
00565     cpl_mask_delete(bpm_im_bin);
00566     bpm_im_bin = NULL;
00567 
00568     if (nod_pos != nodding_p) cpl_free(nod_pos);
00569     nod_pos = NULL;
00570     
00571     if (is_nodding && j != nnod) {
00572         cpl_msg_error(cpl_func, "With nodding exactly half of the images "
00573                       "must be on-object, not %d of %d", j, 2*nnod);
00574         skip_if (1);
00575     }
00576 
00577     if (do_spc_fix) {
00578         const double ksi   = visir_parameterlist_get_double(parlist, recipename,
00579                                                           VISIR_PARAM_SPECSKEW);
00580         const double eps   = visir_parameterlist_get_double(parlist, recipename,
00581                                                             VISIR_PARAM_VERTARC);
00582         const double delta = visir_parameterlist_get_double(parlist, recipename,
00583                                                             VISIR_PARAM_HORIARC);
00584         const double phi   = visir_parameterlist_get_double(parlist, recipename,
00585                                                           VISIR_PARAM_SLITSKEW);
00586         const int doplot   = visir_parameterlist_get_int(parlist, recipename,
00587                                                          VISIR_PARAM_PLOT);
00588 
00589 
00590         skip_if (0);
00591 
00592         images = cpl_malloc(nnod * sizeof(cpl_image*));
00593 
00594         for (j = 0; j < nnod; j++) images[j] = cpl_imagelist_get(nodded, j);
00595 
00596         skip_if (visir_spc_det_fix(images, nnod, CPL_TRUE, wlen, resol,
00597                                    phi, ksi, eps, delta, doplot));
00598     }
00599 
00600     end_skip;
00601 
00602     cpl_msg_set_time_off();
00603 
00604     cpl_free(images);
00605     cpl_imagelist_delete(in);
00606 
00607     if (nod_pos != nodding_p) cpl_free(nod_pos);
00608     cpl_vector_delete(nods_vec);
00609     cpl_image_delete(bpm_im_int);
00610     cpl_mask_delete(bpm_im_bin);
00611     cpl_image_delete(collapsed);
00612     cpl_image_delete(prev);
00613     if (cpl_error_get_code() && nodded != NULL) {
00614         cpl_imagelist_delete(nodded);
00615         nodded = NULL;
00616     }
00617 
00618     return nodded;
00619 }
00620 
00621 /*----------------------------------------------------------------------------*/
00668 /*----------------------------------------------------------------------------*/
00669 cpl_image ** visir_img_recombine(const char * recipename,
00670                                  const cpl_parameterlist * parlist,
00671                                  const irplib_framelist  * rawframes,
00672                                  const char        * badpix,
00673                                  const char        * flat,
00674                                  cpl_geom_combine    combine_mode,
00675                                  cpl_boolean       * pdid_resize,
00676                                  cpl_boolean         do_spc_fix,
00677                                  double              wlen,
00678                                  visir_spc_resol     resol)
00679 {
00680     int                     nfiles;
00681     int                 *   nod_pos = NULL;
00682     cpl_imagelist       *   nodded = NULL;
00683     int                     nnod;
00684     cpl_bivector        *   offsets_est = NULL;
00685     cpl_bivector        *   objs = NULL;
00686     cpl_image           **  combined = NULL;
00687     const cpl_vector    *   sigmas = NULL;
00688     double                  xoff, yoff;
00689     int                     i;
00690 
00691 
00692     bug_if (0);
00693 
00694     bug_if (recipename == NULL);
00695     bug_if (parlist    == NULL);
00696     bug_if (rawframes  == NULL);
00697     bug_if (pdid_resize  == NULL);
00698 
00699     /* Get the number of files */
00700     nfiles = irplib_framelist_get_size(rawframes);
00701 
00702     /* There should be an even number of files */
00703     if (nfiles % 2) {
00704         if (nfiles == 1) {
00705             cpl_msg_error(cpl_func, "At least two files are required");
00706             skip_if (1);
00707         }
00708         cpl_msg_warning(cpl_func, "Expecting even number of files, "
00709                         "ignoring the last of %d files", nfiles);
00710         nfiles--;
00711     }
00712 
00713     skip_if ( nfiles <= 0);
00714 
00715     /* Each file corresponds to a nodding position (object=1 or sky=-1) */
00716     nod_pos = cpl_malloc(nfiles * sizeof(int));
00717 
00718     /* Combine the input frames into the nodded images */
00719     cpl_msg_info(cpl_func, "Combining the input frames into the nodded images");
00720     nodded = visir_inputs_combine(recipename, parlist, rawframes, badpix, flat,
00721                                   nod_pos, do_spc_fix, wlen, resol);
00722 
00723     skip_if (nodded == NULL);
00724     nnod = cpl_imagelist_get_size(nodded);
00725 
00726     /* If only one nodded image, the work is finished */
00727     if (nnod == 1) {
00728 
00729         combined = cpl_malloc(2*sizeof(cpl_image*)); 
00730         combined[1] = NULL; /* In case the unset fails */
00731 
00732         combined[0] = cpl_imagelist_unset(nodded, 0);
00733         bug_if (combined[0] == NULL);
00734 
00735         combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
00736                                     cpl_image_get_size_y(combined[0]),
00737                                     CPL_TYPE_INT);
00738         bug_if (combined[1] == NULL);
00739 
00740         /* Set all pixel values to 1 */
00741         bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
00742 
00743         *pdid_resize = CPL_FALSE;
00744 
00745     } else {
00746         const double psigmas[] = {5, 2, 1, 0.5};
00747         const char * sval;
00748         const char * offsets;
00749         const char * objects;
00750         int sx, sy, mx, my;
00751         int rej_low, rej_high;
00752         cpl_boolean refine;
00753 
00754 
00755         refine = visir_parameterlist_get_bool(parlist, recipename,
00756                                               VISIR_PARAM_REFINE);
00757         skip_if (0);
00758 
00759         offsets = visir_parameterlist_get_string(parlist, recipename,
00760                                                  VISIR_PARAM_OFFSETS);
00761         skip_if (0);
00762 
00763         objects = visir_parameterlist_get_string(parlist, recipename,
00764                                                  VISIR_PARAM_OBJECTS);
00765         skip_if (0);
00766 
00767         sval = visir_parameterlist_get_string(parlist, recipename,
00768                                               VISIR_PARAM_XCORR);
00769         skip_if (0);
00770 
00771         skip_if (sscanf(sval, "%d %d %d %d", &sx, &sy, &mx, &my) != 4);
00772 
00773         sval = visir_parameterlist_get_string(parlist, recipename,
00774                                               VISIR_PARAM_REJECT);
00775         skip_if (0);
00776 
00777         skip_if (sscanf(sval, "%d %d", &rej_low, &rej_high) !=2 );
00778 
00779         /* Get the offsets estimation of each input file pair */
00780         cpl_msg_info(cpl_func, "Get the offsets estimation");
00781         if (offsets != NULL && strlen(offsets)) {
00782             /* A file has been provided on the command line */
00783             offsets_est = cpl_bivector_read(offsets);
00784             skip_if (offsets_est==NULL);
00785 
00786             if (cpl_bivector_get_size(offsets_est) != nnod) {
00787                 cpl_msg_error(cpl_func, "The offsets file %s must have %d "
00788                               "entries, not %d", offsets, nnod,
00789                               cpl_bivector_get_size(offsets_est));
00790                 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
00791                 skip_if (1);
00792             }
00793         } else {
00794             double * offsets_est_x;
00795             double * offsets_est_y;
00796             double   xoff0 = 0.0;  /* Avoid (false) uninit warning */
00797             double   yoff0 = 0.0;  /* Avoid (false) uninit warning */
00798             
00799             /* Get the offsets from the header */
00800             offsets_est = cpl_bivector_new(nnod);
00801             offsets_est_x = cpl_bivector_get_x_data(offsets_est);
00802             offsets_est_y = cpl_bivector_get_y_data(offsets_est);
00803 
00804             skip_if (0);
00805 
00806             offsets_est_x[0] = 0.0;
00807             offsets_est_y[0] = 0.0;
00808 
00809             for (i=0; i < nnod ; i++) {
00810                 const cpl_propertylist * plist;
00811 
00812                 /* Skip every other, non-object frame */ 
00813                 const int iframe = nod_pos[2*i] == 1 ? 2*i : 2*i+1;
00814 
00815                 plist = irplib_framelist_get_propertylist_const(rawframes,
00816                                                                 iframe);
00817                 skip_if(plist == NULL);
00818 
00819                 xoff = visir_pfits_get_cumoffsetx(plist);
00820                 yoff = visir_pfits_get_cumoffsety(plist);
00821 
00822                 skip_if (0);
00823 
00824                 if (i == 0) {
00825                     xoff0 = xoff;
00826                     yoff0 = yoff;
00827                 } else {
00828                     /* Subtract the first offset from all offsets */
00829                     offsets_est_x[i] = xoff0 - xoff;
00830                     offsets_est_y[i] = yoff0 - yoff;
00831                 }
00832             }
00833         }
00834         cpl_free(nod_pos);
00835         nod_pos = NULL;
00836     
00837         /* Read the provided objects file if provided
00838            - if a file has been provided on the command line */
00839         if (objects != NULL && strlen(objects) > 0 && 
00840             (objs = cpl_bivector_read(objects)) == NULL) {
00841             cpl_msg_error(cpl_func, "Could not read objects from %s", objects);
00842             skip_if (1);
00843         }
00844    
00845         cpl_msg_info(cpl_func, "Recombining the list of nodded images using "
00846                      "mode: %d (I=%d:U=%d:F=%d), rej-lo=%d, rej-hi=%d",
00847                      combine_mode, CPL_GEOM_INTERSECT, CPL_GEOM_UNION,
00848                      CPL_GEOM_FIRST, rej_low, rej_high);
00849 
00850         if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00851             cpl_msg_debug(cpl_func, "The offsets for the recombination:");
00852             cpl_bivector_dump(offsets_est, stdout);
00853         }
00854 
00855         sigmas = cpl_vector_wrap(4, (double*)psigmas); /* Not changed */
00856         combined = cpl_geom_img_offset_combine(nodded, offsets_est, refine,
00857                                                objs, sigmas, NULL, sx, sy,
00858                                                mx, my, rej_low, rej_high,
00859                                                combine_mode);
00860         if (combined == NULL) {
00861             cpl_msg_error(cpl_func, "Could not recombine the images");
00862             skip_if(1);
00863         }
00864 
00865         *pdid_resize = (cpl_boolean)(cpl_image_get_size_x(combined[0])
00866                 != cpl_image_get_size_x(cpl_imagelist_get_const(nodded, 0)) ||
00867                 cpl_image_get_size_y(combined[0])
00868                 != cpl_image_get_size_y(cpl_imagelist_get_const(nodded, 0)));
00869     }
00870 
00871     if (visir_parameterlist_get_int(parlist, recipename, VISIR_PARAM_PLOT) > 0)
00872         visir_image_plot("", "t 'The combined image'", "", combined[0]);
00873 
00874     end_skip;
00875 
00876     cpl_free(nod_pos);
00877     cpl_imagelist_delete(nodded);
00878     cpl_bivector_delete(offsets_est);
00879     cpl_bivector_delete(objs);
00880     cpl_vector_unwrap((cpl_vector*)sigmas);
00881 
00882     return combined;
00883 }
00884 
00885 /*----------------------------------------------------------------------------*/
00908 /*----------------------------------------------------------------------------*/
00909 cpl_imagelist * visir_load_hcycle(const irplib_framelist * rawframes, int pos)
00910 {
00911     return visir_load_imagelist(rawframes, pos, CPL_FALSE);
00912 }
00913 
00914 /*----------------------------------------------------------------------------*/
00925 /*----------------------------------------------------------------------------*/
00926 cpl_error_code visir_image_reject_hot(cpl_image * self, const char * bpmfile)
00927 {
00928 
00929     cpl_image  * im_bpm = NULL;
00930     cpl_mask   * bpm = NULL;
00931     const int upper = VISIR_HCYCLE_BPM_THRESHOLD;
00932 
00933 
00934     skip_if (0);
00935 
00936     skip_if (self == NULL);
00937 
00938     if (bpmfile == NULL) {
00939         bpm = cpl_mask_threshold_image_create(self, upper, DBL_MAX);
00940         skip_if (0);
00941     } else {
00942 
00943         /* The bpm is provided by the user */
00944         cpl_msg_info(cpl_func, "Clean user specified bad pixels");
00945         /* Load the bad pixel image */
00946         im_bpm = cpl_image_load(bpmfile, CPL_TYPE_INT, 0, 0);
00947         if (cpl_error_get_code()) {
00948             cpl_msg_error(cpl_func,"Cannot load the bad pixel map %s", bpmfile);
00949             skip_if (1);
00950         }
00951         /* Convert the map from integer to binary */
00952         bpm = cpl_mask_threshold_image_create(im_bpm, -0.5, 0.5);
00953         skip_if (0);
00954         cpl_image_delete(im_bpm);
00955         im_bpm = NULL;
00956 
00957         skip_if (cpl_mask_not(bpm));
00958     }
00959 
00960     skip_if (cpl_image_reject_from_mask(self, bpm));
00961 
00962     end_skip;
00963 
00964     cpl_image_delete(im_bpm);
00965     cpl_mask_delete(bpm);
00966 
00967     return cpl_error_get_code();
00968 
00969 }
00970 
00971 
00972 /*----------------------------------------------------------------------------*/
00979 /*----------------------------------------------------------------------------*/
00980 cpl_imagelist * visir_imagelist_load_last(const irplib_framelist * rawframes)
00981 {
00982     cpl_imagelist * self = NULL;
00983     int naxis3;
00984 
00985     /* Verify that NAXIS3 is the same in all files */
00986     skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00987                                       CPL_TYPE_INT, CPL_TRUE, 0.0));
00988 
00989     naxis3 = visir_pfits_get_naxis3(irplib_framelist_get_propertylist_const(
00990                                                                       rawframes,
00991                                                                       0));
00992 
00993     /* Load the image set */
00994     self = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, naxis3-1,
00995                                            0);
00996 
00997     skip_if (self == NULL);
00998 
00999     end_skip;
01000 
01001     return self;
01002 
01003 }
01004 
01005 
01006 /*----------------------------------------------------------------------------*/
01016 /*----------------------------------------------------------------------------*/
01017 cpl_imagelist * visir_load_imagelist(const irplib_framelist * rawframes,
01018                                      int pos, cpl_boolean is_interm)
01019 {
01020     cpl_errorstate cleanstate = cpl_errorstate_get();
01021     cpl_imagelist    * self = NULL;
01022     cpl_image        * image = NULL;
01023     const char       * file = NULL;
01024     const cpl_propertylist * plist;
01025     int                nchop, naxis3;
01026 
01027 
01028     /* Check the error code */
01029     skip_if (0);
01030 
01031     skip_if (rawframes == NULL);
01032 
01033     file = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
01034     skip_if (file == NULL);
01035 
01036     /* First check if there is no chopping */
01037     plist = irplib_framelist_get_propertylist_const(rawframes, pos);
01038     skip_if (plist == NULL);
01039 
01040     naxis3 = visir_pfits_get_naxis3(plist);
01041     nchop = visir_pfits_get_chop_ncycles(plist);
01042 
01043     skip_if (0);
01044 
01045     if (nchop == 0 && naxis3 == 1 && is_interm) {
01046         self = cpl_imagelist_load(file, CPL_TYPE_FLOAT, 0);
01047     } else {
01048         const char   * sval;
01049         /* If nchop == 1 (and naxis3 == 3) the data unit is both a valid CUBE1
01050            and a valid CUBE2; Set plane_step as if the frame type is CUBE2 */
01051         const int      plane_step = (naxis3 == 2 * nchop + 1) ? 2 : 1;
01052         const cpl_type pixel_type = CPL_TYPE_FLOAT;
01053         int            nsize;
01054         int            iplane;
01055         int            i;
01056 
01057 
01058         if (nchop <= 0) {
01059             cpl_msg_error(cpl_func, "CHOP NCYCLES in %s is non-positive (and "
01060                           "NAXIS3=%d): %d", file, naxis3, nchop);
01061             visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01062             skip_if (1);
01063         }
01064 
01065         if (plane_step == 1 && naxis3 != nchop+2) {
01066             cpl_msg_error(cpl_func, "NAXIS3=%d and CHOP NCYCLES=%d in %s is "
01067                           "not a valid VISIR INTERM+Half-Cycle format", naxis3,
01068                           nchop, file);
01069             visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01070             skip_if (1);
01071         }
01072 
01073         if (plane_step == 1 && nchop > 1)
01074             cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01075                           "Cycle frame (old CUBE1-format)", file, nchop);
01076 
01077         /* Check the data format */
01078         sval = visir_pfits_get_frame_type(plist);
01079         if (sval == NULL) {
01080             /* Has warned about missing frame type card */
01081             visir_error_reset("Could not get FITS key");
01082             /* Don't know whether or not to expect CUBE1 or CUBE2 */
01083         } else if (strlen(sval) == 0) {
01084             /* Don't know whether or not to expect CUBE1 or CUBE2 */
01085         } else if (plane_step == 1) {
01086             if (strcmp(sval, "CUBE2")==0)
01087                 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
01088                                 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01089                                 " the frame type is really CUBE1",  file,
01090                                 naxis3, nchop);
01091         } else if (nchop > 1) {
01092             /* if nchop == 1 format can be CUBE1 or CUBE2 */
01093             if (strcmp(sval, "CUBE1")==0)
01094                 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01095                                 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01096                                 " the frame type is really CUBE2",  file,
01097                                 naxis3, nchop);
01098         } 
01099 
01100         self = cpl_imagelist_new();
01101 
01102         if (plane_step == 1) {
01103             /* All INTERM frames are in the first part of the cube */
01104             iplane = is_interm ? 0 : nchop;
01105             /* - followed by a single Half-cycle image */
01106             nsize  = is_interm ? nchop : 1;
01107         } else {
01108             /* Each INTERM frame follows the Half-cycle frame */
01109             iplane = is_interm ? 1 : 0;
01110             nsize  = nchop;
01111         }
01112 
01113         for (i=0 ; i < nsize; i++, iplane += plane_step) {
01114 
01115             image = cpl_image_load(file, pixel_type, iplane, 0);
01116             skip_if (image == NULL);
01117 
01118             skip_if (!is_interm && visir_offset_hcycle(image));
01119 
01120             skip_if (cpl_imagelist_set(self, image, i));
01121 
01122             image = NULL;
01123         }
01124 
01125         skip_if (i < nsize);
01126     }
01127 
01128     end_skip;
01129 
01130     if (cpl_error_get_code()) {
01131         if (file != NULL) cpl_msg_warning(cpl_func, "Could not load the %s "
01132                                           "frame(s) from: %s",
01133                                           is_interm ? "INTERM" : "Half-Cycle",
01134                                           file);
01135         cpl_image_delete(image);
01136         cpl_imagelist_delete(self);
01137         self = NULL;
01138     }
01139 
01140     return self;
01141 }
01142 
01143 
01146 /*----------------------------------------------------------------------------*/
01170 /*----------------------------------------------------------------------------*/
01171 static cpl_imagelist * visir_load_intermint(const irplib_framelist * rawframes,
01172                                             int pos)
01173 {
01174     return visir_load_imagelist(rawframes, pos, CPL_TRUE);
01175 
01176 }
01177 
01178 /*----------------------------------------------------------------------------*/
01187 /*----------------------------------------------------------------------------*/
01188 static cpl_image * visir_load_average(const char * file,
01189                                       const cpl_propertylist * plist)
01190 {
01191     cpl_errorstate cleanstate = cpl_errorstate_get();
01192     cpl_image        * self = NULL;
01193     int                nchop, naxis3;
01194 
01195 
01196     skip_if (0);
01197     skip_if (file   == NULL);
01198     skip_if (plist == NULL);
01199 
01200     naxis3 = visir_pfits_get_naxis3(plist);
01201     nchop = visir_pfits_get_chop_ncycles(plist);
01202 
01203     skip_if (0);
01204 
01205     if (nchop == 0 && naxis3 == 1) {
01206         self = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
01207     } else {
01208         const char   * sval;
01209         /* If nchop == 1 (and naxis3 == 3) the data unit is both a valid CUBE1
01210            and a valid CUBE2; Set plane_offset as if the frame type is CUBE2 */
01211         const int      plane_offset = (naxis3 == 2 * nchop + 1) ? 2 : 3;
01212 
01213 
01214         if (nchop <= 0) {
01215             cpl_msg_error(cpl_func, "CHOP NCYCLES in %s is non-positive (and "
01216                           "NAXIS3=%d): %d", file, naxis3, nchop);
01217             visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01218             skip_if (1);
01219         }
01220 
01221         if (plane_offset == 3 && naxis3 != nchop+2) {
01222             cpl_msg_error(cpl_func, "NAXIS3=%d and CHOP NCYCLES=%d in %s is "
01223                           "not a valid VISIR INTERM+Half-Cycle format", naxis3,
01224                           nchop, file);
01225             visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01226             skip_if (1);
01227         }
01228 
01229         if (plane_offset == 3 && nchop > 1)
01230             cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01231                           "Cycle frame (old CUBE1-format)", file, nchop);
01232 
01233         /* Check the data format */
01234         sval = visir_pfits_get_frame_type(plist);
01235         if (sval == NULL) {
01236             /* Has warned about missing frame type card */
01237             visir_error_reset("Could not get FITS key");
01238             /* Don't know whether or not to expect CUBE1 or CUBE2 */
01239         } else if (strlen(sval) == 0) {
01240             /* Don't know whether or not to expect CUBE1 or CUBE2 */
01241         } else if (plane_offset == 3) {
01242             if (strcmp(sval, "CUBE2")==0)
01243                 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
01244                                 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01245                                 " the frame type is really CUBE1",  file,
01246                                 naxis3, nchop);
01247         } else if (nchop > 1) {
01248             /* if nchop == 1 format can be CUBE1 or CUBE2 */
01249             if (strcmp(sval, "CUBE1")==0)
01250                 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01251                                 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01252                                 " the frame type is really CUBE2",  file,
01253                                 naxis3, nchop);
01254         } 
01255 
01256         /* Load last INTERM frame */
01257         self = cpl_image_load(file, CPL_TYPE_FLOAT, naxis3-plane_offset, 0);
01258 
01259     }
01260 
01261     skip_if (0);
01262 
01263     end_skip;
01264 
01265     if (cpl_error_get_code()) {
01266         cpl_msg_warning(cpl_func, "Could not load the last INTERM frame from: "
01267                         "%s", file ? file : "<NULL>");
01268         cpl_image_delete(self);
01269         self = NULL;
01270     }
01271 
01272     return self;
01273 }
01274 
01275 /*----------------------------------------------------------------------------*/
01298 /*----------------------------------------------------------------------------*/
01299 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist * self) 
01300 {
01301     cpl_image * iprev;
01302     cpl_image * image;
01303     const int   n = cpl_imagelist_get_size(self);
01304     int         i;
01305 
01306 
01307     skip_if (0);
01308 
01309     if (n == 1) return CPL_ERROR_NONE;
01310 
01311     iprev = cpl_imagelist_get(self, n - 1);
01312 
01313     skip_if (0);
01314 
01315     skip_if (cpl_image_multiply_scalar(iprev, n));
01316 
01317     /* Loop on the images - with first and last iteration peeled off */
01318     for (i = n-1 ; i > 1 ; i--, iprev = image) {
01319         image = cpl_imagelist_get(self, i-1);
01320 
01321         skip_if (0);
01322 
01323         skip_if (cpl_image_multiply_scalar(image, i));
01324 
01325         skip_if (cpl_image_subtract(iprev, image));
01326 
01327     }
01328 
01329     image = cpl_imagelist_get(self, 0);
01330 
01331     skip_if (0);
01332 
01333     skip_if (cpl_image_subtract(iprev, image));
01334 
01335     end_skip;
01336 
01337     return cpl_error_get_code();
01338 }
01339 
01340 /*----------------------------------------------------------------------------*/
01353 /*----------------------------------------------------------------------------*/
01354 static cpl_error_code visir_rem_glitch(cpl_image * glitchy) 
01355 {
01356     cpl_image * med_filt = NULL;
01357     cpl_mask  * bpm = NULL;
01358     cpl_mask  * kernel = cpl_mask_new(3, 3);
01359     double      mean, stdev;
01360     double      low_thresh, high_thresh;
01361     const int   nx = cpl_image_get_size_x(glitchy);
01362     const int   ny = cpl_image_get_size_y(glitchy);
01363     int         i;
01364 
01365     /* Some heuristic constants */
01366     double          factor1 = 3.0;
01367     double          factor2 = 10.0;
01368     const int       niterations = 5;
01369     const double    median_corr = 1.5;
01370 
01371     bug_if (0);
01372 
01373     /* Create the filtering kernel */
01374     bug_if(cpl_mask_not(kernel));
01375     
01376     /* Apply a 3x3 median filter to the input image  */
01377     med_filt = cpl_image_new(cpl_image_get_size_x(glitchy),
01378                              cpl_image_get_size_y(glitchy),
01379                              cpl_image_get_type(glitchy));
01380     bug_if(med_filt == NULL);
01381     bug_if(cpl_image_filter_mask(med_filt, glitchy, kernel, CPL_FILTER_MEDIAN,
01382                                  CPL_BORDER_FILTER));
01383     cpl_mask_delete(kernel);
01384     kernel = NULL;
01385 
01386     /* Noise is glitchy - med_filt */
01387     skip_if (cpl_image_subtract(glitchy, med_filt));
01388 
01389     /* niterations iterations */
01390     for (i=0 ; i < niterations ; i++) {
01391         /* Compute mean and stdev */
01392         mean = cpl_image_get_mean(glitchy);
01393         stdev = cpl_image_get_stdev(glitchy);
01394         
01395         skip_if (0);
01396 
01397         /* Set the thresholds */
01398         low_thresh  = mean - factor1 * stdev;
01399         high_thresh = mean + factor1 * stdev;
01400 
01401         /* Identify where mean-factor1*stdev < glitchy < mean+factor1*stdev */
01402         bpm = cpl_mask_threshold_image_create(glitchy,low_thresh,high_thresh);
01403         skip_if (cpl_mask_not(bpm));
01404         skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01405         cpl_mask_delete(bpm);
01406         bpm = NULL;
01407 
01408         /* Test the number of bad pixels */
01409         skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01410     }
01411 
01412     /* Last iteration */
01413     /* Compute mean and stdev */
01414     mean = cpl_image_get_mean(glitchy);
01415     stdev = cpl_image_get_stdev(glitchy) * median_corr;
01416 
01417     skip_if (0);
01418 
01419     low_thresh  = mean - factor2 * stdev;
01420     high_thresh = mean + factor2 * stdev;
01421 
01422     bpm = cpl_mask_threshold_image_create(glitchy, low_thresh, high_thresh);
01423     skip_if (cpl_mask_not(bpm));
01424     skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01425     cpl_mask_delete(bpm);
01426     bpm = NULL;
01427 
01428     /* Test the number of bad pixels */
01429     skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01430     
01431     /* Set the bad pixels to 0 */
01432     skip_if (cpl_image_fill_rejected(glitchy, 0.0));
01433     skip_if (cpl_image_accept_all(glitchy));
01434 
01435     /* Reconstruct the corrected image */
01436     skip_if (cpl_image_add(glitchy, med_filt));
01437 
01438     end_skip;
01439 
01440     cpl_image_delete(med_filt);
01441     cpl_mask_delete(bpm);
01442     cpl_mask_delete(kernel);
01443     
01444     return cpl_error_get_code();
01445 }
01446 
01447 /*----------------------------------------------------------------------------*/
01458 /*----------------------------------------------------------------------------*/
01459 static cpl_error_code visir_rem_bad_images(cpl_imagelist * in) 
01460 {
01461     cpl_vector * medians = NULL;
01462     cpl_vector * stdevs = NULL;
01463     cpl_vector * selection = NULL;
01464     double       mean_medians, mean_stdevs, stdev_medians, stdev_stdevs;
01465     const double threshold = 3;
01466     const int    nima = cpl_imagelist_get_size(in);
01467     int          i;
01468 
01469 
01470     /* This will catch a NULL input */
01471     skip_if (0);
01472 
01473     if (nima <= 3) return CPL_ERROR_NONE;
01474     
01475     /* Create medians and stdevs arrays */
01476     medians = cpl_vector_new(nima);
01477     stdevs = cpl_vector_new(nima);
01478 
01479     /* Compute the statistics */
01480     for (i=0 ; i < nima ; i++) {
01481         cpl_stats * stats = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
01482                                             CPL_STATS_STDEV | CPL_STATS_MEDIAN);
01483 
01484         cpl_vector_set(medians, i, cpl_stats_get_median(stats));
01485         cpl_vector_set(stdevs,  i, cpl_stats_get_stdev(stats));
01486         cpl_stats_delete(stats); /* :-( */
01487     }
01488 
01489     skip_if( 0);
01490 
01491     /* Get the stats on these arrays */
01492     mean_medians  = cpl_vector_get_mean(medians);
01493     stdev_medians = cpl_vector_get_stdev(medians);
01494     mean_stdevs   = cpl_vector_get_mean(stdevs);
01495     stdev_stdevs  = cpl_vector_get_stdev(stdevs);
01496 
01497     skip_if (cpl_vector_subtract_scalar(medians, mean_medians));
01498     skip_if (cpl_vector_subtract_scalar(stdevs,  mean_stdevs));
01499 
01500     stdev_medians *= threshold;
01501     stdev_stdevs  *= threshold;
01502 
01503     /* Create the selection vector */
01504     selection = cpl_vector_new(nima);
01505     skip_if( cpl_vector_fill(selection, 0)); /* Flag all as good */
01506     for (i=0 ; i < nima ; i++) {
01507         if (fabs(cpl_vector_get(medians, i)) <= stdev_medians &&
01508             fabs(cpl_vector_get(stdevs,  i)) <= stdev_stdevs) continue;
01509 
01510         cpl_vector_set(selection, i, -1);
01511         cpl_msg_info(cpl_func, "Image %d of %d rejected: median=%g, stdev=%g",
01512                      i+1, nima, stdev_medians, stdev_stdevs);
01513     }
01514 
01515     /* Purge the bad images in the images set */
01516     cpl_imagelist_erase(in, selection);
01517 
01518     end_skip;
01519 
01520     cpl_vector_delete(medians);
01521     cpl_vector_delete(stdevs);
01522     
01523     cpl_vector_delete(selection);
01524 
01525     return CPL_ERROR_NONE;
01526 
01527 }
01528 
01529 /*----------------------------------------------------------------------------*/
01538 /*----------------------------------------------------------------------------*/
01539 static cpl_error_code visir_offset_hcycle(cpl_image * hcycle) 
01540 {
01541     double minval;
01542 
01543 
01544     skip_if (0);
01545 
01546     skip_if (cpl_image_add_scalar(hcycle, VISIR_HCYCLE_OFFSET));
01547 
01548     minval = cpl_image_get_min(hcycle);
01549 
01550     /* It seems that the offset really is VISIR_HCYCLE_OFFSET-1, warn if not */
01551     if (minval < 1) cpl_msg_warning(cpl_func, "HCycle pixel minval: %g", minval);
01552 
01553     end_skip;
01554 
01555     return CPL_ERROR_NONE;
01556 }
01557 
01558 #include "visir_destripe.c"

Generated on Tue Jun 29 12:20:52 2010 for VISIR Pipeline Reference Manual by  doxygen 1.4.7