32 #include "muse_postproc.h" 33 #include "muse_instrument.h" 35 #include "muse_astro.h" 37 #include "muse_flux.h" 38 #include "muse_imagelist.h" 39 #include "muse_pfits.h" 40 #include "muse_phys.h" 41 #include "muse_rvcorrect.h" 42 #include "muse_utils.h" 46 #include "muse_lsf_params.h" 48 #include "muse_sky_old.h" 81 case MUSE_POSTPROC_SCIPOST:
82 case MUSE_POSTPROC_STANDARD:
83 case MUSE_POSTPROC_ASTROMETRY:
87 cpl_msg_error(__func__,
"No such setup known: %d", aType);
88 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
113 cpl_propertylist_delete(aProp->
wcs);
115 #ifdef USE_LSF_PARAMS 137 cpl_ensure(aSave, CPL_ERROR_NULL_INPUT, CPL_FALSE);
138 if (strlen(aSave) < 4) {
139 cpl_error_set_message(__func__, CPL_ERROR_DATA_NOT_FOUND,
140 "no (valid) save option given!");
144 cpl_boolean allvalid = CPL_TRUE;
148 ns = cpl_array_get_size(asave),
149 nv = cpl_array_get_size(avalid);
150 for (i = 0; i < ns; i++) {
151 cpl_boolean valid = CPL_FALSE;
152 for (j = 0; j < nv; j++) {
153 if (!strcmp(cpl_array_get_string(asave, i),
154 cpl_array_get_string(avalid, j))) {
159 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_INPUT,
160 "save option %d (%s) is not valid!", i + 1,
161 cpl_array_get_string(asave, i));
162 allvalid = CPL_FALSE;
165 cpl_array_delete(asave);
166 cpl_array_delete(avalid);
190 if (!strncmp(aResampleString,
"nearest", 8)) {
193 if (!strncmp(aResampleString,
"linear", 7)) {
196 if (!strncmp(aResampleString,
"quadratic", 10)) {
199 if (!strncmp(aResampleString,
"renka", 6)) {
202 if (!strncmp(aResampleString,
"drizzle", 8)) {
205 if (!strncmp(aResampleString,
"lanczos", 8)) {
231 if (!strncmp(aCRTypeString,
"iraf", 5)) {
234 if (!strncmp(aCRTypeString,
"mean", 5)) {
237 if (!strncmp(aCRTypeString,
"median", 7)) {
262 if (!strncmp(aFormatString,
"Cube", 5)) {
265 if (!strncmp(aFormatString,
"Euro3D", 7)) {
268 if (!strncmp(aFormatString,
"xCube", 6)) {
271 if (!strncmp(aFormatString,
"xEuro3D", 8)) {
274 if (!strncmp(aFormatString,
"sdpCube", 8)) {
299 if (!strncmp(aWeightString,
"exptime", 8)) {
302 if (!strncmp(aWeightString,
"fwhm", 5)) {
305 if (!strncmp(aWeightString,
"none", 5)) {
339 const cpl_frame *aFrame,
float aWarnLimit,
340 float aErrLimit,
double *aRA,
double *aDEC)
342 cpl_ensure(aHeader && aFrame, CPL_ERROR_NULL_INPUT, NULL);
343 cpl_errorstate state = cpl_errorstate_get();
346 cpl_ensure(cpl_errorstate_is_equal(state), CPL_ERROR_DATA_NOT_FOUND, NULL);
347 cpl_msg_debug(__func__,
"reference coordinates: RA = %e deg, DEC =%e deg",
356 const char *fn = cpl_frame_get_filename(aFrame);
357 cpl_propertylist *header;
358 double dmin = FLT_MAX;
359 int iext, inearest = -1, next = cpl_fits_count_extensions(fn);
360 for (iext = 1; iext <= next; iext++) {
361 header = cpl_propertylist_load(fn, iext);
362 const char *extname = cpl_propertylist_get_string(header,
"EXTNAME");
366 cpl_msg_debug(__func__,
"extension %d [%s]: RA = %e deg, DEC = %e deg --> " 367 "d = %e deg", iext, extname, ra, dec, d);
372 cpl_propertylist_delete(header);
375 if (dmin * 3600. > aErrLimit) {
376 char *msg = cpl_sprintf(
"Distance of nearest reference table to observed " 377 "position is %.2f arcmin, certainly a wrong " 378 "reference object!", dmin * 60.);
379 cpl_msg_error(__func__,
"%s", msg);
380 cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
"%s", msg);
384 if (dmin * 3600. > aWarnLimit) {
385 cpl_msg_warning(__func__,
"Distance of nearest reference table to observed " 386 "position is %.2f arcmin! (Wrong reference object?)",
389 header = cpl_propertylist_load(fn, inearest);
390 const char *extname = cpl_propertylist_get_string(header,
"EXTNAME");
391 cpl_msg_info(__func__,
"Loading \"%s[%s]\" (distance %.1f arcsec)", fn,
392 extname, dmin * 3600.);
393 cpl_propertylist_delete(header);
394 cpl_table *table = cpl_table_load(fn, inearest, 1);
419 cpl_ensure_code(aPt && aPt->
header, CPL_ERROR_NULL_INPUT);
421 return CPL_ERROR_NONE;
425 cpl_boolean respff = cpl_propertylist_has(aResponse->
header,
426 MUSE_HDR_FLUX_FFCORR),
428 if (respff == ptff || !ptff) {
431 return CPL_ERROR_NONE;
434 cpl_msg_warning(__func__,
"Adapt pixel table to %s for backward compatibility" 435 ": revert correction by flat-field spectrum!",
436 MUSE_TAG_STD_RESPONSE);
444 MUSE_PIXTABLE_OPERATION_DIVIDE);
445 cpl_array_unwrap(lambdas);
446 cpl_array_unwrap(ffdata);
447 cpl_table_delete(aPt->
ffspec);
450 cpl_msg_info(__func__,
"Pixel table now convolved with flat-field spectrum " 452 return CPL_ERROR_NONE;
504 cpl_ensure(aProp && aProp->
exposures, CPL_ERROR_NULL_INPUT, NULL);
505 cpl_ensure((
int)aIndex < cpl_table_get_nrow(aProp->
exposures),
506 CPL_ERROR_ILLEGAL_INPUT, NULL);
507 cpl_msg_info(__func__,
"Starting to process exposure %d (DATE-OBS=%s)",
508 aIndex + 1, cpl_table_get_string(aProp->
exposures,
"DATE-OBS",
510 cpl_ensure(aProp->
exposures, CPL_ERROR_NULL_INPUT, NULL);
512 cpl_table *exposure = cpl_table_extract(aProp->
exposures, aIndex, 1);
516 cpl_table_delete(exposure);
521 cpl_propertylist_erase_regexp(pt->
header,
"ESO QC ", 0);
528 cpl_boolean labdata = CPL_FALSE;
529 cpl_errorstate prestate = cpl_errorstate_get();
533 if (!cpl_errorstate_is_equal(prestate) || airmass < 1.) {
534 cpl_msg_warning(__func__,
"This seems to be lab data (RA=%f DEC=%f, " 535 "airmass=%f), not doing any DAR correction!", ra, dec,
537 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
538 cpl_errorstate_set(prestate);
541 cpl_error_code rc = CPL_ERROR_NONE;
543 cpl_msg_debug(__func__,
"WFM detected: starting DAR correction");
545 cpl_msg_debug(__func__,
"DAR correction returned rc=%d: %s", rc,
546 rc != CPL_ERROR_NONE ? cpl_error_get_message() :
"");
548 if (aProp->
darcheck != MUSE_POSTPROC_DARCHECK_NONE) {
549 cpl_boolean dorefine = aProp->
darcheck == MUSE_POSTPROC_DARCHECK_CORRECT;
552 if (rc != CPL_ERROR_NONE) {
553 cpl_msg_warning(__func__,
"Maximum %s shift %f\'\' (rc = %d: %s)",
554 dorefine ?
"corrected" :
"detected", maxshift, rc,
555 cpl_error_get_message());
557 cpl_msg_info(__func__,
"Maximum %s shift %f\'\'",
558 dorefine ?
"corrected" :
"detected", maxshift);
564 if (aProp->
type != MUSE_POSTPROC_STANDARD) {
568 if (rc != CPL_ERROR_NONE && rc != CPL_ERROR_UNSUPPORTED_MODE) {
571 cpl_msg_warning(__func__,
"Flux calibration returned rc=%d: %s", rc,
572 cpl_error_get_message());
576 cpl_msg_debug(__func__,
"Flux calibration returned rc=%d: %s", rc,
577 rc != CPL_ERROR_NONE ? cpl_error_get_message_default(rc) :
"");
580 cpl_msg_info(__func__,
"Skipping flux calibration (no %s curve)",
581 MUSE_TAG_STD_RESPONSE);
585 cpl_table *sky_cont = NULL,
588 (aProp->
skymethod == MUSE_POSTPROC_SKYMETHOD_SIMPLE)) {
592 cpl_table_select_all(sky_pt->
table);
596 cpl_msg_info(__func__,
"Intermediate resampling to produce white-light image" 597 " for sky-spectrum creation:");
598 cpl_msg_indent_more();
604 cpl_msg_error(__func__,
"Could not create cube for whitelight image");
612 cpl_msg_indent_less();
619 cpl_table_select_all(sky_pt->
table);
621 cpl_table *spectrum =
624 if (aProp->
skymethod == MUSE_POSTPROC_SKYMETHOD_MODEL) {
627 double lambda_low = cpl_array_get_min(lambda);
628 double lambda_high = cpl_array_get_max(lambda);
629 sky_lines = cpl_table_duplicate(aProp->
sky_lines);
633 prestate = cpl_errorstate_get();
641 if (!cpl_errorstate_is_equal(prestate)) {
642 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
643 cpl_errorstate_set(prestate);
648 cpl_msg_info(__func__,
"No sky continuum given, create it from the data");
652 cpl_msg_info(__func__,
"Using sky continuum given as input");
656 cpl_image_delete(lsfImage);
657 #ifdef USE_LSF_PARAMS 661 if (!cpl_errorstate_is_equal(prestate)) {
662 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
663 cpl_errorstate_set(prestate);
667 cpl_msg_info(__func__,
"No sky continuum given, create it from the data");
671 cpl_table_erase_column(sky_cont,
"stat");
672 cpl_table_erase_column(sky_cont,
"dq");
673 cpl_table_name_column(sky_cont,
"data",
"flux");
677 cpl_array_unwrap(lambda);
681 cpl_table *spec2 = cpl_table_duplicate(spectrum);
682 cpl_table_name_column(spec2,
"data",
"flux");
684 cpl_table_delete(spec2);
687 aSkyOut->
mask = sky_mask;
691 cpl_table_delete(spectrum);
701 if ((aProp->
skymethod == MUSE_POSTPROC_SKYMETHOD_NONE) ||
702 (aProp->
skymethod == MUSE_POSTPROC_SKYMETHOD_MODEL)) {
704 cpl_msg_debug(__func__,
"doing sky continuum subtraction with input " 707 }
else if (sky_cont) {
708 cpl_msg_debug(__func__,
"doing sky continuum subtraction with created " 713 cpl_msg_debug(__func__,
"doing sky line subtraction with created list");
716 #ifdef USE_LSF_PARAMS 722 cpl_msg_debug(__func__,
"doing sky line subtraction with input list");
725 #ifdef USE_LSF_PARAMS 735 aSkyOut->
lines = sky_lines;
738 cpl_table_delete(sky_lines);
739 cpl_table_delete(sky_cont);
746 if (aProp->
type == MUSE_POSTPROC_STANDARD) {
747 double raref, decref;
752 cpl_msg_error(__func__,
"Correct %s could not be loaded, observed " 753 "target not listed?", MUSE_TAG_STD_FLUX_TABLE);
758 cpl_msg_error(__func__,
"%s does not have a recognized format!",
759 MUSE_TAG_STD_FLUX_TABLE);
760 cpl_table_delete(reftable);
765 prestate = cpl_errorstate_get();
769 cpl_msg_debug(__func__,
"Flux integration found %"CPL_SIZE_FORMAT
" stars",
774 cpl_msg_warning(__func__,
"Invalid airmass derived (%.3e), resetting to " 782 cpl_table_delete(reftable);
787 if (!cpl_errorstate_is_equal(prestate)) {
788 cpl_msg_warning(__func__,
"The following errors happened while computing " 789 "the flux calibration (rc = %d/%s):", rc,
790 cpl_error_get_message_default(rc));
797 if (aProp->
type == MUSE_POSTPROC_ASTROMETRY) {
802 cpl_msg_error(__func__,
"Correct %s could not be loaded, observed " 803 "target not listed?", MUSE_TAG_ASTROMETRY_REFERENCE);
807 prestate = cpl_errorstate_get();
810 wcs->crpix1 = aProp->crpix1;
811 wcs->crpix2 = aProp->
crpix2;
824 cpl_propertylist_update_float(wcs->wcs, MUSE_HDR_WCS_DETSIGMA,
826 cpl_propertylist_set_comment(wcs->wcs, MUSE_HDR_WCS_DETSIGMA,
827 MUSE_HDR_WCS_DETSIGMA_C_ONE);
830 cpl_table_delete(reftable);
831 cpl_msg_debug(__func__,
"Solving astrometry (initial radius %.1f pix, " 832 "initial relative accuracy %.1f, %d iterations with rejection" 833 " sigma %.2f) returned rc=%d: %s", aProp->
radius,
835 rc, rc != CPL_ERROR_NONE ? cpl_error_get_message() :
"");
838 if (!cpl_errorstate_is_equal(prestate)) {
839 cpl_msg_warning(__func__,
"The following errors happened while computing " 840 "the astrometric solution (rc = %d/%s):", rc,
841 cpl_error_get_message());
848 cpl_msg_debug(__func__,
"Astrometry correction returned rc=%d: %s", rc,
849 rc != CPL_ERROR_NONE ? cpl_error_get_message() :
"");
876 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
879 MUSE_TAG_OUTPUT_WCS, 0, CPL_FALSE);
880 if (!fwcs || cpl_frameset_get_size(fwcs) <= 0) {
882 cpl_frameset_delete(fwcs);
885 cpl_frame *frame = cpl_frameset_get_position(fwcs, 0);
886 const char *fn = cpl_frame_get_filename(frame);
887 cpl_propertylist *header = NULL;
888 int iext, next = cpl_fits_count_extensions(fn);
889 for (iext = 0; iext <= next; iext++) {
890 header = cpl_propertylist_load(fn, iext);
891 cpl_errorstate es = cpl_errorstate_get();
892 cpl_wcs *wcs = cpl_wcs_new_from_propertylist(header);
893 if (!cpl_errorstate_is_equal(es)) {
894 cpl_errorstate_set(es);
897 cpl_propertylist_delete(header);
902 int naxis = cpl_wcs_get_image_naxis(wcs);
903 cpl_boolean valid = naxis == 2 || naxis == 3;
905 const cpl_array *ctypes = cpl_wcs_get_ctype(wcs);
906 if (valid && cpl_array_get_string(ctypes, 0)) {
907 valid = valid && !strncmp(cpl_array_get_string(ctypes, 0),
"RA---TAN", 9);
909 if (valid && cpl_array_get_string(ctypes, 1)) {
910 valid = valid && !strncmp(cpl_array_get_string(ctypes, 1),
"DEC--TAN", 9);
913 if (valid && cpl_array_get_string(ctypes, 2)) {
914 const char *ctype3 = cpl_array_get_string(ctypes, 2);
916 && (!strncmp(ctype3,
"AWAV", 5) || !strncmp(ctype3,
"AWAV-LOG", 9) ||
917 !strncmp(ctype3,
"WAVE", 5) || !strncmp(ctype3,
"WAVE-LOG", 9));
921 cpl_propertylist *pc = cpl_propertylist_new();
922 cpl_propertylist_copy_property_regexp(pc, header,
"^PC[0-9]+_[0-9]+", 0);
923 valid = cpl_propertylist_get_size(pc) == 0;
924 cpl_propertylist_delete(pc);
928 cpl_msg_debug(__func__,
"Apparently valid header %s found in extension %d" 929 " of \"%s\"", MUSE_TAG_OUTPUT_WCS, iext, fn);
933 cpl_propertylist_delete(header);
937 cpl_msg_warning(__func__,
"No valid headers for %s found in \"%s\"",
938 MUSE_TAG_OUTPUT_WCS, fn);
940 cpl_frameset_delete(fwcs);
970 cpl_ensure_code(aProcessing && aPixtable && aParams, CPL_ERROR_NULL_INPUT);
988 cpl_msg_info(__func__,
"Resampling to final cube follows, output format " 990 cpl_msg_indent_more();
992 cpl_msg_indent_less();
993 cpl_ensure_code(e3d, cpl_error_get_code());
997 cpl_msg_info(__func__,
"Resampling to final cube follows, output format " 999 cpl_msg_indent_more();
1001 cpl_msg_indent_less();
1002 cpl_ensure_code(fits, cpl_error_get_code());
1008 int i, ipos = 0, nfilters = cpl_array_get_size(filters);
1009 for (i = 0; i < nfilters; i++) {
1012 cpl_array_get_string(filters, i));
1023 if (getenv(
"MUSE_COLLAPSE_PIXTABLE") &&
1024 atoi(getenv(
"MUSE_COLLAPSE_PIXTABLE")) > 0) {
1039 ((
muse_datacube *)cube)->recnames = cpl_array_new(0, CPL_TYPE_STRING);
1044 cpl_array_set_size(((
muse_datacube *)cube)->recnames, ipos+1);
1045 cpl_array_set_string(((
muse_datacube *)cube)->recnames, ipos,
1046 cpl_array_get_string(filters, i));
1052 cpl_array_get_string(filters, i));
1053 cpl_propertylist_update_string(fov->
header, MUSE_HDR_FILTER,
1054 cpl_array_get_string(filters, i));
1056 if (muse_idp_properties_update_fov(fov) != CPL_ERROR_NONE) {
1057 cpl_msg_warning(__func__,
"Writing IDP keywords to field-of-view " 1066 cpl_array_delete(filters);
1072 muse_idp_properties *properties =
1073 muse_idp_properties_collect(aProcessing, ((
muse_datacube *)cube)->header,
1074 MUSE_TAG_CUBE_FINAL);
1078 muse_idp_properties_update((
muse_datacube *)cube)->header, properties);
1081 cpl_error_code rc = CPL_ERROR_NONE;
1102 muse_idp_properties_delete(properties);
1134 cpl_ensure_code(aProcessing && aCube, CPL_ERROR_NULL_INPUT);
1137 char prefix[KEYWORD_LENGTH] =
"";
1138 if (!strncmp(aProcessing->
name,
"muse_scipost", 13)) {
1139 strncpy(prefix, QC_POST_PREFIX_SCIPOST, KEYWORD_LENGTH);
1140 }
else if (!strncmp(aProcessing->
name,
"muse_exp_combine", 17)) {
1141 strncpy(prefix, QC_POST_PREFIX_EXPCOMBINE, KEYWORD_LENGTH);
1142 }
else if (!strncmp(aProcessing->
name,
"muse_standard", 14)) {
1143 strncpy(prefix, QC_POST_PREFIX_STANDARD, KEYWORD_LENGTH);
1144 }
else if (!strncmp(aProcessing->
name,
"muse_astrometry", 16)) {
1145 strncpy(prefix, QC_POST_PREFIX_ASTROMETRY, KEYWORD_LENGTH);
1147 cpl_msg_info(__func__,
"Recipe \"%s\" found, not generating QC1 keywords",
1149 return CPL_ERROR_NONE;
1154 int plane = cpl_imagelist_get_size(aCube->
data) / 2;
1155 cpl_image *cim = cpl_imagelist_get(aCube->
data, plane);
1156 double dsigmas[] = { 5., 4., 3. };
1157 int ndsigmas =
sizeof(dsigmas) /
sizeof(
double);
1158 cpl_vector *vsigmas = cpl_vector_wrap(ndsigmas, dsigmas);
1159 cpl_size isigma = -1;
1160 cpl_errorstate prestate = cpl_errorstate_get();
1161 cpl_apertures *apertures = cpl_apertures_extract(cim, vsigmas, &isigma);
1162 cpl_vector_unwrap(vsigmas);
1165 char keyword[KEYWORD_LENGTH];
1172 ? crval3 * exp((plane + 1. - crpix3) * cd33 / crval3)
1173 : (plane + 1. - crpix3) * cd33 + crval3;
1174 snprintf(keyword, KEYWORD_LENGTH, QC_POST_LAMBDA, prefix);
1175 cpl_propertylist_update_float(aCube->
header, keyword, lambda);
1178 if (!apertures || !cpl_errorstate_is_equal(prestate)) {
1180 snprintf(keyword, KEYWORD_LENGTH, QC_POST_NDET, prefix);
1181 cpl_propertylist_update_int(aCube->
header, keyword, 0);
1183 snprintf(keyword, KEYWORD_LENGTH, QC_POST_POSX, prefix, 0);
1184 cpl_propertylist_update_float(aCube->
header, keyword, -1.);
1185 snprintf(keyword, KEYWORD_LENGTH, QC_POST_POSY, prefix, 0);
1186 cpl_propertylist_update_float(aCube->
header, keyword, -1.);
1187 snprintf(keyword, KEYWORD_LENGTH, QC_POST_FWHMX, prefix, 0);
1188 cpl_propertylist_update_float(aCube->
header, keyword, -1.);
1189 snprintf(keyword, KEYWORD_LENGTH, QC_POST_FWHMY, prefix, 0);
1190 cpl_propertylist_update_float(aCube->
header, keyword, -1.);
1192 cpl_errorstate_set(prestate);
1193 cpl_msg_warning(__func__,
"No sources found for FWHM measurement down to " 1194 "%.1f sigma limit on plane %d, QC parameters will not " 1195 "contain useful information", dsigmas[ndsigmas-1], plane+1);
1196 return CPL_ERROR_DATA_NOT_FOUND;
1198 int ndet = cpl_apertures_get_size(apertures);
1199 snprintf(keyword, KEYWORD_LENGTH, QC_POST_NDET, prefix);
1200 cpl_propertylist_update_int(aCube->
header, keyword, ndet);
1204 double cd11 = kMuseSpaxelSizeX_WFM, cd12 = 0., cd21 = 0.,
1205 cd22 = kMuseSpaxelSizeY_WFM;
1206 cpl_errorstate es = cpl_errorstate_get();
1207 cpl_wcs *wcs = cpl_wcs_new_from_propertylist(aCube->
header);
1208 if (!cpl_errorstate_is_equal(es)) {
1209 cpl_errorstate_set(es);
1213 cd11 = kMuseSpaxelSizeX_NFM;
1214 cd22 = kMuseSpaxelSizeY_NFM;
1217 const cpl_matrix *cd = cpl_wcs_get_cd(wcs);
1219 cd11 = fabs(cpl_matrix_get(cd, 0, 0)) * 3600.,
1220 cd12 = fabs(cpl_matrix_get(cd, 0, 1)) * 3600.,
1221 cd21 = fabs(cpl_matrix_get(cd, 1, 0)) * 3600.,
1222 cd22 = fabs(cpl_matrix_get(cd, 1, 1)) * 3600.;
1224 cpl_wcs_delete(wcs);
1228 cpl_image *statimage = cpl_image_new(ndet, 2, CPL_TYPE_DOUBLE);
1230 printf(
"index RA_FWHM DEC_FWHM\n");
1233 for (n = 1; n <= ndet; n++) {
1234 cpl_size xcen = lround(cpl_apertures_get_centroid_x(apertures, n)),
1235 ycen = lround(cpl_apertures_get_centroid_y(apertures, n));
1237 cpl_errorstate state = cpl_errorstate_get();
1238 cpl_image_get_fwhm(cim, xcen, ycen, &x, &y);
1239 const char *fwhmcomment = NULL;
1240 if (x < 0 || y < 0 || !cpl_errorstate_is_equal(state)) {
1245 cpl_image_reject(statimage, n, 1);
1246 cpl_image_reject(statimage, n, 2);
1247 fwhmcomment =
"[arcsec] failure determining FWHM";
1250 cpl_errorstate_set(state);
1253 x = cd11 * x + cd12 * y;
1254 y = cd22 * y + cd21 * x;
1255 cpl_image_set(statimage, n, 1, x);
1256 cpl_image_set(statimage, n, 2, y);
1259 printf(
"%4d %f %f\n", n, x, y);
1263 snprintf(keyword, KEYWORD_LENGTH, QC_POST_POSX, prefix, n);
1264 cpl_propertylist_update_float(aCube->
header, keyword, xcen);
1265 snprintf(keyword, KEYWORD_LENGTH, QC_POST_POSY, prefix, n);
1266 cpl_propertylist_update_float(aCube->
header, keyword, ycen);
1267 snprintf(keyword, KEYWORD_LENGTH, QC_POST_FWHMX, prefix, n);
1268 cpl_propertylist_update_float(aCube->
header, keyword, x);
1270 cpl_propertylist_set_comment(aCube->
header, keyword, fwhmcomment);
1272 snprintf(keyword, KEYWORD_LENGTH, QC_POST_FWHMY, prefix, n);
1273 cpl_propertylist_update_float(aCube->
header, keyword, y);
1275 cpl_propertylist_set_comment(aCube->
header, keyword, fwhmcomment);
1281 cpl_apertures_delete(apertures);
1284 snprintf(keyword, KEYWORD_LENGTH, QC_POST_FWHM_NVALID, prefix);
1285 cpl_propertylist_update_int(aCube->
header, keyword, ndet - nbad);
1286 cpl_errorstate state = cpl_errorstate_get();
1287 cpl_stats *s = cpl_stats_new_from_image(statimage,
1288 CPL_STATS_MEDIAN | CPL_STATS_MAD);
1289 cpl_boolean error = !cpl_errorstate_is_equal(state);
1290 cpl_errorstate_set(state);
1291 snprintf(keyword, KEYWORD_LENGTH, QC_POST_FWHM_MEDIAN, prefix);
1292 if (error || ndet < 3) {
1293 cpl_propertylist_update_float(aCube->
header, keyword, 0.);
1295 cpl_propertylist_update_float(aCube->
header, keyword, cpl_stats_get_median(s));
1297 snprintf(keyword, KEYWORD_LENGTH, QC_POST_FWHM_MAD, prefix);
1298 if (error || ndet < 3) {
1299 cpl_propertylist_update_float(aCube->
header, keyword, 0.);
1301 cpl_propertylist_update_float(aCube->
header, keyword, cpl_stats_get_mad(s));
1303 cpl_stats_delete(s);
1304 cpl_image_delete(statimage);
1305 cpl_msg_info(__func__,
"Computed FWHM QC parameters for %d of %d source%s " 1306 "found down to the %.1f sigma threshold on plane %d",
1307 ndet - nbad, ndet, ndet == 1 ?
"" :
"s", dsigmas[isigma],
1310 return CPL_ERROR_NONE;
cpl_error_code muse_sky_lines_fit(cpl_table *, cpl_table *, cpl_image *, muse_wcs *)
Fit all entries of the pixel table to the master sky.
cpl_table * muse_sky_continuum_create(cpl_table *, cpl_table *, cpl_image *, muse_wcs *, double)
Create a continuum spectrum.
muse_image * muse_resampling_collapse_pixgrid(muse_pixtable *aPixtable, muse_pixgrid *aGrid, muse_datacube *aCube, const muse_table *aFilter, muse_resampling_params *aParams)
Integrate a pixel table / pixel grid along the wavelength direction.
#define MUSE_PIXTABLE_FFDATA
Structure definition of a MUSE datacube.
muse_rvcorrect_type rvtype
cpl_propertylist * muse_postproc_cube_load_output_wcs(muse_processing *aProcessing)
Find a file with a usable output WCS in the input frameset.
muse_postproc_properties * muse_postproc_properties_new(muse_postproc_type aType)
Create a post-processing properties object.
muse_flux_selection_type select
cpl_error_code muse_flux_compute_qc(muse_flux_object *aFluxObj)
Compute QC parameters, related to on-sky throughput.
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
double muse_pfits_get_cd(const cpl_propertylist *aHeaders, unsigned int aAxisI, unsigned int aAxisJ)
find out the WCS coordinate at the reference point
muse_pixtable * muse_pixtable_duplicate(muse_pixtable *aPixtable)
Make a copy of the pixtanle.
double muse_pfits_get_crval(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS coordinate at the reference point
#define MUSE_PIXTABLE_FFLAMBDA
A structure containing a spatial two-axis WCS.
muse_wcs_centroid_type centroid
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.
double muse_pfits_get_ra(const cpl_propertylist *aHeaders)
find out the right ascension
cpl_image * data
the data extension
cpl_error_code muse_rvcorrect(muse_pixtable *aPixtable, muse_rvcorrect_type aType)
Correct the wavelengths of all pixels of a given pixel table for radial velocity shift.
void muse_mask_delete(muse_mask *aMask)
Deallocate memory associated to a muse_mask object.
muse_xcombine_types muse_postproc_get_weight_type(const char *aWeightString)
Select correct weighting type for weight string.
cpl_error_code muse_dar_correct(muse_pixtable *aPixtable, double aLambdaRef)
Correct the pixel coordinates of all pixels of a given pixel table for differential atmospheric refra...
cpl_error_code muse_postproc_revert_ffspec_maybe(muse_pixtable *aPt, const muse_table *aResponse)
Revert correction of on-sky data with the flat-field spectrum.
cpl_image * muse_lsf_average_cube_all(muse_lsf_cube **aLsfCube, muse_pixtable *aPixtable)
Create an average image from all LSF cubes.
cpl_error_code muse_pixtable_and_selected_mask(muse_pixtable *aPixtable, muse_mask *aMask)
Select all pixels where the (x,y) positions are enabled in the given mask.
muse_resampling_crstats_type muse_postproc_get_cr_type(const char *aCRTypeString)
Select correct cosmic ray rejection type for crtype string.
muse_datacube * muse_resampling_cube(muse_pixtable *aPixtable, muse_resampling_params *aParams, muse_pixgrid **aGrid)
Resample a pixel table onto a regular grid structure representing a FITS NAXIS=3 datacube.
void muse_datacube_delete(muse_datacube *aCube)
Deallocate memory associated to a muse_datacube object.
cpl_error_code muse_dar_check(muse_pixtable *aPixtable, double *aMaxShift, cpl_boolean aCorrect, muse_datacube **aCube)
check that the continuum of objects in the frame is well-aligned perpendicular to the spatial axis...
#define MUSE_HDR_PT_FFCORR
cpl_error_code muse_flux_reference_table_check(cpl_table *aTable)
Check and/or adapt the standard flux reference table format.
cpl_error_code muse_postproc_qc_fwhm(muse_processing *aProcessing, muse_datacube *aCube)
Compute QC1 parameters for datacubes and save them in the FITS header.
void * muse_postproc_process_exposure(muse_postproc_properties *aProp, unsigned int aIndex, muse_postproc_sky_outputs *aSkyOut)
Merge and process pixel tables from one exposure.
WCS object to store data needed while computing the astrometric solution.
Structure definition of MUSE three extension FITS file.
muse_flux_object * muse_flux_object_new(void)
Allocate memory for a new muse_flux_object object.
cpl_error_code muse_flux_calibrate(muse_pixtable *aPixtable, const muse_table *aResponse, const cpl_table *aExtinction, const muse_table *aTelluric)
Convert the input pixel table from counts to fluxes.
cpl_error_code muse_postproc_cube_resample_and_collapse(muse_processing *aProcessing, muse_pixtable *aPixtable, muse_cube_type aFormat, muse_resampling_params *aParams, const char *aFilter)
High level function to resample to a datacube and collapse that to an image of the field of view and ...
cpl_table * table
The pixel table.
muse_flux_profile_type profile
void muse_lsf_params_delete_all(muse_lsf_params **aParams)
Delete an allocated array of muse_lsf_params structure.
muse_postproc_skymethod skymethod
cpl_propertylist * header
the FITS header
muse_lsf_params ** lsf_params
unsigned int muse_imagelist_get_size(muse_imagelist *aList)
Return the number of stored images.
cpl_error_code muse_wcs_project_tan(muse_pixtable *aPixtable, const cpl_propertylist *aWCS)
Carry out a gnomonic projection of a pixel table into native spherical coordinates.
muse_resampling_crstats_type crtype
double muse_pfits_get_crpix(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS reference point
cpl_error_code muse_flux_get_telluric_table(muse_flux_object *aFluxObj)
Get the table of the telluric correction.
void muse_pixgrid_delete(muse_pixgrid *aGrid)
Delete a pixel grid and remove its memory.
cpl_array * muse_cplarray_new_from_delimited_string(const char *aString, const char *aDelim)
Convert a delimited string into an array of strings.
Structure definition of MUSE pixel table.
Flux object to store data needed while computing the flux calibration.
cpl_error_code muse_datacube_convert_dq(muse_datacube *aCube)
Convert the DQ extension of a datacube to NANs in DATA and STAT.
muse_cube_type muse_postproc_get_cube_format(const char *aFormatString)
Select correct cube format for format string.
cpl_error_code muse_sky_subtract_lines_old(muse_pixtable *aPixtable, cpl_table *aLines, muse_lsf_params **aLsfParams)
Subtract sky lines from a pixtable.
cpl_array * muse_cpltable_extract_column(cpl_table *aTable, const char *aColumn)
Create an array from a section of a column.
cpl_boolean muse_postproc_check_save_param(const char *aSave, const char *aValid)
Check the –save parameter contents against allowed options.
cpl_error_code muse_flux_response_compute(muse_flux_object *aFluxObj, muse_flux_selection_type aSelect, double aAirmass, const cpl_table *aReference, const cpl_table *aTellBands, const cpl_table *aExtinct)
Compare measured flux distribution over wavelength with calibrated stellar fluxes and derive instrume...
muse_resampling_crstats_type
Cosmic ray rejection statistics type.
muse_resampling_params * muse_resampling_params_new(muse_resampling_type aMethod)
Create the resampling parameters structure.
cpl_error_code muse_processing_save_cube(muse_processing *aProcessing, int aIFU, void *aCube, const char *aTag, muse_cube_type aType)
Save a MUSE datacube to disk.
cpl_error_code muse_wcs_solve(muse_wcs_object *aWCSObj, cpl_table *aReference, float aRadius, float aFAccuracy, int aIter, float aThresh)
Find the world coordinate solution for a given field using coordinates of detected sources and coordi...
muse_wcs_object * muse_wcs_object_new(void)
Allocate memory for a new muse_wcs_object object.
cpl_table * ffspec
A flat-field spectrum.
muse_flux_smooth_type smooth
Structure definition of the post-processing properties.
void muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
Dump some CPL errors.
void muse_euro3dcube_delete(muse_euro3dcube *aEuro3D)
Deallocate memory associated to a muse_euro3dcube object.
muse_table * muse_table_load_filter(muse_processing *aProcessing, const char *aFilterName)
Load a table for a given filter name.
void muse_postproc_properties_delete(muse_postproc_properties *aProp)
Free memory taken by a post-processing properties object and all its components.
cpl_table * muse_postproc_load_nearest(const cpl_propertylist *aHeader, const cpl_frame *aFrame, float aWarnLimit, float aErrLimit, double *aRA, double *aDEC)
Load the calibration from a multi-table FITS file that is nearest on the sky.
cpl_imagelist * data
the cube containing the actual data values
cpl_error_code muse_sky_subtract_continuum(muse_pixtable *, cpl_table *)
Subtract sky continuum from pixel table.
cpl_error_code muse_sky_lines_set_range(cpl_table *, double, double)
Limit the lines in the table to a wavelength range.
Structure definition of a Euro3D datacube.
double muse_pfits_get_dec(const cpl_propertylist *aHeaders)
find out the declination
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_flux_get_response_table(muse_flux_object *aFluxObj, muse_flux_smooth_type aSmooth)
Get the table of the standard star response function.
void muse_table_delete(muse_table *aTable)
Deallocate memory associated to a muse_table object.
muse_resampling_dispersion_type tlambda
muse_lsf_cube ** lsf_cube
cpl_propertylist * header
the header
const char * muse_pfits_get_ctype(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS axis type string
muse_postproc_type
Type of per-exposure processing to run.
cpl_error_code muse_flux_integrate_std(muse_pixtable *aPixtable, muse_flux_profile_type aProfile, muse_flux_object *aFluxObj)
Reconstruct a cube, detect the standard star, and integrate its flux.
cpl_propertylist * header
the FITS header
int muse_processing_save_image(muse_processing *aProcessing, int aIFU, muse_image *aImage, const char *aTag)
Save a computed MUSE image to disk.
muse_pixtable * muse_pixtable_load_merge_channels(cpl_table *aExposureList, double aLambdaMin, double aLambdaMax)
Load and merge the pixel tables of the 24 MUSE sub-fields.
cpl_error_code muse_wcs_optimize_solution(muse_wcs_object *aWCSObj, float aDetSigma, muse_wcs_centroid_type aCentroid, cpl_table *aReference, float aRadius, float aFAccuracy, int aIter, float aRejSigma)
Find an optimal astrometry solution given a detection image.
muse_resampling_type muse_postproc_get_resampling_type(const char *aResampleString)
Select correct resampling type for resample string.
cpl_error_code muse_phys_air_to_vacuum(muse_pixtable *aPixtable, unsigned int aFlags)
Convert a pixel table from air to vacuum wavelengths.
Handling of "mask" files.
void muse_lsf_cube_delete_all(muse_lsf_cube **aLsfCube)
Delete all LSF cubes.
muse_imagelist * muse_imagelist_new(void)
Create a new (empty) MUSE image list.
muse_mask * muse_sky_create_skymask(muse_image *, double, double, const char *)
Select spaxels to be considered as sky.
cpl_error_code muse_sky_subtract_lines(muse_pixtable *, cpl_table *, muse_lsf_cube **)
Subtract sky lines from a pixtable.
muse_resampling_type
Resampling types.
cpl_error_code muse_pixtable_spectrum_apply(muse_pixtable *aPixtable, const cpl_array *aLambdas, const cpl_array *aFlux, muse_pixtable_operation aOperation)
Apply a spectrum given by two arrays with an operation to a pixel table.
cpl_error_code muse_lsf_fold_rectangle(cpl_image *aLsfImage, const muse_wcs *aWCS, double aBinWidth)
Filter an LSF image with a rectangle to model spectrum binning.
muse_euro3dcube * muse_resampling_euro3d(muse_pixtable *aPixtable, muse_resampling_params *aParams)
Resample a pixel table onto a regular grid structure representing a Euro3D format file...
Structure definition of the post-processing output sky data.
void muse_resampling_params_delete(muse_resampling_params *aParams)
Delete a resampling parameters structure.
muse_image * muse_datacube_collapse(muse_datacube *aCube, const muse_table *aFilter)
Integrate a FITS NAXIS=3 datacube along the wavelength direction.
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_error_code muse_sky_lines_fit_old(cpl_table *aSpectrum, cpl_table *aLines)
Fit all entries of the pixel table to the master sky.
muse_sky_params skymodel_params
void muse_pixtable_delete(muse_pixtable *aPixtable)
Deallocate memory associated to a pixel table object.
muse_postproc_darcheck darcheck
cpl_table * sky_continuum
muse_xcombine_types
Xposure combination types.
cpl_error_code muse_imagelist_set(muse_imagelist *aList, muse_image *aImage, unsigned int aIdx)
Set the muse_image of given list index.
double muse_astro_angular_distance(double aRA1, double aDEC1, double aRA2, double aDEC2)
Compute angular distance in the sky between two positions.
muse_ins_mode muse_pfits_get_mode(const cpl_propertylist *aHeaders)
find out the observation mode
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_wcs_locate_sources(muse_pixtable *aPixtable, float aSigma, muse_wcs_centroid_type aCentroid, muse_wcs_object *aWCSObj)
Determine the centers of stars on an astrometric exposure.
muse_image * muse_euro3dcube_collapse(muse_euro3dcube *aEuro3D, const muse_table *aFilter)
Integrate a Euro3D datacube along the wavelength direction.
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).
double muse_astro_airmass(cpl_propertylist *aHeader)
Derive the effective airmass of an observation from information in a FITS header. ...
cpl_propertylist * header
The FITS header.