38 #define MUSE_TAG_IMAGE_AO "IMAGE_AO" 39 #define MUSE_EXT_IMAGE_AO "AO_IMAGE" 43 #define AO_CAMERA_CHIP_ID "CCD47-20I" 48 static const double AO_CAMERA_PIXEL_SCALE = 0.0833;
53 static const double SIGMA_TO_FWHM = 2.3548200450309493;
63 typedef struct muse_ao_bkg muse_ao_bkg;
71 typedef struct muse_ao_ee muse_ao_ee;
76 MUSE_AO_IMAGE_AOC = 0,
77 MUSE_AO_IMAGE_ATT = 1,
87 usage(
const char *name)
89 fprintf(stderr,
"Usage: %s [-hs] [-T threshold] -F fwhm -S scale " 90 "[-G gap] [-K kappa] [-B -m offset -M fraction] inImage outTable\n",
95 inline static cpl_error_code
96 muse_ao_replace_rejected(cpl_image *aImage,
double aValue)
98 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
100 cpl_size nx = cpl_image_get_size_x(aImage);
101 cpl_size ny = cpl_image_get_size_y(aImage);
104 for (iy = 0; iy < ny; ++iy) {
106 for (ix = 0; ix < nx; ++ix) {
107 if (cpl_image_is_rejected(aImage, ix + 1, iy + 1) == 1) {
108 cpl_image_set(aImage, ix + 1, iy + 1, aValue);
113 return CPL_ERROR_NONE;
131 muse_moffat_2d_function(
const double xy[],
const double p[],
double *f)
133 double xterm = (xy[0] - p[2]) / p[4];
134 double yterm = (xy[1] - p[3]) / p[5];
135 double crossterm = 2 * p[7] * xterm * yterm;
136 double rhoterm = 1. - p[7]*p[7];
137 double base = 1. + (xterm*xterm + crossterm + yterm*yterm) / rhoterm;
139 *f = p[0] + p[1] * (p[6] - 1.) / (CPL_MATH_PI * p[4]*p[5] * sqrt(rhoterm))
146 inline static cpl_error_code
147 muse_ao_estimate_bkg(muse_ao_bkg *bkg,
const cpl_image *aImage,
148 double x,
double y,
double inner,
double outer)
150 cpl_size rmax = (cpl_size)ceil(0.5 * outer);
151 cpl_size rmin = (cpl_size)ceil(0.5 * inner);
152 cpl_size xs = (cpl_size)floor(x);
153 cpl_size ys = (cpl_size)floor(y);
155 cpl_size xl = xs - rmax;
156 cpl_size yl = ys - rmax;
157 cpl_size xu = xs + rmax;
158 cpl_size yu = ys + rmax;
160 cpl_size nx = cpl_image_get_size_x(aImage);
161 cpl_size ny = cpl_image_get_size_y(aImage);
164 cpl_ensure((outer > inner), CPL_ERROR_ILLEGAL_INPUT, CPL_ERROR_ILLEGAL_INPUT);
166 if ((xl < 0) || (xu >= nx)) {
167 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
168 "Box is out of image bounds along X");
169 return CPL_ERROR_INCOMPATIBLE_INPUT;
172 if ((yl < 0) || (yu >= ny)) {
173 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
174 "Box is out of image bounds along Y");
175 return CPL_ERROR_INCOMPATIBLE_INPUT;
178 cpl_msg_debug(cpl_func,
"box position: lower left at (%" CPL_SIZE_FORMAT
179 ", %" CPL_SIZE_FORMAT
"), upper right at (%" CPL_SIZE_FORMAT
", %" 180 CPL_SIZE_FORMAT
")", xl, yl, xu, yu);
182 const double *image = cpl_image_get_data_double_const(aImage);
184 cpl_size nbkg = (2 * rmax + 1) * (2 * rmax + 1) - (2 * rmin + 1) * (2 * rmin + 1);
185 cpl_array *_bkg = cpl_array_new(nbkg, CPL_TYPE_DOUBLE);
193 for (iy = yl; iy <= yu; ++iy) {
194 for (ix = xl; ix <= xu; ++ix) {
195 if ((labs(ix - xs) > rmin) || (labs(iy - ys) > rmin)) {
196 cpl_array_set_double(_bkg, idx, image[iy * nx + ix]);
206 bkg->mean = cpl_array_get_mean(_bkg);
207 bkg->sdev = cpl_array_get_stdev(_bkg);
208 bkg->median = cpl_array_get_median(_bkg);
210 return CPL_ERROR_NONE;
225 muse_ao_calculate_ee_sum(
const cpl_image *aImage,
226 double x,
double y,
double size,
double bkg)
228 cpl_size radius = (cpl_size)ceil(0.5 * size);
229 cpl_size xs = (cpl_size)floor(x);
230 cpl_size ys = (cpl_size)floor(y);
232 cpl_size xl = xs - radius;
233 cpl_size yl = ys - radius;
234 cpl_size xu = xs + radius;
235 cpl_size yu = ys + radius;
237 cpl_size nx = cpl_image_get_size_x(aImage);
238 cpl_size ny = cpl_image_get_size_y(aImage);
240 if ((xl < 0) || (xu >= nx)) {
241 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
242 "Box is out of image bounds along X");
246 if ((yl < 0) || (yu >= ny)) {
247 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
248 "Box is out of image bounds along Y");
252 cpl_msg_debug(cpl_func,
"source position at (%" CPL_SIZE_FORMAT
", %" 253 CPL_SIZE_FORMAT
")", xs, ys);
254 cpl_msg_debug(cpl_func,
"box size: %" CPL_SIZE_FORMAT
", box position: " 255 "lower left at (%" CPL_SIZE_FORMAT
", %" CPL_SIZE_FORMAT
"), upper " 256 "right at (%" CPL_SIZE_FORMAT
", %" CPL_SIZE_FORMAT
")",
257 2 *radius + 1, xl, yl, xu, yu);
259 cpl_size nring = radius + 1;
260 cpl_table *ee = cpl_table_new(nring + 1);
262 cpl_table_new_column(ee,
"Radius", CPL_TYPE_DOUBLE);
263 cpl_table_new_column(ee,
"EE", CPL_TYPE_DOUBLE);
265 const double *image = cpl_image_get_data_double_const(aImage);
267 cpl_table_set_double(ee,
"Radius", 0, 0.);
268 cpl_table_set_double(ee,
"EE", 0, 0.);
270 for (cpl_size iring = 0; iring < nring; ++iring) {
282 for (iy = yl; iy <= yu; ++iy) {
283 for (ix = xl; ix <= xu; ++ix) {
284 cpl_size idx = iy * nx + ix;
285 double epix = image[idx] - bkg;
291 cpl_table_set_double(ee,
"Radius", iring + 1, 0.5 + (
double)iring);
292 cpl_table_set_double(ee,
"EE", iring + 1, esum);
302 muse_ao_calculate_ee_psf(
const cpl_image *aImage,
double x,
double y,
double size,
double bkg)
304 cpl_size radius = (cpl_size)ceil(0.5 * size);
305 cpl_size xs = (cpl_size)floor(x);
306 cpl_size ys = (cpl_size)floor(y);
308 cpl_size xl = xs - radius;
309 cpl_size yl = ys - radius;
310 cpl_size xu = xs + radius;
311 cpl_size yu = ys + radius;
313 cpl_size nx = cpl_image_get_size_x(aImage);
314 cpl_size ny = cpl_image_get_size_y(aImage);
316 if ((xl < 0) || (xu >= nx)) {
317 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
318 "Box is out of image bounds along X");
322 if ((yl < 0) || (yu >= ny)) {
323 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
324 "Box is out of image bounds along Y");
328 cpl_msg_debug(cpl_func,
"source position at (%" CPL_SIZE_FORMAT
", %" 329 CPL_SIZE_FORMAT
")", xs, ys);
330 cpl_msg_debug(cpl_func,
"box size: %" CPL_SIZE_FORMAT
", box position: " 331 "lower left at (%" CPL_SIZE_FORMAT
", %" CPL_SIZE_FORMAT
"), upper " 332 "right at (%" CPL_SIZE_FORMAT
", %" CPL_SIZE_FORMAT
")",
333 2 *radius + 1, xl, yl, xu, yu);
341 cpl_error_code status = cpl_image_get_fwhm(aImage, xs + 1, ys + 1,
344 if (status != CPL_ERROR_NONE) {
345 cpl_msg_error(cpl_func,
"Cannot determine FWHM for source at " 346 "(%.6f, %.6f)", x, y);
350 cpl_msg_info(cpl_func,
"Measured FWHM for source at (%.6f, %.6f): " 351 "%.6f, %.6f", x, y, xfwhm, yfwhm);
353 cpl_size npixel = (xu - xl + 1) * (yu - yl + 1);
354 cpl_matrix *positions = cpl_matrix_new(npixel, 2);
355 cpl_vector *flux = cpl_vector_new(npixel);
356 cpl_vector *rms = cpl_vector_new(npixel);
359 for (cpl_size ix = xl; ix <= xu; ++ix) {
360 for (cpl_size iy = yl; iy <= yu; ++iy) {
362 double value = cpl_image_get(aImage, ix, iy, &rejected);
367 cpl_matrix_set(positions, ndata, 0, ix);
368 cpl_matrix_set(positions, ndata, 1, iy);
369 cpl_vector_set(flux, ndata, value);
373 cpl_vector_set(rms, ndata, sqrt(value));
379 cpl_matrix_set_size(positions, ndata, 2);
380 cpl_vector_set_size(flux, ndata);
381 cpl_vector_set_size(rms, ndata);
384 const double moffatBeta = 2.5;
385 const double moffatAlphaToFwhm = 1. / (2. * sqrt(pow(2., 1. / moffatBeta) - 1.));
387 cpl_array *profile = cpl_array_new(8, CPL_TYPE_DOUBLE);
388 cpl_array *perror = cpl_array_new(8, CPL_TYPE_DOUBLE);
389 cpl_array *pflags = cpl_array_new(8, CPL_TYPE_INT);
392 cpl_array_fill_window(pflags, 0, 8, 0.);
393 cpl_array_set(pflags, 2, 1.);
394 cpl_array_set(pflags, 3, 1.);
396 cpl_array_set(profile, 0, bkg);
397 cpl_array_set(profile, 1, cpl_vector_get_sum(flux));
398 cpl_array_set(profile, 2, xs + 0.5);
399 cpl_array_set(profile, 3, ys + 0.5);
400 cpl_array_set(profile, 4, xfwhm * moffatAlphaToFwhm);
401 cpl_array_set(profile, 5, yfwhm * moffatAlphaToFwhm);
402 cpl_array_set(profile, 6, moffatBeta);
403 cpl_array_set(profile, 7, 0.);
406 double fitChiSqr = -1.;
409 &fitRms, &fitChiSqr);
411 if (cpl_error_get_code() != CPL_ERROR_NONE) {
412 cpl_array_delete(pflags);
413 cpl_array_delete(perror);
414 cpl_array_delete(profile);
416 cpl_vector_delete(rms);
417 cpl_vector_delete(flux);
418 cpl_matrix_delete(positions);
420 cpl_msg_error(cpl_func,
"Fitting Moffat profile (location) to source " 421 "at (%.6f, %.6f) failed!", x, y);
426 double xcenter = cpl_array_get(profile, 2, NULL);
427 double ycenter = cpl_array_get(profile, 3, NULL);
428 double xerror = cpl_array_get(perror, 2, NULL);
429 double yerror = cpl_array_get(perror, 3, NULL);
431 cpl_msg_info(cpl_func,
"Fitted source position (%.6f, %.6f) +/- " 432 "(%.6f, %.6f), RMS = %.6f, chi-square = %.6f", xcenter, ycenter,
433 xerror, yerror, fitRms, fitChiSqr);
436 cpl_array_fill_window(pflags, 0, 8, 0.);
437 cpl_array_set(pflags, 0, 1.);
438 cpl_array_set(pflags, 4, 1.);
439 cpl_array_set(pflags, 5, 1.);
440 cpl_array_set(pflags, 6, 1.);
446 &fitRms, &fitChiSqr);
448 if (cpl_error_get_code() != CPL_ERROR_NONE) {
449 cpl_array_delete(pflags);
450 cpl_array_delete(perror);
451 cpl_array_delete(profile);
453 cpl_vector_delete(rms);
454 cpl_vector_delete(flux);
455 cpl_matrix_delete(positions);
457 cpl_msg_error(cpl_func,
"Fitting Moffat profile (bkg, width, beta) to " 458 "source at (%.6f, %.6f) +/- (%.6f, %.6f) failed!", xcenter, ycenter,
464 double xwidth = cpl_array_get(profile, 4, NULL) / moffatAlphaToFwhm;
465 double ywidth = cpl_array_get(profile, 5, NULL) / moffatAlphaToFwhm;
466 double xwerror = cpl_array_get(perror, 4, NULL) / moffatAlphaToFwhm;
467 double ywerror = cpl_array_get(perror, 5, NULL) / moffatAlphaToFwhm;
469 cpl_msg_info(cpl_func,
"Profile fit parameters: bkg = %.6f +/- %.6f, " 470 "width = (%.6f, %.6f) +/- (%.6f, %.6f), beta = %.6f +/- %.6f," 471 "RMS = %.6f, chi-square = %.6f",
472 cpl_array_get(profile, 0, NULL), cpl_array_get(perror, 0, NULL),
473 xwidth, ywidth, xwerror, ywerror,
474 cpl_array_get(profile, 6, NULL), cpl_array_get(perror, 6, NULL),
477 cpl_array_delete(pflags);
478 cpl_array_delete(perror);
479 cpl_array_delete(profile);
481 cpl_vector_delete(rms);
482 cpl_vector_delete(flux);
483 cpl_matrix_delete(positions);
490 int main(
int argc,
char *argv[])
493 const char *
const progname =
"muse_ao_perf";
497 struct option options[] =
499 {
"help", no_argument, 0,
'h'},
500 {
"verbose", no_argument, 0,
'v'},
501 {
"srclist", required_argument, 0,
's'},
502 {
"threshold", required_argument, 0,
'T'},
503 {
"fwhm", required_argument, 0,
'F'},
504 {
"fwhm-scale", required_argument, 0,
'S'},
505 {
"gap", required_argument, 0,
'G'},
506 {
"bkg-kappa", required_argument, 0,
'K'},
507 {
"bkg-percentile", no_argument, 0,
'B'},
508 {
"bkg-ignore", required_argument, 0,
'm'},
509 {
"bkg-fraction", required_argument, 0,
'M'},
525 } config = {15., 0.5, 10., 0.4, 3., 0.01, 0.25, 0, {
'\0'}, 0};
532 while ((opt = getopt_long(argc, argv,
":hvs:T:S:F:G:Bm:M:K:", options,
533 &option_index)) != -1) {
545 strncpy(config.srcList, optarg, 1023);
546 config.srcList[1023] =
'\0';
550 config.threshold = strtod(optarg, NULL);
554 config.scale = strtod(optarg, NULL);
558 config.fwhm = strtod(optarg, NULL);
563 config.srcGap = strtod(optarg, NULL);
567 config.bkgKappa = strtod(optarg, NULL);
571 config.bkgMethod = 1;
575 config.bkgOffset = strtod(optarg, NULL);
579 config.bkgFraction = strtod(optarg, NULL);
583 fprintf(stderr,
"error: option '%c' requires an argument\n", optopt);
589 fprintf(stderr,
"error: unknown option '%c'\n", optopt);
601 if (argc <= optind) {
602 fprintf(stderr,
"error: missing input image argument\n");
607 if (argc - optind <= 1) {
608 fprintf(stderr,
"error: missing output table argument\n");
613 const char *inImage = argv[optind];
614 const char *outTable = argv[optind + 1];
616 cpl_init(CPL_INIT_DEFAULT);
618 if (config.logDebug) {
619 cpl_msg_set_level(CPL_MSG_DEBUG);
628 cpl_msg_info(progname,
"Locating AO test image in data file '%s'", inImage);
630 cpl_propertylist *header = cpl_propertylist_load(inImage, 0);
633 cpl_error_set_message(cpl_func, cpl_error_get_code(),
"Loading primary FITS " 634 "header of \"%s\" did not succeed", inImage);
640 int imageFormat = -1;
641 cpl_size extNum = -1;
643 if (cpl_propertylist_has(header,
"ESO PRO CATG")) {
646 if (strncmp(format,
"IMAGE_FOV", 9) == 0) {
647 imageFormat = MUSE_AO_IMAGE_FOV;
648 cpl_msg_debug(progname,
"Found MUSE FOV image in '%s'", inImage);
652 extNum = cpl_fits_find_extension(inImage, MUSE_EXT_IMAGE_AO);
655 imageFormat = MUSE_AO_IMAGE_ATT;
656 cpl_msg_debug(progname,
"Found attached AO camera image in '%s'",
660 const char *chipId = cpl_propertylist_get_string(header,
"ESO DET CHIP1 ID");
662 if (chipId && (strncmp(chipId, AO_CAMERA_CHIP_ID, 9) == 0) &&
663 (cpl_propertylist_get_bool(header,
"EXTEND") == CPL_FALSE)) {
664 cpl_msg_debug(progname,
"Found stand-alone AO camera image in '%s'",
666 imageFormat = MUSE_AO_IMAGE_AOC;
675 cpl_propertylist_delete(header);
678 if (imageFormat < 0) {
679 cpl_msg_error(progname,
"Unsupported file format '%s': cannot find AO " 680 "test image", inImage);
688 cpl_msg_info(progname,
"Loading AO test image from '%s'", inImage);
690 double pixelScale = AO_CAMERA_PIXEL_SCALE;
692 cpl_image *aoImage = NULL;
694 switch (imageFormat) {
695 case MUSE_AO_IMAGE_FOV:
699 cpl_msg_error(progname,
"Cannot load FOV image '%s'", inImage);
705 if (strncmp(insMode,
"NFM", 3) == 0) {
706 pixelScale = kMuseSpaxelSizeX_NFM;
709 pixelScale = kMuseSpaxelSizeX_WFM;
712 aoImage = cpl_image_cast(fov->
data, CPL_TYPE_DOUBLE);
718 if (cpl_error_get_code() == CPL_ERROR_NONE) {
719 cpl_msg_info(progname,
"Taking seeing estimate from image header: fwhm = %.6f", fwhm);
729 case MUSE_AO_IMAGE_ATT:
730 case MUSE_AO_IMAGE_AOC:
731 aoImage = cpl_image_load(inImage, CPL_TYPE_DOUBLE, 0, extNum);
739 cpl_msg_error(progname,
"Loading AO test image from '%s' failed!",
749 cpl_image_reject_value(aoImage, CPL_VALUE_NOTFINITE);
763 statistics.min = cpl_image_get_min(aoImage);
764 statistics.max = cpl_image_get_max(aoImage);
765 statistics.mean = cpl_image_get_mean(aoImage);
766 statistics.sdev = cpl_image_get_stdev(aoImage);
767 statistics.median = cpl_image_get_median_dev(aoImage, &statistics.mdev);
769 if (cpl_error_get_code() != CPL_ERROR_NONE) {
770 cpl_image_delete(aoImage);
772 cpl_msg_error(progname,
"Calculating image statistics failed!");
778 cpl_msg_info(progname,
"Image statistics: min = %.6f, max = %.6f, " 779 "mean = %.6f, rms = %.6f, median = %.6f, mdev = %.6f",
780 statistics.min, statistics.max, statistics.mean,
781 statistics.sdev, statistics.median, statistics.mdev);
792 double lower = statistics.median - config.bkgKappa * statistics.mdev;
793 double upper = statistics.median + config.bkgKappa * statistics.mdev;
795 if (config.bkgMethod == 1) {
797 double bkgFraction = config.bkgOffset + config.bkgFraction *
798 (1. - config.bkgOffset);
802 upper = (statistics.median < upper) ? statistics.median : upper;
806 cpl_mask *bkgMask = cpl_mask_threshold_image_create(aoImage, lower, upper);
807 cpl_mask_not(bkgMask);
809 cpl_mask *bpmMask = cpl_image_get_bpm(aoImage);
811 cpl_mask_or(bkgMask, bpmMask);
814 bpmMask = cpl_image_set_bpm(aoImage, bkgMask);
816 double rms = cpl_image_get_stdev(aoImage);
817 double bkgMean = cpl_image_get_mean(aoImage);
818 double bkgMedian = cpl_image_get_median(aoImage);
820 cpl_msg_info(progname,
"Background statistics: min = %.6f, max = %.6f, " 821 "mean = %.6f, sdev = %.6f, median = %.6f", lower, upper, bkgMean, rms,
825 cpl_mask_delete(cpl_image_set_bpm(aoImage, bpmMask));
829 cpl_mask_delete(cpl_image_unset_bpm(aoImage));
832 muse_ao_replace_rejected(aoImage, bkgMedian);
839 cpl_size nx = cpl_image_get_size_x(aoImage);
840 cpl_size ny = cpl_image_get_size_y(aoImage);
842 if ((nx % 2 != 0) || (ny % 2 != 0)) {
843 cpl_msg_debug(progname,
"Trimming image even number of pixels along " 851 cpl_image *_aoImage = cpl_image_extract(aoImage, 1, 1, nx, ny);
853 cpl_image_delete(aoImage);
854 cpl_msg_error(progname,
"Trimming image failed with error code '%d'",
855 cpl_error_get_code());
860 cpl_image_delete(aoImage);
867 cpl_table *aoSources =
muse_find_stars(aoImage, config.threshold * rms,
868 config.fwhm / pixelScale, NULL, NULL);
871 cpl_table_delete(aoSources);
872 cpl_image_delete(aoImage);
874 cpl_msg_error(progname,
"Point source detection failed with error code '%d'",
875 cpl_error_get_code());
881 cpl_size nsrc = cpl_table_get_nrow(aoSources);
882 cpl_msg_info(progname,
"%" CPL_SIZE_FORMAT
" sources detected", nsrc);
884 double xCenter = 0.5 * cpl_image_get_size_x(aoImage);
885 double yCenter = 0.5 * cpl_image_get_size_y(aoImage);
887 cpl_table_new_column(aoSources,
"Distance", CPL_TYPE_DOUBLE);
889 for (cpl_size isrc = 0; isrc < nsrc; ++isrc) {
890 double x = cpl_table_get_double(aoSources,
"X", isrc, NULL);
891 double y = cpl_table_get_double(aoSources,
"Y", isrc, NULL);
893 double distance = sqrt(pow(x - xCenter, 2.) + pow(y - yCenter, 2.));
895 cpl_table_set_double(aoSources,
"Distance", isrc, distance);
899 if (config.srcList[0]) {
900 cpl_table_save(aoSources, NULL, NULL, config.srcList, CPL_IO_CREATE);
907 cpl_table_get_column_minpos(aoSources,
"Distance", &cpos);
909 double xSource = cpl_table_get_double(aoSources,
"X", cpos, NULL);
910 double ySource = cpl_table_get_double(aoSources,
"Y", cpos, NULL);
911 double dSource = cpl_table_get_double(aoSources,
"Distance", cpos, NULL);
913 cpl_msg_info(progname,
"Central source at row %" CPL_SIZE_FORMAT
": " 914 "x = %.6f, y = %.6f, offset = %.6f", cpos, xSource, ySource, dSource);
917 double sz = config.scale * config.fwhm / pixelScale;
919 double szmin = sz + config.srcGap / pixelScale;
920 double szmax = szmin * sqrt(2.);
923 muse_ao_estimate_bkg(&bkg, aoImage, xSource, ySource, szmin, szmax);
925 if (cpl_error_get_code() != CPL_ERROR_NONE) {
926 cpl_table_delete(aoSources);
927 cpl_image_delete(aoImage);
929 cpl_msg_error(progname,
"Failed to estimate local background for source " 930 "at (%.6f, %.6f) and rectangular annulus size (%.6f, %.6f).", xSource,
931 ySource, szmin, szmax);
938 cpl_msg_info(progname,
"Local background estimate from rectangular " 939 "annulus (%.6f, %.6f) for source at (%.6f, %.6f): mean = %.6f, " 940 "rms = %.6f, median = %.6f",
941 szmin, szmax, xSource, ySource, bkg.mean, bkg.sdev, bkg.median);
944 cpl_table *ee = muse_ao_calculate_ee_sum(aoImage, xSource, ySource, sz, bkg.median);
946 if (cpl_error_get_code() != CPL_ERROR_NONE) {
947 cpl_table_delete(ee);
948 cpl_table_delete(aoSources);
949 cpl_image_delete(aoImage);
951 cpl_msg_error(progname,
"Failed to calculate ensquared energy for source " 952 "at (%.6f, %.6f) and box size %.6f.", xSource, ySource, sz);
958 cpl_msg_info(progname,
"Calculated ensquared energy for source " 959 "at (%.6f, %.6f) and box size %.6f: EE = %.6f.",
960 xSource, ySource, sz,
961 cpl_table_get_double(ee,
"EE", cpl_table_get_nrow(ee) - 1, NULL));
967 cpl_array *ee_psf = muse_ao_calculate_ee_psf(aoImage, xSource, ySource, sz,
972 cpl_size nrow = cpl_table_get_nrow(ee);
973 cpl_table *eeTable = cpl_table_new(nrow);
975 cpl_table_new_column(eeTable,
"Rpixel", CPL_TYPE_DOUBLE);
976 cpl_table_new_column(eeTable,
"Rtheta", CPL_TYPE_DOUBLE);
977 cpl_table_new_column(eeTable,
"EE", CPL_TYPE_DOUBLE);
978 cpl_table_new_column(eeTable,
"EEF", CPL_TYPE_DOUBLE);
980 double EEinf = cpl_table_get_column_max(ee,
"EE");
982 for (cpl_size irow = 0; irow < nrow; ++irow) {
984 double _radius = cpl_table_get_double(ee,
"Radius", irow, NULL);
985 double _EE = cpl_table_get_double(ee,
"EE", irow, NULL);
987 cpl_table_set_double(eeTable,
"Rpixel", irow, _radius);
988 cpl_table_set_double(eeTable,
"Rtheta", irow, _radius * pixelScale);
989 cpl_table_set_double(eeTable,
"EE", irow, _EE);
990 cpl_table_set_double(eeTable,
"EEF", irow, _EE / EEinf);
994 cpl_table_save(eeTable, NULL, NULL, outTable, CPL_IO_CREATE);
996 cpl_table_delete(eeTable);
997 cpl_table_delete(ee);
998 cpl_table_delete(aoSources);
999 cpl_image_delete(aoImage);
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
const char * muse_pfits_get_insmode(const cpl_propertylist *aHeaders)
find out the observation mode
cpl_image * data
the data extension
double muse_pfits_get_ia_fwhm(const cpl_propertylist *aHeaders)
find out the image analysis FWHM corrected by airmass (in arcsec)
muse_image * muse_fov_load(const char *aFilename)
Load a FOV image into a MUSE image.
Structure definition of MUSE three extension FITS file.
cpl_propertylist * header
the FITS header
cpl_error_code muse_utils_fit_moffat_2d(const cpl_matrix *aPositions, const cpl_vector *aValues, const cpl_vector *aErrors, cpl_array *aParams, cpl_array *aPErrors, const cpl_array *aPFlags, double *aRMS, double *aRedChisq)
Fit a 2D Moffat function to a given set of data.
double muse_cplimage_get_percentile(const cpl_image *aImage, double aFraction)
Get the percentile of an image.
cpl_table * muse_find_stars(const cpl_image *aImage, double aHmin, double aFwhm, const double *aRoundLimits, const double *aSharpLimits)
Find positive brightness perturbations (i.e stars) in an image.
const char * muse_pfits_get_pro_catg(const cpl_propertylist *aHeaders)
find out the PRO category