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_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
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
00111
00112
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
00160
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);
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
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
00255
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
00279 master_fixed_pattern_noise *= convert_ADU;
00280
00281
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
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
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