34 #include <cpl_multiframe.h> 39 #ifdef HAVE_GETTIMEOFDAY 43 #include "muse_utils.h" 44 #include "muse_instrument.h" 46 #include "muse_cplwrappers.h" 47 #include "muse_flux.h" 48 #include "muse_pfits.h" 49 #include "muse_resampling.h" 50 #include "muse_tracing.h" 56 #define MOFFAT_USE_MUSE_OPTIMIZE 0 58 #if MOFFAT_USE_MUSE_OPTIMIZE 59 #include "muse_optimize.h" 85 return cpl_get_license(PACKAGE_NAME,
"2005, 2017");
101 for (n = 1; n <= kMuseNumIFUs; n++) {
120 cpl_errorstate prestate = cpl_errorstate_get();
121 int i, next = cpl_fits_count_extensions(aFilename);
122 for (i = 0; i <= next; i++) {
123 cpl_propertylist *properties = cpl_propertylist_load(aFilename, i);
125 cpl_propertylist_delete(properties);
128 cpl_propertylist_delete(properties);
130 cpl_errorstate_set(prestate);
161 unsigned char aIFU, cpl_boolean aInvert)
163 cpl_ensure(aFrames, CPL_ERROR_NULL_INPUT, NULL);
164 cpl_frameset *newFrames = cpl_frameset_new();
167 cpl_size iframe, nframes = cpl_frameset_get_size(aFrames);
168 for (iframe = 0; iframe < nframes; iframe++) {
169 const cpl_frame *frame = cpl_frameset_get_position_const(aFrames, iframe);
170 const char *fn = cpl_frame_get_filename(frame),
171 *tag = cpl_frame_get_tag(frame);
175 cpl_boolean matched = !aInvert && (!aTag || (aTag && !strcmp(tag, aTag))),
177 && ((aTag && !tag) || (aTag && strcmp(tag, aTag)));
178 if (matched || unmatched) {
181 cpl_errorstate prestate = cpl_errorstate_get();
185 if (extension == -1) {
187 cpl_errorstate_set(prestate);
189 cpl_propertylist *header = cpl_propertylist_load(fn, extension);
196 prestate = cpl_errorstate_get();
198 if (!cpl_errorstate_is_equal(prestate)) {
200 cpl_errorstate_set(prestate);
204 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
205 }
else if (ifu == 0 && !pipefile) {
208 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
209 }
else if (aIFU == 0) {
211 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
212 }
else if (aTag && (!strncmp(aTag, MUSE_TAG_GEOMETRY_TABLE,
213 strlen(MUSE_TAG_GEOMETRY_TABLE) + 1) ||
214 !strncmp(aTag, MUSE_TAG_TWILIGHT_CUBE,
215 strlen(MUSE_TAG_TWILIGHT_CUBE) + 1))) {
218 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
222 cpl_msg_debug(__func__,
"not added %s / %s / %d", fn,
223 cpl_frame_get_tag(frame), ifu);
226 cpl_propertylist_delete(header);
254 unsigned char aIFU, cpl_boolean aInvert)
256 cpl_ensure(aFrames && aTags, CPL_ERROR_NULL_INPUT, NULL);
257 cpl_ensure(cpl_array_get_type(aTags) == CPL_TYPE_STRING,
258 CPL_ERROR_ILLEGAL_INPUT, NULL);
260 cpl_frameset *outframes = cpl_frameset_new();
261 cpl_size itag, ntags = cpl_array_get_size(aTags);
262 for (itag = 0; itag < ntags; itag++) {
263 const char *tag = cpl_array_get_string(aTags, itag);
265 cpl_frameset_join(outframes, frames);
266 cpl_frameset_delete(frames);
289 cpl_frameset *newFrames = cpl_frameset_new();
292 cpl_size iframe, nframes = cpl_frameset_get_size(foundFrames);
293 cpl_msg_debug(__func__,
"Determine properties of all %"CPL_SIZE_FORMAT
294 " raw frames of IFU %hhu", nframes, aIFU);
295 int binx = -1, biny = -1, readid = -1;
296 char *fn = NULL, *readname = NULL, *chipname = NULL, *chipid = NULL;
297 for (iframe = 0; iframe < nframes; iframe++) {
298 const cpl_frame *frame = cpl_frameset_get_position_const(foundFrames, iframe);
301 const char *fn2 = cpl_frame_get_filename(frame);
303 fn = cpl_strdup(fn2);
305 cpl_propertylist *header = cpl_propertylist_load(fn2, 0);
307 cpl_msg_warning(__func__,
"Cannot read primary FITS header of file " 313 cpl_propertylist *exthead = cpl_propertylist_load(fn2, extension);
314 cpl_propertylist_append(header, exthead);
315 cpl_propertylist_delete(exthead);
317 cpl_boolean isOK = CPL_TRUE;
342 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) was taken with a different" 343 " x-binning factor (reference \"%s\", %d instead of %d)!",
344 fn2, aIFU, fn, binx2, binx);
348 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) was taken with a different" 349 " y-binning factor (reference \"%s\", %d instead of %d)!",
350 fn2, aIFU, fn, biny2, biny);
353 if (readid2 != readid) {
354 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) was taken with a different" 355 " read-out mode (reference \"%s\", %d/%s instead of %d/%s)!",
360 if (!chipname2 || !chipid2 ||
361 strcmp(chipname, chipname2) || strcmp(chipid, chipid2)) {
362 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) has a different chip " 363 "setup (reference \"%s\", name %s vs %s, id %s vs %s)",
364 fn2, aIFU, fn, chipname2, chipname, chipid2, chipid);
368 if (!cpl_frame_get_tag(frame) ||
369 !strncmp(cpl_frame_get_tag(frame), MUSE_TAG_EMPTY, 1) ) {
372 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) is not tagged!", fn2,
375 cpl_propertylist_delete(header);
377 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
384 cpl_frameset_delete(foundFrames);
419 const char *aDateObs, cpl_boolean aSequence)
421 cpl_ensure(aFrames, CPL_ERROR_NULL_INPUT, NULL);
423 cpl_frameset *fraw = cpl_frameset_new(),
424 *fillum = cpl_frameset_new(),
425 *fother = cpl_frameset_new();
428 cpl_size iframe, nframes = cpl_frameset_get_size(aFrames);
429 for (iframe = 0; iframe < nframes; iframe++) {
430 const cpl_frame *frame = cpl_frameset_get_position_const(aFrames, iframe);
431 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_RAW) {
432 const char *tag = cpl_frame_get_tag(frame);
433 if (!tag || (tag && strncmp(tag,
"ILLUM", 6))) {
438 cpl_propertylist *header
439 = cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
441 datematch = dateobs && !strncmp(aDateObs, dateobs, strlen(aDateObs));
442 cpl_propertylist_delete(header);
444 if ((aIndex < 0 && datematch) || aIndex == iraw || aSequence) {
445 cpl_frameset_insert(fraw, cpl_frame_duplicate(frame));
452 cpl_frameset_insert(fillum, cpl_frame_duplicate(frame));
457 cpl_frameset_insert(fother, cpl_frame_duplicate(frame));
461 printf(
"incoming frames (index=%d, DATE-OBS=%s):\n", aIndex, aDateObs);
462 cpl_frameset_dump(aFrames, stdout);
464 printf(
"=============================================================\n" 466 cpl_frameset_dump(fraw, stdout);
467 printf(
"illum frames:\n");
468 cpl_frameset_dump(fillum, stdout);
469 printf(
"-------------------------------------------------------------\n" 471 cpl_frameset_dump(fother, stdout);
472 printf(
"^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^\n");
477 cpl_frameset_join(fraw, fillum);
478 cpl_frameset_join(fraw, fother);
479 cpl_frameset_delete(fother);
480 cpl_frameset_delete(fillum);
482 printf(
"=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=\n" 483 "all sorted frames:\n");
484 cpl_frameset_dump(fraw, stdout);
485 printf(
"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
509 cpl_frame *frame = NULL;
510 if (cpl_frameset_count_tags(frames, aTag) == 1) {
511 frame = cpl_frame_duplicate(cpl_frameset_get_position_const(frames, 0));
513 cpl_frameset_delete(frames);
521 muse_utils_frame_get_basefilename(
const cpl_frame *aFrame)
523 char *filename = cpl_strdup(cpl_frame_get_filename(aFrame)),
524 *end = strstr(filename,
".fits");
528 end = strrchr(filename,
'-');
538 muse_utils_frames_compare_basenames(
const cpl_frame *aF1,
const cpl_frame *aF2)
540 cpl_ensure(aF1 && aF2, CPL_ERROR_NULL_INPUT, -1);
541 cpl_ensure(cpl_frame_get_filename(aF1) && cpl_frame_get_filename(aF2),
542 CPL_ERROR_DATA_NOT_FOUND, -1);
543 char *fn1 = muse_utils_frame_get_basefilename(aF1),
544 *fn2 = muse_utils_frame_get_basefilename(aF2);
545 int cmp = strcmp(fn1, fn2);
548 return cmp == 0 ? 1 : 0;
554 muse_utils_frame_compare(
const cpl_frame *aF1,
const cpl_frame *aF2)
556 const char *fn1 = cpl_frame_get_filename(aF1),
557 *fn2 = cpl_frame_get_filename(aF2);
558 int cmp = strcmp(fn1, fn2);
559 return (cmp < 0) ? -1 : (cmp > 0) ? 1 : 0;
591 cpl_ensure_code(aFrames, CPL_ERROR_NULL_INPUT);
593 cpl_ensure_code(cpl_frameset_get_size(aFrames) > 0, CPL_ERROR_ILLEGAL_INPUT);
595 printf(
"final out frames:\n");
596 cpl_frameset_dump(aFrames, stdout);
602 #define EXTKEYS1 MUSE_WCS_KEYS"|(ESO DET (CHIP|OUT[1-9]*) |ESO QC|ESO DRS)" 603 #define EXTKEYS2 MUSE_WCS_KEYS"|^B(UNIT|SCALE|ZERO)" 604 cpl_regex *regex = cpl_regex_new(EXTKEYS1, TRUE, CPL_REGEX_EXTENDED),
605 *nregex = cpl_regex_new(EXTKEYS1, FALSE, CPL_REGEX_EXTENDED),
606 *nregex2 = cpl_regex_new(EXTKEYS1
"|"EXTKEYS2, FALSE,
610 cpl_frameset *frames = cpl_frameset_new();
613 cpl_size nlabels = 0;
614 cpl_size *labels = cpl_frameset_labelise(aFrames,
615 muse_utils_frames_compare_basenames,
617 for (ilabel = 0; ilabel < nlabels; ilabel++) {
618 cpl_frameset *fset = cpl_frameset_extract(aFrames, labels, ilabel);
621 cpl_frameset_sort(fset, muse_utils_frame_compare);
623 cpl_frame *frame = cpl_frameset_get_position(fset, 0);
624 const char *tag = cpl_frame_get_tag(frame);
628 if (strncmp(tag,
"PIXTABLE_", 9) == 0) {
629 cpl_frameset_delete(fset);
633 int n = cpl_frameset_get_size(fset);
635 cpl_msg_warning(__func__,
"Nothing to merge for tag %s (%d frames)!",
637 cpl_frameset_delete(fset);
641 cpl_multiframe *mf = cpl_multiframe_new(frame,
"", regex);
643 cpl_frameset_delete(fset);
649 for (i = 0; i < n; i++) {
650 frame = cpl_frameset_get_position(fset, i);
651 const char *fn = cpl_frame_get_filename(frame);
652 cpl_msg_debug(__func__,
"Merging \"%s\".", fn);
654 int extdata = cpl_fits_find_extension(fn, EXTNAME_DATA),
655 extdq = cpl_fits_find_extension(fn, EXTNAME_DQ),
656 extstat = cpl_fits_find_extension(fn, EXTNAME_STAT);
657 cpl_errorstate state = cpl_errorstate_get();
658 if (extdata > 0 && extdq > 0 && extstat > 0) {
660 const char *extnames[] = { EXTNAME_DATA, EXTNAME_DQ, EXTNAME_STAT },
661 *updkeys[] = {
"SCIDATA",
"ERRDATA",
"QUALDATA", NULL };
662 const cpl_regex *filters[] = { nregex, nregex, nregex };
663 cpl_multiframe_append_datagroup(mf,
".", frame, 3, extnames, filters,
664 NULL, updkeys, CPL_MULTIFRAME_ID_JOIN);
665 }
else if (cpl_fits_count_extensions(fn) == 0) {
668 cpl_multiframe_append_dataset_from_position(mf,
".", frame, 0,
670 CPL_MULTIFRAME_ID_JOIN);
673 int iext, next = cpl_fits_count_extensions(fn);
674 for (iext = 1; iext <= next; iext++) {
675 cpl_multiframe_append_dataset_from_position(mf,
".", frame, iext,
677 CPL_MULTIFRAME_ID_JOIN);
681 if (!cpl_errorstate_is_equal(state)) {
682 cpl_msg_error(__func__,
"Appending data of \"%s\" for merging failed: %s",
683 fn, cpl_error_get_message());
688 char *basefn = muse_utils_frame_get_basefilename(frame),
689 *outfn = cpl_sprintf(
"%s.fits", basefn);
691 cpl_errorstate state = cpl_errorstate_get();
692 cpl_multiframe_write(mf, outfn);
693 if (!cpl_errorstate_is_equal(state)) {
694 cpl_msg_error(__func__,
"Writing merged data to \"%s\" failed: %s",
695 outfn, cpl_error_get_message());
697 cpl_frame_set_filename(frame, outfn);
700 cpl_frame_set_group(frame, CPL_FRAME_GROUP_PRODUCT);
702 cpl_frameset_insert(frames, cpl_frame_duplicate(frame));
705 cpl_multiframe_delete(mf);
706 cpl_frameset_delete(fset);
708 cpl_regex_delete(regex);
709 cpl_regex_delete(nregex);
710 cpl_regex_delete(nregex2);
713 printf(
"\naFrames (trying to remove these):\n");
714 cpl_frameset_dump(aFrames, stdout);
716 printf(
"\nmerged frames:\n");
717 cpl_frameset_dump(frames, stdout);
722 int iframe, nframes = cpl_frameset_get_size(frames);
723 for (iframe = 0; aDelete == CPL_TRUE && iframe < nframes; iframe++) {
724 cpl_frame *frame = cpl_frameset_get_position(frames, iframe);
726 cpl_msg_debug(__func__,
"===== Starting to compare \"%s\" =====",
727 cpl_frame_get_filename(frame));
730 for (iframe2 = 0; iframe2 < cpl_frameset_get_size(aFrames); iframe2++) {
732 cpl_frame *frame2 = cpl_frameset_get_position(aFrames, iframe2);
733 if (muse_utils_frames_compare_basenames(frame, frame2) == 1) {
734 const char *fn = cpl_frame_get_filename(frame2);
736 char *fb1 = muse_utils_frame_get_basefilename(frame),
737 *fb2 = muse_utils_frame_get_basefilename(frame2);
738 cpl_msg_debug(__func__,
"Removing \"%s\" (\"%s\" vs \"%s\").",
744 cpl_frameset_erase_frame(aFrames, frame2);
749 cpl_frameset_join(aFrames, frames);
750 cpl_frameset_delete(frames);
752 printf(
"\nmerged out frames:\n");
753 cpl_frameset_dump(aFrames, stdout);
756 return CPL_ERROR_NONE;
769 {
"lambda", CPL_TYPE_DOUBLE,
"Angstrom",
"%7.2f",
"wavelength", CPL_TRUE},
770 {
"throughput", CPL_TYPE_DOUBLE,
"",
"%.4e",
771 "filter response (in fractions of 1)", CPL_TRUE},
772 { NULL, 0, NULL, NULL, NULL, CPL_FALSE }
801 cpl_ensure(aFilterName, CPL_ERROR_NULL_INPUT, NULL);
802 if (!strncasecmp(aFilterName,
"none", 4)) {
803 cpl_msg_debug(__func__,
"No filter wanted (filter \"%s\")", aFilterName);
806 if (!strcmp(aFilterName,
"white")) {
807 cpl_msg_debug(__func__,
"White-light integration wanted (filter \"%s\")",
811 cpl_table_set(table,
"lambda", 0, kMuseNominalLambdaMin - 1e-5);
812 cpl_table_set(table,
"lambda", 1, kMuseNominalLambdaMin);
813 cpl_table_set(table,
"lambda", 2, kMuseNominalLambdaMax);
814 cpl_table_set(table,
"lambda", 3, kMuseNominalLambdaMax - 1e-5);
815 cpl_table_set(table,
"throughput", 0, 0.);
816 cpl_table_set(table,
"throughput", 1, 1.);
817 cpl_table_set(table,
"throughput", 2, 1.);
818 cpl_table_set(table,
"throughput", 3, 0.);
822 mt->
header = cpl_propertylist_new();
823 cpl_propertylist_append_string(mt->
header,
"EXTNAME",
"white");
827 MUSE_TAG_FILTER_LIST, 0);
829 cpl_error_set_message(__func__, CPL_ERROR_FILE_NOT_FOUND,
"%s (for filter " 830 "\"%s\") is missing", MUSE_TAG_FILTER_LIST,
836 char *filename = (
char *)cpl_frame_get_filename(frame);
837 int ext = cpl_fits_find_extension(filename, aFilterName);
839 cpl_error_set_message(__func__, CPL_ERROR_DATA_NOT_FOUND,
"\"%s\" does not " 840 "contain filter \"%s\"", filename, aFilterName);
841 cpl_frame_delete(frame);
847 table->
header = cpl_propertylist_load(filename, 0);
849 cpl_error_set_message(__func__, cpl_error_get_code(),
"loading filter " 850 "\"%s\" from file \"%s\" (ext %d) failed",
851 aFilterName, filename, ext);
852 cpl_frame_delete(frame);
857 table->
table = cpl_table_load(filename, ext, 1);
858 if (!table->
table || !cpl_table_get_nrow(table->
table)) {
859 cpl_error_set_message(__func__, cpl_error_get_code(),
"loading filter " 860 "\"%s\" from file \"%s\" (ext %d) failed",
861 aFilterName, filename, ext);
862 cpl_frame_delete(frame);
867 cpl_propertylist *hext = cpl_propertylist_load(filename, ext);
868 cpl_propertylist_copy_property_regexp(table->
header, hext,
869 "^EXTNAME$|^Z|^COMMENT", 0);
870 cpl_propertylist_delete(hext);
872 cpl_msg_info(__func__,
"loaded filter \"%s\" from file \"%s\" (ext %d)",
873 aFilterName, filename, ext);
896 cpl_ensure(aFilter && aFilter->
table, CPL_ERROR_NULL_INPUT, -1.);
899 const cpl_table *table = aFilter->
table;
900 int nrow = cpl_table_get_nrow(table);
901 double lbda1 = cpl_table_get(table,
"lambda", 0, NULL),
902 lbda2 = cpl_table_get(table,
"lambda", nrow - 1, NULL);
910 for (lambda = lbda1; lambda <= lbda2; lambda++) {
914 if (lambda >= aLambda1 && lambda <= aLambda2) {
937 cpl_ensure_code(aHeader && aFilter && aFilter->
header, CPL_ERROR_NULL_INPUT);
941 cpl_propertylist_update_string(aHeader, MUSE_HDR_FILTER,
942 cpl_propertylist_get_string(aFilter->
header,
944 cpl_propertylist_set_comment(aHeader, MUSE_HDR_FILTER, MUSE_HDR_FILTER_C);
945 if (cpl_propertylist_has(aFilter->
header,
"ZP_VEGA")) {
946 cpl_propertylist_update_double(aHeader, MUSE_HDR_FILTER_ZPVEGA,
947 cpl_propertylist_get_double(aFilter->
header,
949 cpl_propertylist_set_comment(aHeader, MUSE_HDR_FILTER_ZPVEGA,
950 MUSE_HDR_FILTER_ZPVEGA_C);
952 if (cpl_propertylist_has(aFilter->
header,
"ZP_AB")) {
953 cpl_propertylist_update_double(aHeader, MUSE_HDR_FILTER_ZPAB,
954 cpl_propertylist_get_double(aFilter->
header,
956 cpl_propertylist_set_comment(aHeader, MUSE_HDR_FILTER_ZPAB,
957 MUSE_HDR_FILTER_ZPAB_C);
959 cpl_propertylist_update_float(aHeader, MUSE_HDR_FILTER_FFRAC,
961 cpl_propertylist_set_comment(aHeader, MUSE_HDR_FILTER_FFRAC,
962 MUSE_HDR_FILTER_FFRAC_C);
964 return CPL_ERROR_NONE;
991 cpl_ensure(aHeader, CPL_ERROR_NULL_INPUT, NULL);
993 char *lampname = NULL;
995 for (n = 1; n <= nlamps; n++) {
996 cpl_errorstate prestate = cpl_errorstate_get();
999 if (!cpl_errorstate_is_equal(prestate)) {
1000 cpl_errorstate_set(prestate);
1006 if (!strncmp(name,
"CU-LAMP-", 8)) {
1009 if (!strcmp(name,
"CU-LAMP3") || !strcmp(name,
"CU-LAMP6")) {
1014 }
else if (!strcmp(name,
"CU-LAMP4")) {
1018 }
else if (!strcmp(name,
"CU-LAMP5")) {
1026 char *temp = lampname;
1027 lampname = cpl_sprintf(
"%s%c%s", temp, aSep, name);
1030 lampname = cpl_sprintf(
"%s", name);
1058 cpl_ensure(aHeader, CPL_ERROR_NULL_INPUT, NULL);
1061 cpl_array *lampnumbers = cpl_array_new(0, CPL_TYPE_INT);
1063 for (n = 1; n <= nlamps; n++) {
1064 cpl_errorstate prestate = cpl_errorstate_get();
1067 if (!cpl_errorstate_is_equal(prestate)) {
1068 cpl_errorstate_set(prestate);
1074 cpl_array_set_size(lampnumbers, cpl_array_get_size(lampnumbers) + 1);
1075 cpl_array_set_int(lampnumbers, cpl_array_get_size(lampnumbers) - 1,
1078 if (cpl_array_get_size(lampnumbers) < 1) {
1079 cpl_array_delete(lampnumbers);
1101 cpl_matrix *kernel = cpl_matrix_new(2*aXHalfwidth+1, 2*aYHalfwidth+1);
1103 cpl_msg_error(__func__,
"Could not create matrix: %s",
1104 cpl_error_get_message());
1109 for (i = -aXHalfwidth; i <= aXHalfwidth; i++) {
1111 for (j = -aYHalfwidth; j <= aYHalfwidth; j++) {
1113 double gauss = 1. / (aSigma*sqrt(2.*CPL_MATH_PI))
1114 * exp(-(i*i + j*j) / (2.*aSigma*aSigma));
1115 cpl_matrix_set(kernel, i+aXHalfwidth, j+aYHalfwidth, gauss);
1120 cpl_matrix_divide_scalar(kernel, sum);
1148 unsigned short aYOrder)
1150 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, NULL);
1154 int nx = cpl_image_get_size_x(aImage),
1155 ny = cpl_image_get_size_y(aImage);
1156 cpl_matrix *pos = cpl_matrix_new(2, nx * ny);
1157 cpl_vector *val = cpl_vector_new(nx * ny);
1159 for (i = 1; i < nx; i++) {
1160 for (j = 1; j < ny; j++) {
1161 if (cpl_image_is_rejected(aImage, i, j)) {
1164 cpl_matrix_set(pos, 0, np, i);
1165 cpl_matrix_set(pos, 1, np, j);
1167 cpl_vector_set(val, np, cpl_image_get(aImage, i, j, &err));
1173 cpl_matrix_delete(pos);
1174 cpl_vector_delete(val);
1175 cpl_error_set_message(__func__, CPL_ERROR_DATA_NOT_FOUND,
"No good pixels " 1176 "found in image, polynomial fit cannot be performed!");
1180 cpl_matrix_set_size(pos, 2, np);
1181 cpl_vector_set_size(val, np);
1184 cpl_polynomial *poly = cpl_polynomial_new(2);
1185 const cpl_boolean sym = CPL_FALSE;
1186 const cpl_size mindeg[] = { 0, 0 },
1187 maxdeg[] = { aXOrder, aYOrder };
1188 cpl_error_code rc = cpl_polynomial_fit(poly, pos, &sym, val, NULL, CPL_TRUE,
1190 cpl_matrix_delete(pos);
1191 cpl_vector_delete(val);
1194 cpl_image *fit = NULL;
1195 if (rc == CPL_ERROR_NONE) {
1196 fit = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1197 cpl_image_fill_polynomial(fit, poly, 1, 1, 1, 1);
1198 if (cpl_image_get_bpm_const(aImage)) {
1199 cpl_image_reject_from_mask(fit, cpl_image_get_bpm_const(aImage));
1202 cpl_polynomial_delete(poly);
1235 int aX2,
int aY2,
double *aX,
double *aY,
1238 cpl_ensure_code(aImage, CPL_ERROR_NULL_INPUT);
1239 cpl_ensure_code(aX || aY, CPL_ERROR_NULL_INPUT);
1241 cpl_image *im = cpl_image_extract(aImage, aX1, aY1, aX2, aY2);
1242 cpl_ensure_code(im, cpl_error_get_code());
1246 bg = cpl_image_get_mean(im);
1248 bg = cpl_image_get_median(im);
1251 CPL_ERROR_ILLEGAL_INPUT);
1253 cpl_image_subtract_scalar(im, bg);
1257 cpl_image *row = cpl_image_collapse_create(im, 0);
1260 int i, n = cpl_image_get_size_x(row);
1261 for (i = 1; i <= n; i++) {
1263 double value = cpl_image_get(row, i, 1, &err);
1270 *aX = w / f + aX1 - 1;
1271 cpl_image_delete(row);
1275 cpl_image *col = cpl_image_collapse_create(im, 1);
1278 int j, n = cpl_image_get_size_y(col);
1279 for (j = 1; j <= n; j++) {
1281 double value = cpl_image_get(col, 1, j, &err);
1288 *aY = w / f + aY1 - 1;
1289 cpl_image_delete(col);
1291 cpl_image_delete(im);
1293 return CPL_ERROR_NONE;
1329 const cpl_vector *aValues,
const cpl_vector *aErrors,
1332 cpl_ensure_code(aPositions && aValues, CPL_ERROR_NULL_INPUT);
1333 cpl_ensure_code(cpl_matrix_get_ncol(aPositions) == 2, CPL_ERROR_ILLEGAL_INPUT);
1334 int npoints = cpl_matrix_get_nrow(aPositions);
1335 cpl_ensure_code(npoints == cpl_vector_get_size(aValues), CPL_ERROR_ILLEGAL_INPUT);
1337 cpl_ensure_code(cpl_vector_get_size(aValues) == cpl_vector_get_size(aErrors),
1338 CPL_ERROR_ILLEGAL_INPUT);
1340 cpl_ensure_code(aX || aY, CPL_ERROR_NULL_INPUT);
1342 const double *values = cpl_vector_get_data_const(aValues);
1343 double xcen = 0., ycen = 0.,
1344 weight = 0., bg = 0.;
1346 bg = cpl_vector_get_mean(aValues);
1348 bg = cpl_vector_get_median_const(aValues);
1351 CPL_ERROR_ILLEGAL_INPUT);
1355 for (i = 0; i < npoints; i++) {
1356 double w = values[i] - bg;
1361 w /= cpl_vector_get(aErrors, i);
1363 xcen += cpl_matrix_get(aPositions, i, 0) * w;
1364 ycen += cpl_matrix_get(aPositions, i, 1) * w;
1376 return CPL_ERROR_NONE;
1404 muse_utils_multigauss(
const double x[],
const double p[],
double *f)
1406 const double xp = x[0];
1407 const cpl_size ncoeffs = p[0],
1409 const double sigma = p[2 + ncoeffs];
1412 for (i = 0; i < npeaks; i++) {
1413 if (p[2 + ncoeffs + 1 + i] == xp) {
1426 for (ic = 0; ic < ncoeffs; ic++) {
1427 *f += p[2 + ic] * pow(xp, ic);
1431 for (ip = 0; ip < npeaks; ip++) {
1432 const double xi = p[3 + ncoeffs + ip],
1433 Ai = p[3 + ncoeffs + npeaks + ip],
1434 exponent = (xi - xp) / sigma;
1435 *f += Ai / CPL_MATH_SQRT2PI / sigma * exp(-0.5 * exponent*exponent);
1438 printf(
"eval at %f --> %f\n", xp, *f);
1440 for (i = 0; i < ncoeffs + 2*npeaks + 3; i++) {
1441 printf(
" [%02d] %f\n", i, p[i]);
1460 muse_utils_dmultigauss(
const double x[],
const double p[],
double f[])
1462 const cpl_size ncoeffs = p[0],
1464 const double sigma = p[2 + ncoeffs];
1466 memset(f, 0,
sizeof(
double) * (ncoeffs + 2*npeaks + 3));
1470 const double xp = x[0];
1474 for (ic = 0; ic < ncoeffs; ic++) {
1475 f[2 + ic] = pow(xp, ic);
1478 f[2 + ncoeffs] = 0.;
1480 for (ip = 0; ip < npeaks; ip++) {
1481 const double xi = p[3 + ncoeffs + ip],
1482 Ai = p[3 + ncoeffs + npeaks + ip],
1483 exponent = (xi - xp) / sigma,
1484 expsq = exponent * exponent,
1485 expfunc = exp(-0.5 * expsq);
1486 f[2 + ncoeffs] -= Ai / CPL_MATH_SQRT2PI / (sigma*sigma)
1487 * (1 - expsq) * expfunc;
1489 f[3 + ncoeffs + ip] = -Ai / CPL_MATH_SQRT2PI / (sigma*sigma*sigma)
1490 * (xi - xp) * expfunc;
1492 f[3 + ncoeffs + npeaks + ip] = 1 / CPL_MATH_SQRT2PI / sigma * expfunc;
1495 printf(
"deval at %f -->\n", xp);
1497 for (i = 0; i < ncoeffs + 2*npeaks + 3; i++) {
1498 printf(
" [%02d] %e %f\n", i, f[i], p[i]);
1559 cpl_vector *aCenter,
double *aSigma,
1560 cpl_vector *aFlux, cpl_vector *aPoly,
1561 double *aMSE,
double *aRedChisq,
1562 cpl_matrix **aCovariance)
1565 *aCovariance = NULL;
1567 cpl_ensure_code(aX && aY && aCenter && aSigma, CPL_ERROR_NULL_INPUT);
1568 cpl_size npoints = cpl_vector_get_size(aX);
1569 cpl_ensure_code(npoints == cpl_bivector_get_size(aY), CPL_ERROR_INCOMPATIBLE_INPUT);
1570 cpl_size npeaks = cpl_vector_get_size(aCenter);
1571 cpl_ensure_code(!aFlux || npeaks == cpl_vector_get_size(aFlux),
1572 CPL_ERROR_INCOMPATIBLE_INPUT);
1573 cpl_size ncoeffs = aPoly ? cpl_vector_get_size(aPoly) : 0,
1576 cpl_ensure_code(!aRedChisq || npoints >= npars, CPL_ERROR_ILLEGAL_INPUT);
1579 cpl_matrix *x = cpl_matrix_wrap(npoints, 1, (
double *)cpl_vector_get_data_const(aX));
1580 const cpl_vector *y = cpl_bivector_get_x_const(aY),
1581 *ye = cpl_bivector_get_y_const(aY);
1583 cpl_vector *p = cpl_vector_new(npars + 2);
1584 int *pflags = cpl_calloc(npars + 2,
sizeof(
int));
1586 cpl_vector_set(p, 0, ncoeffs);
1587 cpl_vector_set(p, 1, npeaks);
1589 for (i = 2; i < npars + 2; i++) {
1593 cpl_array *aflags = cpl_array_wrap_int(pflags, npars + 2);
1594 printf(
"aflags, non-zero means parameter is fitted by cpl_fit_lvmq():\n");
1595 cpl_array_dump(aflags, 0, 1000, stdout);
1597 cpl_array_unwrap(aflags);
1601 for (j = 0, i = 2; j < ncoeffs; j++, i++) {
1602 cpl_vector_set(p, i, cpl_vector_get(aPoly, j));
1605 double sigma = fabs(*aSigma);
1609 cpl_vector_set(p, i++, sigma);
1611 for (j = 0; j < npeaks; j++, i++) {
1612 cpl_vector_set(p, i, cpl_vector_get(aCenter, j));
1615 for (j = 0; j < npeaks; j++, i++) {
1617 cpl_vector_set(p, i, cpl_vector_get(aFlux, j));
1619 cpl_vector_set(p, i, 1.);
1623 printf(
"input parameters p and their pflags:\n");
1624 for (j = 0; j < cpl_vector_get_size(p); j++) {
1625 printf(
" [%02d] %f %s\n", j, cpl_vector_get(p, j),
1626 pflags[j] ?
"\tfitted" :
"constant");
1629 cpl_matrix *covariance = NULL;
1630 cpl_error_code rc = cpl_fit_lvmq(x, NULL, y, ye, p, pflags,
1631 muse_utils_multigauss, muse_utils_dmultigauss,
1632 CPL_FIT_LVMQ_TOLERANCE, CPL_FIT_LVMQ_COUNT,
1633 CPL_FIT_LVMQ_MAXITER, aMSE, aRedChisq,
1635 cpl_matrix_unwrap(x);
1638 printf(
"output parameters vector p (%e, %e):\n",
1639 aMSE ? sqrt(*aMSE) : 0.0, aRedChisq ? *aRedChisq : 0.0);
1640 cpl_vector_dump(p, stdout);
1644 for (j = 0, i = 2; j < ncoeffs; j++, i++) {
1645 cpl_vector_set(aPoly, j, cpl_vector_get(p, i));
1650 *aSigma = fabs(cpl_vector_get(p, i++));
1651 for (j = 0; j < npeaks; j++, i++) {
1652 cpl_vector_set(aCenter, j, cpl_vector_get(p, i));
1656 for (j = 0; j < npeaks; j++, i++) {
1657 cpl_vector_set(aFlux, j, cpl_vector_get(p, i));
1663 *aCovariance = cpl_matrix_extract(covariance, 2, 2, 1, 1,
1664 cpl_matrix_get_nrow(covariance) - 2,
1665 cpl_matrix_get_ncol(covariance) - 2);
1667 cpl_matrix_delete(covariance);
1668 cpl_vector_delete(p);
1672 #if MOFFAT_USE_MUSE_OPTIMIZE 1676 const cpl_matrix *positions;
1677 const cpl_vector *values;
1678 const cpl_vector *errors;
1694 static cpl_error_code
1695 muse_moffat_2d_optfunc(
void *aData, cpl_array *aParams, cpl_array *aResiduals)
1697 const cpl_matrix *pos = ((fitdata_t *)aData)->positions;
1698 const cpl_vector *val = ((fitdata_t *)aData)->values,
1699 *err = ((fitdata_t *)aData)->errors;
1701 const double *p = cpl_array_get_data_double_const(aParams);
1702 double *residuals = cpl_array_get_data_double(aResiduals);
1703 int i, npoints = cpl_vector_get_size(val);
1704 for (i = 0; i < npoints; i++) {
1705 double xterm = (cpl_matrix_get(pos, i, 0) - p[2]) / p[4],
1706 yterm = (cpl_matrix_get(pos, i, 1) - p[3]) / p[5],
1707 crossterm = 2 * p[7] * xterm * yterm,
1708 base = 1 + (xterm*xterm + crossterm + yterm*yterm) / (1 + p[7]*p[7]),
1709 moffat = p[0] + p[1] * (p[6] - 1)
1710 / (CPL_MATH_PI * p[4]*p[5] * sqrt(1 - p[7]*p[7]))
1713 residuals[i] = cpl_vector_get(val, i) - moffat;
1715 residuals[i] /= cpl_vector_get(err, i);
1717 return CPL_ERROR_NONE;
1736 muse_moffat_2d_function(
const double xy[],
const double p[],
double *f)
1738 double xterm = (xy[0] - p[2]) / p[4],
1739 yterm = (xy[1] - p[3]) / p[5],
1740 crossterm = 2 * p[7] * xterm * yterm,
1741 rhoterm = 1. - p[7]*p[7],
1742 base = 1. + (xterm*xterm + crossterm + yterm*yterm) / rhoterm;
1743 *f = p[0] + p[1] * (p[6] - 1.) / (CPL_MATH_PI * p[4]*p[5] * sqrt(rhoterm))
1764 muse_moffat_2d_derivative(
const double xy[],
const double p[],
double f[])
1766 double xterm = (xy[0] - p[2]) / p[4],
1767 yterm = (xy[1] - p[3]) / p[5],
1768 crossterm = 2 * p[7] * xterm * yterm,
1769 rhoterm = 1. - p[7]*p[7],
1770 base = 1. + (xterm*xterm + crossterm + yterm*yterm) / (rhoterm);
1772 f[1] = (p[6] - 1.) / (CPL_MATH_PI * p[4]*p[5] * sqrt(rhoterm))
1774 f[2] = 2 * p[1] * p[6]*(p[6] - 1.)
1775 / (CPL_MATH_PI * p[4]*p[4] * p[5] * pow(rhoterm, 3./2.))
1776 * (xterm + p[7] * yterm) * pow(base, -p[6]-1.);
1777 f[3] = 2 * p[1] * p[6]*(p[6] - 1.)
1778 / (CPL_MATH_PI * p[4] * p[5]*p[5] * pow(rhoterm, 3./2.))
1779 * (yterm + p[7] * xterm) * pow(base, -p[6]-1.);
1780 f[4] = p[1] * (p[6] - 1.)
1781 / (CPL_MATH_PI * p[4]*p[4] * p[5] * sqrt(rhoterm))
1782 * (-pow(base, -p[6]) + 2 * p[6] / (rhoterm) * pow(base, -p[6]-1.)
1783 * (xterm*xterm + 0.5*crossterm));
1784 f[5] = p[1] * (p[6] - 1.)
1785 / (CPL_MATH_PI * p[4] * p[5]*p[5] * sqrt(rhoterm))
1786 * (-pow(base, -p[6]) + 2 * p[6] / (rhoterm) * pow(base, -p[6]-1.)
1787 * (yterm*yterm + 0.5*crossterm));
1788 f[6] = p[1] / (CPL_MATH_PI * p[4]*p[5] * sqrt(rhoterm))
1789 * pow(base, -p[6]) * (1. + (p[6] - 1.) * log(base));
1790 f[7] = p[1] * (p[6] - 1.)
1791 / (CPL_MATH_PI * p[4]*p[5] * pow(rhoterm, 3./2.))
1792 * (p[7] * pow(base, -p[6])
1793 - 2. * p[6] * pow(base, -p[6]-1.)
1794 * (xterm*yterm * (1 + 2*p[7]*p[7] / rhoterm)
1795 + p[7] / rhoterm * (xterm*xterm + yterm*yterm) ));
1879 const cpl_vector *aValues,
const cpl_vector *aErrors,
1880 cpl_array *aParams, cpl_array *aPErrors,
1881 const cpl_array *aPFlags,
1882 double *aRMS,
double *aRedChisq)
1886 return cpl_error_set_message(__func__, CPL_ERROR_NULL_INPUT,
1887 "Missing input positions.");
1890 return cpl_error_set_message(__func__, CPL_ERROR_NULL_INPUT,
1891 "Missing input values / errors.");
1893 if (cpl_matrix_get_ncol(aPositions) != 2) {
1894 return cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
1895 "Input positions are not for two-dimensional data.");
1897 if (cpl_vector_get_size(aValues) != cpl_matrix_get_nrow(aPositions)) {
1898 return cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
1899 "Input positions and values data must have same size.");
1901 if (aErrors && (cpl_vector_get_size(aValues) != cpl_vector_get_size(aErrors))) {
1902 return cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
1903 "Input vectors must have same size.");
1906 return cpl_error_set_message(__func__, CPL_ERROR_NULL_INPUT,
1907 "Missing input parameters array.");
1909 if (cpl_array_get_type(aParams) != CPL_TYPE_DOUBLE) {
1910 return cpl_error_set_message(__func__, CPL_ERROR_INVALID_TYPE,
1911 "Parameters array should be CPL_TYPE_DOUBLE.");
1913 if (aPErrors && (cpl_array_get_type(aPErrors) != CPL_TYPE_DOUBLE)) {
1914 return cpl_error_set_message(__func__, CPL_ERROR_INVALID_TYPE,
1915 "Parameters error array should be CPL_TYPE_DOUBLE.");
1917 if (aPFlags && (cpl_array_get_type(aPFlags) != CPL_TYPE_INT)) {
1918 return cpl_error_set_message(__func__, CPL_ERROR_INVALID_TYPE,
1919 "Parameters error array should be CPL_TYPE_INT.");
1921 if ((aPErrors || aRedChisq) && !aErrors) {
1922 return cpl_error_set_message(__func__, CPL_ERROR_DATA_NOT_FOUND,
1923 "Missing input parameters errors.");
1925 int npoints = cpl_matrix_get_nrow(aPositions);
1928 return cpl_error_set_message(__func__, CPL_ERROR_SINGULAR_MATRIX,
1929 "%d are not enough points to fit a Moffat profile.",
1933 int pflags[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
1936 int idx, nparam = 0;
1937 for (idx = 0; idx < 8; idx++) {
1938 int err, flag = cpl_array_get_int(aPFlags, idx, &err);
1944 cpl_array_get_double(aParams, idx, &err);
1946 return cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_INPUT,
1947 "Missing frozen value for parameter %d.", idx);
1952 return cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_INPUT,
1953 "No free parameters");
1963 double bg = cpl_array_get_double(aParams, 0, &invalid);
1965 bg = cpl_vector_get_median_const(aValues);
1970 double volguess = (cpl_vector_get_mean(aValues) - bg) * npoints;
1971 if (fabs(volguess) < FLT_EPSILON) {
1973 cpl_array_set_double(aParams, 0, bg);
1974 cpl_array_set_double(aParams, 1, 0.);
1975 cpl_array_set_invalid(aParams, 2);
1976 cpl_array_set_invalid(aParams, 3);
1977 cpl_array_set_invalid(aParams, 4);
1978 cpl_array_set_invalid(aParams, 5);
1979 cpl_array_set_double(aParams, 6, 1.);
1981 printf(
"flat Moffat:\n");
1982 cpl_array_dump(aParams, 0, 10, stdout);
1985 return CPL_ERROR_NONE;
1994 double xc = cpl_array_get_double(aParams, 2, &invalid);
1998 double yc = cpl_array_get_double(aParams, 3, &invalid);
2007 double beta = cpl_array_get_double(aParams, 6, &invalid);
2017 double alphay, alphax = cpl_array_get_double(aParams, 4, &invalid);
2019 alphay = cpl_array_get_double(aParams, 5, &invalid);
2021 double amplitude = 0.;
2022 if (volguess > 0.) {
2023 amplitude = cpl_vector_get_max(aValues) - bg;
2025 amplitude = cpl_vector_get_min(aValues) - bg;
2027 double halfpeak = amplitude / 2. + bg,
2028 limit = amplitude * 0.01;
2029 const double *values = cpl_vector_get_data_const(aValues);
2030 cpl_vector *vradius = cpl_vector_new(1);
2034 for (i = 0; i < npoints; i++) {
2035 if (values[i] > halfpeak - limit && values[i] < halfpeak + limit) {
2036 cpl_vector_set_size(vradius, nfound + 1);
2037 double radius = sqrt(pow(cpl_matrix_get(aPositions, i, 0) - xcen, 2)
2038 + pow(cpl_matrix_get(aPositions, i, 1) - ycen, 2));
2040 printf(
"radius(%d, %d) = %f\n", i, nfound+1, radius);
2042 cpl_vector_set(vradius, nfound++, radius);
2049 printf(
"found %d points (limit = %f)\n", nfound, limit / 2);
2051 }
while (nfound < 3 && isfinite(limit));
2052 if (!isfinite(limit)) {
2055 alphax = alphay = 1.;
2060 alphax = alphay = cpl_vector_get_mean(vradius) / sqrt(pow(2., 1./beta)-1);
2062 printf(
"estimated alphas = %f from radius %f\n", alphax, cpl_vector_get_mean(vradius));
2066 cpl_vector_delete(vradius);
2071 alphay = cpl_array_get_double(aParams, 5, &invalid);
2079 double volume = cpl_array_get_double(aParams, 1, &invalid);
2090 double rho = cpl_array_get_double(aParams, 7, &invalid);
2096 cpl_vector *params = cpl_vector_new(8);
2097 cpl_vector_set(params, 0, bg);
2098 cpl_vector_set(params, 1, volume);
2099 cpl_vector_set(params, 2, xc);
2100 cpl_vector_set(params, 3, yc);
2101 cpl_vector_set(params, 4, alphax);
2102 cpl_vector_set(params, 5, alphay);
2103 cpl_vector_set(params, 6, beta);
2104 cpl_vector_set(params, 7, rho);
2106 printf(
"initial guess values for Moffat (vol %e):\n", (cpl_vector_get_mean(aValues) - bg) * npoints);
2107 cpl_vector_dump(params, stdout);
2110 cpl_matrix *covariance = NULL;
2112 cpl_error_code rc = CPL_ERROR_NONE;
2113 #if MOFFAT_USE_MUSE_OPTIMIZE 2115 fitdata.positions = aPositions;
2116 fitdata.values = aValues;
2117 fitdata.errors = aErrors;
2118 cpl_array *optparams = cpl_array_wrap_double(cpl_vector_get_data(params), 8);
2120 muse_moffat_2d_optfunc, NULL);
2121 cpl_array_unwrap(optparams);
2123 cpl_errorstate prestate = cpl_errorstate_get();
2124 rc = cpl_fit_lvmq(aPositions, NULL, aValues, aErrors, params, pflags,
2125 muse_moffat_2d_function, muse_moffat_2d_derivative,
2126 CPL_FIT_LVMQ_TOLERANCE, CPL_FIT_LVMQ_COUNT,
2127 CPL_FIT_LVMQ_MAXITER, aRMS,
2128 aErrors ? aRedChisq : NULL, aErrors ? &covariance : NULL);
2131 *aRMS = sqrt(*aRMS);
2135 printf(
"Moffat fit (rc=%d, %s):\n", rc, cpl_error_get_message());
2136 cpl_vector_dump(params, stdout);
2139 if (rc == CPL_ERROR_NONE || rc == CPL_ERROR_SINGULAR_MATRIX ||
2140 rc == CPL_ERROR_CONTINUE) {
2146 if (isfinite(cpl_vector_get(params, 0)) &&
2147 isfinite(cpl_vector_get(params, 1)) &&
2148 isfinite(cpl_vector_get(params, 2)) &&
2149 isfinite(cpl_vector_get(params, 3)) &&
2150 isfinite(cpl_vector_get(params, 4)) &&
2151 isfinite(cpl_vector_get(params, 5)) &&
2152 isfinite(cpl_vector_get(params, 6)) &&
2153 isfinite(cpl_vector_get(params, 7))) {
2155 rc = CPL_ERROR_NONE;
2156 cpl_errorstate_set(prestate);
2161 cpl_array_set_double(aParams, 0, cpl_vector_get(params, 0));
2162 cpl_array_set_double(aParams, 1, cpl_vector_get(params, 1));
2163 cpl_array_set_double(aParams, 2, cpl_vector_get(params, 2));
2164 cpl_array_set_double(aParams, 3, cpl_vector_get(params, 3));
2165 cpl_array_set_double(aParams, 4, fabs(cpl_vector_get(params, 4)));
2166 cpl_array_set_double(aParams, 5, fabs(cpl_vector_get(params, 5)));
2167 cpl_array_set_double(aParams, 6, cpl_vector_get(params, 6));
2168 cpl_array_set_double(aParams, 7, cpl_vector_get(params, 7));
2170 if (aErrors && covariance) {
2172 for (idx = 0; idx < 8; idx++) {
2173 if (pflags[idx] && aPErrors) {
2174 cpl_array_set_double(aPErrors, idx,
2175 sqrt(cpl_matrix_get(covariance, idx, idx)));
2183 cpl_matrix_delete(covariance);
2184 cpl_vector_delete(params);
2235 cpl_vector *aErr, cpl_table *aExtra,
2236 const unsigned int aOrder,
const double aRSigma,
2237 double *aMSE,
double *aChiSq)
2246 cpl_ensure(aPos && aVal, CPL_ERROR_NULL_INPUT, NULL);
2247 cpl_ensure(cpl_matrix_get_ncol(aPos) == cpl_vector_get_size(aVal),
2248 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
2250 cpl_ensure(cpl_vector_get_size(aVal) == cpl_vector_get_size(aErr),
2251 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
2254 cpl_ensure(cpl_vector_get_size(aVal) == cpl_table_get_nrow(aExtra),
2255 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
2260 for (idx = 0; idx < cpl_vector_get_size(aVal); idx++) {
2262 if (isfinite(cpl_vector_get(aVal, idx))) {
2266 if (cpl_vector_get_size(aVal) == 1) {
2267 cpl_msg_warning(__func__,
"Input vector only contained non-finite elements!");
2271 cpl_matrix_erase_columns(aPos, idx, 1);
2278 cpl_table_erase_window(aExtra, idx, 1);
2284 int ndim = cpl_matrix_get_nrow(aPos);
2285 cpl_polynomial *fit = cpl_polynomial_new(ndim);
2286 int large_residuals = 1;
2287 while (large_residuals > 0) {
2288 const cpl_boolean sym = CPL_FALSE;
2289 cpl_size *mindeg = cpl_calloc(ndim,
sizeof(cpl_size)),
2290 *maxdeg = cpl_malloc(ndim *
sizeof(cpl_size));
2292 for (i = 0; i < ndim; i++) {
2295 cpl_error_code rc = cpl_polynomial_fit(fit, aPos, &sym, aVal, NULL,
2296 CPL_FALSE, mindeg, maxdeg);
2299 const cpl_size coeff = 0;
2300 if (rc != CPL_ERROR_NONE || !isfinite(cpl_polynomial_get_coeff(fit, &coeff))) {
2302 cpl_errorstate prestate = cpl_errorstate_get();
2304 printf(
"%s: output polynomial:\n", __func__);
2305 cpl_polynomial_dump(fit, stdout);
2306 printf(
"%s: positions and values that we tried to fit:\n", __func__);
2307 cpl_matrix_dump(aPos, stdout);
2308 cpl_vector_dump(aVal, stdout);
2311 cpl_polynomial_delete(fit);
2313 if (!cpl_errorstate_is_equal(prestate)) {
2314 cpl_errorstate_set(prestate);
2320 cpl_vector *res = cpl_vector_new(cpl_vector_get_size(aVal));
2321 cpl_vector_fill_polynomial_fit_residual(res, aVal, NULL, fit, aPos, aChiSq);
2322 double rms = sqrt(cpl_vector_product(res, res) / cpl_vector_get_size(res));
2328 printf(
"%s: polynomial fit (RMS %g chisq %g aRSigma %f -> limit %g):\n",
2329 __func__, rms, aChiSq ? *aChiSq : 0., aRSigma, aRSigma * rms);
2330 cpl_polynomial_dump(fit, stdout);
2332 char *title = cpl_sprintf(
"set title \"%s: RMS %g\"\n" 2333 "unset key\n", __func__, rms);
2334 cpl_plot_vector(title,
"",
"", res);
2338 large_residuals = 0;
2339 for (i = 0; i < cpl_vector_get_size(res); i++) {
2341 if (fabs(cpl_vector_get(res, i)) < (aRSigma * rms)) {
2348 cpl_msg_debug(__func__,
"residual %f RMS %f aRSigma %f -> limit %f",
2349 cpl_vector_get(res, i), rms, aRSigma, aRSigma * rms);
2352 if (cpl_vector_get_size(res) == 1) {
2353 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
"tried to " 2354 "remove the last vector/matrix element when " 2355 "checking fit residuals (residual %g RMS %g " 2356 "aRSigma %f -> limit %g)", cpl_vector_get(res, i),
2357 rms, aRSigma, aRSigma * rms);
2358 cpl_polynomial_delete(fit);
2360 rms = sqrt(DBL_MAX);
2364 large_residuals = 0;
2369 cpl_matrix_erase_columns(aPos, i, 1);
2376 cpl_table_erase_window(aExtra, i, 1);
2381 cpl_vector_delete(res);
2443 double aHalfWidth,
double aBinSize,
2444 float aLo,
float aHi,
unsigned char aIter,
2445 cpl_array *aResults, cpl_array *aErrors)
2447 cpl_ensure(aPixtable && aPixtable->
table && aPixtable->
header,
2448 CPL_ERROR_NULL_INPUT, 0.);
2453 cpl_boolean flip = aLambda < 0.;
2454 double lambda = fabs(aLambda);
2457 cpl_table_unselect_all(aPixtable->
table);
2459 CPL_NOT_LESS_THAN, lambda - aHalfWidth);
2461 CPL_NOT_GREATER_THAN, lambda + aHalfWidth);
2462 cpl_size nsel = cpl_table_count_selected(aPixtable->
table);
2463 cpl_ensure(nsel > 0, CPL_ERROR_DATA_NOT_FOUND, 0.);
2467 cpl_errorstate state = cpl_errorstate_get();
2470 cpl_table_unselect_all(aPixtable->
table);
2471 if (!cpl_errorstate_is_equal(state)) {
2473 cpl_table_delete(spec);
2474 cpl_error_set(__func__, cpl_error_get_code());
2480 cpl_table_multiply_scalar(spec,
"data", -1.);
2484 cpl_size nbins = cpl_table_get_nrow(spec);
2486 cpl_table_power_column(spec,
"stat", 0.5);
2487 cpl_table_name_column(spec,
"stat",
"error");
2488 cpl_table_set_column_unit(spec,
"error",
2489 cpl_table_get_column_unit(spec,
"data"));
2491 char *fn = cpl_sprintf(
"spec_ifu%02hhu_%p_%.3f.fits",
2493 (
void *)aPixtable, aLambda);
2494 cpl_msg_debug(__func__,
"----> saving spectrum as \"%s\"", fn);
2495 cpl_table_save(spec, NULL, NULL, fn, CPL_IO_CREATE);
2499 cpl_vector *pos = cpl_vector_wrap(nbins, cpl_table_get_data_double(spec,
"lambda")),
2500 *val = cpl_vector_wrap(nbins, cpl_table_get_data_double(spec,
"data")),
2501 *err = cpl_vector_wrap(nbins, cpl_table_get_data_double(spec,
"error"));
2502 state = cpl_errorstate_get();
2503 double xc, xerr = 2 * aHalfWidth,
2504 sigma, area, bglevel, mse;
2505 cpl_matrix *covariance = NULL;
2506 cpl_error_code rc = cpl_vector_fit_gaussian(pos, NULL, val, err, CPL_FIT_ALL,
2507 &xc, &sigma, &area, &bglevel,
2508 &mse, NULL, &covariance);
2509 cpl_vector_unwrap(pos);
2510 cpl_vector_unwrap(val);
2511 cpl_vector_unwrap(err);
2512 cpl_table_delete(spec);
2513 if (rc == CPL_ERROR_CONTINUE) {
2515 xerr = sqrt(sigma * sigma / area);
2516 cpl_errorstate_set(state);
2517 }
else if (rc == CPL_ERROR_SINGULAR_MATRIX || !covariance) {
2518 xerr = sqrt(sigma * sigma / area);
2519 cpl_errorstate_set(state);
2521 xerr = sqrt(cpl_matrix_get(covariance, 0, 0));
2523 cpl_msg_debug(__func__,
"covariance matrix:");
2524 cpl_matrix_dump(covariance, stdout);
2528 if (aResults && cpl_array_get_type(aResults) == CPL_TYPE_DOUBLE) {
2529 cpl_array_set_size(aResults, 4);
2530 cpl_array_set_double(aResults, 0, xc);
2531 cpl_array_set_double(aResults, 1, sigma);
2532 cpl_array_set_double(aResults, 2, area);
2533 cpl_array_set_double(aResults, 3, bglevel);
2535 if (aErrors && cpl_array_get_type(aErrors) == CPL_TYPE_DOUBLE) {
2536 cpl_array_set_size(aErrors, 4);
2537 cpl_array_set_double(aErrors, 0, xerr);
2538 if (rc != CPL_ERROR_NONE || !covariance) {
2539 cpl_array_fill_window_invalid(aErrors, 1, 3);
2541 cpl_array_set_double(aErrors, 1, sqrt(cpl_matrix_get(covariance, 1, 1)));
2542 cpl_array_set_double(aErrors, 2, sqrt(cpl_matrix_get(covariance, 2, 2)));
2543 cpl_array_set_double(aErrors, 3, sqrt(cpl_matrix_get(covariance, 3, 3)));
2546 cpl_matrix_delete(covariance);
2547 cpl_msg_debug(__func__,
"Gaussian fit (%s): %f +/- %f Angstrom, %f, %f, %f " 2548 "(RMS %f)", rc != CPL_ERROR_NONE ? cpl_error_get_message() :
"",
2549 xc, xerr, bglevel, area, sigma, sqrt(mse));
2571 const char *aKeyword,
const char *aString)
2573 cpl_ensure_code(aH1 && aH2 && aKeyword && aString, CPL_ERROR_NULL_INPUT);
2574 const char *hin = cpl_propertylist_get_string(aH1, aKeyword);
2575 cpl_ensure_code(hin, CPL_ERROR_ILLEGAL_INPUT);
2576 char *hstring = cpl_sprintf(
"%s (%s)", hin, aString);
2577 cpl_error_code rc = cpl_propertylist_update_string(aH2, aKeyword, hstring);
2612 const char *aExtData,
const char *aExtDQ,
2613 const char *aExtStat)
2615 cpl_ensure_code(aHeader && aClass2 && aExtData, CPL_ERROR_NULL_INPUT);
2616 cpl_ensure_code(!strcmp(aClass2,
"DATA") || !strcmp(aClass2,
"ERROR") ||
2617 !strcmp(aClass2,
"QUALITY"), CPL_ERROR_ILLEGAL_INPUT);
2620 #define ESO_HDU_HEADERS_REGEXP "HDU(CLASS|CLAS1|CLAS2|CLAS3|DOC|VERS)$" \ 2621 "|^SCIDATA$|^QUAL(DATA|MASK)$|^ERRDATA$" 2622 cpl_propertylist_erase_regexp(aHeader, ESO_HDU_HEADERS_REGEXP, 0);
2624 if (cpl_propertylist_has(aHeader,
"EXTNAME")) {
2625 cpl_propertylist_insert_after_string(aHeader,
"EXTNAME",
"HDUCLASS",
"ESO");
2627 cpl_propertylist_append_string(aHeader,
"HDUCLASS",
"ESO");
2629 cpl_propertylist_set_comment(aHeader,
"HDUCLASS",
"class name (ESO format)");
2630 cpl_propertylist_insert_after_string(aHeader,
"HDUCLASS",
"HDUDOC",
"DICD");
2631 cpl_propertylist_set_comment(aHeader,
"HDUDOC",
"document with class description");
2632 cpl_propertylist_insert_after_string(aHeader,
"HDUDOC",
"HDUVERS",
2634 cpl_propertylist_set_comment(aHeader,
"HDUVERS",
2635 "version number (according to spec v2.5.1)");
2636 cpl_propertylist_insert_after_string(aHeader,
"HDUVERS",
"HDUCLAS1",
"IMAGE");
2637 cpl_propertylist_set_comment(aHeader,
"HDUCLAS1",
"Image data format");
2638 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS1",
"HDUCLAS2", aClass2);
2639 if (!strcmp(aClass2,
"DATA")) {
2640 cpl_propertylist_set_comment(aHeader,
"HDUCLAS2",
2641 "this extension contains the data itself");
2644 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS2",
"QUALDATA", aExtDQ);
2647 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS2",
"ERRDATA", aExtStat);
2649 }
else if (!strcmp(aClass2,
"ERROR")) {
2650 cpl_propertylist_set_comment(aHeader,
"HDUCLAS2",
"this extension contains variance");
2651 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS2",
"HDUCLAS3",
"MSE");
2652 cpl_propertylist_set_comment(aHeader,
"HDUCLAS3",
2653 "the extension contains variances (sigma**2)");
2654 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS3",
"SCIDATA", aExtData);
2656 cpl_propertylist_insert_after_string(aHeader,
"SCIDATA",
"QUALDATA", aExtDQ);
2659 cpl_propertylist_set_comment(aHeader,
"HDUCLAS2",
2660 "this extension contains bad pixel mask");
2661 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS2",
"HDUCLAS3",
"FLAG32BIT");
2662 cpl_propertylist_set_comment(aHeader,
"HDUCLAS3",
"extension contains 32bit" 2663 " Euro3D bad pixel information");
2665 cpl_propertylist_insert_after_long(aHeader,
"HDUCLAS3",
"QUALMASK", 0xFFFFFFFF);
2666 cpl_propertylist_set_comment(aHeader,
"QUALMASK",
"all non-zero values are bad");
2667 cpl_propertylist_insert_after_string(aHeader,
"QUALMASK",
"SCIDATA", aExtData);
2669 cpl_propertylist_insert_after_string(aHeader,
"SCIDATA",
"ERRDATA", aExtStat);
2673 if (cpl_propertylist_has(aHeader,
"SCIDATA")) {
2674 cpl_propertylist_set_comment(aHeader,
"SCIDATA",
"pointer to the data extension");
2676 if (cpl_propertylist_has(aHeader,
"ERRDATA")) {
2677 cpl_propertylist_set_comment(aHeader,
"ERRDATA",
"pointer to the variance extension");
2679 if (cpl_propertylist_has(aHeader,
"QUALDATA")) {
2680 cpl_propertylist_set_comment(aHeader,
"QUALDATA",
2681 "pointer to the bad pixel mask extension");
2684 return CPL_ERROR_NONE;
2704 char *exe = getenv(
"MUSE_DEBUG_MEMORY_PROGRAM");
2709 printf(
"=== %s ===\n", aMarker);
2712 if (strlen(exe) > 0) {
2713 snprintf(command, 999,
2714 "ps -C %s -o comm,start_time,pid,tid,pcpu,stat,rss,size,vsize",
2718 snprintf(command, 999,
2719 "ps -o comm,start_time,pid,tid,pcpu,stat,rss,size,vsize");
2723 int rc = system(command);
2724 UNUSED_ARGUMENT(rc);
2750 cpl_ensure(aImage && aKernel, CPL_ERROR_NULL_INPUT, NULL);
2752 cpl_size nx = cpl_image_get_size_x(aImage);
2753 cpl_size ny = cpl_image_get_size_y(aImage);
2754 cpl_size nc = cpl_matrix_get_ncol(aKernel);
2755 cpl_size nr = cpl_matrix_get_nrow(aKernel);
2757 cpl_ensure(cpl_image_get_type(aImage) == CPL_TYPE_DOUBLE,
2758 CPL_ERROR_INVALID_TYPE, NULL);
2759 cpl_ensure(nx % 2 == 0, CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
2761 cpl_size kstart[2] = {(nx - nc) / 2, (ny - nr) / 2};
2762 cpl_size kend[2] = {kstart[0] + nc, kstart[1] + nr};
2764 cpl_image *kernel = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
2765 double *_kernel = cpl_image_get_data_double(kernel);
2767 const double *_aKernel = cpl_matrix_get_data_const(aKernel);
2769 for (iy = 0; iy < ny; ++iy) {
2771 for (ix = 0; ix < nx; ++ix) {
2772 cpl_size idx = nx * iy + ix;
2773 cpl_boolean inside = ((ix >= kstart[0]) && (ix < kend[0])) &&
2774 ((iy >= kstart[1]) && (iy < kend[1]));
2776 _kernel[idx] = _aKernel[nc * (iy - kstart[1]) + (ix - kstart[0])];
2781 cpl_size nxhalf = nx / 2 + 1;
2782 cpl_image *fft_image = cpl_image_new(nxhalf, ny, CPL_TYPE_DOUBLE_COMPLEX);
2783 cpl_image *fft_kernel = cpl_image_new(nxhalf, ny, CPL_TYPE_DOUBLE_COMPLEX);
2785 cpl_error_code status;
2786 status = cpl_fft_image(fft_image, aImage, CPL_FFT_FORWARD);
2787 if (status != CPL_ERROR_NONE) {
2788 cpl_image_delete(fft_kernel);
2789 cpl_image_delete(fft_image);
2790 cpl_image_delete(kernel);
2791 cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
2792 "FFT of input image failed!");
2795 status = cpl_fft_image(fft_kernel, kernel, CPL_FFT_FORWARD);
2796 if (status != CPL_ERROR_NONE) {
2797 cpl_image_delete(fft_kernel);
2798 cpl_image_delete(fft_image);
2799 cpl_image_delete(kernel);
2800 cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
2801 "FFT of convolution kernel failed!");
2804 cpl_image_delete(kernel);
2806 double complex *_fft_image = cpl_image_get_data_double_complex(fft_image);
2807 double complex *_fft_kernel = cpl_image_get_data_double_complex(fft_kernel);
2821 for (iy = 0; iy < ny; ++iy) {
2823 for (ix = 0; ix < nxhalf; ++ix) {
2824 cpl_size idx = nxhalf * iy + ix;
2825 int sign = ((ix + iy) % 2) ? -1 : 1;
2826 _fft_image[idx] *= sign * _fft_kernel[idx] / (nx * ny);
2829 cpl_image_delete(fft_kernel);
2831 cpl_image *result = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
2832 status = cpl_fft_image(result, fft_image, CPL_FFT_BACKWARD | CPL_FFT_NOSCALE);
2833 if (status != CPL_ERROR_NONE) {
2834 cpl_image_delete(result);
2835 cpl_image_delete(fft_image);
2836 cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
2837 "Backward FFT of convolution result failed!");
2840 cpl_image_delete(fft_image);
2868 image->
header = cpl_propertylist_load(aFilename, 0);
2870 cpl_error_set_message(__func__, cpl_error_get_code(),
"Loading primary FITS " 2871 "header of \"%s\" did not succeed", aFilename);
2877 int extension = cpl_fits_find_extension(aFilename, EXTNAME_DATA);
2878 cpl_propertylist *hdata = cpl_propertylist_load(aFilename, extension);
2882 cpl_msg_debug(__func__,
"Skipping extension %d [%s]", extension,
2884 cpl_propertylist_delete(hdata);
2886 hdata = cpl_propertylist_load(aFilename, extension);
2888 cpl_msg_debug(__func__,
"Taking extension %d [%s]", extension,
2893 image->
data = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, extension);
2895 cpl_error_set_message(__func__, MUSE_ERROR_READ_DATA,
"Could not load " 2896 "extension %s from \"%s\"", extname, aFilename);
2902 if (cpl_propertylist_has(hdata,
"BUNIT")) {
2903 cpl_propertylist_append_string(image->
header,
"BUNIT",
2905 cpl_propertylist_set_comment(image->
header,
"BUNIT",
2906 cpl_propertylist_get_comment(hdata,
"BUNIT"));
2908 cpl_msg_warning(__func__,
"No BUNIT given in extension %d [%s] of \"%s\"!",
2909 extension, extname, aFilename);
2912 if (!cpl_propertylist_has(hdata,
"CUNIT1") ||
2913 !cpl_propertylist_has(hdata,
"CUNIT2")) {
2914 cpl_msg_warning(__func__,
"No WCS found in extension %d [%s] of \"%s\"!",
2915 extension, extname, aFilename);
2920 cpl_propertylist_erase_regexp(hdata,
"(^ESO |" MUSE_WCS_KEYS ")", 1);
2921 cpl_propertylist_append(image->
header, hdata);
2922 cpl_propertylist_delete(hdata);
2926 if (extname && !strncmp(extname, EXTNAME_DATA, strlen(EXTNAME_DATA)+1)) {
2928 extension = cpl_fits_find_extension(aFilename, EXTNAME_STAT);
2931 char *statname = cpl_sprintf(
"%s_STAT", extname);
2932 extension = cpl_fits_find_extension(aFilename, statname);
2935 if (extension > 0) {
2936 cpl_errorstate status = cpl_errorstate_get();
2937 image->
stat = cpl_image_load(aFilename, CPL_TYPE_INT, 0, extension);
2938 if (!cpl_errorstate_is_equal(status)) {
2939 if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
2940 cpl_errorstate_set(status);
2941 cpl_msg_debug(__func__,
"Ignoring empty extension %s in \"%s\"",
2942 EXTNAME_STAT, aFilename);
2944 cpl_error_set_message(__func__, MUSE_ERROR_READ_STAT,
"Could not load " 2945 "extension %s from \"%s\"", EXTNAME_STAT, aFilename);
2955 if (extname && !strncmp(extname, EXTNAME_DATA, strlen(EXTNAME_DATA)+1)) {
2957 extension = cpl_fits_find_extension(aFilename, EXTNAME_DQ);
2960 char *dqname = cpl_sprintf(
"%s_DQ", extname);
2961 extension = cpl_fits_find_extension(aFilename, dqname);
2964 if (extension > 0) {
2965 cpl_errorstate status = cpl_errorstate_get();
2966 image->
dq = cpl_image_load(aFilename, CPL_TYPE_INT, 0, extension);
2967 if (!cpl_errorstate_is_equal(status)) {
2968 cpl_errorstate_set(status);
2969 cpl_error_set_message(__func__, MUSE_ERROR_READ_DQ,
"Could not load " 2970 "extension %s from \"%s\"", EXTNAME_DQ, aFilename);
const muse_cpltable_def muse_filtertable_def[]
MUSE filter table definition.
cpl_boolean muse_pfits_has_ifu(const cpl_propertylist *aHeaders, unsigned char aIFU)
Find out the whether this header related to a certain IFU.
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
const char * muse_pfits_get_extname(const cpl_propertylist *aHeaders)
find out the extension name
double muse_utils_pixtable_fit_line_gaussian(muse_pixtable *aPixtable, double aLambda, double aHalfWidth, double aBinSize, float aLo, float aHi, unsigned char aIter, cpl_array *aResults, cpl_array *aErrors)
Fit a 1D Gaussian to a given wavelength range in a pixel table.
int muse_pfits_get_read_id(const cpl_propertylist *aHeaders)
find out the readout mode id
int muse_utils_get_extension_for_ifu(const char *aFilename, unsigned char aIFU)
Return extension number that corresponds to this IFU/channel number.
unsigned char muse_utils_get_ifu(const cpl_propertylist *aHeaders)
Find out the IFU/channel from which this header originated.
cpl_table * muse_resampling_spectrum_iterate(muse_pixtable *aPixtable, double aBinwidth, float aLo, float aHi, unsigned char aIter)
Iteratively resample selected pixels of a pixel table into spectrum.
cpl_size muse_pfits_get_naxis(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the size of a given axis
cpl_image * data
the data extension
int muse_pfits_get_shut_status(const cpl_propertylist *aHeaders, int aShutter)
query the status of one shutter
muse_utils_centroid_type
Background handling when computing centroids.
cpl_error_code muse_cpl_optimize_lvmq(void *aData, cpl_array *aPar, int aSize, muse_cpl_evaluate_func *aFunction, muse_cpl_optimize_control_t *aCtrl)
Minimize a function with the Levenberg-Marquardt algorithm.
cpl_error_code muse_utils_filter_copy_properties(cpl_propertylist *aHeader, const muse_table *aFilter, double aFraction)
Add/propagate filter properties to header of collapsed image.
void muse_utils_memory_dump(const char *aMarker)
Display the current memory usage of the given program.
cpl_image * stat
the statistics extension
const char * muse_pfits_get_dateobs(const cpl_propertylist *aHeaders)
find out the date of observations
muse_image * muse_fov_load(const char *aFilename)
Load a FOV image into a MUSE image.
const char * muse_pfits_get_bunit(const cpl_propertylist *aHeaders)
find out the unit string
muse_table * muse_table_new(void)
Allocate memory for a new muse_table object.
Structure definition of MUSE three extension FITS file.
cpl_table * table
The pixel table.
int muse_pfits_get_lampnum(const cpl_propertylist *aHeaders)
query the number of lamps installed
cpl_propertylist * header
the FITS header
cpl_error_code muse_utils_set_hduclass(cpl_propertylist *aHeader, const char *aClass2, const char *aExtData, const char *aExtDQ, const char *aExtStat)
Set HDU headers for the ESO FITS data format.
cpl_image * dq
the data quality extension
cpl_table * muse_cpltable_new(const muse_cpltable_def *aDef, cpl_size aLength)
Create an empty table according to the specified definition.
double muse_flux_response_interpolate(const cpl_table *aResponse, double aLambda, double *aError, muse_flux_interpolation_type aType)
Compute linearly interpolated response of some kind at given wavelength.
const char * muse_get_license(void)
Get the pipeline copyright and license.
int muse_pfits_get_biny(const cpl_propertylist *aHeaders)
find out the binning factor in y direction
Structure definition of MUSE pixel table.
#define MUSE_WCS_KEYS
regular expression for WCS properties
const char * muse_pfits_get_lamp_name(const cpl_propertylist *aHeaders, int aLamp)
query the name of one lamp
cpl_error_code muse_cplvector_erase_element(cpl_vector *aVector, int aElement)
delete the given element from the input vector
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.
const char * muse_pfits_get_pipefile(const cpl_propertylist *aHeaders)
find out the pipefile
cpl_polynomial * muse_utils_iterate_fit_polynomial(cpl_matrix *aPos, cpl_vector *aVal, cpl_vector *aErr, cpl_table *aExtra, const unsigned int aOrder, const double aRSigma, double *aMSE, double *aChiSq)
Iterate a polynomial fit.
const char * muse_pfits_get_read_name(const cpl_propertylist *aHeaders)
find out the readout mode name
cpl_frameset * muse_frameset_sort_raw_other(const cpl_frameset *aFrames, int aIndex, const char *aDateObs, cpl_boolean aSequence)
Create a new frameset containing all relevant raw frames first then all other frames.
cpl_table * table
The table.
muse_table * muse_table_load_filter(muse_processing *aProcessing, const char *aFilterName)
Load a table for a given filter name.
void muse_processing_append_used(muse_processing *aProcessing, cpl_frame *aFrame, cpl_frame_group aGroup, int aDuplicate)
Add a frame to the set of used frames.
Structure to store a table together with a property list.
cpl_error_code muse_utils_fit_multigauss_1d(const cpl_vector *aX, const cpl_bivector *aY, cpl_vector *aCenter, double *aSigma, cpl_vector *aFlux, cpl_vector *aPoly, double *aMSE, double *aRedChisq, cpl_matrix **aCovariance)
Carry out a multi-Gaussian fit of data in a vector.
void muse_table_delete(muse_table *aTable)
Deallocate memory associated to a muse_table object.
char * muse_utils_header_get_lamp_names(cpl_propertylist *aHeader, char aSep)
Concatenate names of all active calibration lamps.
double muse_utils_filter_fraction(const muse_table *aFilter, double aLambda1, double aLambda2)
Compute fraction of filter area covered by the data range.
const char * muse_pfits_get_chip_id(const cpl_propertylist *aHeaders)
find out the chip id
cpl_propertylist * header
the header
int muse_pfits_get_binx(const cpl_propertylist *aHeaders)
find out the binning factor in x direction
cpl_array * muse_utils_header_get_lamp_numbers(cpl_propertylist *aHeader)
List numbers of all active calibration lamps.
cpl_image * muse_utils_image_fit_polynomial(const cpl_image *aImage, unsigned short aXOrder, unsigned short aYOrder)
Create a smooth version of a 2D image by fitting it with a 2D polynomial.
int muse_pfits_get_lamp_status(const cpl_propertylist *aHeaders, int aLamp)
query the status of one lamp
#define MUSE_PIXTABLE_LAMBDA
cpl_image * muse_convolve_image(const cpl_image *aImage, const cpl_matrix *aKernel)
Compute the convolution of an image with a kernel.
cpl_error_code muse_utils_image_get_centroid_window(cpl_image *aImage, int aX1, int aY1, int aX2, int aY2, double *aX, double *aY, muse_utils_centroid_type aBgType)
Compute centroid over an image window, optionally marginalizing over the background.
Definition of a cpl table structure.
muse_image * muse_image_new(void)
Allocate memory for a new muse_image object.
cpl_matrix * muse_matrix_new_gaussian_2d(int aXHalfwidth, int aYHalfwidth, double aSigma)
Create a matrix that contains a normalized 2D Gaussian.
cpl_frameset * muse_frameset_check_raw(const cpl_frameset *aFrames, const cpl_array *aTags, unsigned char aIFU)
return frameset containing good raw input data
cpl_frameset * muse_frameset_find(const cpl_frameset *aFrames, const char *aTag, unsigned char aIFU, cpl_boolean aInvert)
return frameset containing data from an IFU/channel with a certain tag
const char * muse_pfits_get_chip_name(const cpl_propertylist *aHeaders)
find out the chip name
cpl_error_code muse_utils_frameset_merge_frames(cpl_frameset *aFrames, cpl_boolean aDelete)
Merge IFU-specific files from a frameset to create multi-IFU outputs.
cpl_frame * muse_frameset_find_master(const cpl_frameset *aFrames, const char *aTag, unsigned char aIFU)
find the master frame according to its CCD number and tag
cpl_error_code muse_utils_copy_modified_header(cpl_propertylist *aH1, cpl_propertylist *aH2, const char *aKeyword, const char *aString)
Copy a modified header keyword from one header to another.
cpl_error_code muse_image_dq_to_nan(muse_image *aImage)
Convert pixels flagged in the DQ extension to NANs in DATA (and STAT, if present).
cpl_error_code muse_utils_get_centroid(const cpl_matrix *aPositions, const cpl_vector *aValues, const cpl_vector *aErrors, double *aX, double *aY, muse_utils_centroid_type aBgType)
Compute centroid of a two-dimensional dataset.
cpl_propertylist * header
The FITS header.
cpl_frameset * muse_frameset_find_tags(const cpl_frameset *aFrames, const cpl_array *aTags, unsigned char aIFU, cpl_boolean aInvert)
return frameset containing data from an IFU/channel with the given tag(s)