fors_tools.c

00001 /* $Id: fors_tools.c,v 1.21 2010/09/14 07:49:30 cizzo Exp $
00002  *
00003  * This file is part of the FORS Library
00004  * Copyright (C) 2002-2010 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  02110-1301 USA
00019  */
00020 
00021 /*
00022  * $Author: cizzo $
00023  * $Date: 2010/09/14 07:49:30 $
00024  * $Revision: 1.21 $
00025  * $Name: fors-4_8_6 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include <fors_tools.h>
00033 
00034 #include <fors_pfits.h>
00035 #include <fors_utils.h>
00036 
00037 #include <cpl.h>
00038 #include <math.h>
00039 #include <stdbool.h>
00040 #include <assert.h>
00041 
00042 /*----------------------------------------------------------------------------*/
00046 /*----------------------------------------------------------------------------*/
00047 
00050 #undef cleanup
00051 #define cleanup \
00052 do { \
00053     cpl_propertylist_delete(header); \
00054 } while(0)
00055 
00064 double
00065 fors_star_ext_corr(fors_star_list *stars, 
00066                    const fors_setting *setting,
00067                    double ext_coeff,
00068                    double dext_coeff,
00069                    const cpl_frame *raw_frame)
00070 {
00071     cpl_propertylist *header = NULL;
00072     
00073     
00074     cpl_msg_info(cpl_func, "Extinction correction");
00075     
00076     assure( cpl_frame_get_filename(raw_frame) != NULL, return -1, NULL );
00077     
00078     header = cpl_propertylist_load(cpl_frame_get_filename(raw_frame), 0);
00079     assure( !cpl_error_get_code(), return -1,
00080             "Failed to load %s primary header",
00081             cpl_frame_get_filename(raw_frame));
00082 
00083 
00084     double avg_airmass = fors_get_airmass(header);
00085     assure( !cpl_error_get_code(), return -1,
00086             "%s: Could not read airmass",
00087             cpl_frame_get_filename(raw_frame));
00088 
00089     cpl_msg_indent_more();
00090     cpl_msg_info(cpl_func, "Exposure time = %f s", setting->exposure_time);
00091     cpl_msg_info(cpl_func, "Gain          = %f ADU/e-", setting->average_gain);
00092     cpl_msg_info(cpl_func, "Ext. coeff.   = %f +- %f mag/airmass", 
00093                  ext_coeff, dext_coeff);
00094     cpl_msg_info(cpl_func, "Avg. airmass  = %f airmass", avg_airmass);  
00095     /* The quantity and the unit are both 'airmass' */
00096 
00097     cpl_msg_indent_less();
00098     
00099     {
00100         fors_star *star;
00101         
00102         for (star = fors_star_list_first(stars);
00103              star != NULL;
00104              star = fors_star_list_next(stars)) {
00105             star->magnitude_corr = star->magnitude 
00106                 + 2.5*log(setting->average_gain)/log(10)
00107                 + 2.5*log(setting->exposure_time)/log(10)
00108                 - ext_coeff * avg_airmass;
00109 
00110             /* Propagate error from ext.coeff.
00111                gain, exptime and airmass
00112                have zero error */
00113             star->dmagnitude_corr = sqrt(star->dmagnitude * star->dmagnitude
00114                                          + dext_coeff*dext_coeff * avg_airmass*avg_airmass);
00115         }
00116     }
00117 
00118     cleanup;
00119     return avg_airmass;
00120 }
00121 
00129 cpl_table *
00130 fors_create_sources_table(fors_star_list *sources)
00131 {
00132     cpl_table *t = NULL;
00133     
00134     t = cpl_table_new(fors_star_list_size(sources));
00135     cpl_table_new_column(t, "X", CPL_TYPE_DOUBLE);
00136     cpl_table_new_column(t, "Y", CPL_TYPE_DOUBLE);
00137     cpl_table_new_column(t, "FWHM", CPL_TYPE_DOUBLE);
00138     cpl_table_new_column(t, "A", CPL_TYPE_DOUBLE);
00139     cpl_table_new_column(t, "B", CPL_TYPE_DOUBLE);
00140     cpl_table_new_column(t, "THETA", CPL_TYPE_DOUBLE);
00141     cpl_table_new_column(t, "ELL", CPL_TYPE_DOUBLE);
00142     cpl_table_new_column(t, "INSTR_MAG", CPL_TYPE_DOUBLE);
00143     cpl_table_new_column(t, "DINSTR_MAG", CPL_TYPE_DOUBLE);
00144     cpl_table_new_column(t, "INSTR_CMAG", CPL_TYPE_DOUBLE);
00145     cpl_table_new_column(t, "DINSTR_CMAG", CPL_TYPE_DOUBLE);
00146     cpl_table_new_column(t, "CLASS_STAR", CPL_TYPE_DOUBLE);
00147 
00148     cpl_table_new_column(t, "OBJECT", CPL_TYPE_STRING);
00149     cpl_table_new_column(t, "RA", CPL_TYPE_DOUBLE);
00150     cpl_table_new_column(t, "DEC", CPL_TYPE_DOUBLE);
00151     cpl_table_new_column(t, "MAG", CPL_TYPE_DOUBLE);
00152     cpl_table_new_column(t, "DMAG", CPL_TYPE_DOUBLE);
00153     cpl_table_new_column(t, "CAT_MAG", CPL_TYPE_DOUBLE);
00154     cpl_table_new_column(t, "DCAT_MAG", CPL_TYPE_DOUBLE);
00155     cpl_table_new_column(t, "COLOR", CPL_TYPE_DOUBLE);
00156     cpl_table_new_column(t, "DCOLOR", CPL_TYPE_DOUBLE);
00157     cpl_table_new_column(t, "COV_CATM_COL", CPL_TYPE_DOUBLE);
00158     cpl_table_new_column(t, "USE_CAT", CPL_TYPE_INT);
00159     /* Shift in x and y between initial guess FITS header WCS position
00160        and measured position */
00161     cpl_table_new_column(t, "SHIFT_X", CPL_TYPE_DOUBLE); 
00162     cpl_table_new_column(t, "SHIFT_Y", CPL_TYPE_DOUBLE);
00163     cpl_table_new_column(t, "ZEROPOINT", CPL_TYPE_DOUBLE);
00164     cpl_table_new_column(t, "DZEROPOINT", CPL_TYPE_DOUBLE);
00165     cpl_table_new_column(t, "WEIGHT", CPL_TYPE_DOUBLE);
00166 
00167     {
00168         fors_star *s;
00169         int i;
00170         for (s = fors_star_list_first(sources), i = 0;
00171              s != NULL;
00172              s = fors_star_list_next(sources), i++) {
00173 
00174             const fors_std_star *id = s->id;
00175             
00176             cpl_table_set_double(t, "X", i, s->pixel->x);
00177             cpl_table_set_double(t, "Y", i, s->pixel->y);
00178             cpl_table_set_double(t, "FWHM", i, s->fwhm);
00179             cpl_table_set_double(t, "A", i, s->semi_major);
00180             cpl_table_set_double(t, "B", i, s->semi_minor);
00181             cpl_table_set_double(t, "THETA", i, s->orientation);
00182             cpl_table_set_double(t, "ELL", i, fors_star_ellipticity(s, NULL));
00183             cpl_table_set_double(t, "INSTR_MAG", i, s->magnitude);
00184             cpl_table_set_double(t, "DINSTR_MAG", i, s->dmagnitude);
00185             cpl_table_set_double(t, "INSTR_CMAG", i, s->magnitude_corr);
00186             cpl_table_set_double(t, "DINSTR_CMAG", i, s->dmagnitude_corr);
00187             cpl_table_set_double(t, "CLASS_STAR", i, s->stellarity_index);
00188             cpl_table_set_double(t, "WEIGHT", i, s->weight);
00189             
00190             if (id != NULL)
00191             {
00192                 cpl_table_set_string(t, "OBJECT",       i, id->name); /* possibly NULL */
00193                 cpl_table_set_double(t, "RA",           i, id->ra);
00194                 cpl_table_set_double(t, "DEC",          i, id->dec);
00195                 cpl_table_set_double(t, "MAG",          i, id->magnitude);
00196                 cpl_table_set_double(t, "DMAG",         i, id->dmagnitude);
00197                 cpl_table_set_double(t, "CAT_MAG",      i, id->cat_magnitude);
00198                 cpl_table_set_double(t, "DCAT_MAG",     i, id->dcat_magnitude);
00199                 cpl_table_set_double(t, "COLOR",        i, id->color);
00200                 cpl_table_set_double(t, "DCOLOR",       i, id->dcolor);
00201                 cpl_table_set_double(t, "COV_CATM_COL", i, id->cov_catm_color);
00202                 cpl_table_set_double(t, "SHIFT_X",      i,  s->pixel->x
00203                                                             - id->pixel->x);
00204                 cpl_table_set_double(t, "SHIFT_Y",      i,  s->pixel->y
00205                                                             - id->pixel->y);
00206                 cpl_table_set_double(t, "ZEROPOINT",    i, 
00207                                      fors_star_get_zeropoint(s, NULL));
00208                 cpl_table_set_double(t, "DZEROPOINT",   i, 
00209                                      fors_star_get_zeropoint_err(s, NULL));
00210                 /* fit this magnitude in fors_photometry? (fit = !trusted) */
00211                 cpl_table_set_int   (t, "USE_CAT",      i,
00212                                             ((id->trusted) ? 1 : 0));
00213             }
00214             else {
00215                 cpl_table_set_invalid(t, "RA" , i);
00216                 cpl_table_set_invalid(t, "DEC", i);
00217                 cpl_table_set_invalid(t, "MAG", i);
00218                 cpl_table_set_invalid(t, "DMAG", i);
00219                 cpl_table_set_invalid(t, "SHIFT_X", i);
00220                 cpl_table_set_invalid(t, "SHIFT_Y", i);
00221                 cpl_table_set_invalid(t, "ZEROPOINT", i);
00222                 cpl_table_set_invalid(t, "DZEROPOINT", i);
00223             }
00224         }
00225     }
00226 
00227     return t;
00228 }
00229 
00230 #undef cleanup
00231 #define cleanup \
00232 do { \
00233     fors_image_delete(&image); \
00234     fors_image_delete(&image2); \
00235 } while(0)
00236 
00243 double
00244 fors_fixed_pattern_noise(const fors_image *master,
00245                          double convert_ADU,
00246                          double master_noise)
00247 {
00248     double master_fixed_pattern_noise;
00249     fors_image *image = NULL;
00250     fors_image *image2 = NULL;
00251 
00252     assure( master != NULL, return -1, NULL );
00253 
00254     /* Use central 101x101 window 
00255        and 101x101 window shifted (10, 10) from center
00256     */
00257     if (fors_image_get_size_x(master) >= 121 &&
00258         fors_image_get_size_y(master) >= 121) {
00259         
00260         int mid_x = (fors_image_get_size_x(master) + 1) / 2;
00261         int mid_y = (fors_image_get_size_y(master) + 1) / 2;
00262         
00263         image = fors_image_duplicate(master);       
00264         fors_image_crop(image, 
00265                         mid_x - 50, mid_y - 50,
00266                         mid_x + 50, mid_y + 50);
00267         
00268         image2 = fors_image_duplicate(master);       
00269         fors_image_crop(image2, 
00270                         mid_x + 10 - 50, mid_y + 10 - 50,
00271                         mid_x + 10 + 50, mid_y + 10 + 50);
00272 
00273         fors_image_subtract(image, image2);
00274 
00275         master_fixed_pattern_noise = 
00276             fors_image_get_stdev(image, NULL) / sqrt(2);
00277 
00278         /* Convert to ADU */
00279         master_fixed_pattern_noise *= convert_ADU;
00280 
00281         /* Subtract photon noise */
00282         if (master_fixed_pattern_noise >= master_noise) {
00283             
00284             master_fixed_pattern_noise = sqrt(master_fixed_pattern_noise*
00285                                               master_fixed_pattern_noise
00286                                               -
00287                                               master_noise*
00288                                               master_noise);
00289         }
00290         else {
00291             cpl_msg_warning(cpl_func,
00292                             "Zero-shift noise (%f ADU) is greater than "
00293                             "accumulated zero-shift and fixed pattern noise (%f ADU), "
00294                             "setting fixed pattern noise to zero",
00295                             master_noise,
00296                             master_fixed_pattern_noise);
00297             master_fixed_pattern_noise = 0;
00298         }
00299     }
00300     else {
00301         cpl_msg_warning(cpl_func,
00302                         "Master flat too small (%dx%d), "
00303                         "need size 121x121 to compute master flat "
00304                         "fixed pattern noise",
00305                         fors_image_get_size_x(master),
00306                         fors_image_get_size_y(master));
00307         master_fixed_pattern_noise = -1;
00308     }
00309 
00310     cleanup;
00311     return master_fixed_pattern_noise;
00312 }
00313 
00314 
00315 #undef cleanup
00316 #define cleanup \
00317 do { \
00318     fors_image_delete(&image); \
00319     fors_image_delete(&image2); \
00320 } while(0)
00321 
00328 double
00329 fors_fixed_pattern_noise_bias(const fors_image *first_raw,
00330                               const fors_image *second_raw,
00331                               double ron)
00332 {
00333     double bias_fixed_pattern_noise;
00334     fors_image *image = NULL;
00335     fors_image *image2 = NULL;
00336     int nx, ny;
00337 
00338     assure( first_raw != NULL, return -1, NULL );
00339     assure( second_raw != NULL, return -1, NULL );
00340 
00341     /* 
00342      * Extract the largest possible two windows shifted (10, 10) 
00343      */
00344 
00345     nx = fors_image_get_size_x(first_raw);
00346     ny = fors_image_get_size_y(first_raw);
00347 
00348     image = fors_image_duplicate(first_raw);       
00349     fors_image_crop(image, 
00350                     1, 1,
00351                     nx - 10, ny - 10);
00352         
00353     image2 = fors_image_duplicate(second_raw);       
00354     fors_image_crop(image2, 
00355                     11, 11,
00356                     nx, ny);
00357 
00358     fors_image_subtract(image, image2);
00359 
00360     bias_fixed_pattern_noise = fors_image_get_stdev_robust(image, 50, NULL) 
00361                              / sqrt(2);
00362 
00363     /* 
00364      * Subtract ron quadratically
00365      */
00366 
00367     if (bias_fixed_pattern_noise > ron) {
00368             
00369         bias_fixed_pattern_noise = sqrt(bias_fixed_pattern_noise *
00370                                         bias_fixed_pattern_noise
00371                                         -
00372                                         ron * ron);
00373     }
00374     else {
00375         cpl_msg_warning(cpl_func,
00376                         "Zero-shift noise (%f ADU) is greater than "
00377                         "accumulated zero-shift and fixed pattern "
00378                         "noise (%f ADU), "
00379                         "setting fixed pattern noise to zero",
00380                         ron,
00381                         bias_fixed_pattern_noise);
00382         bias_fixed_pattern_noise = 0;
00383     }
00384 
00385     cleanup;
00386     return bias_fixed_pattern_noise;
00387 }
00388 
00389 
00390 #undef cleanup
00391 #define cleanup
00392 
00397 double
00398 fors_get_airmass(const cpl_propertylist *header)
00399 {
00400   double airmass_start, airmass_end;
00401   airmass_start = cpl_propertylist_get_double(header, FORS_PFITS_AIRMASS_START);
00402   assure( !cpl_error_get_code(), return -1, 
00403           "Could not read %s from header", 
00404           FORS_PFITS_AIRMASS_START);
00405   
00406   airmass_end = cpl_propertylist_get_double(header, FORS_PFITS_AIRMASS_END);
00407   assure( !cpl_error_get_code(), return -1,
00408           "Could not read %s from header", 
00409           FORS_PFITS_AIRMASS_END);
00410   
00411   return 0.5 * (airmass_start + airmass_end);
00412 }
00413 

Generated on Fri Mar 4 09:46:01 2011 for FORS Pipeline Reference Manual by  doxygen 1.4.7