00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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 name = "cr_remove";
00097 full_name = cpl_sprintf("%s.%s", context, name);
00098 p = cpl_parameter_new_value(full_name,
00099 CPL_TYPE_BOOL,
00100 "Cosmic ray removal",
00101 context,
00102 false);
00103 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00104 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00105 cpl_parameterlist_append(parameters, p);
00106 cpl_free((void *)full_name); full_name = NULL;
00107
00108 fors_extract_define_parameters(parameters, context);
00109
00110 cpl_free((void *)context);
00111
00112 return;
00113 }
00114
00115
00116 #undef cleanup
00117 #define cleanup \
00118 do { \
00119 cpl_frameset_delete(sci_frame); \
00120 cpl_frameset_delete(master_bias_frame); \
00121 cpl_frameset_delete(master_flat_frame); \
00122 fors_image_delete(&sci); \
00123 fors_image_delete_const(&master_bias); \
00124 fors_image_delete(&master_flat); \
00125 cpl_table_delete(phot); \
00126 cpl_table_delete(sources); \
00127 cpl_image_delete(background); \
00128 fors_extract_method_delete(&em); \
00129 fors_star_list_delete(&stars, fors_star_delete); \
00130 cpl_free((void *)context); \
00131 fors_setting_delete(&setting); \
00132 cpl_propertylist_delete(qc); \
00133 cpl_propertylist_delete(product_header); \
00134 cpl_propertylist_delete(header); \
00135 } while (0)
00136
00137
00138
00139
00140
00147 void fors_img_science(cpl_frameset *frames, const cpl_parameterlist *parameters)
00148 {
00149
00150 cpl_frameset *sci_frame = NULL;
00151 fors_image *sci = NULL;
00152
00153
00154 cpl_frameset *master_bias_frame = NULL;
00155 const fors_image *master_bias = NULL;
00156
00157 cpl_frameset *master_flat_frame = NULL;
00158 fors_image *master_flat = NULL;
00159
00160
00161
00162
00163
00164
00165
00166 cpl_propertylist *qc = cpl_propertylist_new();
00167 cpl_propertylist *product_header = cpl_propertylist_new();
00168 cpl_propertylist *header = NULL;
00169 cpl_table *phot = NULL;
00170 fors_extract_sky_stats sky_stats;
00171 cpl_image *background = NULL;
00172 cpl_table *sources = NULL;
00173
00174
00175 extract_method *em = NULL;
00176
00177
00178 const char *context = cpl_sprintf("fors.%s", fors_img_science_name);
00179 fors_star_list *stars = NULL;
00180 fors_setting *setting = NULL;
00181 double avg_airmass = 0.0;
00182
00183
00184 em = fors_extract_method_new(parameters, context);
00185 assure( !cpl_error_get_code(), return,
00186 "Could not get extraction parameters" );
00187
00188
00189 sci_frame = fors_frameset_extract(frames, SCIENCE_IMG);
00190 assure( cpl_frameset_get_size(sci_frame) == 1, return,
00191 "Exactly 1 %s required. %d found",
00192 SCIENCE_IMG, cpl_frameset_get_size(sci_frame) );
00193
00194
00195 master_bias_frame = fors_frameset_extract(frames, MASTER_BIAS);
00196 assure( cpl_frameset_get_size(master_bias_frame) == 1, return,
00197 "One %s required. %d found",
00198 MASTER_BIAS, cpl_frameset_get_size(master_bias_frame) );
00199
00200 master_flat_frame = fors_frameset_extract(frames, MASTER_SKY_FLAT_IMG);
00201 assure( cpl_frameset_get_size(master_flat_frame) == 1, return,
00202 "One %s required. %d found",
00203 MASTER_SKY_FLAT_IMG, cpl_frameset_get_size(master_flat_frame) );
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 setting = fors_setting_new(cpl_frameset_get_first(sci_frame));
00216 assure( !cpl_error_get_code(), return, "Could not get instrument setting" );
00217
00218
00219 master_bias = fors_image_load(cpl_frameset_get_first(master_bias_frame),
00220 NULL, setting, NULL);
00221 assure( !cpl_error_get_code(), return,
00222 "Could not load master bias");
00223
00224
00225 sci = fors_image_load(cpl_frameset_get_first(sci_frame), master_bias,
00226 setting, NULL);
00227 assure( !cpl_error_get_code(), return, "Could not load standard image");
00228 fors_image_delete_const(&master_bias);
00229
00230
00231 master_flat = fors_image_load(cpl_frameset_get_first(master_flat_frame),
00232 NULL, setting, NULL);
00233 assure( !cpl_error_get_code(), return, "Could not load master flat");
00234
00235
00236 fors_image_divide_scalar(master_flat,
00237 fors_image_get_median(master_flat, NULL), -1.0);
00238
00239 fors_image_divide(sci, master_flat);
00240 assure( !cpl_error_get_code(), return, "Could not divide by master flat");
00241 fors_image_delete(&master_flat);
00242
00243
00244 stars = fors_extract(sci, setting, em,
00245 &sky_stats, &background, &sources);
00246 assure( !cpl_error_get_code(), return, "Could not extract objects");
00247
00248
00249 fors_qc_start_group(qc, fors_qc_dic_version, setting->instrument);
00250
00251 fors_qc_write_group_heading(cpl_frameset_get_first(sci_frame),
00252 PHOTOMETRY_TABLE,
00253 setting->instrument);
00254 assure( !cpl_error_get_code(), return, "Could not write %s QC parameters",
00255 PHOTOMETRY_TABLE);
00256
00257
00258 double sky_mag;
00259 double sky_mag_rms;
00260 if (sky_stats.mean > 0) {
00261 sky_mag = -2.5*log(sky_stats.mean /
00262 (setting->pixel_scale*setting->pixel_scale))/log(10);
00263 }
00264 else {
00265 cpl_msg_warning(cpl_func,
00266 "Average sky background is negative (%f ADU), "
00267 "cannot compute magnitude, setting QC.SKYAVG to 99999.",
00268 sky_stats.mean);
00269 sky_mag = 99999.;
00270 }
00271 fors_qc_write_qc_double(qc,
00272 sky_mag,
00273 "QC.SKYAVG",
00274 "mag/arcsec^2",
00275 "Mean of sky background",
00276 setting->instrument);
00277
00278 if (sky_stats.median > 0) {
00279 sky_mag = -2.5*log(sky_stats.median /
00280 (setting->pixel_scale*setting->pixel_scale))/log(10);
00281
00282 sky_mag_rms = fabs(-2.5 * (1.0/log(10))*sky_stats.rms/sky_stats.median);
00283 }
00284 else {
00285 cpl_msg_warning(cpl_func,
00286 "Median sky background is negative (%f ADU), "
00287 "cannot compute magnitude: setting both QC.SKYMED "
00288 "and QC.SKYRMS to 99999.",
00289 sky_mag);
00290 sky_mag = 99999.;
00291 sky_mag_rms = 99999.;
00292 }
00293 fors_qc_write_qc_double(qc,
00294 sky_mag,
00295 "QC.SKYMED",
00296 "mag/arcsec^2",
00297 "Median of sky background",
00298 setting->instrument);
00299
00300 fors_qc_write_qc_double(qc,
00301 sky_mag_rms,
00302 "QC.SKYRMS",
00303 "mag/arcsec^2",
00304 "Standard deviation of sky background",
00305 setting->instrument);
00306
00307 double image_quality_error;
00308 double stellarity;
00309 double ellipticity, ellipticity_rms;
00310 double image_quality = get_image_quality(stars,
00311 &image_quality_error,
00312 &stellarity,
00313 &ellipticity,
00314 &ellipticity_rms);
00315
00316 if (image_quality > 0.) {
00317 image_quality *= TWOSQRT2LN2 * setting->pixel_scale;
00318 image_quality_error *= TWOSQRT2LN2 * setting->pixel_scale;
00319 }
00320
00321 fors_qc_write_qc_double(qc,
00322 image_quality,
00323 "QC.IMGQU",
00324 "arcsec",
00325 "Image quality of scientific exposure",
00326 setting->instrument);
00327
00328 fors_qc_write_qc_double(qc,
00329 image_quality_error,
00330 "QC.IMGQUERR",
00331 "arcsec",
00332 "Uncertainty of image quality",
00333 setting->instrument);
00334
00335 fors_qc_write_qc_double(qc,
00336 stellarity,
00337 "QC.STELLAVG",
00338 NULL,
00339 "Mean stellarity index",
00340 setting->instrument);
00341
00342 fors_qc_write_qc_double(qc,
00343 ellipticity,
00344 "QC.IMGQUELL",
00345 NULL,
00346 "Mean star ellipticity",
00347 setting->instrument);
00348
00349 fors_qc_write_qc_double(qc,
00350 ellipticity_rms,
00351 "QC.IMGQUELLERR",
00352 NULL,
00353 "Standard deviation of star ellipticities",
00354 setting->instrument);
00355
00356 fors_qc_end_group();
00357
00358
00359
00360
00361
00362 header = cpl_propertylist_load(
00363 cpl_frame_get_filename(
00364 cpl_frameset_get_first(sci_frame)), 0);
00365
00366 if (header == NULL) {
00367 cpl_msg_error(cpl_func, "Failed to load raw header");
00368 cleanup;
00369 return;
00370 }
00371
00372 avg_airmass = fors_get_airmass(header);
00373
00374 cpl_propertylist_update_double(qc, "AIRMASS", avg_airmass);
00375 cpl_propertylist_update_double(product_header, "AIRMASS", avg_airmass);
00376
00377
00378
00379 fors_dfs_add_wcs(qc, cpl_frameset_get_first(sci_frame), setting);
00380 fors_dfs_add_exptime(qc, cpl_frameset_get_first(sci_frame), 0.);
00381 fors_dfs_add_wcs(product_header, cpl_frameset_get_first(sci_frame),
00382 setting);
00383 fors_dfs_add_exptime(product_header, cpl_frameset_get_first(sci_frame), 0.);
00384
00385 fors_dfs_save_image(frames, sci, SCIENCE_REDUCED_IMG,
00386 qc, parameters, fors_img_science_name,
00387 cpl_frameset_get_first(sci_frame));
00388 assure( !cpl_error_get_code(), return, "Saving %s failed",
00389 SCIENCE_REDUCED_IMG);
00390
00391 fors_image_delete(&sci);
00392
00393 dfs_save_image(frames, background, PHOT_BACKGROUND_SCI_IMG,
00394 product_header, parameters, fors_img_science_name,
00395 setting->version);
00396 assure( !cpl_error_get_code(), return, "Saving %s failed",
00397 PHOT_BACKGROUND_SCI_IMG);
00398
00399 cpl_image_delete(background); background = NULL;
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 phot = fors_create_sources_table(stars);
00421 assure( !cpl_error_get_code(), return,
00422 "Failed to create extracted sources table");
00423
00424
00425
00426
00427
00428 cpl_table_erase_column(phot, "INSTR_CMAG");
00429 cpl_table_erase_column(phot, "DINSTR_CMAG");
00430 cpl_table_erase_column(phot, "OBJECT");
00431 cpl_table_erase_column(phot, "MAG");
00432 cpl_table_erase_column(phot, "DMAG");
00433 cpl_table_erase_column(phot, "CAT_MAG");
00434 cpl_table_erase_column(phot, "DCAT_MAG");
00435 cpl_table_erase_column(phot, "COLOR");
00436
00437 if (cpl_table_has_column(phot, "DCOLOR"))
00438 cpl_table_erase_column(phot, "DCOLOR");
00439 if (cpl_table_has_column(phot, "COV_CATM_COL"))
00440 cpl_table_erase_column(phot, "COV_CATM_COL");
00441 cpl_table_erase_column(phot, "USE_CAT");
00442 cpl_table_erase_column(phot, "SHIFT_X");
00443 cpl_table_erase_column(phot, "SHIFT_Y");
00444 cpl_table_erase_column(phot, "ZEROPOINT");
00445 cpl_table_erase_column(phot, "DZEROPOINT");
00446 cpl_table_erase_column(phot, "WEIGHT");
00447
00448 fors_dfs_save_table(frames, sources, SOURCES_SCI,
00449 NULL, parameters, fors_img_science_name,
00450 cpl_frameset_get_first(sci_frame));
00451 assure( !cpl_error_get_code(), return, "Saving %s failed",
00452 SOURCES_SCI);
00453
00454 fors_dfs_save_table(frames, phot, PHOTOMETRY_TABLE,
00455 NULL, parameters, fors_img_science_name,
00456 cpl_frameset_get_first(sci_frame));
00457 assure( !cpl_error_get_code(), return, "Saving %s failed",
00458 PHOTOMETRY_TABLE);
00459
00460 cleanup;
00461 return;
00462 }
00463
00464 #undef cleanup
00465 #define cleanup
00466
00472 static bool
00473 is_star(const fors_star *s, void *data)
00474 {
00475 data = data;
00476 assure( s != NULL, return false, NULL );
00477
00478
00479
00480
00481 return s->stellarity_index >= 0.7;
00482 }
00483
00484 #undef cleanup
00485 #define cleanup \
00486 do { \
00487 fors_star_list_delete(&stars, fors_star_delete); \
00488 } while(0)
00489
00502 static double
00503 get_image_quality(const fors_star_list *sources, double *image_quality_err,
00504 double *stellarity,
00505 double *ellipticity,
00506 double *ellipticity_rms)
00507 {
00508 fors_star_list *stars = fors_star_list_extract(sources,
00509 fors_star_duplicate,
00510 is_star, NULL);
00511
00512 double fwhm;
00513 if (fors_star_list_size(stars) >= 1) {
00514 *image_quality_err = fors_star_list_mad(stars, fors_star_extension, NULL)
00515 * STDEV_PR_MAD;
00516
00517 fwhm = fors_star_list_median(stars, fors_star_extension , NULL);
00518
00519 *stellarity = fors_star_list_mean(stars, fors_star_stellarity, NULL);
00520 *ellipticity = fors_star_list_mean(stars, fors_star_ellipticity, NULL);
00521 *ellipticity_rms = fors_star_list_mad(stars, fors_star_ellipticity, NULL)
00522 * STDEV_PR_MAD;
00523 }
00524 else {
00525 cpl_msg_warning(cpl_func, "No stars found! Cannot compute image quality, "
00526 "setting QC parameters to -1");
00527
00528
00529 *image_quality_err = -1;
00530 fwhm = -1;
00531 *stellarity = -1;
00532 *ellipticity = -1;
00533 *ellipticity_rms = -1;
00534 }
00535
00536 cleanup;
00537 return fwhm;
00538 }
00539