uves_reduce_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: 2010/09/24 09:32:07 $
00023  * $Revision: 1.13 $
00024  * $Name: uves-4_9_1 $
00025  * $Log: uves_reduce_utils.c,v $
00026  * Revision 1.13  2010/09/24 09:32:07  amodigli
00027  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
00028  *
00029  * Revision 1.11  2007/06/06 08:17:33  amodigli
00030  * replace tab with 4 spaces
00031  *
00032  * Revision 1.10  2007/04/24 12:50:29  jmlarsen
00033  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00034  *
00035  * Revision 1.9  2007/04/10 07:09:37  jmlarsen
00036  * Changed interface of uves_spline_hermite()
00037  *
00038  * Revision 1.8  2006/11/06 15:19:41  jmlarsen
00039  * Removed unused include directives
00040  *
00041  * Revision 1.7  2006/08/17 13:56:53  jmlarsen
00042  * Reduced max line length
00043  *
00044  * Revision 1.6  2006/05/12 15:10:07  jmlarsen
00045  * Shortened lines
00046  *
00047  * Revision 1.5  2006/04/10 12:38:13  jmlarsen
00048  * Bugfix: don't read uninitialized memory (caused atmospheric extinction step 
00049  * to be randomly disabled)
00050  *
00051  * Revision 1.4  2006/04/06 08:49:23  jmlarsen
00052  * Propagate errors when normalizing spectrum
00053  *
00054  * Revision 1.3  2005/12/19 16:17:56  jmlarsen
00055  * Replaced bool -> int
00056  *
00057  * Revision 1.2  2005/12/16 14:22:23  jmlarsen
00058  * Removed midas test data; Added sof files
00059  *
00060  * Revision 1.1  2005/11/11 13:18:54  jmlarsen
00061  * Reorganized code, renamed source files
00062  *
00063  */
00064 
00065 #ifdef HAVE_CONFIG_H
00066 #  include <config.h>
00067 #endif
00068 
00069 /*----------------------------------------------------------------------------*/
00073 /*----------------------------------------------------------------------------*/
00076 /*-----------------------------------------------------------------------------
00077                                 Includes
00078  -----------------------------------------------------------------------------*/
00079 
00080 #include <uves_reduce_utils.h>
00081 
00082 #include <uves_pfits.h>
00083 #include <uves_utils.h>
00084 #include <uves_utils_wrappers.h>
00085 #include <uves_error.h>
00086 #include <uves_msg.h>
00087 
00088 #include <cpl.h>
00089 
00090 /*-----------------------------------------------------------------------------
00091                             Functions prototypes
00092  -----------------------------------------------------------------------------*/
00093 
00094 /*-----------------------------------------------------------------------------
00095                             Implementation
00096  -----------------------------------------------------------------------------*/
00097 
00098 /*----------------------------------------------------------------------------*/
00120 /*----------------------------------------------------------------------------*/
00121 cpl_image *
00122 uves_normalize_spectrum(const cpl_image *spectrum, const cpl_image *spectrum_error,
00123             const uves_propertylist *spectrum_header,
00124             const uves_propertylist *raw_header,
00125             int n_traces,
00126             enum uves_chip chip,
00127             const cpl_table *atm_extinction,
00128             bool correct_binning,
00129             cpl_image **scaled_error)
00130 {
00131     cpl_image *scaled = NULL;
00132     double exptime, gain;
00133     int binx;
00134     int norders, ny, nx;
00135     
00136     assure_nomsg( spectrum != NULL, CPL_ERROR_NULL_INPUT);
00137     assure_nomsg( scaled_error == NULL || spectrum_error != NULL, CPL_ERROR_NULL_INPUT);
00138     assure_nomsg( spectrum_header != NULL, CPL_ERROR_NULL_INPUT);
00139 
00140     nx = cpl_image_get_size_x(spectrum);
00141     ny = cpl_image_get_size_y(spectrum);
00142 
00143     if (spectrum_error != NULL)
00144     {
00145         assure( nx == cpl_image_get_size_x(spectrum_error) &&
00146             ny == cpl_image_get_size_y(spectrum_error), CPL_ERROR_INCOMPATIBLE_INPUT,
00147             "Error spectrum geometry differs from spectrum: %dx%d vs. %dx%d",
00148             cpl_image_get_size_x(spectrum_error),
00149             cpl_image_get_size_y(spectrum_error),
00150             nx, ny);
00151     }
00152     
00153     assure( ny % n_traces == 0, CPL_ERROR_INCOMPATIBLE_INPUT,
00154         "Spectrum image height (%d) is not a multiple of "
00155         "the number of traces (%d). Confused, bailing out",
00156         ny, n_traces);
00157     
00158     norders = ny / n_traces;
00159 
00160     /*
00161      * Correct for exposure time, gain, bin 
00162      */
00163     check( exptime = uves_pfits_get_exptime(raw_header),
00164        "Could not read exposure time");
00165     
00166     check( gain = uves_pfits_get_gain(raw_header, chip),
00167        "Could not read gain factor");
00168     
00169     if (correct_binning)
00170     {
00171         /* x-binning of rotated image is y-binning of raw image */
00172         check( binx  = uves_pfits_get_biny(raw_header),
00173            "Could not read binning");
00174     }
00175     else
00176     {
00177         uves_msg("Spectrum will not be normalized to unit binning");
00178         binx = 1;
00179     }
00180     
00181     assure( exptime > 0, CPL_ERROR_ILLEGAL_INPUT, "Non-positive exposure time: %f s", exptime);
00182     assure( gain    > 0, CPL_ERROR_ILLEGAL_INPUT, "Non-positive gain: %f", gain);
00183     assure( binx    > 0, CPL_ERROR_ILLEGAL_INPUT, "Illegal binning: %d", binx);
00184     
00185     uves_msg("Correcting for exposure time = %f s, gain = %f, binx = %d", exptime, gain, binx);
00186     
00187     check( scaled        = cpl_image_divide_scalar_create(spectrum, exptime * gain * binx),
00188        "Error correcting spectrum for gain, exposure time, binning");
00189     
00190     if (scaled_error != NULL)
00191     {
00192         check( *scaled_error = cpl_image_divide_scalar_create(spectrum_error, 
00193                                   exptime * gain * binx),
00194            "Error correcting rebinned spectrum for gain, exposure time, binning");
00195     }
00196     
00197     /* 
00198      * Correct for atmospheric extinction 
00199      */
00200     {
00201     double airmass;
00202     double dlambda, lambda_start;
00203     int order;
00204 
00205     {
00206         double airmass_start, airmass_end;
00207         
00208         check( airmass_start = uves_pfits_get_airmass_start(raw_header),
00209            "Error reading airmass start");
00210         
00211         check( airmass_end = uves_pfits_get_airmass_end(raw_header),
00212            "Error reading airmass end");
00213         
00214         /* Use arithmetic mean of airmass start/end */
00215         airmass = (airmass_start + airmass_end) / 2;
00216     
00217     }
00218 
00219     uves_msg("Correcting for extinction through airmass %f", airmass);
00220         
00221     check( dlambda = uves_pfits_get_cdelt1(spectrum_header),
00222            "Error reading bin width from header");
00223     
00224     for (order = 1; order <= norders; order++)
00225         {
00226         int trace;
00227 
00228         /* If spectrum was already merged, then read crval1,
00229          * otherwise read wstart for each order
00230          */
00231         
00232         if (norders == 1)
00233             {
00234             check( lambda_start = uves_pfits_get_crval1(spectrum_header),
00235                    "Error reading start wavelength from header");    
00236             }
00237         else
00238             {
00239             check( lambda_start = uves_pfits_get_wstart(spectrum_header, order),
00240                    "Error reading start wavelength from header");    
00241             }
00242 
00243         for (trace = 1; trace <= n_traces; trace++)
00244             {
00245             int spectrum_row = (order - 1)*n_traces + trace;
00246             int x;
00247             
00248             for (x = 1; x <= nx; x++)
00249                 {
00250                 int pis_rejected1;
00251                 int pis_rejected2;
00252                 double flux;
00253                 double dflux = 0;
00254                 double extinction;
00255                 double lambda;
00256 
00257                 lambda = lambda_start + (x-1) * dlambda;
00258                 
00259                 flux  = cpl_image_get(scaled, x, spectrum_row, &pis_rejected1);
00260                 if (scaled_error != NULL)
00261                     {
00262                     dflux = cpl_image_get(*scaled_error, x, 
00263                                   spectrum_row, &pis_rejected2);
00264                     }
00265 
00266                 if (!pis_rejected1 && (scaled_error == NULL || !pis_rejected2))
00267                     {
00268                                         int istart = 0;
00269 
00270                     /* Read extinction (units: magnitude per airmass) */
00271                     check( extinction = 
00272                            uves_spline_hermite_table(
00273                            lambda, atm_extinction,
00274                            "LAMBDA", "LA_SILLA", &istart),
00275                            "Error interpolating extinction coefficient");
00276                     
00277                     /* Correct for extinction using
00278                      * the magnitude/flux relation
00279                      * m = -2.5 log_10 F
00280                      *  => 
00281                      * F = 10^(-m*0.4)
00282                      *
00283                      * m_top-of-atmosphere = m - ext.coeff*airmass
00284                      * F_top-of-atmosphere = F * 10^(0.4 * ext.coeff*airmass)
00285                      */
00286 
00287                     cpl_image_set(
00288                         scaled, x, spectrum_row,
00289                         flux * pow(10, 0.4 * extinction * airmass));
00290                     if (scaled_error != NULL)
00291                         {
00292                         cpl_image_set(
00293                             *scaled_error, x, spectrum_row,
00294                             dflux * pow(10, 0.4 * extinction * airmass));
00295                         }
00296                     }
00297                 else
00298                     {
00299                     cpl_image_reject(scaled, x, spectrum_row);
00300                     if (scaled_error != NULL)
00301                         {
00302                         cpl_image_reject(*scaled_error, x, spectrum_row);
00303                         }
00304                     }
00305                 } /* for each x */
00306 
00307             } /* for each (possibly only 1) trace */
00308 
00309         } /* for each (possibly only 1) order */
00310     }
00311     
00312   cleanup:
00313     if (cpl_error_get_code() != CPL_ERROR_NONE)
00314     {
00315         uves_free_image(&scaled);
00316         if (scaled_error != NULL)
00317         {
00318             uves_free_image(scaled_error);
00319         }
00320     }
00321     
00322     return scaled;
00323 }
00324 

Generated on 8 Mar 2011 for UVES Pipeline Reference Manual by  doxygen 1.6.1