38 #ifdef HAVE_GETTIMEOFDAY
42 #include "muse_utils.h"
43 #include "muse_cplwrappers.h"
44 #include "muse_instrument.h"
46 #include "muse_pfits.h"
47 #include "muse_resampling.h"
48 #include "muse_tracing.h"
53 #define MOFFAT_USE_MUSE_OPTIMIZE 0
55 #if MOFFAT_USE_MUSE_OPTIMIZE
56 #include "muse_optimize.h"
82 return cpl_get_license(PACKAGE_NAME,
"2005, 2014");
98 for (n = 1; n <= kMuseNumIFUs; n++) {
117 cpl_errorstate prestate = cpl_errorstate_get();
118 int i, next = cpl_fits_count_extensions(aFilename);
119 for (i = 0; i <= next; i++) {
120 cpl_propertylist *properties = cpl_propertylist_load(aFilename, i);
122 cpl_propertylist_delete(properties);
125 cpl_propertylist_delete(properties);
127 cpl_errorstate_set(prestate);
155 unsigned char aIFU, cpl_boolean aInvert)
157 cpl_ensure(aFrames, CPL_ERROR_NULL_INPUT, NULL);
158 cpl_frameset *newFrames = cpl_frameset_new();
161 cpl_size iframe, nframes = cpl_frameset_get_size(aFrames);
162 for (iframe = 0; iframe < nframes; iframe++) {
163 const cpl_frame *frame = cpl_frameset_get_position_const(aFrames, iframe);
164 const char *fn = cpl_frame_get_filename(frame),
165 *tag = cpl_frame_get_tag(frame);
169 cpl_boolean matched = !aInvert && (!aTag || (aTag && !strcmp(tag, aTag))),
171 && ((aTag && !tag) || (aTag && strcmp(tag, aTag)));
172 if (matched || unmatched) {
175 cpl_errorstate prestate = cpl_errorstate_get();
179 if (extension == -1) {
181 cpl_errorstate_set(prestate);
183 cpl_propertylist *header = cpl_propertylist_load(fn, extension);
185 prestate = cpl_errorstate_get();
187 if (!cpl_errorstate_is_equal(prestate)) {
189 cpl_errorstate_set(prestate);
193 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
194 }
else if (ifu == 0 && !pipefile) {
197 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
198 }
else if (aIFU == 0) {
200 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
201 }
else if (!strncmp(aTag,
"GEOMETRY_TABLE", 15)) {
204 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
208 cpl_msg_debug(__func__,
"not added %s / %s / %d", fn,
209 cpl_frame_get_tag(frame), ifu);
212 cpl_propertylist_delete(header);
236 cpl_frameset *newFrames = cpl_frameset_new();
239 cpl_size iframe, nframes = cpl_frameset_get_size(foundFrames);
240 cpl_msg_debug(__func__,
"Determine properties of all %"CPL_SIZE_FORMAT
241 " raw frames of IFU %hhu", nframes, aIFU);
242 int binx = -1, biny = -1, readid = -1;
243 char *fn = NULL, *readname = NULL, *chipname = NULL, *chipid = NULL;
244 for (iframe = 0; iframe < nframes; iframe++) {
245 const cpl_frame *frame = cpl_frameset_get_position_const(foundFrames, iframe);
248 const char *fn2 = cpl_frame_get_filename(frame);
250 fn = cpl_strdup(fn2);
252 cpl_propertylist *header = cpl_propertylist_load(fn2, 0);
255 cpl_propertylist *exthead = cpl_propertylist_load(fn2, extension);
256 cpl_propertylist_append(header, exthead);
257 cpl_propertylist_delete(exthead);
260 cpl_msg_warning(__func__,
"Cannot read FITS header of file \"%s\"!", fn2);
263 cpl_boolean isOK = CPL_TRUE;
288 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) was taken with a different"
289 " x-binning factor (reference \"%s\", %d instead of %d)!",
290 fn2, aIFU, fn, binx2, binx);
294 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) was taken with a different"
295 " y-binning factor (reference \"%s\", %d instead of %d)!",
296 fn2, aIFU, fn, biny2, biny);
299 if (readid2 != readid) {
300 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) was taken with a different"
301 " read-out mode (reference \"%s\", %d/%s instead of %d/%s)!",
306 if (!chipname2 || !chipid2 ||
307 strcmp(chipname, chipname2) || strcmp(chipid, chipid2)) {
308 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) has a different chip "
309 "setup (reference \"%s\", name %s vs %s, id %s vs %s)",
310 fn2, aIFU, fn, chipname2, chipname, chipid2, chipid);
314 if (!cpl_frame_get_tag(frame) ||
315 !strncmp(cpl_frame_get_tag(frame), MUSE_TAG_EMPTY, 1) ) {
318 cpl_msg_warning(__func__,
"File \"%s\" (IFU %hhu) is not tagged!", fn2,
321 cpl_propertylist_delete(header);
323 cpl_frameset_insert(newFrames, cpl_frame_duplicate(frame));
330 cpl_frameset_delete(foundFrames);
357 const char *aDateObs, cpl_boolean aSequence)
359 cpl_ensure(aFrames, CPL_ERROR_NULL_INPUT, NULL);
361 cpl_frameset *fraw = cpl_frameset_new(),
362 *fother = cpl_frameset_new();
364 cpl_size iframe, nframes = cpl_frameset_get_size(aFrames);
365 for (iframe = 0; iframe < nframes; iframe++) {
366 const cpl_frame *frame = cpl_frameset_get_position_const(aFrames, iframe);
367 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_RAW) {
371 cpl_propertylist *header
372 = cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
374 datematch = !strncmp(aDateObs, dateobs, strlen(aDateObs));
375 cpl_propertylist_delete(header);
377 if ((aIndex < 0 && datematch) || aIndex == iraw || aSequence) {
378 cpl_frameset_insert(fraw, cpl_frame_duplicate(frame));
382 cpl_frameset_insert(fother, cpl_frame_duplicate(frame));
386 printf(
"incoming frames (index=%d, DATE-OBS=%s):\n", aIndex, aDateObs);
387 cpl_frameset_dump(aFrames, stdout);
389 printf(
"=============================================================\n"
391 cpl_frameset_dump(fraw, stdout);
393 printf(
"-------------------------------------------------------------\n"
395 cpl_frameset_dump(fother, stdout);
400 cpl_frameset_join(fraw, fother);
401 cpl_frameset_delete(fother);
403 printf(
"=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=_=\n"
404 "all sorted frames:\n");
405 cpl_frameset_dump(fraw, stdout);
429 cpl_frame *frame = NULL;
430 if (cpl_frameset_count_tags(frames, aTag) == 1) {
431 frame = cpl_frame_duplicate(cpl_frameset_get_position_const(frames, 0));
433 cpl_frameset_delete(frames);
459 cpl_msg_debug(__func__,
"No table found for tag %s and IFU %hhu", aTag,
463 cpl_msg_debug(__func__,
"No table found for tag %s", aTag);
469 const char *fn = cpl_frame_get_filename(frame);
472 if (extension <= 0) {
474 cpl_msg_debug(__func__,
"didn't find a specific extension for IFU %hhu, "
475 "will just use the first one", aIFU);
479 cpl_table *table = cpl_table_load(fn, extension, 0);
480 if (!table || !cpl_table_get_nrow(table)) {
481 cpl_msg_info(__func__,
"loading %s from file \"%s\" (ext %d) failed: %s",
482 aTag, fn, extension, cpl_error_get_message());
483 cpl_frame_delete(frame);
484 cpl_table_delete(table);
487 cpl_propertylist *header = cpl_propertylist_load(fn, extension);
488 cpl_errorstate state = cpl_errorstate_get();
490 char *extname = NULL;
491 if (en && cpl_errorstate_is_equal(state)) {
492 extname = cpl_sprintf(
"[%s]", en);
494 cpl_errorstate_set(state);
495 extname = cpl_sprintf(
"%c",
'\0');
497 cpl_msg_info(__func__,
"loaded %s from file \"%s%s\" (ext %d)", aTag, fn,
500 cpl_propertylist_delete(header);
525 cpl_msg_debug(__func__,
"No propertylist found for tag %s", aTag);
529 const char *filename = cpl_frame_get_filename(frame);
530 cpl_propertylist *pl = cpl_propertylist_load(filename, 0);
532 cpl_msg_info(__func__,
"loading %s from file %s failed: %s", aTag,
533 filename, cpl_error_get_message());
534 cpl_frame_delete(frame);
537 cpl_msg_info(__func__,
"loaded %s from file %s", aTag, filename);
555 {
"lambda", CPL_TYPE_DOUBLE,
"Angstrom",
"%7.2f",
"wavelength", CPL_TRUE},
556 {
"throughput", CPL_TYPE_DOUBLE,
"",
"%.4e",
557 "filter response (in fractions of 1)", CPL_TRUE},
558 { NULL, 0, NULL, NULL, NULL, CPL_FALSE }
587 cpl_ensure(aFilterName, CPL_ERROR_NULL_INPUT, NULL);
588 if (!strncasecmp(aFilterName,
"none", 4)) {
589 cpl_msg_debug(__func__,
"No filter wanted (filter \"%s\")", aFilterName);
592 if (!strcmp(aFilterName,
"white")) {
593 cpl_msg_debug(__func__,
"White-light integration wanted (filter \"%s\")",
597 cpl_table_set(table,
"lambda", 0, kMuseNominalLambdaMin - 1e-5);
598 cpl_table_set(table,
"lambda", 1, kMuseNominalLambdaMin);
599 cpl_table_set(table,
"lambda", 2, kMuseNominalLambdaMax);
600 cpl_table_set(table,
"lambda", 3, kMuseNominalLambdaMax - 1e-5);
601 cpl_table_set(table,
"throughput", 0, 0.);
602 cpl_table_set(table,
"throughput", 1, 1.);
603 cpl_table_set(table,
"throughput", 2, 1.);
604 cpl_table_set(table,
"throughput", 3, 0.);
608 MUSE_TAG_FILTER_LIST, 0);
610 cpl_error_set_message(__func__, CPL_ERROR_FILE_NOT_FOUND,
"%s (for filter "
611 "\"%s\") is missing", MUSE_TAG_FILTER_LIST,
617 char *filename = (
char *)cpl_frame_get_filename(frame);
618 int ext = cpl_fits_find_extension(filename, aFilterName);
620 cpl_error_set_message(__func__, CPL_ERROR_DATA_NOT_FOUND,
"\"%s\" does not "
621 "contain filter \"%s\"", filename, aFilterName);
622 cpl_frame_delete(frame);
626 cpl_table *table = cpl_table_load(filename, ext, 0);
627 if (!table || !cpl_table_get_nrow(table)) {
628 cpl_error_set_message(__func__, cpl_error_get_code(),
"loading filter "
629 "\"%s\" from file \"%s\" (ext %d) failed",
630 aFilterName, filename, ext);
631 cpl_frame_delete(frame);
632 cpl_table_delete(table);
635 cpl_msg_info(__func__,
"loaded filter \"%s\" from file \"%s\" (ext %d)",
636 aFilterName, filename, ext);
667 cpl_ensure(aHeader, CPL_ERROR_NULL_INPUT, NULL);
669 char *lampname = NULL;
671 for (n = 1; n <= nlamps; n++) {
672 cpl_errorstate prestate = cpl_errorstate_get();
675 if (!cpl_errorstate_is_equal(prestate)) {
676 cpl_errorstate_set(prestate);
682 if (!strncmp(name,
"CU-LAMP-", 8)) {
685 if (!strcmp(name,
"CU-LAMP3") || !strcmp(name,
"CU-LAMP6")) {
690 }
else if (!strcmp(name,
"CU-LAMP4")) {
694 }
else if (!strcmp(name,
"CU-LAMP5")) {
702 char *temp = lampname;
703 lampname = cpl_sprintf(
"%s%c%s", temp, aSep, name);
706 lampname = cpl_sprintf(
"%s", name);
734 cpl_ensure(aHeader, CPL_ERROR_NULL_INPUT, NULL);
737 cpl_array *lampnumbers = cpl_array_new(0, CPL_TYPE_INT);
739 for (n = 1; n <= nlamps; n++) {
740 cpl_errorstate prestate = cpl_errorstate_get();
743 if (!cpl_errorstate_is_equal(prestate)) {
744 cpl_errorstate_set(prestate);
750 cpl_array_set_size(lampnumbers, cpl_array_get_size(lampnumbers) + 1);
751 cpl_array_set_int(lampnumbers, cpl_array_get_size(lampnumbers) - 1,
754 if (cpl_array_get_size(lampnumbers) < 1) {
755 cpl_array_delete(lampnumbers);
777 cpl_matrix *kernel = cpl_matrix_new(2*aXHalfwidth+1, 2*aYHalfwidth+1);
779 cpl_msg_error(__func__,
"Could not create matrix: %s",
780 cpl_error_get_message());
785 for (i = -aXHalfwidth; i <= aXHalfwidth; i++) {
787 for (j = -aYHalfwidth; j <= aYHalfwidth; j++) {
789 double gauss = 1. / (aSigma*sqrt(2.*CPL_MATH_PI))
790 * exp(-(i*i + j*j) / (2.*aSigma*aSigma));
791 cpl_matrix_set(kernel, i+aXHalfwidth, j+aYHalfwidth, gauss);
796 cpl_matrix_divide_scalar(kernel, sum);
830 int aX2,
int aY2,
double *aX,
double *aY,
833 cpl_ensure_code(aImage, CPL_ERROR_NULL_INPUT);
834 cpl_ensure_code(aX || aY, CPL_ERROR_NULL_INPUT);
836 cpl_image *im = cpl_image_extract(aImage, aX1, aY1, aX2, aY2);
837 cpl_ensure_code(im, cpl_error_get_code());
841 bg = cpl_image_get_mean(im);
843 bg = cpl_image_get_median(im);
846 CPL_ERROR_ILLEGAL_INPUT);
848 cpl_image_subtract_scalar(im, bg);
852 cpl_image *row = cpl_image_collapse_create(im, 0);
855 int i, n = cpl_image_get_size_x(row);
856 for (i = 1; i <= n; i++) {
858 double value = cpl_image_get(row, i, 1, &err);
865 *aX = w / f + aX1 - 1;
866 cpl_image_delete(row);
870 cpl_image *col = cpl_image_collapse_create(im, 1);
873 int j, n = cpl_image_get_size_y(col);
874 for (j = 1; j <= n; j++) {
876 double value = cpl_image_get(col, 1, j, &err);
883 *aY = w / f + aY1 - 1;
884 cpl_image_delete(col);
886 cpl_image_delete(im);
888 return CPL_ERROR_NONE;
924 const cpl_vector *aValues,
const cpl_vector *aErrors,
927 cpl_ensure_code(aPositions && aValues, CPL_ERROR_NULL_INPUT);
928 cpl_ensure_code(cpl_matrix_get_ncol(aPositions) == 2, CPL_ERROR_ILLEGAL_INPUT);
929 int npoints = cpl_matrix_get_nrow(aPositions);
930 cpl_ensure_code(npoints == cpl_vector_get_size(aValues), CPL_ERROR_ILLEGAL_INPUT);
932 cpl_ensure_code(cpl_vector_get_size(aValues) == cpl_vector_get_size(aErrors),
933 CPL_ERROR_ILLEGAL_INPUT);
935 cpl_ensure_code(aX || aY, CPL_ERROR_NULL_INPUT);
937 const double *values = cpl_vector_get_data_const(aValues);
938 double xcen = 0., ycen = 0.,
939 weight = 0., bg = 0.;
941 bg = cpl_vector_get_mean(aValues);
943 bg = cpl_vector_get_median_const(aValues);
946 CPL_ERROR_ILLEGAL_INPUT);
950 for (i = 0; i < npoints; i++) {
951 double w = values[i] - bg;
956 w /= cpl_vector_get(aErrors, i);
958 xcen += cpl_matrix_get(aPositions, i, 0) * w;
959 ycen += cpl_matrix_get(aPositions, i, 1) * w;
971 return CPL_ERROR_NONE;
999 muse_utils_multigauss(
const double x[],
const double p[],
double *f)
1001 const double xp = x[0];
1002 const cpl_size ncoeffs = p[0],
1004 const double sigma = p[2 + ncoeffs];
1007 for (i = 0; i < npeaks; i++) {
1008 if (p[2 + ncoeffs + 1 + i] == xp) {
1021 for (ic = 0; ic < ncoeffs; ic++) {
1022 *f += p[2 + ic] * pow(xp, ic);
1026 for (ip = 0; ip < npeaks; ip++) {
1027 const double xi = p[3 + ncoeffs + ip],
1028 Ai = p[3 + ncoeffs + npeaks + ip],
1029 exponent = (xi - xp) / sigma;
1030 *f += Ai / CPL_MATH_SQRT2PI / sigma * exp(-0.5 * exponent*exponent);
1033 printf(
"eval at %f --> %f\n", xp, *f);
1035 for (i = 0; i < ncoeffs + 2*npeaks + 3; i++) {
1036 printf(
" [%02d] %f\n", i, p[i]);
1055 muse_utils_dmultigauss(
const double x[],
const double p[],
double f[])
1057 const cpl_size ncoeffs = p[0],
1059 const double sigma = p[2 + ncoeffs];
1061 memset(f, 0,
sizeof(
double) * (ncoeffs + 2*npeaks + 3));
1065 const double xp = x[0];
1069 for (ic = 0; ic < ncoeffs; ic++) {
1070 f[2 + ic] = pow(xp, ic);
1073 f[2 + ncoeffs] = 0.;
1075 for (ip = 0; ip < npeaks; ip++) {
1076 const double xi = p[3 + ncoeffs + ip],
1077 Ai = p[3 + ncoeffs + npeaks + ip],
1078 exponent = (xi - xp) / sigma,
1079 expsq = exponent * exponent,
1080 expfunc = exp(-0.5 * expsq);
1081 f[2 + ncoeffs] -= Ai / CPL_MATH_SQRT2PI / (sigma*sigma)
1082 * (1 - expsq) * expfunc;
1084 f[3 + ncoeffs + ip] = -Ai / CPL_MATH_SQRT2PI / (sigma*sigma*sigma)
1085 * (xi - xp) * expfunc;
1087 f[3 + ncoeffs + npeaks + ip] = 1 / CPL_MATH_SQRT2PI / sigma * expfunc;
1090 printf(
"deval at %f -->\n", xp);
1092 for (i = 0; i < ncoeffs + 2*npeaks + 3; i++) {
1093 printf(
" [%02d] %e %f\n", i, f[i], p[i]);
1154 cpl_vector *aCenter,
double *aSigma,
1155 cpl_vector *aFlux, cpl_vector *aPoly,
1156 double *aMSE,
double *aRedChisq,
1157 cpl_matrix **aCovariance)
1160 *aCovariance = NULL;
1162 cpl_ensure_code(aX && aY && aCenter && aSigma, CPL_ERROR_NULL_INPUT);
1163 cpl_size npoints = cpl_vector_get_size(aX);
1164 cpl_ensure_code(npoints == cpl_bivector_get_size(aY), CPL_ERROR_INCOMPATIBLE_INPUT);
1165 cpl_size npeaks = cpl_vector_get_size(aCenter);
1166 cpl_ensure_code(!aFlux || npeaks == cpl_vector_get_size(aFlux),
1167 CPL_ERROR_INCOMPATIBLE_INPUT);
1168 cpl_size ncoeffs = aPoly ? cpl_vector_get_size(aPoly) : 0,
1171 cpl_ensure_code(!aRedChisq || npoints >= npars, CPL_ERROR_ILLEGAL_INPUT);
1174 cpl_matrix *x = cpl_matrix_wrap(npoints, 1, (
double *)cpl_vector_get_data_const(aX));
1175 const cpl_vector *y = cpl_bivector_get_x_const(aY),
1176 *ye = cpl_bivector_get_y_const(aY);
1178 cpl_vector *p = cpl_vector_new(npars + 2);
1179 int *pflags = cpl_calloc(npars + 2,
sizeof(
int));
1181 cpl_vector_set(p, 0, ncoeffs);
1182 cpl_vector_set(p, 1, npeaks);
1184 for (i = 2; i < npars + 2; i++) {
1188 cpl_array *aflags = cpl_array_wrap_int(pflags, npars + 2);
1189 printf(
"aflags, non-zero means parameter is fitted by cpl_fit_lvmq():\n");
1190 cpl_array_dump(aflags, 0, 1000, stdout);
1192 cpl_array_unwrap(aflags);
1196 for (j = 0, i = 2; j < ncoeffs; j++, i++) {
1197 cpl_vector_set(p, i, cpl_vector_get(aPoly, j));
1200 double sigma = fabs(*aSigma);
1204 cpl_vector_set(p, i++, sigma);
1206 for (j = 0; j < npeaks; j++, i++) {
1207 cpl_vector_set(p, i, cpl_vector_get(aCenter, j));
1210 for (j = 0; j < npeaks; j++, i++) {
1212 cpl_vector_set(p, i, cpl_vector_get(aFlux, j));
1214 cpl_vector_set(p, i, 1.);
1218 printf(
"input parameters p and their pflags:\n");
1219 for (j = 0; j < cpl_vector_get_size(p); j++) {
1220 printf(
" [%02d] %f %s\n", j, cpl_vector_get(p, j),
1221 pflags[j] ?
"\tfitted" :
"constant");
1224 cpl_matrix *covariance = NULL;
1225 cpl_error_code rc = cpl_fit_lvmq(x, NULL, y, ye, p, pflags,
1226 muse_utils_multigauss, muse_utils_dmultigauss,
1227 CPL_FIT_LVMQ_TOLERANCE, CPL_FIT_LVMQ_COUNT,
1228 CPL_FIT_LVMQ_MAXITER, aMSE, aRedChisq,
1230 cpl_matrix_unwrap(x);
1233 printf(
"output parameters vector p (%e, %e):\n",
1234 aMSE ? sqrt(*aMSE) : 0.0, aRedChisq ? *aRedChisq : 0.0);
1235 cpl_vector_dump(p, stdout);
1239 for (j = 0, i = 2; j < ncoeffs; j++, i++) {
1240 cpl_vector_set(aPoly, j, cpl_vector_get(p, i));
1245 *aSigma = fabs(cpl_vector_get(p, i++));
1246 for (j = 0; j < npeaks; j++, i++) {
1247 cpl_vector_set(aCenter, j, cpl_vector_get(p, i));
1251 for (j = 0; j < npeaks; j++, i++) {
1252 cpl_vector_set(aFlux, j, cpl_vector_get(p, i));
1258 *aCovariance = cpl_matrix_extract(covariance, 2, 2, 1, 1,
1259 cpl_matrix_get_nrow(covariance) - 2,
1260 cpl_matrix_get_ncol(covariance) - 2);
1262 cpl_matrix_delete(covariance);
1263 cpl_vector_delete(p);
1267 #if MOFFAT_USE_MUSE_OPTIMIZE
1271 const cpl_matrix *positions;
1272 const cpl_vector *values;
1273 const cpl_vector *errors;
1289 static cpl_error_code
1290 muse_moffat_2d_optfunc(
void *aData, cpl_array *aParams, cpl_array *aResiduals)
1292 const cpl_matrix *pos = ((fitdata_t *)aData)->positions;
1293 const cpl_vector *val = ((fitdata_t *)aData)->values,
1294 *err = ((fitdata_t *)aData)->errors;
1296 const double *p = cpl_array_get_data_double_const(aParams);
1297 double *residuals = cpl_array_get_data_double(aResiduals);
1298 int i, npoints = cpl_vector_get_size(val);
1299 for (i = 0; i < npoints; i++) {
1300 double xterm = (cpl_matrix_get(pos, i, 0) - p[2]) / p[4],
1301 yterm = (cpl_matrix_get(pos, i, 1) - p[3]) / p[5],
1302 crossterm = 2 * p[7] * xterm * yterm,
1303 base = 1 + (xterm*xterm + crossterm + yterm*yterm) / (1 + p[7]*p[7]),
1304 moffat = p[0] + p[1] * (p[6] - 1)
1305 / (CPL_MATH_PI * p[4]*p[5] * sqrt(1 - p[7]*p[7]))
1308 residuals[i] = cpl_vector_get(val, i) - moffat;
1310 residuals[i] /= cpl_vector_get(err, i);
1312 return CPL_ERROR_NONE;
1331 muse_moffat_2d_function(
const double xy[],
const double p[],
double *f)
1333 double xterm = (xy[0] - p[2]) / p[4],
1334 yterm = (xy[1] - p[3]) / p[5],
1335 crossterm = 2 * p[7] * xterm * yterm,
1336 rhoterm = 1. - p[7]*p[7],
1337 base = 1. + (xterm*xterm + crossterm + yterm*yterm) / rhoterm;
1338 *f = p[0] + p[1] * (p[6] - 1.) / (CPL_MATH_PI * p[4]*p[5] * sqrt(rhoterm))
1359 muse_moffat_2d_derivative(
const double xy[],
const double p[],
double f[])
1361 double xterm = (xy[0] - p[2]) / p[4],
1362 yterm = (xy[1] - p[3]) / p[5],
1363 crossterm = 2 * p[7] * xterm * yterm,
1364 rhoterm = 1. - p[7]*p[7],
1365 base = 1. + (xterm*xterm + crossterm + yterm*yterm) / (rhoterm);
1367 f[1] = (p[6] - 1.) / (CPL_MATH_PI * p[4]*p[5] * sqrt(rhoterm))
1369 f[2] = 2 * p[1] * p[6]*(p[6] - 1.)
1370 / (CPL_MATH_PI * p[4]*p[4] * p[5] * pow(rhoterm, 3./2.))
1371 * (xterm + p[7] * yterm) * pow(base, -p[6]-1.);
1372 f[3] = 2 * p[1] * p[6]*(p[6] - 1.)
1373 / (CPL_MATH_PI * p[4] * p[5]*p[5] * pow(rhoterm, 3./2.))
1374 * (yterm + p[7] * xterm) * pow(base, -p[6]-1.);
1375 f[4] = p[1] * (p[6] - 1.)
1376 / (CPL_MATH_PI * p[4]*p[4] * p[5] * sqrt(rhoterm))
1377 * (-pow(base, -p[6]) + 2 * p[6] / (rhoterm) * pow(base, -p[6]-1.)
1378 * (xterm*xterm + 0.5*crossterm));
1379 f[5] = p[1] * (p[6] - 1.)
1380 / (CPL_MATH_PI * p[4] * p[5]*p[5] * sqrt(rhoterm))
1381 * (-pow(base, -p[6]) + 2 * p[6] / (rhoterm) * pow(base, -p[6]-1.)
1382 * (yterm*yterm + 0.5*crossterm));
1383 f[6] = p[1] / (CPL_MATH_PI * p[4]*p[5] * sqrt(rhoterm))
1384 * pow(base, -p[6]) * (1. + (p[6] - 1.) * log(base));
1385 f[7] = p[1] * (p[6] - 1.)
1386 / (CPL_MATH_PI * p[4]*p[5] * pow(rhoterm, 3./2.))
1387 * (p[7] * pow(base, -p[6])
1388 - 2. * p[6] * pow(base, -p[6]-1.)
1389 * (xterm*yterm * (1 + 2*p[7]*p[7] / rhoterm)
1390 + p[7] / rhoterm * (xterm*xterm + yterm*yterm) ));
1474 const cpl_vector *aValues,
const cpl_vector *aErrors,
1475 cpl_array *aParams, cpl_array *aPErrors,
1476 const cpl_array *aPFlags,
1477 double *aRMS,
double *aRedChisq)
1481 return cpl_error_set_message(__func__, CPL_ERROR_NULL_INPUT,
1482 "Missing input positions.");
1485 return cpl_error_set_message(__func__, CPL_ERROR_NULL_INPUT,
1486 "Missing input values / errors.");
1488 if (cpl_matrix_get_ncol(aPositions) != 2) {
1489 return cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
1490 "Input positions are not for two-dimensional data.");
1492 if (cpl_vector_get_size(aValues) != cpl_matrix_get_nrow(aPositions)) {
1493 return cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
1494 "Input positions and values data must have same size.");
1496 if (aErrors && (cpl_vector_get_size(aValues) != cpl_vector_get_size(aErrors))) {
1497 return cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
1498 "Input vectors must have same size.");
1501 return cpl_error_set_message(__func__, CPL_ERROR_NULL_INPUT,
1502 "Missing input parameters array.");
1504 if (cpl_array_get_type(aParams) != CPL_TYPE_DOUBLE) {
1505 return cpl_error_set_message(__func__, CPL_ERROR_INVALID_TYPE,
1506 "Parameters array should be CPL_TYPE_DOUBLE.");
1508 if (aPErrors && (cpl_array_get_type(aPErrors) != CPL_TYPE_DOUBLE)) {
1509 return cpl_error_set_message(__func__, CPL_ERROR_INVALID_TYPE,
1510 "Parameters error array should be CPL_TYPE_DOUBLE.");
1512 if (aPFlags && (cpl_array_get_type(aPFlags) != CPL_TYPE_INT)) {
1513 return cpl_error_set_message(__func__, CPL_ERROR_INVALID_TYPE,
1514 "Parameters error array should be CPL_TYPE_INT.");
1516 if ((aPErrors || aRedChisq) && !aErrors) {
1517 return cpl_error_set_message(__func__, CPL_ERROR_DATA_NOT_FOUND,
1518 "Missing input parameters errors.");
1520 int npoints = cpl_matrix_get_nrow(aPositions);
1523 return cpl_error_set_message(__func__, CPL_ERROR_SINGULAR_MATRIX,
1524 "%d are not enough points to fit a Moffat profile.",
1528 int pflags[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
1531 int idx, nparam = 0;
1532 for (idx = 0; idx < 8; idx++) {
1533 int err, flag = cpl_array_get_int(aPFlags, idx, &err);
1539 cpl_array_get_double(aParams, idx, &err);
1541 return cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_INPUT,
1542 "Missing frozen value for parameter %d.", idx);
1547 return cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_INPUT,
1548 "No free parameters");
1558 double bg = cpl_array_get_double(aParams, 0, &invalid);
1560 bg = cpl_vector_get_median_const(aValues);
1565 double volguess = (cpl_vector_get_mean(aValues) - bg) * npoints;
1566 if (fabs(volguess) < FLT_EPSILON) {
1568 cpl_array_set_double(aParams, 0, bg);
1569 cpl_array_set_double(aParams, 1, 0.);
1570 cpl_array_set_invalid(aParams, 2);
1571 cpl_array_set_invalid(aParams, 3);
1572 cpl_array_set_invalid(aParams, 4);
1573 cpl_array_set_invalid(aParams, 5);
1574 cpl_array_set_double(aParams, 6, 1.);
1576 printf(
"flat Moffat:\n");
1577 cpl_array_dump(aParams, 0, 10, stdout);
1580 return CPL_ERROR_NONE;
1589 double xc = cpl_array_get_double(aParams, 2, &invalid);
1593 double yc = cpl_array_get_double(aParams, 3, &invalid);
1602 double beta = cpl_array_get_double(aParams, 6, &invalid);
1612 double alphay, alphax = cpl_array_get_double(aParams, 4, &invalid);
1614 alphay = cpl_array_get_double(aParams, 5, &invalid);
1616 double amplitude = 0.;
1617 if (volguess > 0.) {
1618 amplitude = cpl_vector_get_max(aValues) - bg;
1620 amplitude = cpl_vector_get_min(aValues) - bg;
1622 double halfpeak = amplitude / 2. + bg,
1623 limit = amplitude * 0.01;
1624 const double *values = cpl_vector_get_data_const(aValues);
1625 cpl_vector *vradius = cpl_vector_new(1);
1629 for (i = 0; i < npoints; i++) {
1630 if (values[i] > halfpeak - limit && values[i] < halfpeak + limit) {
1631 cpl_vector_set_size(vradius, nfound + 1);
1632 double radius = sqrt(pow(cpl_matrix_get(aPositions, i, 0) - xcen, 2)
1633 + pow(cpl_matrix_get(aPositions, i, 1) - ycen, 2));
1635 printf(
"radius(%d, %d) = %f\n", i, nfound+1, radius);
1637 cpl_vector_set(vradius, nfound++, radius);
1644 printf(
"found %d points (limit = %f)\n", nfound, limit / 2);
1646 }
while (nfound < 3 && isfinite(limit));
1647 if (!isfinite(limit)) {
1650 alphax = alphay = 1.;
1655 alphax = alphay = cpl_vector_get_mean(vradius) / sqrt(pow(2., 1./beta)-1);
1657 printf(
"estimated alphas = %f from radius %f\n", alphax, cpl_vector_get_mean(vradius));
1661 cpl_vector_delete(vradius);
1666 alphay = cpl_array_get_double(aParams, 5, &invalid);
1674 double volume = cpl_array_get_double(aParams, 1, &invalid);
1685 double rho = cpl_array_get_double(aParams, 7, &invalid);
1691 cpl_vector *params = cpl_vector_new(8);
1692 cpl_vector_set(params, 0, bg);
1693 cpl_vector_set(params, 1, volume);
1694 cpl_vector_set(params, 2, xc);
1695 cpl_vector_set(params, 3, yc);
1696 cpl_vector_set(params, 4, alphax);
1697 cpl_vector_set(params, 5, alphay);
1698 cpl_vector_set(params, 6, beta);
1699 cpl_vector_set(params, 7, rho);
1701 printf(
"initial guess values for Moffat (vol %e):\n", (cpl_vector_get_mean(aValues) - bg) * npoints);
1702 cpl_vector_dump(params, stdout);
1705 cpl_matrix *covariance = NULL;
1707 cpl_error_code rc = CPL_ERROR_NONE;
1708 #if MOFFAT_USE_MUSE_OPTIMIZE
1710 fitdata.positions = aPositions;
1711 fitdata.values = aValues;
1712 fitdata.errors = aErrors;
1713 cpl_array *optparams = cpl_array_wrap_double(cpl_vector_get_data(params), 8);
1715 muse_moffat_2d_optfunc, NULL);
1716 cpl_array_unwrap(optparams);
1718 cpl_errorstate prestate = cpl_errorstate_get();
1719 rc = cpl_fit_lvmq(aPositions, NULL, aValues, aErrors, params, pflags,
1720 muse_moffat_2d_function, muse_moffat_2d_derivative,
1721 CPL_FIT_LVMQ_TOLERANCE, CPL_FIT_LVMQ_COUNT,
1722 CPL_FIT_LVMQ_MAXITER, aRMS,
1723 aErrors ? aRedChisq : NULL, aErrors ? &covariance : NULL);
1726 *aRMS = sqrt(*aRMS);
1730 printf(
"Moffat fit (rc=%d, %s):\n", rc, cpl_error_get_message());
1731 cpl_vector_dump(params, stdout);
1734 if (rc == CPL_ERROR_NONE || rc == CPL_ERROR_SINGULAR_MATRIX ||
1735 rc == CPL_ERROR_CONTINUE) {
1741 if (isfinite(cpl_vector_get(params, 0)) &&
1742 isfinite(cpl_vector_get(params, 1)) &&
1743 isfinite(cpl_vector_get(params, 2)) &&
1744 isfinite(cpl_vector_get(params, 3)) &&
1745 isfinite(cpl_vector_get(params, 4)) &&
1746 isfinite(cpl_vector_get(params, 5)) &&
1747 isfinite(cpl_vector_get(params, 6)) &&
1748 isfinite(cpl_vector_get(params, 7))) {
1750 rc = CPL_ERROR_NONE;
1751 cpl_errorstate_set(prestate);
1756 cpl_array_set_double(aParams, 0, cpl_vector_get(params, 0));
1757 cpl_array_set_double(aParams, 1, cpl_vector_get(params, 1));
1758 cpl_array_set_double(aParams, 2, cpl_vector_get(params, 2));
1759 cpl_array_set_double(aParams, 3, cpl_vector_get(params, 3));
1760 cpl_array_set_double(aParams, 4, fabs(cpl_vector_get(params, 4)));
1761 cpl_array_set_double(aParams, 5, fabs(cpl_vector_get(params, 5)));
1762 cpl_array_set_double(aParams, 6, cpl_vector_get(params, 6));
1763 cpl_array_set_double(aParams, 7, cpl_vector_get(params, 7));
1765 if (aErrors && covariance) {
1767 for (idx = 0; idx < 8; idx++) {
1768 if (pflags[idx] && aPErrors) {
1769 cpl_array_set_double(aPErrors, idx,
1770 sqrt(cpl_matrix_get(covariance, idx, idx)));
1778 cpl_matrix_delete(covariance);
1779 cpl_vector_delete(params);
1830 cpl_vector *aErr, cpl_table *aExtra,
1831 const unsigned int aOrder,
const double aRSigma,
1832 double *aMSE,
double *aChiSq)
1841 cpl_ensure(aPos && aVal, CPL_ERROR_NULL_INPUT, NULL);
1842 cpl_ensure(cpl_matrix_get_ncol(aPos) == cpl_vector_get_size(aVal),
1843 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
1845 cpl_ensure(cpl_vector_get_size(aVal) == cpl_vector_get_size(aErr),
1846 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
1849 cpl_ensure(cpl_vector_get_size(aVal) == cpl_table_get_nrow(aExtra),
1850 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
1855 for (idx = 0; idx < cpl_vector_get_size(aVal); idx++) {
1857 if (isfinite(cpl_vector_get(aVal, idx))) {
1861 if (cpl_vector_get_size(aVal) == 1) {
1862 cpl_msg_warning(__func__,
"Input vector only contained non-finite elements!");
1866 cpl_matrix_erase_columns(aPos, idx, 1);
1873 cpl_table_erase_window(aExtra, idx, 1);
1879 int ndim = cpl_matrix_get_nrow(aPos);
1880 cpl_polynomial *fit = cpl_polynomial_new(ndim);
1881 int large_residuals = 1;
1882 while (large_residuals > 0) {
1883 const cpl_boolean sym = CPL_FALSE;
1884 cpl_size *mindeg = cpl_calloc(ndim,
sizeof(cpl_size)),
1885 *maxdeg = cpl_malloc(ndim *
sizeof(cpl_size));
1887 for (i = 0; i < ndim; i++) {
1890 cpl_error_code rc = cpl_polynomial_fit(fit, aPos, &sym, aVal, NULL,
1891 CPL_FALSE, mindeg, maxdeg);
1894 const cpl_size coeff = 0;
1895 if (rc != CPL_ERROR_NONE || !isfinite(cpl_polynomial_get_coeff(fit, &coeff))) {
1897 cpl_errorstate prestate = cpl_errorstate_get();
1899 printf(
"%s: output polynomial:\n", __func__);
1900 cpl_polynomial_dump(fit, stdout);
1901 printf(
"%s: positions and values that we tried to fit:\n", __func__);
1902 cpl_matrix_dump(aPos, stdout);
1903 cpl_vector_dump(aVal, stdout);
1906 cpl_polynomial_delete(fit);
1908 if (!cpl_errorstate_is_equal(prestate)) {
1909 cpl_errorstate_set(prestate);
1915 cpl_vector *res = cpl_vector_new(cpl_vector_get_size(aVal));
1916 cpl_vector_fill_polynomial_fit_residual(res, aVal, NULL, fit, aPos, aChiSq);
1917 double rms = sqrt(cpl_vector_product(res, res) / cpl_vector_get_size(res));
1923 printf(
"%s: polynomial fit (RMS %g chisq %g aRSigma %f -> limit %g):\n",
1924 __func__, rms, aChiSq ? *aChiSq : 0., aRSigma, aRSigma * rms);
1925 cpl_polynomial_dump(fit, stdout);
1927 char *title = cpl_sprintf(
"set title \"%s: RMS %g\"\n"
1928 "unset key\n", __func__, rms);
1929 cpl_plot_vector(title,
"",
"", res);
1933 large_residuals = 0;
1934 for (i = 0; i < cpl_vector_get_size(res); i++) {
1936 if (fabs(cpl_vector_get(res, i)) < (aRSigma * rms)) {
1943 cpl_msg_debug(__func__,
"residual %f RMS %f aRSigma %f -> limit %f",
1944 cpl_vector_get(res, i), rms, aRSigma, aRSigma * rms);
1947 if (cpl_vector_get_size(res) == 1) {
1948 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
"tried to "
1949 "remove the last vector/matrix element when "
1950 "checking fit residuals (residual %g RMS %g "
1951 "aRSigma %f -> limit %g)", cpl_vector_get(res, i),
1952 rms, aRSigma, aRSigma * rms);
1953 cpl_polynomial_delete(fit);
1955 rms = sqrt(DBL_MAX);
1959 large_residuals = 0;
1964 cpl_matrix_erase_columns(aPos, i, 1);
1971 cpl_table_erase_window(aExtra, i, 1);
1976 cpl_vector_delete(res);
2034 double aLambda,
double aHalfWidth,
2036 cpl_array *aResults, cpl_array *aErrors)
2038 cpl_ensure(aPixtable, CPL_ERROR_NULL_INPUT, 0.);
2041 cpl_table_unselect_all(aPixtable->
table);
2042 cpl_table_or_selected_float(aPixtable->
table, MUSE_PIXTABLE_LAMBDA,
2043 CPL_NOT_LESS_THAN, aLambda - aHalfWidth);
2044 cpl_table_and_selected_float(aPixtable->
table, MUSE_PIXTABLE_LAMBDA,
2045 CPL_NOT_GREATER_THAN, aLambda + aHalfWidth);
2046 cpl_size nsel = cpl_table_count_selected(aPixtable->
table);
2047 cpl_ensure(nsel > 0, CPL_ERROR_DATA_NOT_FOUND, 0.);
2051 cpl_errorstate state = cpl_errorstate_get();
2053 cpl_table_unselect_all(aPixtable->
table);
2054 if (!cpl_errorstate_is_equal(state)) {
2056 cpl_table_delete(spec);
2057 cpl_error_set(__func__, cpl_error_get_code());
2062 cpl_size nbins = cpl_table_get_nrow(spec);
2064 cpl_table_power_column(spec,
"stat", 0.5);
2065 cpl_table_name_column(spec,
"stat",
"error");
2066 cpl_table_set_column_unit(spec,
"error",
2067 cpl_table_get_column_unit(spec,
"data"));
2069 cpl_table_save(spec, NULL, NULL,
"spec.fits", CPL_IO_CREATE);
2072 cpl_vector *pos = cpl_vector_wrap(nbins, cpl_table_get_data_double(spec,
"lambda")),
2073 *val = cpl_vector_wrap(nbins, cpl_table_get_data_double(spec,
"data")),
2074 *err = cpl_vector_wrap(nbins, cpl_table_get_data_double(spec,
"error"));
2075 double xc, xerr = 2 * aHalfWidth,
2076 sigma, area, bglevel, mse;
2077 cpl_matrix *covariance;
2078 cpl_error_code rc = cpl_vector_fit_gaussian(pos, NULL, val, err, CPL_FIT_ALL,
2079 &xc, &sigma, &area, &bglevel,
2080 &mse, NULL, &covariance);
2081 cpl_vector_unwrap(pos);
2082 cpl_vector_unwrap(val);
2083 cpl_vector_unwrap(err);
2084 cpl_table_delete(spec);
2085 if (rc == CPL_ERROR_CONTINUE) {
2087 xerr = sqrt(sigma * sigma / area);
2088 }
else if (rc == CPL_ERROR_SINGULAR_MATRIX || !covariance) {
2089 xerr = sqrt(sigma * sigma / area);
2091 xerr = sqrt(cpl_matrix_get(covariance, 0, 0));
2093 cpl_msg_debug(__func__,
"covariance matrix:");
2094 cpl_matrix_dump(covariance, stdout);
2098 if (aResults && cpl_array_get_type(aResults) == CPL_TYPE_DOUBLE) {
2099 cpl_array_set_size(aResults, 4);
2100 cpl_array_set_double(aResults, 0, xc);
2101 cpl_array_set_double(aResults, 1, sigma);
2102 cpl_array_set_double(aResults, 2, area);
2103 cpl_array_set_double(aResults, 3, bglevel);
2105 if (aErrors && cpl_array_get_type(aErrors) == CPL_TYPE_DOUBLE) {
2106 cpl_array_set_size(aErrors, 4);
2107 cpl_array_set_double(aErrors, 0, xerr);
2108 if (rc != CPL_ERROR_NONE || !covariance) {
2109 cpl_array_fill_window_invalid(aErrors, 1, 3);
2111 cpl_array_set_double(aErrors, 1, sqrt(cpl_matrix_get(covariance, 1, 1)));
2112 cpl_array_set_double(aErrors, 2, sqrt(cpl_matrix_get(covariance, 2, 2)));
2113 cpl_array_set_double(aErrors, 3, sqrt(cpl_matrix_get(covariance, 3, 3)));
2116 cpl_matrix_delete(covariance);
2117 cpl_msg_debug(__func__,
"Gaussian fit (%s): %f +/- %f Angstrom, %f, %f, %f "
2118 "(RMS %f)", rc != CPL_ERROR_NONE ? cpl_error_get_message() :
"",
2119 xc, xerr, bglevel, area, sigma, sqrt(mse));
2141 const char *aKeyword,
const char *aString)
2143 cpl_ensure_code(aH1 && aH2 && aKeyword && aString, CPL_ERROR_NULL_INPUT);
2144 const char *hin = cpl_propertylist_get_string(aH1, aKeyword);
2145 cpl_ensure_code(hin, CPL_ERROR_ILLEGAL_INPUT);
2146 char *hstring = cpl_sprintf(
"%s (%s)", hin, aString);
2147 cpl_error_code rc = cpl_propertylist_update_string(aH2, aKeyword, hstring);
2182 const char *aExtData,
const char *aExtDQ,
2183 const char *aExtStat)
2185 cpl_ensure_code(aHeader && aClass2 && aExtData, CPL_ERROR_NULL_INPUT);
2186 cpl_ensure_code(!strcmp(aClass2,
"DATA") || !strcmp(aClass2,
"ERROR") ||
2187 !strcmp(aClass2,
"QUALITY"), CPL_ERROR_ILLEGAL_INPUT);
2190 #define ESO_HDU_HEADERS_REGEXP "HDU(CLASS|CLAS1|CLAS2|CLAS3|DOC|VERS)$" \
2191 "|^SCIDATA$|^QUAL(DATA|MASK)$|^ERRDATA$"
2192 cpl_propertylist_erase_regexp(aHeader, ESO_HDU_HEADERS_REGEXP, 0);
2194 if (cpl_propertylist_has(aHeader,
"EXTNAME")) {
2195 cpl_propertylist_insert_after_string(aHeader,
"EXTNAME",
"HDUCLASS",
"ESO");
2197 cpl_propertylist_append_string(aHeader,
"HDUCLASS",
"ESO");
2199 cpl_propertylist_set_comment(aHeader,
"HDUCLASS",
"class name (ESO format)");
2200 cpl_propertylist_insert_after_string(aHeader,
"HDUCLASS",
"HDUDOC",
"DICD");
2201 cpl_propertylist_set_comment(aHeader,
"HDUDOC",
"document with class description");
2202 cpl_propertylist_insert_after_string(aHeader,
"HDUDOC",
"HDUVERS",
2204 cpl_propertylist_set_comment(aHeader,
"HDUVERS",
2205 "version number (according to spec v2.5.1)");
2206 cpl_propertylist_insert_after_string(aHeader,
"HDUVERS",
"HDUCLAS1",
"IMAGE");
2207 cpl_propertylist_set_comment(aHeader,
"HDUCLAS1",
"Image data format");
2208 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS1",
"HDUCLAS2", aClass2);
2209 if (!strcmp(aClass2,
"DATA")) {
2210 cpl_propertylist_set_comment(aHeader,
"HDUCLAS2",
2211 "this extension contains the data itself");
2214 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS2",
"QUALDATA", aExtDQ);
2217 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS2",
"ERRDATA", aExtStat);
2219 }
else if (!strcmp(aClass2,
"ERROR")) {
2220 cpl_propertylist_set_comment(aHeader,
"HDUCLAS2",
"this extension contains variance");
2221 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS2",
"HDUCLAS3",
"MSE");
2222 cpl_propertylist_set_comment(aHeader,
"HDUCLAS3",
2223 "the extension contains variances (sigma**2)");
2224 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS3",
"SCIDATA", aExtData);
2226 cpl_propertylist_insert_after_string(aHeader,
"SCIDATA",
"QUALDATA", aExtDQ);
2229 cpl_propertylist_set_comment(aHeader,
"HDUCLAS2",
2230 "this extension contains bad pixel mask");
2231 cpl_propertylist_insert_after_string(aHeader,
"HDUCLAS2",
"HDUCLAS3",
"FLAG32BIT");
2232 cpl_propertylist_set_comment(aHeader,
"HDUCLAS3",
"extension contains 32bit"
2233 " Euro3D bad pixel information");
2235 cpl_propertylist_insert_after_long(aHeader,
"HDUCLAS3",
"QUALMASK", 0xFFFFFFFF);
2236 cpl_propertylist_set_comment(aHeader,
"QUALMASK",
"all non-zero values are bad");
2237 cpl_propertylist_insert_after_string(aHeader,
"QUALMASK",
"SCIDATA", aExtData);
2239 cpl_propertylist_insert_after_string(aHeader,
"SCIDATA",
"ERRDATA", aExtStat);
2243 if (cpl_propertylist_has(aHeader,
"SCIDATA")) {
2244 cpl_propertylist_set_comment(aHeader,
"SCIDATA",
"pointer to the data extension");
2246 if (cpl_propertylist_has(aHeader,
"ERRDATA")) {
2247 cpl_propertylist_set_comment(aHeader,
"ERRDATA",
"pointer to the variance extension");
2249 if (cpl_propertylist_has(aHeader,
"QUALDATA")) {
2250 cpl_propertylist_set_comment(aHeader,
"QUALDATA",
2251 "pointer to the bad pixel mask extension");
2254 return CPL_ERROR_NONE;
2274 char *exe = getenv(
"MUSE_DEBUG_MEMORY_PROGRAM");
2279 printf(
"=== %s ===\n", aMarker);
2282 if (strlen(exe) > 0) {
2283 snprintf(command, 999,
2284 "ps -C %s -o comm,start_time,pid,tid,pcpu,stat,rss,size,vsize",
2288 snprintf(command, 999,
2289 "ps -o comm,start_time,pid,tid,pcpu,stat,rss,size,vsize");
2293 int rc = system(command);
2294 UNUSED_ARGUMENT(rc);
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.
const char * muse_pfits_get_extname(const cpl_propertylist *aHeaders)
find out the extension name
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.
double muse_utils_pixtable_fit_line_gaussian(muse_pixtable *aPixtable, double aLambda, double aHalfWidth, double aBinSize, cpl_array *aResults, cpl_array *aErrors)
Fit a 1D Gaussian to a given wavelength range in a pixel table.
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.
void muse_utils_memory_dump(const char *aMarker)
Display the current memory usage of the given program.
const char * muse_pfits_get_dateobs(const cpl_propertylist *aHeaders)
find out the exposure time
cpl_frameset * muse_frameset_check_raw(const cpl_frameset *aFrames, const char *aTag, unsigned char aIFU)
return frameset containing good raw input data
cpl_table * table
The pixel table.
int muse_pfits_get_lampnum(const cpl_propertylist *aHeaders)
query the number of lamps installed
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_table * muse_table_load_filter(muse_processing *aProcessing, const char *aFilterName)
Load a table for a given filter name.
cpl_table * muse_cpltable_new(const muse_cpltable_def *aDef, cpl_size aLength)
Create an empty table according to the specified definition.
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.
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.
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.
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.
char * muse_utils_header_get_lamp_names(cpl_propertylist *aHeader, char aSep)
Concatenate names of all active calibration lamps.
const char * muse_pfits_get_chip_id(const cpl_propertylist *aHeaders)
find out the chip id
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.
int muse_pfits_get_lamp_status(const cpl_propertylist *aHeaders, int aLamp)
query the status of one lamp
cpl_table * muse_table_load(muse_processing *aProcessing, const char *aTag, unsigned char aIFU)
load a table according to its tag and IFU/channel number
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.
cpl_propertylist * muse_propertylist_load(muse_processing *aProcessing, const char *aTag)
load a propertylist according to its tag
cpl_matrix * muse_matrix_new_gaussian_2d(int aXHalfwidth, int aYHalfwidth, double aSigma)
Create a matrix that contains a normalized 2D Gaussian.
cpl_table * muse_resampling_spectrum(muse_pixtable *aPixtable, double aBinwidth)
Resample the selected pixels of a pixel table into a spectrum.
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
cpl_frameset * inputFrames
const char * muse_pfits_get_chip_name(const cpl_propertylist *aHeaders)
find out the chip name
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_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.