visir_spc_distortion.c

00001 /* $Id: visir_spc_distortion.c,v 1.43 2008/03/25 10:24:08 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: 2008/03/25 10:24:08 $
00024  * $Revision: 1.43 $
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 
00039 #include <cpl.h>
00040 
00041 #include "visir_spc_distortion.h"
00042 #include "visir_utils.h"
00043 
00044 /*----------------------------------------------------------------------------*/
00048 /*----------------------------------------------------------------------------*/
00049 
00050 /*-----------------------------------------------------------------------------
00051                                    Functions prototypes
00052  -----------------------------------------------------------------------------*/
00053 
00054 static cpl_error_code visir_spc_det_warp(cpl_image **, int, double, double,
00055                                          double, double);
00056 
00057 static cpl_error_code visir_spc_det_warp_xy(int, double, double, double, double,
00058                                             double, double, double, double,
00059                                             double *, double*);
00060 
00061 /*-----------------------------------------------------------------------------
00062                                    Functions code
00063  -----------------------------------------------------------------------------*/
00066 /*----------------------------------------------------------------------------*/
00092 /*----------------------------------------------------------------------------*/
00093 cpl_error_code visir_spc_det_fix(cpl_image ** images, int nimages,
00094                                  cpl_boolean is_interm,
00095                                  double wlen, visir_spc_resol resol,
00096                                  double phi, double ksi, double eps, 
00097                                  double delta, int doplot)
00098 {
00099 
00100     cpl_image * spectrum = NULL;
00101 
00102     int nx = 0;  /* Avoid (false) uninit warning */
00103     int ny = 0;  /* Avoid (false) uninit warning */
00104     int k;
00105 
00106 
00107     skip_if (0);
00108 
00109     skip_if (images == NULL);
00110     skip_if (nimages <= 0);
00111 
00112     skip_if (!is_interm && nimages != 1);
00113 
00114     for (k=0; k < nimages; k++) {
00115         if (images[k] == NULL) break;
00116 
00117         if (cpl_image_get_type(images[k]) != CPL_TYPE_FLOAT) {
00118             /* Done only with --fixcombi (used for backwards compatability */
00119             cpl_image * to_float = cpl_image_cast(images[k], CPL_TYPE_FLOAT);
00120 
00121             cpl_image_delete(images[k]);
00122 
00123             images[k] = to_float;
00124 
00125         }
00126 
00127         if (k == 0) {
00128             nx = cpl_image_get_size_x(images[0]);
00129             ny = cpl_image_get_size_y(images[0]);
00130 
00131             skip_if (nx < 1);
00132         } else {
00133             skip_if (nx != cpl_image_get_size_x(images[k]));
00134             skip_if (ny != cpl_image_get_size_y(images[k]));
00135         }
00136 
00137     }
00138 
00139     /* In HR only phi is used */
00140     /* HR Grism mode has its own recipe and needs no hard-coded changes here */
00141     if (resol == VISIR_SPC_R_HR) {
00142 
00143         visir_optmod ins_settings;
00144 
00145         if (visir_spc_optmod_init(VISIR_SPC_R_HR, wlen, &ins_settings)) {
00146             visir_error_set(CPL_ERROR_ILLEGAL_INPUT);
00147             skip_if(1);
00148         }
00149 
00150         if (visir_spc_optmod_side_is_A(&ins_settings)) {
00151             /* Line curvature is zero in HR-A */
00152             eps   = 0;
00153             /* Spectrum curvature is 1.5 times bigger in HR-A than in LMR */
00154             delta *= 1.5;
00155         } else {
00156             /* Line curvature is 2.21 times bigger in HR-B than in LR */
00157             eps   *= 0.115/0.052;
00158             /* Spectrum curvature is 2 times smaller in HR-B than in LMR */
00159             delta *= 0.5;
00160         }
00161         ksi = 0; /* ksi is zero */
00162     } else if (resol == VISIR_SPC_R_MR) {
00163         eps *=  0.25; /* Line curvature is 4 times smaller in MR than in LR */
00164     }
00165 
00166     cpl_msg_info(cpl_func, "Skew and Curvature: %g %g %g %g", phi, ksi, eps,
00167                  delta);
00168 
00169     /* The angles are coded in degrees and then converted to radians */
00170     ksi *= CPL_MATH_RAD_DEG; 
00171     phi *= CPL_MATH_RAD_DEG;
00172 
00173     if (!is_interm) {
00174 
00175         float * px;
00176         const double fdead = 0.25;
00177         int ndead = 0; /* Number of rows of dead pixels */
00178         const int mdeadmax = 4; /* Check 3 outermost rows */
00179         int i,j;
00180 
00181         skip_if (visir_image_reject_hot(images[0], NULL));
00182 
00183         /* Check that the top row of pixels are not too small */
00184 
00185         spectrum = cpl_image_collapse_create(images[0], 1);
00186         skip_if (0);
00187 
00188         px = cpl_image_get_data(spectrum);
00189 
00190         if (doplot > 1) visir_image_col_plot("", "t 'The collapsed 1/2-cycle "
00191                                              "spectrum'", "", spectrum, 1,1,1);
00192 
00193         for (j = 1; j < mdeadmax; j++) {
00194             const float g0 = px[ny  -j] - px[ny-1-j];
00195             const float g1 = px[ny-1-j] - px[ny-2-j];
00196 
00197             cpl_msg_debug(cpl_func, "GRAD(%g): %g <> %g", ny-j-0.5, g0, g1);
00198 
00199             if ((g1 < 0 && g0 * fdead < g1) || (g1 >=0 && g0 < g1 * fdead))
00200                 ndead = j;
00201         }
00202 
00203         if (ndead) {
00204             cpl_msg_info(cpl_func, "Rejecting dead pixels %d -> %d. "
00205                             "GRAD: %g << %g", ny-ndead, ny-1,
00206                             px[ny  -ndead] - px[ny-1-ndead],
00207                             px[ny-1-ndead] - px[ny-2-ndead]);
00208 
00209             for (i = 0; i < nx; i++) {
00210                 for (j = ny-ndead; j < ny; j++) {
00211                     skip_if (cpl_image_reject(images[0], i+1, j+1));
00212                 }
00213             }
00214             ndead = 0;
00215         }
00216 
00217         px = cpl_image_get_data(spectrum);
00218 
00219         for (j = 1; j < mdeadmax; j++) {
00220             const float g0 = px[j-1] - px[j];
00221             const float g1 = px[j] - px[j+1];
00222 
00223             cpl_msg_debug(cpl_func, "GRAD(%g:%d): %g <> %g", j-0.5, ndead, g0, g1);
00224      
00225             if ((g1 < 0 && g0 * fdead < g1) || (g1 >=0 && g0 < g1 * fdead))
00226                 ndead = j;
00227         }
00228 
00229         if (ndead) {
00230             cpl_msg_info(cpl_func, "Rejecting dead pixels 1 -> %d. GRAD: "
00231                             "%g << %g", ndead, px[ndead-1] - px[ndead],
00232                             px[ndead] - px[ndead+1]);
00233 
00234             for (i = 0; i < nx; i++) {
00235                 for (j = 0; j < ndead; j++) {
00236                     skip_if (cpl_image_reject(images[0], i+1, j+1));
00237                 }
00238             }
00239         }
00240         cpl_image_delete(spectrum);
00241         spectrum = NULL;
00242 
00243     }
00244 
00245     /* Apply the distortion correction  */
00246     skip_if (visir_spc_det_warp(images, nimages, phi, ksi, eps, delta));
00247 
00248     if (doplot > 1) visir_image_plot("", "t 'The first corrected image'",
00249                                      "", images[0]);
00250 
00251     end_skip;
00252 
00253     cpl_image_delete(spectrum);
00254 
00255     return cpl_error_get_code();
00256 
00257 }
00258 
00259 
00262 /*----------------------------------------------------------------------------*/
00278 /*----------------------------------------------------------------------------*/
00279 static cpl_error_code visir_spc_det_warp(cpl_image ** images, int nimages,
00280                                          double phi, double ksi,
00281                                          double eps, double delta)
00282 {
00283 
00284 
00285     const double radius = CPL_KERNEL_DEF_WIDTH;
00286     const int tabsperpix = CPL_KERNEL_TABSPERPIX;
00287     double fluxprev, fluxpost;
00288     const int nx = cpl_image_get_size_x(images[0]);
00289     const int ny = cpl_image_get_size_y(images[0]);
00290     const cpl_boolean do_warp = phi != 0 || ksi != 0 || eps != 0 || delta != 0;
00291     int iu, iv;
00292     int iimage;
00293     int nbad = 0; /* Avoid (false) uninit warning */
00294     int ipix;
00295 
00296     cpl_image  * copy = NULL;
00297     cpl_vector * xyprofile = NULL;
00298     cpl_mask   * rejected = NULL;
00299     cpl_binary * preject = NULL; /* Avoid (false) uninit warning */
00300     cpl_image  * coord_x = NULL;
00301     cpl_image  * coord_y = NULL;
00302     double * piv = NULL; /* Avoid (false) uninit warning */
00303     double * piu = NULL;
00304 
00305 
00306     skip_if (0);
00307 
00308     if (do_warp) {
00309         double x = 0.0; /* Avoid (false) uninit warning */ 
00310         double y = 0.0; /* Avoid (false) uninit warning */ 
00311 
00312         rejected = cpl_mask_new(nx, ny);
00313         preject = cpl_mask_get_data(rejected);
00314 
00315         skip_if (0);
00316 
00317         /* Avoid unnecessary interpolation */
00318 
00319         xyprofile = cpl_vector_new(1 + radius * tabsperpix);
00320         cpl_vector_fill_kernel_profile(xyprofile, CPL_KERNEL_DEFAULT, radius);
00321         coord_x = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00322         coord_y = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00323 
00324         piu = cpl_image_get_data(coord_x);
00325         piv = cpl_image_get_data(coord_y);
00326 
00327         skip_if (0);
00328 
00329         for (ipix = 0, iv = 1; iv <= ny; iv++) {
00330             for (iu = 1; iu <= nx; iu++, ipix++) {
00331 
00332                 skip_if (visir_spc_det_warp_xy(1, nx, ny, iu, iv, phi, ksi, eps,
00333                                                delta, &x, &y));
00334                 piu[ipix] = x;
00335                 piv[ipix] = y;
00336             }
00337         }
00338 
00339     }
00340 
00341 
00342     for (iimage = 0 ; iimage < nimages; iimage++) {
00343         cpl_image * image = images[iimage];
00344         float     * px    = cpl_image_get_data(image);
00345 
00346         if (!do_warp || cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00347             nbad = cpl_image_count_rejected(image);
00348 
00349             cpl_msg_debug(cpl_func, "Raw image has %d bad pixels", nbad);
00350         }
00351 
00352         skip_if (0);
00353 
00354         if (!do_warp && nbad == 0) continue;
00355 
00356         fluxprev = cpl_image_get_flux(image);
00357 
00358         skip_if(0);
00359 
00360         if (do_warp) {
00361             copy = cpl_image_duplicate(image);
00362 
00363             skip_if (0);
00364 
00365             nbad = 0;
00366             for (ipix = 0, iv = 1; iv <= ny; iv++) {
00367                 for (iu = 1; iu <= nx; iu++, ipix++) {
00368                     double value;
00369                     double confidence;
00370 
00371                     value = cpl_image_get_interpolated(copy, piu[ipix], piv[ipix],
00372                                                        xyprofile, radius,
00373                                                        xyprofile, radius,
00374                                                        &confidence);
00375                     skip_if (confidence < 0);
00376 
00377                     if (confidence < 0.5) {
00378                         nbad++;
00379                         preject[ipix] = CPL_BINARY_1;
00380                     } else {
00381                         /* The equivalent of at least 2 of the
00382                            nearest 4 pixels are good */
00383                         px[ipix] = value;
00384                     }
00385                 }
00386             }
00387 
00388             cpl_image_delete(copy);
00389             copy = NULL;
00390         }
00391 
00392         if (nbad > 0) {
00393             if (do_warp) {
00394                 skip_if(cpl_image_reject_from_mask(image, rejected));
00395 
00396                 cpl_mask_delete(rejected);
00397                 rejected = cpl_mask_new(nx, ny);
00398                 preject = cpl_mask_get_data(rejected);
00399 
00400 
00401             }
00402             if (iimage == 0) cpl_msg_info(cpl_func, "Cleaning %d bad pixels in eac"
00403                                           "h of the %d images", nbad, nimages);
00404             skip_if (cpl_detector_interpolate_rejected(image));
00405 
00406         }
00407 
00408         fluxpost = cpl_image_get_flux(image);
00409 
00410         skip_if(0);
00411 
00412         cpl_msg_info(cpl_func, "Corrected distortion in image %d, flux: %g => %g",
00413                      1+iimage, fluxprev, fluxpost);
00414 
00415     }
00416 
00417     end_skip;
00418 
00419     if (cpl_error_get_code())
00420         cpl_msg_error(cpl_func, "Detector unwarp failed (at %s): %s",
00421                       cpl_error_get_where(), cpl_error_get_message());
00422 
00423     cpl_mask_delete(rejected);
00424     cpl_vector_delete(xyprofile);
00425     cpl_image_delete(copy);
00426     cpl_image_delete(coord_x);
00427     cpl_image_delete(coord_y);
00428 
00429     return cpl_error_get_code();
00430 }
00431 
00432 /*----------------------------------------------------------------------------*/
00464 /*----------------------------------------------------------------------------*/
00465 static cpl_error_code visir_spc_det_warp_xy(int inv, double nx, double ny,
00466                                      double x, double y,
00467                                      double phi, double ksi,
00468                                      double eps, double delta,
00469                                      double *pu, double *pv)
00470 {
00471 
00472 
00473 #ifdef VISIR_DET_WARP_ROTATE
00474     double z;
00475     const double skew = phi + ksi;
00476 #endif
00477 
00478     cpl_ensure_code(pu,       CPL_ERROR_NULL_INPUT);
00479     cpl_ensure_code(pv,       CPL_ERROR_NULL_INPUT);
00480 
00481     cpl_ensure_code(nx > 0, CPL_ERROR_ILLEGAL_INPUT);
00482     cpl_ensure_code(ny > 0, CPL_ERROR_ILLEGAL_INPUT);
00483 
00484 
00485     /* Transform Origo to center of detector */
00486     x -= (nx+1)/2;
00487     y -= (ny+1)/2;
00488 
00489     if (inv) {
00490 
00491         if (delta != 0) {
00492             /* Correct vertical curvature */
00493             const double R = ((ny/2)*(ny/2) + delta*delta) / fabs(2 * delta);
00494 
00495             cpl_ensure_code(R >= y, CPL_ERROR_ILLEGAL_INPUT);
00496 
00497             x -= (R - sqrt(R*R - y * y)) * (delta > 0 ? 1 : -1);
00498         }
00499 
00500         if (eps != 0) {
00501             /* Correct horizontal curvature */
00502             const double R = ((ny/2)*(ny/2) + eps*eps) / fabs(2 * eps);
00503 
00504             cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
00505 
00506             y += (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
00507         }
00508 
00509         /* Skew into horizontal lines */
00510         y -= x * tan(phi);
00511 
00512         /* Skew into vertical lines */
00513         x -= y * tan(ksi);
00514 
00515     } else {
00516 
00517         /* Skew into vertical lines */
00518         x += y * tan(ksi);
00519 
00520         /* Skew into horizontal lines */
00521         y += x * tan(phi);
00522 
00523         if (eps != 0) {
00524             /* Correct horizontal curvature */
00525             const double R = ((ny/2)*(ny/2) + eps*eps) / fabs(2 * eps);
00526 
00527             cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
00528 
00529             y -= (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
00530         }
00531         if (delta != 0) {
00532             /* Correct vertical curvature */
00533             const double R = ((ny/2)*(ny/2) + delta*delta) / fabs(2 * delta);
00534 
00535             cpl_ensure_code(R >= y, CPL_ERROR_ILLEGAL_INPUT);
00536 
00537             x += (R - sqrt(R*R - y * y)) * (delta > 0 ? 1 : -1);
00538         }
00539     }
00540 
00541     /* Transform Origo back from center of detector */
00542     x += (nx+1)/2;
00543     y += (ny+1)/2;
00544 
00545     *pu = x;
00546     *pv = y;
00547 
00548     return cpl_error_get_code();
00549 
00550 }

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