FORS Pipeline Reference Manual 4.9.9
|
00001 /* $Id: fors_img_science_impl.c,v 1.48 2011/07/20 12:07:24 cgarcia 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: cgarcia $ 00023 * $Date: 2011/07/20 12:07:24 $ 00024 * $Revision: 1.48 $ 00025 * $Name: fors-4_9_9 $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 #include <fors_img_science_impl.h> 00033 00034 #include <fors_extract.h> 00035 #include <fors_tools.h> 00036 #include <fors_setting.h> 00037 #include <fors_data.h> 00038 #include <fors_image.h> 00039 #include <fors_qc.h> 00040 #include <fors_dfs.h> 00041 #include <fors_utils.h> 00042 00043 #include <cpl.h> 00044 #include <math.h> 00045 #include <stdbool.h> 00046 00053 const char *const fors_img_science_name = "fors_img_science"; 00054 const char *const fors_img_science_description_short = "Reduce scientific exposure"; 00055 const char *const fors_img_science_author = "Jonas M. Larsen"; 00056 const char *const fors_img_science_email = PACKAGE_BUGREPORT; 00057 const char *const fors_img_science_description = 00058 "Input files:\n" 00059 " DO category: Type: Explanation: Number:\n" 00060 " SCIENCE_IMG Raw Science image 1\n" 00061 " MASTER_BIAS FITS image Master bias 1\n" 00062 " MASTER_SKY_FLAT_IMG FITS image Master sky flat field 1\n" 00063 "\n" 00064 "Output files:\n" 00065 " DO category: Data type: Explanation:\n" 00066 " SCIENCE_REDUCED_IMG FITS image Reduced science image\n" 00067 " PHOT_BACKGROUND_SCI_IMG FITS image Reduced science image background\n" 00068 " SOURCES_SCI_IMG FITS image Unfiltered SExtractor output\n" 00069 " OBJECT_TABLE_SCI_IMG FITS table Extracted sources properties\n"; 00070 00071 00072 static double 00073 get_image_quality(const fors_star_list *sources, double *image_quality_err, 00074 double *stellarity, 00075 double *ellipticity, 00076 double *ellipticity_rms); 00077 00078 #undef cleanup 00079 #define cleanup \ 00080 do { \ 00081 cpl_free((void *)full_name); \ 00082 } while (0) 00083 00089 void fors_img_science_define_parameters(cpl_parameterlist *parameters) 00090 { 00091 cpl_parameter *p; 00092 const char *context = cpl_sprintf("fors.%s", fors_img_science_name); 00093 const char *full_name = NULL; 00094 const char *name; 00095 00096 /* This parameter is not yet implemented 00097 name = "cr_remove"; 00098 full_name = cpl_sprintf("%s.%s", context, name); 00099 p = cpl_parameter_new_value(full_name, 00100 CPL_TYPE_BOOL, 00101 "Cosmic ray removal", 00102 context, 00103 false); 00104 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name); 00105 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00106 cpl_parameterlist_append(parameters, p); 00107 cpl_free((void *)full_name); full_name = NULL; 00108 */ 00109 00110 name = "magsyserr"; 00111 full_name = cpl_sprintf("%s.%s", context, name); 00112 p = cpl_parameter_new_value(full_name, 00113 CPL_TYPE_DOUBLE, 00114 "Systematic error in magnitude", 00115 context, 00116 0.01); 00117 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name); 00118 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00119 cpl_parameterlist_append(parameters, p); 00120 cpl_free((void *)full_name); full_name = NULL; 00121 00122 fors_extract_define_parameters(parameters, context); 00123 00124 cpl_free((void *)context); 00125 00126 return; 00127 } 00128 00129 00130 #undef cleanup 00131 #define cleanup \ 00132 do { \ 00133 cpl_frameset_delete(sci_frame); \ 00134 cpl_frameset_delete(master_bias_frame); \ 00135 cpl_frameset_delete(master_flat_frame); \ 00136 fors_image_delete(&sci); \ 00137 fors_image_delete_const(&master_bias); \ 00138 fors_image_delete(&master_flat); \ 00139 cpl_table_delete(phot); \ 00140 cpl_table_delete(sources); \ 00141 cpl_image_delete(background); \ 00142 fors_extract_method_delete(&em); \ 00143 fors_star_list_delete(&stars, fors_star_delete); \ 00144 cpl_free((void *)context); \ 00145 fors_setting_delete(&setting); \ 00146 cpl_propertylist_delete(qc); \ 00147 cpl_propertylist_delete(product_header); \ 00148 cpl_propertylist_delete(header); \ 00149 } while (0) 00150 00151 /* %%% Removed from cleanup 00152 cpl_frameset_delete(phot_table); \ 00153 */ 00154 00161 void fors_img_science(cpl_frameset *frames, const cpl_parameterlist *parameters) 00162 { 00163 /* Raw */ 00164 cpl_frameset *sci_frame = NULL; 00165 fors_image *sci = NULL; 00166 00167 /* Calibration */ 00168 cpl_frameset *master_bias_frame = NULL; 00169 const fors_image *master_bias = NULL; 00170 00171 cpl_frameset *master_flat_frame = NULL; 00172 fors_image *master_flat = NULL; 00173 00174 /* %%% 00175 cpl_frameset *phot_table = NULL; 00176 double ext_coeff, dext_coeff; 00177 */ 00178 00179 /* Products */ 00180 cpl_propertylist *qc = cpl_propertylist_new(); 00181 cpl_propertylist *product_header = cpl_propertylist_new(); 00182 cpl_propertylist *header = NULL; 00183 cpl_table *phot = NULL; 00184 fors_extract_sky_stats sky_stats; 00185 cpl_image *background = NULL; 00186 cpl_table *sources = NULL; 00187 00188 /* Parameters */ 00189 extract_method *em = NULL; 00190 double magsyserr; 00191 00192 /* Other */ 00193 const char *context = cpl_sprintf("fors.%s", fors_img_science_name); 00194 fors_star_list *stars = NULL; 00195 fors_setting *setting = NULL; 00196 double avg_airmass = 0.0; 00197 char *name; 00198 00199 /* Get parameters */ 00200 em = fors_extract_method_new(parameters, context); 00201 assure( !cpl_error_get_code(), return, 00202 "Could not get extraction parameters" ); 00203 00204 cpl_msg_indent_more(); 00205 name = cpl_sprintf("%s.%s", context, "magsyserr"); 00206 magsyserr = dfs_get_parameter_double_const(parameters, 00207 name); 00208 cpl_free((void *)name); name = NULL; 00209 cpl_msg_indent_less(); 00210 assure( !cpl_error_get_code(), return, NULL ); 00211 assure( magsyserr >= 0, return, 00212 "Input systematic error (magsyserr=%f) cannot be negative", 00213 magsyserr); 00214 00215 /* Find raw */ 00216 sci_frame = fors_frameset_extract(frames, SCIENCE_IMG); 00217 assure( cpl_frameset_get_size(sci_frame) == 1, return, 00218 "Exactly 1 %s required. %d found", 00219 SCIENCE_IMG, cpl_frameset_get_size(sci_frame) ); 00220 00221 /* Find calibration */ 00222 master_bias_frame = fors_frameset_extract(frames, MASTER_BIAS); 00223 assure( cpl_frameset_get_size(master_bias_frame) == 1, return, 00224 "One %s required. %d found", 00225 MASTER_BIAS, cpl_frameset_get_size(master_bias_frame) ); 00226 00227 master_flat_frame = fors_frameset_extract(frames, MASTER_SKY_FLAT_IMG); 00228 assure( cpl_frameset_get_size(master_flat_frame) == 1, return, 00229 "One %s required. %d found", 00230 MASTER_SKY_FLAT_IMG, cpl_frameset_get_size(master_flat_frame) ); 00231 00232 /* %%% 00233 phot_table = fors_frameset_extract(frames, PHOT_TABLE); 00234 assure( cpl_frameset_get_size(phot_table) == 1, return, 00235 "One %s required. %d found", 00236 PHOT_TABLE, cpl_frameset_get_size(phot_table)); 00237 */ 00238 00239 /* Done finding frames */ 00240 00241 /* Get instrument setting */ 00242 setting = fors_setting_new(cpl_frameset_get_first(sci_frame)); 00243 assure( !cpl_error_get_code(), return, "Could not get instrument setting" ); 00244 00245 00246 master_bias = fors_image_load(cpl_frameset_get_first(master_bias_frame), 00247 NULL, setting, NULL); 00248 assure( !cpl_error_get_code(), return, 00249 "Could not load master bias"); 00250 00251 /* Load raw frames, subtract bias */ 00252 sci = fors_image_load(cpl_frameset_get_first(sci_frame), master_bias, 00253 setting, NULL); 00254 assure( !cpl_error_get_code(), return, "Could not load standard image"); 00255 fors_image_delete_const(&master_bias); 00256 00257 /* Load master flat */ 00258 master_flat = fors_image_load(cpl_frameset_get_first(master_flat_frame), 00259 NULL, setting, NULL); 00260 assure( !cpl_error_get_code(), return, "Could not load master flat"); 00261 00262 /* Divide by normalized flat */ 00263 fors_image_divide_scalar(master_flat, 00264 fors_image_get_median(master_flat, NULL), -1.0); 00265 00266 fors_image_divide(sci, master_flat); 00267 assure( !cpl_error_get_code(), return, "Could not divide by master flat"); 00268 fors_image_delete(&master_flat); 00269 00270 /* Extract sources */ 00271 stars = fors_extract(sci, setting, em, magsyserr, 00272 &sky_stats, &background, &sources); 00273 assure( !cpl_error_get_code(), return, "Could not extract objects"); 00274 00275 /* QC */ 00276 fors_qc_start_group(qc, fors_qc_dic_version, setting->instrument); 00277 00278 fors_qc_write_group_heading(cpl_frameset_get_first(sci_frame), 00279 PHOTOMETRY_TABLE, 00280 setting->instrument); 00281 assure( !cpl_error_get_code(), return, "Could not write %s QC parameters", 00282 PHOTOMETRY_TABLE); 00283 00284 00285 double sky_mag; 00286 double sky_mag_rms; 00287 if (sky_stats.mean > 0) { 00288 sky_mag = -2.5*log(sky_stats.mean / 00289 (setting->pixel_scale*setting->pixel_scale))/log(10); 00290 } 00291 else { 00292 cpl_msg_warning(cpl_func, 00293 "Average sky background is negative (%f ADU), " 00294 "cannot compute magnitude, setting QC.SKYAVG to 99999.", 00295 sky_stats.mean); 00296 sky_mag = 99999.; 00297 } 00298 fors_qc_write_qc_double(qc, 00299 sky_mag, 00300 "QC.SKYAVG", 00301 "mag/arcsec^2", 00302 "Mean of sky background", 00303 setting->instrument); 00304 00305 if (sky_stats.median > 0) { 00306 sky_mag = -2.5*log(sky_stats.median / 00307 (setting->pixel_scale*setting->pixel_scale))/log(10); 00308 /* deltaM = -2.5*log10(e)*deltaF/F */ 00309 sky_mag_rms = fabs(-2.5 * (1.0/log(10))*sky_stats.rms/sky_stats.median); 00310 } 00311 else { 00312 cpl_msg_warning(cpl_func, 00313 "Median sky background is negative (%f ADU), " 00314 "cannot compute magnitude: setting both QC.SKYMED " 00315 "and QC.SKYRMS to 99999.", 00316 sky_mag); 00317 sky_mag = 99999.; 00318 sky_mag_rms = 99999.; 00319 } 00320 fors_qc_write_qc_double(qc, 00321 sky_mag, 00322 "QC.SKYMED", 00323 "mag/arcsec^2", 00324 "Median of sky background", 00325 setting->instrument); 00326 00327 fors_qc_write_qc_double(qc, 00328 sky_mag_rms, 00329 "QC.SKYRMS", 00330 "mag/arcsec^2", 00331 "Standard deviation of sky background", 00332 setting->instrument); 00333 00334 double image_quality_error; 00335 double stellarity; 00336 double ellipticity, ellipticity_rms; 00337 double image_quality = get_image_quality(stars, 00338 &image_quality_error, 00339 &stellarity, 00340 &ellipticity, 00341 &ellipticity_rms); 00342 00343 if (image_quality > 0.) { 00344 image_quality *= TWOSQRT2LN2 * setting->pixel_scale; 00345 image_quality_error *= TWOSQRT2LN2 * setting->pixel_scale; 00346 } 00347 00348 fors_qc_write_qc_double(qc, 00349 image_quality, 00350 "QC.IMGQU", 00351 "arcsec", 00352 "Image quality of scientific exposure", 00353 setting->instrument); 00354 00355 fors_qc_write_qc_double(qc, 00356 image_quality_error, 00357 "QC.IMGQUERR", 00358 "arcsec", 00359 "Uncertainty of image quality", 00360 setting->instrument); 00361 00362 fors_qc_write_qc_double(qc, 00363 stellarity, 00364 "QC.STELLAVG", 00365 NULL, 00366 "Mean stellarity index", 00367 setting->instrument); 00368 00369 fors_qc_write_qc_double(qc, 00370 ellipticity, 00371 "QC.IMGQUELL", 00372 NULL, 00373 "Mean star ellipticity", 00374 setting->instrument); 00375 00376 fors_qc_write_qc_double(qc, 00377 ellipticity_rms, 00378 "QC.IMGQUELLERR", 00379 NULL, 00380 "Standard deviation of star ellipticities", 00381 setting->instrument); 00382 00383 fors_qc_end_group(); 00384 00385 /* Save SCIENCE_REDUCED, PHOT_BACKGROUND_SCI_IMG */ 00386 00387 /* %%% */ 00388 00389 header = cpl_propertylist_load( 00390 cpl_frame_get_filename( 00391 cpl_frameset_get_first(sci_frame)), 0); 00392 00393 if (header == NULL) { 00394 cpl_msg_error(cpl_func, "Failed to load raw header"); 00395 cleanup; 00396 return; 00397 } 00398 00399 avg_airmass = fors_get_airmass(header); 00400 00401 cpl_propertylist_update_double(qc, "AIRMASS", avg_airmass); 00402 cpl_propertylist_update_double(product_header, "AIRMASS", avg_airmass); 00403 00404 /* %%% */ 00405 00406 fors_dfs_add_wcs(qc, cpl_frameset_get_first(sci_frame), setting); 00407 fors_dfs_add_exptime(qc, cpl_frameset_get_first(sci_frame), 0.); 00408 fors_dfs_add_wcs(product_header, cpl_frameset_get_first(sci_frame), 00409 setting); 00410 fors_dfs_add_exptime(product_header, cpl_frameset_get_first(sci_frame), 0.); 00411 00412 fors_dfs_save_image(frames, sci, SCIENCE_REDUCED_IMG, 00413 qc, parameters, fors_img_science_name, 00414 cpl_frameset_get_first(sci_frame)); 00415 assure( !cpl_error_get_code(), return, "Saving %s failed", 00416 SCIENCE_REDUCED_IMG); 00417 00418 fors_image_delete(&sci); 00419 00420 dfs_save_image(frames, background, PHOT_BACKGROUND_SCI_IMG, 00421 product_header, parameters, fors_img_science_name, 00422 setting->version); 00423 assure( !cpl_error_get_code(), return, "Saving %s failed", 00424 PHOT_BACKGROUND_SCI_IMG); 00425 00426 cpl_image_delete(background); background = NULL; 00427 00428 /* Load filter coefficients */ 00429 00430 /* %%% 00431 fors_phot_table_load(cpl_frameset_get_first(phot_table), setting, 00432 NULL, NULL, 00433 &ext_coeff, &dext_coeff, 00434 NULL, NULL); 00435 assure( !cpl_error_get_code(), return, "Could not load photometry table" ); 00436 */ 00437 00438 /* Correct for atmospheric extinction */ 00439 /* %%% 00440 fors_star_ext_corr(stars, setting, ext_coeff, dext_coeff, 00441 cpl_frameset_get_first(sci_frame)); 00442 assure( !cpl_error_get_code(), return, 00443 "Extinction correction failed"); 00444 */ 00445 00446 /* Create, save FITS product */ 00447 phot = fors_create_sources_table(stars); 00448 assure( !cpl_error_get_code(), return, 00449 "Failed to create extracted sources table"); 00450 00451 /* 00452 * Eliminate unused columns from photometry table 00453 */ 00454 00455 cpl_table_erase_column(phot, "INSTR_CMAG"); 00456 cpl_table_erase_column(phot, "DINSTR_CMAG"); 00457 cpl_table_erase_column(phot, "OBJECT"); 00458 cpl_table_erase_column(phot, "MAG"); 00459 cpl_table_erase_column(phot, "DMAG"); 00460 cpl_table_erase_column(phot, "CAT_MAG"); 00461 cpl_table_erase_column(phot, "DCAT_MAG"); 00462 cpl_table_erase_column(phot, "COLOR"); 00463 /* new columns since 4.4.10 */ 00464 if (cpl_table_has_column(phot, "DCOLOR")) 00465 cpl_table_erase_column(phot, "DCOLOR"); 00466 if (cpl_table_has_column(phot, "COV_CATM_COL")) 00467 cpl_table_erase_column(phot, "COV_CATM_COL"); 00468 cpl_table_erase_column(phot, "USE_CAT"); 00469 cpl_table_erase_column(phot, "SHIFT_X"); 00470 cpl_table_erase_column(phot, "SHIFT_Y"); 00471 cpl_table_erase_column(phot, "ZEROPOINT"); 00472 cpl_table_erase_column(phot, "DZEROPOINT"); 00473 cpl_table_erase_column(phot, "WEIGHT"); 00474 00475 fors_dfs_save_table(frames, sources, SOURCES_SCI, 00476 NULL, parameters, fors_img_science_name, 00477 cpl_frameset_get_first(sci_frame)); 00478 assure( !cpl_error_get_code(), return, "Saving %s failed", 00479 SOURCES_SCI); 00480 00481 fors_dfs_save_table(frames, phot, PHOTOMETRY_TABLE, 00482 NULL, parameters, fors_img_science_name, 00483 cpl_frameset_get_first(sci_frame)); 00484 assure( !cpl_error_get_code(), return, "Saving %s failed", 00485 PHOTOMETRY_TABLE); 00486 00487 cleanup; 00488 return; 00489 } 00490 00491 #undef cleanup 00492 #define cleanup 00493 00499 static bool 00500 is_star(const fors_star *s, void *data) 00501 { 00502 data = data; 00503 assure( s != NULL, return false, NULL ); 00504 00505 /*FIXME 00506 All stars for the moment... */ 00507 00508 return s->stellarity_index >= 0.7; 00509 } 00510 00511 #undef cleanup 00512 #define cleanup \ 00513 do { \ 00514 fors_star_list_delete(&stars, fors_star_delete); \ 00515 } while(0) 00516 00529 static double 00530 get_image_quality(const fors_star_list *sources, double *image_quality_err, 00531 double *stellarity, 00532 double *ellipticity, 00533 double *ellipticity_rms) 00534 { 00535 fors_star_list *stars = fors_star_list_extract(sources, 00536 fors_star_duplicate, 00537 is_star, NULL); 00538 00539 double fwhm; 00540 if (fors_star_list_size(stars) >= 1) { 00541 *image_quality_err = fors_star_list_mad(stars, fors_star_extension, NULL) 00542 * STDEV_PR_MAD; 00543 00544 fwhm = fors_star_list_median(stars, fors_star_extension , NULL); 00545 00546 *stellarity = fors_star_list_mean(stars, fors_star_stellarity, NULL); 00547 *ellipticity = fors_star_list_mean(stars, fors_star_ellipticity, NULL); 00548 *ellipticity_rms = fors_star_list_mad(stars, fors_star_ellipticity, NULL) 00549 * STDEV_PR_MAD; 00550 } 00551 else { 00552 cpl_msg_warning(cpl_func, "No stars found! Cannot compute image quality, " 00553 "setting QC parameters to -1"); 00554 00555 /* -1 is not a valid value for any of these */ 00556 *image_quality_err = -1; 00557 fwhm = -1; 00558 *stellarity = -1; 00559 *ellipticity = -1; 00560 *ellipticity_rms = -1; 00561 } 00562 00563 cleanup; 00564 return fwhm; 00565 } 00566