uves_wavecal_utils.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019 
00020 /*
00021  * $Author: amodigli $
00022  * $Date: 2007/06/06 08:17:34 $
00023  * $Revision: 1.11 $
00024  * $Name: uves-4_2_2 $
00025  * $Log: uves_wavecal_utils.c,v $
00026  * Revision 1.11  2007/06/06 08:17:34  amodigli
00027  * replace tab with 4 spaces
00028  *
00029  * Revision 1.10  2007/05/07 14:25:43  jmlarsen
00030  * Changed formatting
00031  *
00032  * Revision 1.9  2007/03/05 10:43:16  jmlarsen
00033  * Reject outliers based on line FWHM and fit residual
00034  *
00035  * Revision 1.8  2006/11/06 15:19:42  jmlarsen
00036  * Removed unused include directives
00037  *
00038  * Revision 1.7  2006/10/10 11:20:11  jmlarsen
00039  * Renamed line table columns to match MIDAS
00040  *
00041  * Revision 1.6  2006/07/14 12:52:57  jmlarsen
00042  * Exported/renamed function find_nearest
00043  *
00044  * Revision 1.5  2006/06/06 08:40:25  jmlarsen
00045  * Shortened max line length
00046  *
00047  * Revision 1.4  2006/06/01 14:43:17  jmlarsen
00048  * Added missing documentation
00049  *
00050  * Revision 1.3  2006/04/21 12:29:30  jmlarsen
00051  * Write QC parameters to line table
00052  *
00053  * Revision 1.2  2006/02/15 13:19:15  jmlarsen
00054  * Reduced source code max. line length
00055  *
00056  * Revision 1.1  2006/02/03 07:46:30  jmlarsen
00057  * Moved recipe implementations to ./uves directory
00058  *
00059  * Revision 1.3  2005/12/19 16:17:55  jmlarsen
00060  * Replaced bool -> int
00061  *
00062  * Revision 1.2  2005/11/14 13:18:44  jmlarsen
00063  * Minor update
00064  *
00065  * Revision 1.1  2005/11/11 13:18:54  jmlarsen
00066  * Reorganized code, renamed source files
00067  *
00068  */
00069 
00070 #ifdef HAVE_CONFIG_H
00071 #  include <config.h>
00072 #endif
00073 
00074 /*----------------------------------------------------------------------------*/
00078 /*----------------------------------------------------------------------------*/
00081 /*-----------------------------------------------------------------------------
00082                                 Includes
00083  -----------------------------------------------------------------------------*/
00084 
00085 #include <uves_wavecal_utils.h>
00086 #include <uves_utils.h>
00087 #include <uves_utils_wrappers.h>
00088 #include <uves_error.h>
00089 #include <uves_msg.h>
00090 
00091 #include <cpl.h>
00092 
00093 /*-----------------------------------------------------------------------------
00094                             Functions prototypes
00095  -----------------------------------------------------------------------------*/
00096 
00097 /*-----------------------------------------------------------------------------
00098                             Implementation
00099  -----------------------------------------------------------------------------*/
00100 /*----------------------------------------------------------------------------*/
00108 /*----------------------------------------------------------------------------*/
00109 
00110 lt_type *uves_lt_new(int windows, int traces)
00111 {
00112     /* Allocate all line tables for this chip */
00113     lt_type *lt = cpl_malloc(sizeof(lt_type));
00114 
00115     assure_mem( lt );
00116     
00117     lt->windows = windows;
00118     lt->traces = traces;
00119 
00120     /* Initialize pointer to NULL */
00121     lt->table                = cpl_calloc(windows*traces, sizeof(cpl_table *));
00122     lt->dispersion_relation  = cpl_calloc(windows*traces, sizeof(polynomial *));
00123     lt->absolute_order       = cpl_calloc(windows*traces, sizeof(polynomial *));
00124     lt->first_absolute_order = cpl_calloc(windows*traces, sizeof(int));
00125     lt->last_absolute_order  = cpl_calloc(windows*traces, sizeof(int));
00126 
00127   cleanup:
00128     return lt;
00129 }
00130 
00131 /*----------------------------------------------------------------------------*/
00136 /*----------------------------------------------------------------------------*/
00137 
00138 void uves_lt_delete(lt_type **lt)
00139 {
00140     if (lt != NULL && *lt != NULL)
00141     {
00142         int i;
00143         for (i = 0; i < (*lt)->windows * (*lt)->traces; i++)
00144         {
00145             uves_free_table       (&((*lt)->table[i]));
00146             uves_polynomial_delete(&((*lt)->dispersion_relation[i]));
00147             uves_polynomial_delete(&((*lt)->absolute_order[i]));
00148         }
00149 
00150         cpl_free((*lt)->table);
00151         cpl_free((*lt)->dispersion_relation);
00152         cpl_free((*lt)->absolute_order);
00153         cpl_free((*lt)->first_absolute_order);
00154         cpl_free((*lt)->last_absolute_order);
00155         
00156         cpl_free(*lt);
00157     }
00158 
00159     return;
00160 }
00161 
00162 /*----------------------------------------------------------------------------*/
00170 /*----------------------------------------------------------------------------*/
00171 cpl_table **
00172 uves_lt_get_table(const lt_type *lt, int window, int trace)
00173 {
00174     return &(lt->table[trace + (window-1)*lt->traces]);
00175 }
00176 
00177 /*----------------------------------------------------------------------------*/
00185 /*----------------------------------------------------------------------------*/
00186 polynomial **
00187 uves_lt_get_disprel(const lt_type *lt, int window, int trace)
00188 {
00189     return &(lt->dispersion_relation[trace + (window-1)*lt->traces]);
00190 }
00191 /*----------------------------------------------------------------------------*/
00199 /*----------------------------------------------------------------------------*/
00200 polynomial **
00201 uves_lt_get_absord(const lt_type *lt, int window, int trace)
00202 {
00203     return &(lt->absolute_order[trace + (window-1)*lt->traces]);
00204 }
00205 /*----------------------------------------------------------------------------*/
00213 /*----------------------------------------------------------------------------*/
00214 int *
00215 uves_lt_get_firstabs(const lt_type *lt, int window, int trace)
00216 {
00217     return &(lt->first_absolute_order[trace + (window-1)*lt->traces]);
00218 }
00219 /*----------------------------------------------------------------------------*/
00227 /*----------------------------------------------------------------------------*/
00228 int *
00229 uves_lt_get_lastabs(const lt_type *lt, int window, int trace)
00230 {
00231     return &(lt->last_absolute_order[trace + (window-1)*lt->traces]);
00232 }
00233 
00234 /*----------------------------------------------------------------------------*/
00250 /*----------------------------------------------------------------------------*/
00251 int
00252 uves_wavecal_find_nearest(const cpl_table *line_refer, double lambda, int lo, int hi)
00253 {
00254     if (lo == hi) /* One-row interval */
00255     {
00256         return lo;
00257     }
00258     else if (lo + 1 == hi)
00259     {  /* Two-row interval */
00260         double llo, lhi;
00261         lhi = cpl_table_get_double(line_refer, "Wave", hi, NULL);
00262         llo = cpl_table_get_double(line_refer, "Wave", lo, NULL);
00263         
00264         /* Return the one of 'llo' and 'lhi' that is closest to 'lambda' */
00265         return ((llo-lambda)*(llo-lambda) < (lhi-lambda)*(lhi-lambda)) ? lo : hi;
00266     }
00267     else
00268     { /* Three or more rows to consider */ 
00269         double lmid;
00270         int mid = (lo + hi)/2;
00271         /* mid is different from both 'lo' and 'hi', so this will terminate */
00272         
00273         lmid = cpl_table_get_double(line_refer, "Wave", mid, NULL);
00274         
00275         if (lmid < lambda)
00276         {
00277             return uves_wavecal_find_nearest(line_refer, lambda, mid, hi);
00278         }
00279         else
00280         {
00281             return uves_wavecal_find_nearest(line_refer, lambda, lo, mid);
00282         }
00283     }
00284 }
00285 
00286 
00287 /*----------------------------------------------------------------------------*/
00302 /*----------------------------------------------------------------------------*/
00303 int
00304 uves_delete_bad_lines(cpl_table *table, double TOLERANCE, double kappa)
00305 {    
00306     int result = 0;
00307     int numb_lines = cpl_table_get_nrow(table);
00308 
00309     /* Delete rows with invalid 'Ident' (and therefore invalid 'Residual_xxx') */
00310     check( uves_erase_invalid_table_rows(table, "Ident"),
00311        "Error erasing un-identified lines");
00312 
00313     assure( cpl_table_has_column(table, "Residual_pix"),
00314             CPL_ERROR_DATA_NOT_FOUND,
00315             "Missing column 'Residual_pix'");
00316 
00317     assure( cpl_table_has_column(table, LINETAB_RESIDUAL),
00318             CPL_ERROR_DATA_NOT_FOUND,
00319             "Missing column '" LINETAB_RESIDUAL "'");
00320 
00321     if (TOLERANCE > 0)
00322     {   
00323             /* Pixel units */
00324         check(( uves_erase_table_rows(table,        /*  >  tol  */
00325                       "Residual_pix", CPL_GREATER_THAN, TOLERANCE),
00326             uves_erase_table_rows(table,        /*  < -tol */
00327                       "Residual_pix", CPL_LESS_THAN   , -TOLERANCE)),
00328             "Error removing rows");
00329     }
00330     else
00331     {  
00332             /* Wavelength units */
00333         check(( uves_erase_table_rows(table,       /*  >  |tol| */
00334                       LINETAB_RESIDUAL, CPL_GREATER_THAN, -TOLERANCE),
00335             uves_erase_table_rows(table,       /*  < -|tol| */
00336                       LINETAB_RESIDUAL, CPL_LESS_THAN   , TOLERANCE)),
00337           "Error removing rows");
00338     }
00339 
00340 
00341     /* Also reject outliers (if more than 2 points)
00342        by kappa sigma clipping                       */
00343 
00344     if (cpl_table_get_nrow(table) - cpl_table_count_invalid(table, "Residual_pix") >= 2)
00345         {
00346             check_nomsg( uves_average_reject(table,
00347                                              "Residual_pix", "temp",
00348                                              kappa));
00349 
00350             check_nomsg( uves_average_reject(table,
00351                                              "Xwidth", "temp",
00352                                              kappa));
00353 
00354 
00355             /* Don't do this:
00356                the same is achieved by detecting fewer
00357                lines from the start 
00358             check_nomsg( uves_erase_table_rows(table,
00359                                                "Peak",
00360                                                CPL_LESS_THAN,
00361                                                0.5 *
00362                                                cpl_table_get_column_median(table, "Peak")));
00363             */
00364         }
00365     
00366     result = numb_lines - cpl_table_get_nrow(table);
00367 
00368   cleanup:
00369     return result;
00370 }
00371 
00372 /*----------------------------------------------------------------------------*/
00402 /*----------------------------------------------------------------------------*/
00403 cpl_error_code
00404 uves_draw_lines(cpl_image *image, polynomial *dispersion, 
00405         const polynomial *order_locations, const cpl_table *t, 
00406         const char *lambda_column, const char *abs_order, 
00407         const int *relative_order, int minorder, int maxorder,
00408         bool vertical, int offset)
00409 {
00410     int nx, ny;
00411     int row;
00412     
00413     /* Check input */
00414     passure( image != NULL, " ");
00415     passure( dispersion != NULL, " ");
00416     passure( uves_polynomial_get_dimension(dispersion) == 2, "%d", 
00417          uves_polynomial_get_dimension(dispersion));
00418     passure( order_locations != NULL, " ");
00419     passure( uves_polynomial_get_dimension(order_locations) == 2, "%d",
00420          uves_polynomial_get_dimension(order_locations));
00421     passure( t != NULL, " ");
00422     passure( cpl_table_has_column(t, lambda_column), "%s", lambda_column);
00423     if (abs_order != NULL)
00424     {
00425         passure( cpl_table_has_column(t, abs_order), "%s", abs_order);
00426     }
00427 
00428     nx = cpl_image_get_size_x(image);
00429     ny = cpl_image_get_size_y(image);
00430     
00431     for (row = 0; row < cpl_table_get_nrow(t); row++) {
00432     double x, xguess;
00433     double lambda, lambda_left, lambda_right;
00434     int order;
00435     
00436     check( lambda    = cpl_table_get_double(t, lambda_column, row, NULL),
00437            "Error reading table");
00438     
00439     if (abs_order != NULL)
00440         check (minorder = maxorder = cpl_table_get_int(t, abs_order, row, NULL),
00441            "Error reading table");
00442     
00443     for (order = minorder; order <= maxorder; order++) {
00444         lambda_left  = uves_polynomial_evaluate_2d(dispersion, 1 , order)/order;
00445         lambda_right = uves_polynomial_evaluate_2d(dispersion, nx, order)/order;
00446         
00447         /* Solve  dispersion(x, m) = ident*m */
00448         xguess = 1 + (nx - 1) * (lambda - lambda_left)/(lambda_right - lambda_left);
00449             /* Simple linear interpolation */
00450         
00451         /* Skip if lambda is not in this order */
00452         if (1 <= xguess && xguess <= nx) {
00453         x = uves_polynomial_solve_2d(dispersion, lambda*order, xguess,
00454                          1,                 /* multiplicity */
00455                          2,                 /* fix this variable number */
00456                          order);            /* ... to this value */
00457         
00458         /* Ignore if solve failed */
00459         if (cpl_error_get_code() != CPL_ERROR_NONE)
00460             {
00461             uves_error_reset();
00462             }
00463         else {
00464             /* Otherwise plot the solution */
00465             uves_msg_debug("lambda(x=%f)\t = %f", x     ,
00466                    uves_polynomial_evaluate_2d(dispersion, x     , order)/order);
00467             uves_msg_debug("lambda(x0=%f)\t = %f", xguess,
00468                    uves_polynomial_evaluate_2d(dispersion, xguess, order)/order);
00469             
00470             if (1 <= x && x <= nx) {
00471             double y = uves_polynomial_evaluate_2d(order_locations, x,
00472                                    relative_order[order]);
00473             int i;
00474             
00475             for (i = -3; i <= 3; i++) {
00476                 if (vertical) {
00477                 check( cpl_image_set(image,
00478                              uves_min_int(nx, uves_max_int(1, x    )),
00479                              uves_min_int(ny, uves_max_int(1, (int) y + i +
00480                                            offset)), 0),
00481                     "Error writing image");
00482                 }
00483                 else {
00484                 check( cpl_image_set(image, 
00485                              uves_min_int(nx, uves_max_int(1, x - i)),
00486                              uves_min_int(ny, uves_max_int(1, (int) y +
00487                                            offset)), 0),
00488                        "Error writing image");
00489                 }
00490             }
00491             }
00492         } /* Solve succeeded */
00493         } /* if lambda was inside this order */
00494         
00495     } /* for each order */
00496     
00497     } /* for each lambda */
00498     
00499   cleanup:
00500     return cpl_error_get_code();
00501 }
00502 

Generated on Mon Apr 21 10:56:57 2008 for UVES Pipeline Reference Manual by  doxygen 1.5.1