39 #include "irplib_plugin.h"
40 #include "irplib_utils.h"
41 #include "irplib_calib.h"
42 #include "irplib_strehl.h"
44 #include "sofi_utils.h"
45 #include "sofi_pfits.h"
52 #define RECIPE_STRING "sofi_img_illum"
58 static cpl_image * sofi_img_illum_reduce(cpl_frameset *,
const char *,
59 const char *,
const char *,
61 static cpl_bivector * sofi_img_illum_find_pos(
const cpl_imagelist *,
62 const cpl_bivector *);
63 static cpl_vector * sofi_img_illum_phot(cpl_imagelist *, cpl_bivector *,
int *);
65 cpl_error_code sofi_img_illum_save(cpl_frameset *,
const cpl_image *,
66 const cpl_table *,
const cpl_parameterlist *);
68 cpl_recipe_define(sofi_img_illum, SOFI_BINARY_VERSION,
69 "Lars Lundin", PACKAGE_BUGREPORT,
"2002,2003,2009",
70 "SOFI imaging illumination frame recipe",
71 RECIPE_STRING
" -- SOFI imaging illumination frame recipe.\n"
72 "The files listed in the Set Of Frames (sof-file) "
74 "raw-file.fits "SOFI_IMG_ILLUM_RAW
" or\n"
75 "flat-file.fits "SOFI_CALIB_FLAT
" or\n"
76 "dark-file.fits "SOFI_CALIB_DARK
"\n");
100 } sofi_img_illum_config;
117 cpl_error_code sofi_img_illum_fill_parameterlist(cpl_parameterlist *
self)
119 const char * context = PACKAGE
"." RECIPE_STRING;
122 cpl_ensure_code(
self, CPL_ERROR_NULL_INPUT);
127 err = irplib_parameterlist_set_double(
self, PACKAGE, RECIPE_STRING,
"star_r",
129 "The star radius [pixel]");
130 cpl_ensure_code(!err, err);
133 err = irplib_parameterlist_set_double(
self, PACKAGE, RECIPE_STRING,
"bg_r1",
134 12.0, NULL, context,
"The internal "
135 "background radius [pixel]");
136 cpl_ensure_code(!err, err);
139 err = irplib_parameterlist_set_double(
self, PACKAGE, RECIPE_STRING,
"bg_r2",
140 30.0, NULL, context,
"The external "
141 "background radius [pixel]");
142 cpl_ensure_code(!err, err);
145 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"s_hx",
146 50, NULL, context,
"Half-size of the "
147 "search box in X [pixel]");
148 cpl_ensure_code(!err, err);
151 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"s_hy",
152 50, NULL, context,
"Half-size of the "
153 "search box in Y [pixel]");
154 cpl_ensure_code(!err, err);
157 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"pos_x",
158 -1, NULL, context,
"The star "
159 "X-position [pixel]");
160 cpl_ensure_code(!err, err);
163 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
"pos_y",
164 -1, NULL, context,
"The star "
165 "Y-position [pixel]");
166 cpl_ensure_code(!err, err);
168 return CPL_ERROR_NONE;
181 static int sofi_img_illum(cpl_frameset * framelist,
182 const cpl_parameterlist * parlist)
184 cpl_frameset * rawframes = NULL;
185 cpl_image * ima = NULL;
186 cpl_table * flux = NULL;
192 sofi_img_illum_config.s_hx
193 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
195 sofi_img_illum_config.s_hy
196 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
198 sofi_img_illum_config.star_r
199 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
201 sofi_img_illum_config.bg_r1
202 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
204 sofi_img_illum_config.bg_r2
205 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
207 sofi_img_illum_config.pos_x
208 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
210 sofi_img_illum_config.pos_y
211 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
225 error_if (rawframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
226 "Cannot find any raw frame in the input");
229 cpl_msg_info(cpl_func,
"Apply the reduction");
230 cpl_msg_indent_more();
231 ima = sofi_img_illum_reduce(rawframes, flat, dark, NULL, &flux);
232 cpl_msg_indent_less();
234 skip_if (ima == NULL);
237 cpl_msg_info(cpl_func,
"Saving the products");
238 skip_if (sofi_img_illum_save(framelist, ima, flux, parlist));
242 cpl_image_delete(ima);
243 cpl_table_delete(flux);
244 cpl_frameset_delete(rawframes);
246 return cpl_error_get_code();
261 static cpl_image * sofi_img_illum_reduce(
268 cpl_bivector * offsets;
270 cpl_bivector * positions;
271 cpl_matrix * purged_pos;
272 double * positions_x,
275 cpl_vector * purged_flux;
276 cpl_polynomial * poly;
277 cpl_image * poly_ima;
286 cpl_msg_info(cpl_func,
"Get the offsets from the files headers");
287 cpl_msg_indent_more();
289 cpl_msg_error(cpl_func,
"Cannot get the offsets");
290 cpl_msg_indent_less();
293 cpl_msg_indent_less();
296 cpl_msg_info(cpl_func,
"Load the input data");
297 cpl_msg_indent_more();
298 if ((in = cpl_imagelist_load_frameset(raw, CPL_TYPE_FLOAT, 1, 0)) == NULL) {
299 cpl_msg_error(cpl_func,
"Cannot load input data");
300 cpl_bivector_delete(offsets);
301 cpl_msg_indent_less();
304 cpl_msg_indent_less();
307 if (flat || dark || bpm) {
308 cpl_msg_info(cpl_func,
"Apply the calibrations");
309 cpl_msg_indent_more();
310 if (irplib_flat_dark_bpm_calib(in, flat, dark, bpm) == -1) {
311 cpl_msg_error(cpl_func,
"Cannot calibrate the data");
312 cpl_imagelist_delete(in);
313 cpl_bivector_delete(offsets);
314 cpl_msg_indent_less();
317 cpl_msg_indent_less();
321 cpl_msg_info(cpl_func,
"Find the positions");
322 cpl_msg_indent_more();
323 if ((positions=sofi_img_illum_find_pos(in, offsets)) == NULL) {
324 cpl_msg_error(cpl_func,
"Cannot find the positions");
325 cpl_imagelist_delete(in);
326 cpl_bivector_delete(offsets);
327 cpl_msg_indent_less();
330 cpl_bivector_delete(offsets);
331 cpl_msg_indent_less();
334 cpl_msg_info(cpl_func,
"Compute the photometry");
335 cpl_msg_indent_more();
336 if ((flux=sofi_img_illum_phot(in, positions, &nval)) == NULL) {
337 cpl_msg_error(cpl_func,
"Cannot find the positions");
338 cpl_imagelist_delete(in);
339 cpl_bivector_delete(positions);
340 cpl_msg_indent_less();
343 nx = cpl_image_get_size_x(cpl_imagelist_get(in, 0));
344 ny = cpl_image_get_size_y(cpl_imagelist_get(in, 0));
345 cpl_imagelist_delete(in);
346 cpl_msg_indent_less();
348 cpl_msg_error(cpl_func,
"No flux computed");
349 cpl_bivector_delete(positions);
350 cpl_vector_delete(flux);
355 purged_pos = cpl_matrix_new(2, nval);
356 positions_x = cpl_bivector_get_x_data(positions);
357 positions_y = cpl_bivector_get_y_data(positions);
358 purged_flux = cpl_vector_new(nval);
360 for (i=0; i<cpl_vector_get_size(flux); i++) {
361 if (fabs(cpl_vector_get(flux, i)) > 0) {
362 cpl_matrix_set(purged_pos, 0, j, positions_x[i]);
363 cpl_matrix_set(purged_pos, 1, j, positions_y[i]);
364 cpl_vector_set(purged_flux, j, cpl_vector_get(flux, i));
370 *fl = cpl_table_new(cpl_vector_get_size(flux));
371 cpl_table_new_column(*fl,
"POSX", CPL_TYPE_DOUBLE);
372 cpl_table_new_column(*fl,
"POSY", CPL_TYPE_DOUBLE);
373 cpl_table_new_column(*fl,
"FLUX", CPL_TYPE_DOUBLE);
374 for (i=0; i<cpl_vector_get_size(flux); i++) {
375 cpl_table_set_double(*fl,
"POSX", i, positions_x[i]);
376 cpl_table_set_double(*fl,
"POSY", i, positions_y[i]);
377 cpl_table_set_double(*fl,
"FLUX", i, cpl_vector_get(flux, i));
379 cpl_bivector_delete(positions);
380 cpl_vector_delete(flux);
384 sofi_img_illum_config.poly_deg = 2;
385 }
else if (nval >= 3) {
386 sofi_img_illum_config.poly_deg = 1;
388 sofi_img_illum_config.poly_deg = 0;
390 cpl_msg_info(cpl_func,
"Fitting a %d-degree 2D-polynomial to %d points",
391 (
int)sofi_img_illum_config.poly_deg, nval);
392 poly = cpl_polynomial_new(2);
393 if (cpl_polynomial_fit(poly, purged_pos, NULL, purged_flux, NULL,
394 CPL_FALSE, NULL, &(sofi_img_illum_config.poly_deg))) {
395 cpl_matrix_delete(purged_pos);
396 cpl_vector_delete(purged_flux);
397 cpl_error_set_where(cpl_func);
398 cpl_polynomial_delete(poly);
399 cpl_table_delete(*fl);
403 cpl_matrix_delete(purged_pos);
404 cpl_vector_delete(purged_flux);
407 power[0] = 0; power[1] = 0;
408 sofi_img_illum_config.illum1 = cpl_polynomial_get_coeff(poly, power);
409 if (sofi_img_illum_config.poly_deg >= 1) {
410 power[0] = 1; power[1] = 0;
411 sofi_img_illum_config.illumx = cpl_polynomial_get_coeff(poly, power);
412 power[0] = 0; power[1] = 1;
413 sofi_img_illum_config.illumy = cpl_polynomial_get_coeff(poly, power);
415 if (sofi_img_illum_config.poly_deg >= 2) {
416 power[0] = 1; power[1] = 1;
417 sofi_img_illum_config.illumxy = cpl_polynomial_get_coeff(poly, power);
418 power[0] = 2; power[1] = 0;
419 sofi_img_illum_config.illumxx = cpl_polynomial_get_coeff(poly, power);
420 power[0] = 0; power[1] = 2;
421 sofi_img_illum_config.illumyy = cpl_polynomial_get_coeff(poly, power);
423 cpl_msg_info(cpl_func,
"P(X,Y)=a0+a1*X+a2*Y+a3*X*Y+a4*X^2+a5*Y^2");
424 cpl_msg_info(cpl_func,
"a0 = %g", sofi_img_illum_config.illum1);
425 cpl_msg_info(cpl_func,
"a1 = %g", sofi_img_illum_config.illumx);
426 cpl_msg_info(cpl_func,
"a2 = %g", sofi_img_illum_config.illumy);
427 cpl_msg_info(cpl_func,
"a3 = %g", sofi_img_illum_config.illumxy);
428 cpl_msg_info(cpl_func,
"a4 = %g", sofi_img_illum_config.illumxx);
429 cpl_msg_info(cpl_func,
"a5 = %g", sofi_img_illum_config.illumyy);
432 poly_ima = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
433 cpl_image_fill_polynomial(poly_ima, poly, 1.0, 1.0, 1.0, 1.0);
434 cpl_polynomial_delete(poly);
437 cpl_image_normalise(poly_ima, CPL_NORM_MEAN);
452 static cpl_vector * sofi_img_illum_phot(
453 cpl_imagelist * ilist,
454 cpl_bivector * positions,
459 double * positions_x;
460 double * positions_y;
467 if (ilist == NULL || positions == NULL || nvalid == NULL)
return NULL;
468 ni = cpl_imagelist_get_size(ilist);
469 positions_x = cpl_bivector_get_x_data(positions);
470 positions_y = cpl_bivector_get_y_data(positions);
474 flux = cpl_vector_new(ni);
477 for (i=0; i<ni; i++) {
478 cur_ima = cpl_imagelist_get(ilist, i);
479 bg = irplib_strehl_ring_background(cur_ima, (
int)positions_x[i],
480 (
int)positions_y[i], sofi_img_illum_config.bg_r1,
481 sofi_img_illum_config.bg_r2, IRPLIB_BG_METHOD_MEDIAN);
482 fl = irplib_strehl_disk_flux(cur_ima, (
int)positions_x[i],
483 (
int)positions_y[i], sofi_img_illum_config.star_r, bg);
484 cpl_vector_set(flux, i, fl);
485 if (fabs(fl)>1e-3) nok++;
486 cpl_msg_info(cpl_func,
"Flux for image %d: %g", i+1, fl);
501 static cpl_bivector * sofi_img_illum_find_pos(
const cpl_imagelist * ilist,
502 const cpl_bivector * offsets)
504 const int ni = cpl_imagelist_get_size(ilist);
505 const int nx = cpl_image_get_size_x(cpl_imagelist_get_const(ilist, 0));
506 const int ny = cpl_image_get_size_y(cpl_imagelist_get_const(ilist, 0));
507 cpl_bivector * positions;
508 double * positions_x;
509 double * positions_y;
510 const double * offsets_x = cpl_bivector_get_x_data_const(offsets);
511 const double * offsets_y = cpl_bivector_get_y_data_const(offsets);
512 cpl_image * img_window = NULL;
513 cpl_image * img_filter = NULL;
514 cpl_mask * kernel = NULL;
518 cpl_ensure(ilist != NULL, CPL_ERROR_NULL_INPUT, NULL);
519 cpl_ensure(offsets != NULL, CPL_ERROR_NULL_INPUT, NULL);
520 cpl_ensure(cpl_bivector_get_size(offsets) == ni,
521 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
524 positions = cpl_bivector_new(ni);
525 positions_x = cpl_bivector_get_x_data(positions);
526 positions_y = cpl_bivector_get_y_data(positions);
529 kernel = cpl_mask_new(3, 3);
530 cpl_mask_not(kernel);
533 for (i=0; i < ni; i++) {
534 const cpl_image * image = cpl_imagelist_get_const(ilist, i);
537 const int pos_x = sofi_img_illum_config.pos_x > 0
538 ? sofi_img_illum_config.pos_x : nx/2;
539 const int pos_y = sofi_img_illum_config.pos_y > 0
540 ? sofi_img_illum_config.pos_y : ny/2;
542 const int llx = pos_x + offsets_x[i] - sofi_img_illum_config.s_hx;
543 const int urx = pos_x + offsets_x[i] + sofi_img_illum_config.s_hx;
544 const int lly = pos_y + offsets_y[i] - sofi_img_illum_config.s_hy;
545 const int ury = pos_y + offsets_y[i] + sofi_img_illum_config.s_hy;
550 if (llx > urx || lly > ury || llx < 1 || urx > nx || lly < 1 ||
552 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
553 "Bad specified zone: llx=%d, urx=%d, "
554 "lly=%d, ury=%d", llx, urx, lly, ury);
560 cpl_image_delete(img_window);
561 cpl_image_delete(img_filter);
562 img_window = cpl_image_extract(image, llx, lly, urx, ury);
563 img_filter = cpl_image_new(1 + urx - llx, 1 + ury - lly,
564 cpl_image_get_type(img_window));
566 cpl_image_filter_mask(img_filter, img_window, kernel,
567 CPL_FILTER_MEDIAN, CPL_BORDER_FILTER);
570 cpl_image_get_maxpos(img_filter, &posx, &posy);
571 positions_x[i] = llx + posx;
572 positions_y[i] = lly + posy;
573 cpl_msg_info(cpl_func,
"Star found at pos %g, %g in image %d",
574 positions_x[i], positions_y[i], i+1);
577 cpl_image_delete(img_window);
578 cpl_image_delete(img_filter);
579 cpl_mask_delete(kernel);
581 cpl_bivector_delete(positions);
599 static cpl_error_code sofi_img_illum_save(cpl_frameset * set,
600 const cpl_image * ima,
601 const cpl_table * flux,
602 const cpl_parameterlist * parlist)
604 const cpl_frame * ref_frame;
605 cpl_propertylist * plist;
606 cpl_propertylist * paflist;
607 cpl_propertylist * qclist;
610 qclist = cpl_propertylist_new();
611 cpl_propertylist_append_double(qclist,
"ESO QC ILLUM1",
612 sofi_img_illum_config.illum1);
613 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMX",
614 sofi_img_illum_config.illumx);
615 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMY",
616 sofi_img_illum_config.illumy);
617 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMXY",
618 sofi_img_illum_config.illumxy);
619 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMXX",
620 sofi_img_illum_config.illumxx);
621 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMYY",
622 sofi_img_illum_config.illumyy);
625 irplib_dfs_save_image(set,
634 PACKAGE
"/" PACKAGE_VERSION,
635 "sofi_img_illum.fits");
639 irplib_dfs_save_table(set,
648 PACKAGE
"/" PACKAGE_VERSION,
649 "sofi_img_illum_flux.fits");
653 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
656 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
658 cpl_msg_error(cpl_func,
"getting header from reference frame");
659 cpl_propertylist_delete(qclist);
660 return cpl_error_set_where(cpl_func);
664 paflist = cpl_propertylist_new();
665 cpl_propertylist_copy_property_regexp(paflist, plist,
666 "^(ARCFILE|MJD-OBS|ESO TPL ID|DATE-OBS|ESO DET DIT|ESO DET NDIT|"
667 "ESO DET NCORRS|ESO DET MODE NAME)$", 0);
668 cpl_propertylist_delete(plist);
671 cpl_propertylist_copy_property_regexp(paflist, qclist,
".", 0);
672 cpl_propertylist_delete(qclist);
675 cpl_dfs_save_paf(
"SOFI",
678 "sofi_img_illum.paf");
679 cpl_propertylist_delete(paflist);
680 return cpl_error_get_code();