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
00033
00034
00035
00036 #include <math.h>
00037 #include <cpl.h>
00038
00039 #include "irplib_plugin.h"
00040 #include "irplib_utils.h"
00041 #include "irplib_calib.h"
00042 #include "irplib_strehl.h"
00043
00044 #include "sofi_utils.h"
00045 #include "sofi_pfits.h"
00046 #include "sofi_dfs.h"
00047
00048
00049
00050
00051
00052 #define RECIPE_STRING "sofi_img_illum"
00053
00054
00055
00056
00057
00058 static cpl_image * sofi_img_illum_reduce(cpl_frameset *, const char *,
00059 const char *, const char *,
00060 cpl_table **);
00061 static cpl_bivector * sofi_img_illum_find_pos(const cpl_imagelist *,
00062 const cpl_bivector *);
00063 static cpl_vector * sofi_img_illum_phot(cpl_imagelist *, cpl_bivector *,int *);
00064 static
00065 cpl_error_code sofi_img_illum_save(cpl_frameset *, const cpl_image *,
00066 const cpl_table *, const cpl_parameterlist *);
00067
00068 cpl_recipe_define(sofi_img_illum, SOFI_BINARY_VERSION,
00069 "Lars Lundin", PACKAGE_BUGREPORT, "2002,2003,2009",
00070 "SOFI imaging illumination frame recipe",
00071 RECIPE_STRING " -- SOFI imaging illumination frame recipe.\n"
00072 "The files listed in the Set Of Frames (sof-file) "
00073 "must be tagged:\n"
00074 "raw-file.fits "SOFI_IMG_ILLUM_RAW" or\n"
00075 "flat-file.fits "SOFI_CALIB_FLAT" or\n"
00076 "dark-file.fits "SOFI_CALIB_DARK"\n");
00077
00078
00079
00080
00081
00082 static struct {
00083
00084 int s_hx;
00085 int s_hy;
00086 double star_r;
00087 double bg_r1;
00088 double bg_r2;
00089 int pos_x;
00090 int pos_y;
00091
00092
00093 cpl_size poly_deg;
00094 double illum1;
00095 double illumx;
00096 double illumy;
00097 double illumxy;
00098 double illumxx;
00099 double illumyy;
00100 } sofi_img_illum_config;
00101
00102
00103
00104
00105
00106
00107
00115
00116 static
00117 cpl_error_code sofi_img_illum_fill_parameterlist(cpl_parameterlist * self)
00118 {
00119 const char * context = PACKAGE "." RECIPE_STRING;
00120 cpl_error_code err;
00121
00122 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00123
00124
00125
00126
00127 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING, "star_r",
00128 10.0, NULL, context,
00129 "The star radius [pixel]");
00130 cpl_ensure_code(!err, err);
00131
00132
00133 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING, "bg_r1",
00134 12.0, NULL, context, "The internal "
00135 "background radius [pixel]");
00136 cpl_ensure_code(!err, err);
00137
00138
00139 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING, "bg_r2",
00140 30.0, NULL, context, "The external "
00141 "background radius [pixel]");
00142 cpl_ensure_code(!err, err);
00143
00144
00145 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "s_hx",
00146 50, NULL, context, "Half-size of the "
00147 "search box in X [pixel]");
00148 cpl_ensure_code(!err, err);
00149
00150
00151 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "s_hy",
00152 50, NULL, context, "Half-size of the "
00153 "search box in Y [pixel]");
00154 cpl_ensure_code(!err, err);
00155
00156
00157 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "pos_x",
00158 -1, NULL, context, "The star "
00159 "X-position [pixel]");
00160 cpl_ensure_code(!err, err);
00161
00162
00163 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "pos_y",
00164 -1, NULL, context, "The star "
00165 "Y-position [pixel]");
00166 cpl_ensure_code(!err, err);
00167
00168 return CPL_ERROR_NONE;
00169 }
00170
00171
00172
00180
00181 static int sofi_img_illum(cpl_frameset * framelist,
00182 const cpl_parameterlist * parlist)
00183 {
00184 cpl_frameset * rawframes = NULL;
00185 cpl_image * ima = NULL;
00186 cpl_table * flux = NULL;
00187 const char * flat;
00188 const char * dark;
00189
00190
00191
00192 sofi_img_illum_config.s_hx
00193 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00194 "s_hx");
00195 sofi_img_illum_config.s_hy
00196 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00197 "s_hy");
00198 sofi_img_illum_config.star_r
00199 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
00200 "star_r");
00201 sofi_img_illum_config.bg_r1
00202 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
00203 "bg_r1");
00204 sofi_img_illum_config.bg_r2
00205 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
00206 "bg_r2");
00207 sofi_img_illum_config.pos_x
00208 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00209 "pos_x");
00210 sofi_img_illum_config.pos_y
00211 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00212 "pos_y");
00213
00214 bug_if(0);
00215
00216
00217 skip_if (sofi_dfs_set_groups(framelist));
00218
00219
00220 flat = sofi_extract_filename(framelist, SOFI_CALIB_FLAT);
00221 dark = sofi_extract_filename(framelist, SOFI_CALIB_DARK);
00222
00223
00224 rawframes = sofi_extract_frameset(framelist, SOFI_IMG_ILLUM_RAW);
00225 error_if (rawframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
00226 "Cannot find any raw frame in the input");
00227
00228
00229 cpl_msg_info(cpl_func, "Apply the reduction");
00230 cpl_msg_indent_more();
00231 ima = sofi_img_illum_reduce(rawframes, flat, dark, NULL, &flux);
00232 cpl_msg_indent_less();
00233
00234 skip_if (ima == NULL);
00235
00236
00237 cpl_msg_info(cpl_func, "Saving the products");
00238 skip_if (sofi_img_illum_save(framelist, ima, flux, parlist));
00239
00240 end_skip;
00241
00242 cpl_image_delete(ima);
00243 cpl_table_delete(flux);
00244 cpl_frameset_delete(rawframes);
00245
00246 return cpl_error_get_code();
00247 }
00248
00249
00260
00261 static cpl_image * sofi_img_illum_reduce(
00262 cpl_frameset * raw,
00263 const char * flat,
00264 const char * dark,
00265 const char * bpm,
00266 cpl_table ** fl)
00267 {
00268 cpl_bivector * offsets;
00269 cpl_imagelist * in;
00270 cpl_bivector * positions;
00271 cpl_matrix * purged_pos;
00272 double * positions_x,
00273 * positions_y;
00274 cpl_vector * flux;
00275 cpl_vector * purged_flux;
00276 cpl_polynomial * poly;
00277 cpl_image * poly_ima;
00278 int nval, nx, ny;
00279 cpl_size power[2];
00280 int i, j;
00281
00282
00283 *fl = NULL;
00284
00285
00286 cpl_msg_info(cpl_func, "Get the offsets from the files headers");
00287 cpl_msg_indent_more();
00288 if ((offsets = sofi_get_offsets(raw)) == NULL) {
00289 cpl_msg_error(cpl_func, "Cannot get the offsets");
00290 cpl_msg_indent_less();
00291 return NULL;
00292 }
00293 cpl_msg_indent_less();
00294
00295
00296 cpl_msg_info(cpl_func, "Load the input data");
00297 cpl_msg_indent_more();
00298 if ((in = cpl_imagelist_load_frameset(raw, CPL_TYPE_FLOAT, 1, 0)) == NULL) {
00299 cpl_msg_error(cpl_func, "Cannot load input data");
00300 cpl_bivector_delete(offsets);
00301 cpl_msg_indent_less();
00302 return NULL;
00303 }
00304 cpl_msg_indent_less();
00305
00306
00307 if (flat || dark || bpm) {
00308 cpl_msg_info(cpl_func, "Apply the calibrations");
00309 cpl_msg_indent_more();
00310 if (irplib_flat_dark_bpm_calib(in, flat, dark, bpm) == -1) {
00311 cpl_msg_error(cpl_func, "Cannot calibrate the data");
00312 cpl_imagelist_delete(in);
00313 cpl_bivector_delete(offsets);
00314 cpl_msg_indent_less();
00315 return NULL;
00316 }
00317 cpl_msg_indent_less();
00318 }
00319
00320
00321 cpl_msg_info(cpl_func, "Find the positions");
00322 cpl_msg_indent_more();
00323 if ((positions=sofi_img_illum_find_pos(in, offsets)) == NULL) {
00324 cpl_msg_error(cpl_func, "Cannot find the positions");
00325 cpl_imagelist_delete(in);
00326 cpl_bivector_delete(offsets);
00327 cpl_msg_indent_less();
00328 return NULL;
00329 }
00330 cpl_bivector_delete(offsets);
00331 cpl_msg_indent_less();
00332
00333
00334 cpl_msg_info(cpl_func, "Compute the photometry");
00335 cpl_msg_indent_more();
00336 if ((flux=sofi_img_illum_phot(in, positions, &nval)) == NULL) {
00337 cpl_msg_error(cpl_func, "Cannot find the positions");
00338 cpl_imagelist_delete(in);
00339 cpl_bivector_delete(positions);
00340 cpl_msg_indent_less();
00341 return NULL;
00342 }
00343 nx = cpl_image_get_size_x(cpl_imagelist_get(in, 0));
00344 ny = cpl_image_get_size_y(cpl_imagelist_get(in, 0));
00345 cpl_imagelist_delete(in);
00346 cpl_msg_indent_less();
00347 if (nval < 1) {
00348 cpl_msg_error(cpl_func, "No flux computed");
00349 cpl_bivector_delete(positions);
00350 cpl_vector_delete(flux);
00351 return NULL;
00352 }
00353
00354
00355 purged_pos = cpl_matrix_new(2, nval);
00356 positions_x = cpl_bivector_get_x_data(positions);
00357 positions_y = cpl_bivector_get_y_data(positions);
00358 purged_flux = cpl_vector_new(nval);
00359 j = 0;
00360 for (i=0; i<cpl_vector_get_size(flux); i++) {
00361 if (fabs(cpl_vector_get(flux, i)) > 0) {
00362 cpl_matrix_set(purged_pos, 0, j, positions_x[i]);
00363 cpl_matrix_set(purged_pos, 1, j, positions_y[i]);
00364 cpl_vector_set(purged_flux, j, cpl_vector_get(flux, i));
00365 j++;
00366 }
00367 }
00368
00369
00370 *fl = cpl_table_new(cpl_vector_get_size(flux));
00371 cpl_table_new_column(*fl, "POSX", CPL_TYPE_DOUBLE);
00372 cpl_table_new_column(*fl, "POSY", CPL_TYPE_DOUBLE);
00373 cpl_table_new_column(*fl, "FLUX", CPL_TYPE_DOUBLE);
00374 for (i=0; i<cpl_vector_get_size(flux); i++) {
00375 cpl_table_set_double(*fl, "POSX", i, positions_x[i]);
00376 cpl_table_set_double(*fl, "POSY", i, positions_y[i]);
00377 cpl_table_set_double(*fl, "FLUX", i, cpl_vector_get(flux, i));
00378 }
00379 cpl_bivector_delete(positions);
00380 cpl_vector_delete(flux);
00381
00382
00383 if (nval >= 6) {
00384 sofi_img_illum_config.poly_deg = 2;
00385 } else if (nval >= 3) {
00386 sofi_img_illum_config.poly_deg = 1;
00387 } else {
00388 sofi_img_illum_config.poly_deg = 0;
00389 }
00390 cpl_msg_info(cpl_func, "Fitting a %d-degree 2D-polynomial to %d points",
00391 (int)sofi_img_illum_config.poly_deg, nval);
00392 poly = cpl_polynomial_new(2);
00393 if (cpl_polynomial_fit(poly, purged_pos, NULL, purged_flux, NULL,
00394 CPL_FALSE, NULL, &(sofi_img_illum_config.poly_deg))) {
00395 cpl_matrix_delete(purged_pos);
00396 cpl_vector_delete(purged_flux);
00397 cpl_error_set_where(cpl_func);
00398 cpl_polynomial_delete(poly);
00399 cpl_table_delete(*fl);
00400 *fl = NULL;
00401 return NULL;
00402 }
00403 cpl_matrix_delete(purged_pos);
00404 cpl_vector_delete(purged_flux);
00405
00406
00407 power[0] = 0; power[1] = 0;
00408 sofi_img_illum_config.illum1 = cpl_polynomial_get_coeff(poly, power);
00409 if (sofi_img_illum_config.poly_deg >= 1) {
00410 power[0] = 1; power[1] = 0;
00411 sofi_img_illum_config.illumx = cpl_polynomial_get_coeff(poly, power);
00412 power[0] = 0; power[1] = 1;
00413 sofi_img_illum_config.illumy = cpl_polynomial_get_coeff(poly, power);
00414 }
00415 if (sofi_img_illum_config.poly_deg >= 2) {
00416 power[0] = 1; power[1] = 1;
00417 sofi_img_illum_config.illumxy = cpl_polynomial_get_coeff(poly, power);
00418 power[0] = 2; power[1] = 0;
00419 sofi_img_illum_config.illumxx = cpl_polynomial_get_coeff(poly, power);
00420 power[0] = 0; power[1] = 2;
00421 sofi_img_illum_config.illumyy = cpl_polynomial_get_coeff(poly, power);
00422 }
00423 cpl_msg_info(cpl_func, "P(X,Y)=a0+a1*X+a2*Y+a3*X*Y+a4*X^2+a5*Y^2");
00424 cpl_msg_info(cpl_func, "a0 = %g", sofi_img_illum_config.illum1);
00425 cpl_msg_info(cpl_func, "a1 = %g", sofi_img_illum_config.illumx);
00426 cpl_msg_info(cpl_func, "a2 = %g", sofi_img_illum_config.illumy);
00427 cpl_msg_info(cpl_func, "a3 = %g", sofi_img_illum_config.illumxy);
00428 cpl_msg_info(cpl_func, "a4 = %g", sofi_img_illum_config.illumxx);
00429 cpl_msg_info(cpl_func, "a5 = %g", sofi_img_illum_config.illumyy);
00430
00431
00432 poly_ima = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00433 cpl_image_fill_polynomial(poly_ima, poly, 1.0, 1.0, 1.0, 1.0);
00434 cpl_polynomial_delete(poly);
00435
00436
00437 cpl_image_normalise(poly_ima, CPL_NORM_MEAN);
00438
00439 return poly_ima;
00440 }
00441
00442
00451
00452 static cpl_vector * sofi_img_illum_phot(
00453 cpl_imagelist * ilist,
00454 cpl_bivector * positions,
00455 int * nvalid)
00456 {
00457 cpl_vector * flux;
00458 cpl_image * cur_ima;
00459 double * positions_x;
00460 double * positions_y;
00461 int ni;
00462 int nok;
00463 double bg, fl;
00464 int i;
00465
00466
00467 if (ilist == NULL || positions == NULL || nvalid == NULL) return NULL;
00468 ni = cpl_imagelist_get_size(ilist);
00469 positions_x = cpl_bivector_get_x_data(positions);
00470 positions_y = cpl_bivector_get_y_data(positions);
00471 nok = 0;
00472
00473
00474 flux = cpl_vector_new(ni);
00475
00476
00477 for (i=0; i<ni; i++) {
00478 cur_ima = cpl_imagelist_get(ilist, i);
00479 bg = irplib_strehl_ring_background(cur_ima, (int)positions_x[i],
00480 (int)positions_y[i], sofi_img_illum_config.bg_r1,
00481 sofi_img_illum_config.bg_r2, IRPLIB_BG_METHOD_MEDIAN);
00482 fl = irplib_strehl_disk_flux(cur_ima, (int)positions_x[i],
00483 (int)positions_y[i], sofi_img_illum_config.star_r, bg);
00484 cpl_vector_set(flux, i, fl);
00485 if (fabs(fl)>1e-3) nok++;
00486 cpl_msg_info(cpl_func, "Flux for image %d: %g", i+1, fl);
00487 }
00488 *nvalid = nok;
00489 return flux;
00490 }
00491
00492
00500
00501 static cpl_bivector * sofi_img_illum_find_pos(const cpl_imagelist * ilist,
00502 const cpl_bivector * offsets)
00503 {
00504 const int ni = cpl_imagelist_get_size(ilist);
00505 const int nx = cpl_image_get_size_x(cpl_imagelist_get_const(ilist, 0));
00506 const int ny = cpl_image_get_size_y(cpl_imagelist_get_const(ilist, 0));
00507 cpl_bivector * positions;
00508 double * positions_x;
00509 double * positions_y;
00510 const double * offsets_x = cpl_bivector_get_x_data_const(offsets);
00511 const double * offsets_y = cpl_bivector_get_y_data_const(offsets);
00512 cpl_image * img_window = NULL;
00513 cpl_image * img_filter = NULL;
00514 cpl_mask * kernel = NULL;
00515 int i;
00516
00517
00518 cpl_ensure(ilist != NULL, CPL_ERROR_NULL_INPUT, NULL);
00519 cpl_ensure(offsets != NULL, CPL_ERROR_NULL_INPUT, NULL);
00520 cpl_ensure(cpl_bivector_get_size(offsets) == ni,
00521 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
00522
00523
00524 positions = cpl_bivector_new(ni);
00525 positions_x = cpl_bivector_get_x_data(positions);
00526 positions_y = cpl_bivector_get_y_data(positions);
00527
00528
00529 kernel = cpl_mask_new(3, 3);
00530 cpl_mask_not(kernel);
00531
00532
00533 for (i=0; i < ni; i++) {
00534 const cpl_image * image = cpl_imagelist_get_const(ilist, i);
00535
00536
00537 const int pos_x = sofi_img_illum_config.pos_x > 0
00538 ? sofi_img_illum_config.pos_x : nx/2;
00539 const int pos_y = sofi_img_illum_config.pos_y > 0
00540 ? sofi_img_illum_config.pos_y : ny/2;
00541
00542 const int llx = pos_x + offsets_x[i] - sofi_img_illum_config.s_hx;
00543 const int urx = pos_x + offsets_x[i] + sofi_img_illum_config.s_hx;
00544 const int lly = pos_y + offsets_y[i] - sofi_img_illum_config.s_hy;
00545 const int ury = pos_y + offsets_y[i] + sofi_img_illum_config.s_hy;
00546
00547 cpl_size posx, posy;
00548
00549
00550 if (llx > urx || lly > ury || llx < 1 || urx > nx || lly < 1 ||
00551 ury > ny) {
00552 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00553 "Bad specified zone: llx=%d, urx=%d, "
00554 "lly=%d, ury=%d", llx, urx, lly, ury);
00555 break;
00556 }
00557
00558
00559
00560 cpl_image_delete(img_window);
00561 cpl_image_delete(img_filter);
00562 img_window = cpl_image_extract(image, llx, lly, urx, ury);
00563 img_filter = cpl_image_new(1 + urx - llx, 1 + ury - lly,
00564 cpl_image_get_type(img_window));
00565
00566 cpl_image_filter_mask(img_filter, img_window, kernel,
00567 CPL_FILTER_MEDIAN, CPL_BORDER_FILTER);
00568
00569
00570 cpl_image_get_maxpos(img_filter, &posx, &posy);
00571 positions_x[i] = llx + posx;
00572 positions_y[i] = lly + posy;
00573 cpl_msg_info(cpl_func, "Star found at pos %g, %g in image %d",
00574 positions_x[i], positions_y[i], i+1);
00575
00576 }
00577 cpl_image_delete(img_window);
00578 cpl_image_delete(img_filter);
00579 cpl_mask_delete(kernel);
00580 if (i != ni) {
00581 cpl_bivector_delete(positions);
00582 positions = NULL;
00583 }
00584
00585 return positions;
00586 }
00587
00588
00598
00599 static cpl_error_code sofi_img_illum_save(cpl_frameset * set,
00600 const cpl_image * ima,
00601 const cpl_table * flux,
00602 const cpl_parameterlist * parlist)
00603 {
00604 const cpl_frame * ref_frame;
00605 cpl_propertylist * plist;
00606 cpl_propertylist * paflist;
00607 cpl_propertylist * qclist;
00608
00609
00610 qclist = cpl_propertylist_new();
00611 cpl_propertylist_append_double(qclist, "ESO QC ILLUM1",
00612 sofi_img_illum_config.illum1);
00613 cpl_propertylist_append_double(qclist, "ESO QC ILLUMX",
00614 sofi_img_illum_config.illumx);
00615 cpl_propertylist_append_double(qclist, "ESO QC ILLUMY",
00616 sofi_img_illum_config.illumy);
00617 cpl_propertylist_append_double(qclist, "ESO QC ILLUMXY",
00618 sofi_img_illum_config.illumxy);
00619 cpl_propertylist_append_double(qclist, "ESO QC ILLUMXX",
00620 sofi_img_illum_config.illumxx);
00621 cpl_propertylist_append_double(qclist, "ESO QC ILLUMYY",
00622 sofi_img_illum_config.illumyy);
00623
00624
00625 irplib_dfs_save_image(set,
00626 parlist,
00627 set,
00628 ima,
00629 CPL_BPP_IEEE_FLOAT,
00630 "sofi_img_illum",
00631 SOFI_IMG_ILLUM_RES,
00632 qclist,
00633 NULL,
00634 PACKAGE "/" PACKAGE_VERSION,
00635 "sofi_img_illum.fits");
00636
00637
00638 if (flux != NULL) {
00639 irplib_dfs_save_table(set,
00640 parlist,
00641 set,
00642 flux,
00643 NULL,
00644 "sofi_img_illum",
00645 SOFI_IMG_ILLUM_TAB,
00646 qclist,
00647 NULL,
00648 PACKAGE "/" PACKAGE_VERSION,
00649 "sofi_img_illum_flux.fits");
00650 }
00651
00652
00653 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
00654
00655
00656 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
00657 0)) == NULL) {
00658 cpl_msg_error(cpl_func, "getting header from reference frame");
00659 cpl_propertylist_delete(qclist);
00660 return cpl_error_set_where(cpl_func);
00661 }
00662
00663
00664 paflist = cpl_propertylist_new();
00665 cpl_propertylist_copy_property_regexp(paflist, plist,
00666 "^(ARCFILE|MJD-OBS|ESO TPL ID|DATE-OBS|ESO DET DIT|ESO DET NDIT|"
00667 "ESO DET NCORRS|ESO DET MODE NAME)$", 0);
00668 cpl_propertylist_delete(plist);
00669
00670
00671 cpl_propertylist_copy_property_regexp(paflist, qclist, "", 0);
00672 cpl_propertylist_delete(qclist);
00673
00674
00675 cpl_dfs_save_paf("SOFI",
00676 "sofi_img_illum",
00677 paflist,
00678 "sofi_img_illum.paf");
00679 cpl_propertylist_delete(paflist);
00680 return cpl_error_get_code();
00681 }