39 #include "irplib_plugin.h"
40 #include "irplib_utils.h"
41 #include "irplib_calib.h"
42 #include "irplib_strehl.h"
44 #include "isaac_utils.h"
45 #include "isaac_pfits.h"
46 #include "isaac_dfs.h"
52 #define RECIPE_STRING "isaac_img_illum"
58 static cpl_image * isaac_img_illum_reduce(
const cpl_frameset *,
const char *,
59 const char *,
const char *,
61 static cpl_bivector * isaac_img_illum_find_pos(
const cpl_imagelist *,
62 const cpl_bivector *);
63 static cpl_vector * isaac_img_illum_phot(
const cpl_imagelist *,
64 const cpl_bivector *,
int *);
65 static cpl_error_code isaac_img_illum_save(cpl_frameset *,
66 const cpl_parameterlist *,
67 const cpl_image *,
const cpl_table *);
69 cpl_recipe_define(isaac_img_illum, ISAAC_BINARY_VERSION,
70 "Lars Lundin", PACKAGE_BUGREPORT,
"2008",
71 "ISAAC imaging illumination frame recipe",
72 RECIPE_STRING
" -- ISAAC imaging illumination frame recipe.\n"
73 "The files listed in the Set Of Frames (sof-file) "
75 "raw-file.fits " ISAAC_IMG_ILLUM_RAW
" or\n"
76 "flat-file.fits " ISAAC_CALIB_FLAT
" or\n"
77 "bpm-file.fits " ISAAC_CALIB_BPM
" or\n"
78 "dark-file.fits " ISAAC_CALIB_DARK
"\n");
104 } isaac_img_illum_config;
120 cpl_error_code isaac_img_illum_fill_parameterlist(cpl_parameterlist *
self)
122 const char * context = PACKAGE
"." RECIPE_STRING;
125 cpl_ensure_code(
self, CPL_ERROR_NULL_INPUT);
130 err = irplib_parameterlist_set_double(
self, PACKAGE, RECIPE_STRING,
131 "star_r", 10.0, NULL, context,
133 cpl_ensure_code(!err, err);
136 err = irplib_parameterlist_set_double(
self, PACKAGE, RECIPE_STRING,
137 "bg_r1", 12.0, NULL, context,
138 "The internal background radius");
139 cpl_ensure_code(!err, err);
142 err = irplib_parameterlist_set_double(
self, PACKAGE, RECIPE_STRING,
143 "bg_r2", 30.0, NULL, context,
144 "The external background radius");
145 cpl_ensure_code(!err, err);
148 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
149 "s_hx", 50, NULL, context,
150 "Half size of the seach box in x");
151 cpl_ensure_code(!err, err);
154 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
155 "s_hy", 50, NULL, context,
156 "Half size of the seach box in y");
157 cpl_ensure_code(!err, err);
160 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
161 "pos_x", -1, NULL, context,
162 "The star position in x");
163 cpl_ensure_code(!err, err);
166 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
167 "pos_y", -1, NULL, context,
168 "The star position in y");
169 cpl_ensure_code(!err, err);
171 return CPL_ERROR_NONE;
183 static int isaac_img_illum(cpl_frameset * framelist,
184 const cpl_parameterlist * parlist)
186 cpl_frameset * rawframes = NULL;
187 cpl_image * ima = NULL;
188 cpl_table * flux = NULL;
195 isaac_img_illum_config.s_hx
196 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
"s_hx");
198 isaac_img_illum_config.s_hy
199 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
"s_hy");
201 isaac_img_illum_config.star_r
202 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
204 isaac_img_illum_config.bg_r1
205 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
207 isaac_img_illum_config.bg_r2
208 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
210 isaac_img_illum_config.pos_x
211 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
213 isaac_img_illum_config.pos_y
214 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
227 error_if(rawframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
228 "Cannot find any raw frame in the input");
231 cpl_msg_info(cpl_func,
"Apply the reduction");
232 ima = isaac_img_illum_reduce(rawframes, flat, dark, bpm, &flux);
233 error_if (ima == NULL, cpl_error_get_code(),
"Cannot reduce the data");
236 cpl_msg_info(cpl_func,
"Saving the products");
237 skip_if (isaac_img_illum_save(framelist, parlist, ima, flux));
241 cpl_image_delete(ima);
242 cpl_table_delete(flux);
243 cpl_frameset_delete(rawframes);
245 return cpl_error_get_code();
259 static cpl_image * isaac_img_illum_reduce(
const cpl_frameset * raw,
265 cpl_bivector * offsets;
267 cpl_bivector * positions;
268 cpl_matrix * purged_pos;
269 double * positions_x,
274 cpl_vector * purged_flux;
275 cpl_polynomial * poly;
276 cpl_image * poly_ima;
287 cpl_msg_info(cpl_func,
"Get the offsets from the files headers");
288 cpl_msg_indent_more();
290 cpl_msg_error(cpl_func,
"Cannot get the offsets");
291 cpl_msg_indent_less();
294 cpl_msg_indent_less();
297 cpl_msg_info(cpl_func,
"Load the input data");
298 cpl_msg_indent_more();
299 if ((in = cpl_imagelist_load_frameset(raw, CPL_TYPE_FLOAT, 1, 0)) == NULL) {
300 cpl_msg_error(cpl_func,
"Cannot load input data");
301 cpl_bivector_delete(offsets);
302 cpl_msg_indent_less();
305 cpl_msg_indent_less();
308 if (flat || dark || bpm) {
309 cpl_msg_info(cpl_func,
"Apply the calibrations");
310 cpl_msg_indent_more();
311 if (irplib_flat_dark_bpm_calib(in, flat, dark, bpm) == -1) {
312 cpl_msg_error(cpl_func,
"Cannot calibrate the data");
313 cpl_imagelist_delete(in);
314 cpl_bivector_delete(offsets);
315 cpl_msg_indent_less();
318 cpl_msg_indent_less();
322 cpl_msg_info(cpl_func,
"Find the positions");
323 cpl_msg_indent_more();
324 if ((positions=isaac_img_illum_find_pos(in, offsets)) == NULL) {
325 cpl_msg_error(cpl_func,
"Cannot find the positions");
326 cpl_imagelist_delete(in);
327 cpl_bivector_delete(offsets);
328 cpl_msg_indent_less();
331 cpl_bivector_delete(offsets);
332 cpl_msg_indent_less();
335 cpl_msg_info(cpl_func,
"Compute the photometry");
336 cpl_msg_indent_more();
337 if ((flux=isaac_img_illum_phot(in, positions, &nval)) == NULL) {
338 cpl_msg_error(cpl_func,
"Cannot find the positions");
339 cpl_imagelist_delete(in);
340 cpl_bivector_delete(positions);
341 cpl_msg_indent_less();
344 nflux = cpl_vector_get_size(flux);
345 nx = cpl_image_get_size_x(cpl_imagelist_get(in, 0));
346 ny = cpl_image_get_size_y(cpl_imagelist_get(in, 0));
347 cpl_imagelist_delete(in);
348 cpl_msg_indent_less();
350 cpl_msg_error(cpl_func,
"No flux computed");
351 cpl_bivector_delete(positions);
352 cpl_vector_delete(flux);
357 purged_pos = cpl_matrix_new(2, nval);
358 purged_pos_x = cpl_matrix_get_data(purged_pos);
359 purged_pos_y = purged_pos_x + nval;
360 positions_x = cpl_bivector_get_x_data(positions);
361 positions_y = cpl_bivector_get_y_data(positions);
362 purged_flux = cpl_vector_new(nval);
364 for (i=0; i < nflux; i++) {
365 if (fabs(cpl_vector_get(flux, i)) > 0) {
366 purged_pos_x[j] = positions_x[i];
367 purged_pos_y[j] = positions_y[i];
368 cpl_vector_set(purged_flux, j, cpl_vector_get(flux, i));
374 cpl_msg_warning(cpl_func,
"Fixing size inconsistency: %d <=> %d",
376 cpl_matrix_set_size(purged_pos, 2, j);
377 cpl_vector_set_size(purged_flux, j);
381 *fl = cpl_table_new(cpl_vector_get_size(flux));
382 cpl_table_new_column(*fl,
"POSX", CPL_TYPE_DOUBLE);
383 cpl_table_new_column(*fl,
"POSY", CPL_TYPE_DOUBLE);
384 cpl_table_new_column(*fl,
"FLUX", CPL_TYPE_DOUBLE);
385 for (i=0; i<cpl_vector_get_size(flux); i++) {
386 cpl_table_set_double(*fl,
"POSX", i, positions_x[i]);
387 cpl_table_set_double(*fl,
"POSY", i, positions_y[i]);
388 cpl_table_set_double(*fl,
"FLUX", i, cpl_vector_get(flux, i));
390 cpl_bivector_delete(positions);
391 cpl_vector_delete(flux);
395 isaac_img_illum_config.poly_deg = 2;
396 else if (nval >= 3) isaac_img_illum_config.poly_deg = 1;
397 else isaac_img_illum_config.poly_deg = 0;
399 cpl_msg_info(cpl_func,
"Fitting a %d-degree 2D-polynomial using %d of %d "
400 "fluxes", (
int)isaac_img_illum_config.poly_deg, nval, nflux);
403 poly = cpl_polynomial_new(2);
404 if (cpl_polynomial_fit(poly, purged_pos, NULL, purged_flux, NULL, CPL_FALSE,
405 NULL, &(isaac_img_illum_config.poly_deg))) {
406 cpl_msg_error(cpl_func,
"Cannot fit the polynomial");
407 cpl_matrix_delete(purged_pos);
408 cpl_vector_delete(purged_flux);
409 cpl_polynomial_delete(poly);
410 cpl_table_delete(*fl);
415 cpl_vector_fill_polynomial_fit_residual(purged_flux, purged_flux, NULL, poly,
418 cpl_matrix_delete(purged_pos);
420 isaac_img_illum_config.fit_error
421 = cpl_vector_product(purged_flux, purged_flux)
422 / cpl_vector_get_size(purged_flux);
424 if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
425 cpl_vector_dump(purged_flux, stdout);
427 cpl_vector_delete(purged_flux);
430 power[0] = 0; power[1] = 0;
431 isaac_img_illum_config.illum1 = cpl_polynomial_get_coeff(poly, power);
432 if (isaac_img_illum_config.poly_deg >= 1) {
433 power[0] = 1; power[1] = 0;
434 isaac_img_illum_config.illumx = cpl_polynomial_get_coeff(poly, power);
435 power[0] = 0; power[1] = 1;
436 isaac_img_illum_config.illumy = cpl_polynomial_get_coeff(poly, power);
438 if (isaac_img_illum_config.poly_deg >= 2) {
439 power[0] = 1; power[1] = 1;
440 isaac_img_illum_config.illumxy = cpl_polynomial_get_coeff(poly, power);
441 power[0] = 2; power[1] = 0;
442 isaac_img_illum_config.illumxx = cpl_polynomial_get_coeff(poly, power);
443 power[0] = 0; power[1] = 2;
444 isaac_img_illum_config.illumyy = cpl_polynomial_get_coeff(poly, power);
446 cpl_msg_info(cpl_func,
"P(X,Y)=a0+a1*X+a2*Y+a3*X*Y+a4*X^2+a5*Y^2");
447 cpl_msg_info(cpl_func,
"a0 = %g", isaac_img_illum_config.illum1);
448 cpl_msg_info(cpl_func,
"a1 = %g", isaac_img_illum_config.illumx);
449 cpl_msg_info(cpl_func,
"a2 = %g", isaac_img_illum_config.illumy);
450 cpl_msg_info(cpl_func,
"a3 = %g", isaac_img_illum_config.illumxy);
451 cpl_msg_info(cpl_func,
"a4 = %g", isaac_img_illum_config.illumxx);
452 cpl_msg_info(cpl_func,
"a5 = %g", isaac_img_illum_config.illumyy);
453 cpl_msg_info(cpl_func,
"error = %g", isaac_img_illum_config.fit_error);
456 poly_ima = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
457 cpl_image_fill_polynomial(poly_ima, poly, 1.0, 1.0, 1.0, 1.0);
458 cpl_polynomial_delete(poly);
461 isaac_img_illum_config.norm = cpl_image_get_mean(poly_ima);
462 cpl_image_divide_scalar(poly_ima, isaac_img_illum_config.norm);
476 static cpl_vector * isaac_img_illum_phot(
const cpl_imagelist * ilist,
477 const cpl_bivector * positions,
480 const int ni = cpl_imagelist_get_size(ilist);
482 cpl_vector *
self = cpl_vector_new(ni);
483 const double * positions_x = cpl_bivector_get_x_data_const(positions);
484 const double * positions_y = cpl_bivector_get_y_data_const(positions);
489 bug_if(ilist == NULL);
490 bug_if(positions == NULL);
491 bug_if(nvalid == NULL);
494 for (i=0; i < ni; i++) {
495 const cpl_image * cur_ima = cpl_imagelist_get_const(ilist, i);
497 = irplib_strehl_ring_background(cur_ima, positions_x[i],
499 isaac_img_illum_config.bg_r1,
500 isaac_img_illum_config.bg_r2,
501 IRPLIB_BG_METHOD_MEDIAN);
503 = irplib_strehl_disk_flux(cur_ima, positions_x[i], positions_y[i],
504 isaac_img_illum_config.star_r, bg);
505 cpl_vector_set(
self, i, fl);
506 if (fabs(fl)>1e-3) nok++;
507 cpl_msg_info(cpl_func,
"Image %2d has flux at (%g,%g): %g", i+1,
508 positions_x[i], positions_y[i], fl);
515 if (cpl_error_get_code()) {
516 cpl_vector_delete(
self);
531 static cpl_bivector * isaac_img_illum_find_pos(
const cpl_imagelist * ilist,
532 const cpl_bivector * offsets)
534 const int ni = cpl_imagelist_get_size(ilist);
536 cpl_bivector *
self = cpl_bivector_new(ni);
537 double * self_x = cpl_bivector_get_x_data(
self);
538 double * self_y = cpl_bivector_get_y_data(
self);
539 const double * offsets_x = cpl_bivector_get_x_data_const(offsets);
540 const double * offsets_y = cpl_bivector_get_y_data_const(offsets);
541 cpl_image * tmp_ima = NULL;
542 cpl_image * filtered_ima = NULL;
543 cpl_mask * kernel = cpl_mask_new(3, 3);
546 bug_if(ilist == NULL);
547 bug_if(offsets == NULL);
550 bug_if(cpl_mask_not(kernel));
553 for (i=0; i < ni; i++) {
554 const cpl_image * cur_ima = cpl_imagelist_get_const(ilist, i);
555 const int nx = cpl_image_get_size_x(cur_ima);
556 const int ny = cpl_image_get_size_y(cur_ima);
557 int llx, lly, urx, ury;
561 if (isaac_img_illum_config.pos_x > 0 &&
562 isaac_img_illum_config.pos_y > 0) {
563 llx = isaac_img_illum_config.pos_x + offsets_x[i] -
564 isaac_img_illum_config.s_hx;
565 urx = isaac_img_illum_config.pos_x + offsets_x[i] +
566 isaac_img_illum_config.s_hx;
567 lly = isaac_img_illum_config.pos_y + offsets_y[i] -
568 isaac_img_illum_config.s_hy;
569 ury = isaac_img_illum_config.pos_y + offsets_y[i] +
570 isaac_img_illum_config.s_hy;
572 llx = nx/2 + offsets_x[i] - isaac_img_illum_config.s_hx;
573 urx = nx/2 + offsets_x[i] + isaac_img_illum_config.s_hx;
574 lly = ny/2 + offsets_y[i] - isaac_img_illum_config.s_hy;
575 ury = ny/2 + offsets_y[i] + isaac_img_illum_config.s_hy;
579 cpl_image_delete(tmp_ima);
580 tmp_ima = cpl_image_extract(cur_ima, llx, lly, urx, ury);
581 any_if (
"Bad star zone. llx=%d, urx=%d, nx=%d. "
582 "lly=%d, ury=%d, ny=%d", llx, urx, nx, lly, ury, ny);
584 cpl_image_delete(filtered_ima);
585 filtered_ima = cpl_image_new(urx-llx+1, ury-lly+1,
586 cpl_image_get_type(tmp_ima));
587 cpl_image_filter_mask(filtered_ima, tmp_ima, kernel, CPL_FILTER_MEDIAN,
591 bug_if(cpl_image_get_maxpos(filtered_ima, &posx, &posy));
592 self_x[i] = llx + posx;
593 self_y[i] = lly + posy;
594 cpl_msg_info(cpl_func,
"image %2d has star at: %g, %g", i+1,
595 self_x[i], self_y[i]);
600 cpl_image_delete(tmp_ima);
601 cpl_image_delete(filtered_ima);
602 cpl_mask_delete(kernel);
604 if (cpl_error_get_code()) {
605 cpl_bivector_delete(
self);
622 static cpl_error_code isaac_img_illum_save(cpl_frameset * set,
623 const cpl_parameterlist * parlist,
624 const cpl_image * ima,
625 const cpl_table * flux)
628 const char * filename = cpl_frame_get_filename
629 (irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW));
630 cpl_propertylist * plist = NULL;
631 cpl_propertylist * qclist = cpl_propertylist_new();
636 plist = cpl_propertylist_load(filename, 0);
637 skip_if(plist == NULL);
640 if (cpl_error_get_code()) cpl_error_reset();
641 else cpl_propertylist_append_string(qclist,
"ESO QC FILTER OBS", sval);
643 cpl_propertylist_append_double(qclist,
"ESO QC ILLUM1",
644 isaac_img_illum_config.illum1);
645 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMX",
646 isaac_img_illum_config.illumx);
647 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMY",
648 isaac_img_illum_config.illumy);
649 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMXY",
650 isaac_img_illum_config.illumxy);
651 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMXX",
652 isaac_img_illum_config.illumxx);
653 cpl_propertylist_append_double(qclist,
"ESO QC ILLUMYY",
654 isaac_img_illum_config.illumyy);
655 cpl_propertylist_append_double(qclist,
"ESO QC FITERROR",
656 isaac_img_illum_config.fit_error);
657 cpl_propertylist_append_double(qclist,
"ESO QC FITNORM",
658 isaac_img_illum_config.norm);
663 (void)cpl_propertylist_erase_regexp(plist,
664 "^(ARCFILE|MJD-OBS|ESO TPL ID|DATE-OBS"
665 "|ESO DET DIT|ESO DET NDIT"
666 "|ESO DET NCORRS|ESO DET MODE NAME"
667 "|ESO OCS SELECT-ARM)$", 1);
670 skip_if(irplib_dfs_save_image(set, parlist, set, ima, CPL_BPP_IEEE_FLOAT,
671 RECIPE_STRING, ISAAC_IMG_ILLUM_RES,
672 qclist, NULL, PACKAGE
"/" PACKAGE_VERSION,
673 RECIPE_STRING CPL_DFS_FITS));
677 skip_if(irplib_dfs_save_table(set, parlist, set, flux, NULL,
678 RECIPE_STRING, ISAAC_IMG_ILLUM_TAB,
679 qclist, NULL, PACKAGE
"/" PACKAGE_VERSION,
680 RECIPE_STRING
"_flux" CPL_DFS_FITS));
684 bug_if(cpl_propertylist_append(plist, qclist));
685 cpl_propertylist_empty(qclist);
688 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG,
689 ISAAC_IMG_ILLUM_RES);
692 skip_if(cpl_dfs_save_paf(
"ISAAC", RECIPE_STRING, plist,
693 RECIPE_STRING CPL_DFS_PAF));
697 cpl_propertylist_delete(plist);
698 cpl_propertylist_delete(qclist);
700 return cpl_error_get_code();
int isaac_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
const char * isaac_pfits_get_filter(const cpl_propertylist *plist)
find out the filter
const char * isaac_extract_filename(const cpl_frameset *self, const char *tag)
Extract the filename of the first frame of the given tag.
cpl_bivector * isaac_get_offsets(const cpl_frameset *fset)
Get the offsets from a set of frames.
cpl_frameset * isaac_extract_frameset(const cpl_frameset *self, const char *tag)
Extract the frames with the given tag from a frameset.