visir_util_undistort.c

00001 /* $Id: visir_util_undistort.c,v 1.5 2012/01/13 11:45:54 jtaylor 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: jtaylor $
00023  * $Date: 2012/01/13 11:45:54 $
00024  * $Revision: 1.5 $
00025  * $Name: visir-3_5_0 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include "visir_recipe.h"
00037 
00038 #include "visir_spc_distortion.h"
00039 
00040 /*-----------------------------------------------------------------------------
00041                                 Defines
00042  -----------------------------------------------------------------------------*/
00043 
00044 #define RECIPE_STRING   "visir_util_undistort"
00045 
00046 /*-----------------------------------------------------------------------------
00047                             Private Functions prototypes
00048  -----------------------------------------------------------------------------*/
00049 
00050 static cpl_error_code visir_util_undistort_one(cpl_frameset *,
00051                                                irplib_framelist *, int,
00052                                                const cpl_parameterlist *,
00053                                                const cpl_frame *,
00054                                                const cpl_mask *);
00055 
00056 cpl_recipe_define(visir_util_undistort, VISIR_BINARY_VERSION,
00057                   "Lars Lundin", PACKAGE_BUGREPORT, "2011", 
00058                   "Correct the distortion in spectral data",
00059                   "The files listed in the Set Of Frames (sof-file) "
00060                   "must be tagged:\n"
00061                   "VISIR-chopnod-corrected-file.fits " VISIR_UTIL_UNDISTORT_RAW
00062                   "\nOptionally, a bad pixel map may be provided:\n"
00063                   "VISIR-bpm-file.fits " VISIR_CALIB_STATIC_MASK "\n"
00064                   "\nThe product(s) will have a FITS card\n"
00065                   "'HIERARCH ESO PRO CATG' with a value of:\n"
00066                   VISIR_UTIL_UNDISTORT_PROCATG "\n"
00067 #ifdef VISIR_UTIL_UNDISTORT_AUTO_REJECT
00068 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(5, 4, 0) 
00069                   "If no bad pixel map is provided, the recipe will "
00070                   "automatically flag input intensities greater than or equal "
00071                   "to 32767 as bad.\n"
00072 #endif
00073 #endif
00074                   "The recipe default values for the transformation are only "
00075                   "valid for spectral data taken in Low resolution mode");
00076 
00077 /*----------------------------------------------------------------------------*/
00081 /*----------------------------------------------------------------------------*/
00082 
00083 /*-----------------------------------------------------------------------------
00084                                 Functions code
00085  -----------------------------------------------------------------------------*/
00086 
00087 
00088 /*----------------------------------------------------------------------------*/
00096 /*----------------------------------------------------------------------------*/
00097 static cpl_error_code
00098 visir_util_undistort_fill_parameterlist(cpl_parameterlist * self)
00099 {
00100 
00101     return visir_parameter_set(self, RECIPE_STRING, VISIR_PARAM_SLITSKEW |
00102                                VISIR_PARAM_SPECSKEW | VISIR_PARAM_VERTARC |
00103                                VISIR_PARAM_HORIARC)
00104         ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
00105 }
00106 
00107 
00108 /*----------------------------------------------------------------------------*/
00115 /*----------------------------------------------------------------------------*/
00116 static int visir_util_undistort(cpl_frameset            * framelist,
00117                                 const cpl_parameterlist * parlist)
00118 {
00119 #ifdef _OPENMP
00120     cpl_errorstate     cleanstate = cpl_errorstate_get();
00121 #endif
00122     cpl_error_code     didfail    = CPL_ERROR_NONE;
00123     const cpl_frame  * bpmframe   = cpl_frameset_find_const
00124         (framelist, VISIR_CALIB_STATIC_MASK);
00125     irplib_framelist * allframes  = NULL;
00126     irplib_framelist * rawframes  = NULL;
00127     cpl_image        * imbpm      = NULL;
00128     cpl_mask         * bpm        = NULL;
00129     int                i, n;
00130 
00131 
00132     /* Identify the RAW and CALIB frames in the input frameset */
00133     skip_if (visir_dfs_set_groups(framelist));
00134 
00135     /* Objects observation */
00136     allframes = irplib_framelist_cast(framelist);
00137     skip_if(allframes == NULL);
00138     rawframes = irplib_framelist_extract_regexp(allframes, "^("
00139                                                 VISIR_UTIL_UNDISTORT_RAW ")$",
00140                                                 CPL_FALSE);
00141     skip_if (rawframes == NULL);
00142     n = irplib_framelist_get_size(rawframes);
00143 
00144     if (bpmframe != NULL) {
00145         /* Load any static mask here to avoid that the file is loaded
00146            multiple times */
00147         const char * badpix = cpl_frame_get_filename(bpmframe);
00148 
00149 
00150 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(5, 4, 0) 
00151         bpm = cpl_mask_load(badpix, 0, 0);
00152 #else
00153         /* FIXME: Remove once CPL 5.x is no longer supported */
00154         imbpm = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
00155         skip_if (imbpm == NULL);
00156 
00157         bpm = cpl_mask_threshold_image_create(imbpm, 0.5, DBL_MAX);
00158 #endif
00159         skip_if (bpm == NULL);
00160     }
00161     
00162 #ifdef _OPENMP
00163 #pragma omp parallel for private(i)
00164 #endif
00165     for (i = 0; i < n; i++) {
00166         if (!didfail) {
00167 
00168             /* The total number of iterations must be pre-determined for the
00169                parallelism to work. In case of an error we can therefore not
00170                break, so instead we skip immediately to the next iteration.
00171                FIXME: This check on didfail does not guarantee that only one
00172                iteration can cause an error to be dumped, but it is not
00173                worse than checking on a thread-local state, e.g. errori. */
00174 
00175             if (visir_util_undistort_one(framelist, rawframes, i, parlist,
00176                                          bpmframe, bpm)) {
00177                 const cpl_error_code errori = cpl_error_set_where(cpl_func);
00178 #ifdef _OPENMP
00179                 /* Cannot access these errors after the join,
00180                    so dump them now. :-(((((((((((((((((((( */
00181                 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
00182                 cpl_errorstate_set(cleanstate);
00183 #pragma omp critical(visir_util_undistort)
00184 #endif
00185                 didfail = errori;
00186             }
00187         }
00188     }
00189 
00190     error_if(didfail, didfail, "Failed to undistort images in %d frame(s)", n);
00191 
00192     end_skip;
00193 
00194     irplib_framelist_delete(allframes);
00195     irplib_framelist_delete(rawframes);
00196     cpl_image_delete(imbpm);
00197     cpl_mask_delete(bpm);
00198 
00199     return cpl_error_get_code();
00200 }
00201 
00202 
00203 /*----------------------------------------------------------------------------*/
00215 /*----------------------------------------------------------------------------*/
00216 static
00217 cpl_error_code visir_util_undistort_one(cpl_frameset * framelist,
00218                                         irplib_framelist * rawframes, int i,
00219                                         const cpl_parameterlist * parlist,
00220                                         const cpl_frame * bpmframe,
00221                                         const cpl_mask * bpm)
00222 {
00223 
00224     cpl_frameset  * products   = cpl_frameset_new();
00225     cpl_frameset  * usedframes = cpl_frameset_new();
00226     const cpl_frame * rawframe  = irplib_framelist_get_const(rawframes, i);
00227     const char      * filename  = cpl_frame_get_filename(rawframe);
00228     /* visir_spc_det_fix() casts to float in any case */
00229     cpl_image       * distorted = NULL;
00230     char            * proname   = cpl_sprintf(RECIPE_STRING "_%d" CPL_DFS_FITS,
00231                                               1+i);
00232 
00233 
00234     /* The angles are given in degrees and then converted to radians */
00235 
00236     const double ksi   = visir_parameterlist_get_double(parlist, RECIPE_STRING,
00237                                                         VISIR_PARAM_SPECSKEW)
00238         * CPL_MATH_RAD_DEG;
00239     const double eps   = visir_parameterlist_get_double(parlist, RECIPE_STRING,
00240                                                         VISIR_PARAM_VERTARC);
00241     const double delta = visir_parameterlist_get_double(parlist, RECIPE_STRING,
00242                                                         VISIR_PARAM_HORIARC);
00243     const double phi   = visir_parameterlist_get_double(parlist, RECIPE_STRING,
00244                                                         VISIR_PARAM_SLITSKEW)
00245         * CPL_MATH_RAD_DEG;
00246     const int next = cpl_frame_get_nextensions(rawframe);
00247 
00248     skip_if(0);
00249 
00250     bug_if(cpl_frameset_insert(usedframes, cpl_frame_duplicate
00251                                (irplib_framelist_get_const(rawframes, i))));
00252 
00253     skip_if(irplib_dfs_save_propertylist(products, parlist, usedframes,
00254                                          RECIPE_STRING,
00255                                          VISIR_UTIL_UNDISTORT_PROCATG, NULL,
00256                                          NULL,
00257                                          visir_pipe_id, proname));
00258 
00259     for (int iext = 0; iext <= next; iext++) {
00260         cpl_errorstate prestate = cpl_errorstate_get();
00261 
00262         distorted = cpl_image_load(filename, CPL_TYPE_FLOAT, 0, iext);
00263         if (distorted == NULL) {
00264             cpl_msg_info(cpl_func, "No image-data in extension %d", iext);
00265             cpl_errorstate_set(prestate);
00266             continue;
00267         }
00268 
00269         if (bpm != NULL) {
00270             bug_if (bpmframe == NULL);
00271             bug_if(cpl_frameset_insert(usedframes, cpl_frame_duplicate(bpmframe)));
00272 
00273             skip_if(cpl_image_reject_from_mask(distorted, bpm));
00274         } else {
00275             bug_if (bpmframe != NULL);
00276 #ifdef VISIR_UTIL_UNDISTORT_AUTO_REJECT
00277 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(5, 4, 0) 
00278 
00279             skip_if(cpl_mask_threshold_image(cpl_image_get_bpm(distorted),
00280                                              distorted, -DBL_MAX, 32767.0,
00281                                              CPL_BINARY_0));
00282 #endif
00283 #endif
00284         }
00285         skip_if(visir_spc_det_warp(&distorted, 1, phi, ksi, eps, delta));
00286 
00287         cpl_image_save(distorted, proname, CPL_BPP_IEEE_FLOAT,
00288                        NULL, CPL_IO_EXTEND);
00289     }
00290 
00291     for (const cpl_frame * frame = cpl_frameset_get_first_const(products);
00292          frame != NULL;
00293          frame = cpl_frameset_get_next_const(products)) {
00294         cpl_frame * copy = cpl_frame_duplicate(frame);
00295         cpl_error_code error;
00296 
00297 #ifdef _OPENMP
00298 #pragma omp critical(visir_util_undistort_one)
00299 #endif
00300         error = cpl_frameset_insert(framelist, copy);
00301 
00302         skip_if(error);
00303     }
00304 
00305 
00306     end_skip;
00307 
00308     cpl_image_delete(distorted);
00309     cpl_frameset_delete(usedframes);
00310     cpl_frameset_delete(products);
00311     cpl_free(proname);
00312 
00313     return cpl_error_get_code();
00314 }

Generated on Mon Feb 6 15:23:49 2012 for VISIR Pipeline Reference Manual by  doxygen 1.5.8