00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026
00027
00028
00029 #include <math.h>
00030
00031 #include "muse_sky.h"
00032
00033 #include "muse_cplwrappers.h"
00034 #include "muse_data_format_z.h"
00035 #include "muse_quality.h"
00036 #include "muse_mask.h"
00037 #include "muse_pfits.h"
00038
00039
00040
00041
00045
00054
00055 const muse_cpltable_def muse_fluxspectrum_def[] = {
00056 {"lambda", CPL_TYPE_DOUBLE, "Angstrom", "%7.2f", "wavelength", CPL_TRUE},
00057 {"flux", CPL_TYPE_DOUBLE, "erg/(s cm^2 arcsec^2)", "%e", "Flux", CPL_TRUE},
00058 { NULL, 0, NULL, NULL, NULL, CPL_FALSE }
00059 };
00060
00061
00068
00069 cpl_table *
00070 muse_sky_spectrum_from_cube(muse_datacube *aCube, const cpl_mask *aMask) {
00071 unsigned count = cpl_imagelist_get_size(aCube->data);
00072 cpl_table *spectrum = muse_cpltable_new(muse_dataspectrum_def, count);
00073 double crval3 = muse_pfits_get_crval(aCube->header, 3);
00074 double crpix3 = muse_pfits_get_crpix(aCube->header, 3);
00075 double cdelt3 = muse_pfits_get_cd(aCube->header, 3, 3);
00076 unsigned i;
00077 cpl_mask *nmask = cpl_mask_duplicate(aMask);
00078 cpl_mask_not(nmask);
00079 for (i = 0; i < count; i++) {
00080 cpl_table_set(spectrum, "lambda", i, crval3 + (i + 1 - crpix3) * cdelt3);
00081
00082 cpl_image *img = cpl_imagelist_get(aCube->data, i);
00083 cpl_mask *bpm = cpl_image_get_bpm(img);
00084 cpl_mask_or(bpm, nmask);
00085 if (aCube->dq != NULL) {
00086 cpl_image *dq = cpl_imagelist_get(aCube->dq, i);
00087 cpl_mask *dq_mask = cpl_mask_threshold_image_create(dq, -0.5, 0.5);
00088 cpl_mask_not(dq_mask);
00089 cpl_mask_or(bpm, dq_mask);
00090 cpl_mask_delete(dq_mask);
00091 }
00092 double dev = cpl_image_get_stdev(img);
00093 double mean = cpl_image_get_mean(img);
00094 cpl_table_set(spectrum, "data", i, mean);
00095 cpl_table_set(spectrum, "stat", i, dev / sqrt(cpl_mask_count(bpm)));
00096 cpl_table_set(spectrum, "dq", i, (cpl_mask_count(bpm) < 3));
00097 }
00098 cpl_mask_delete(nmask);
00099
00100 return spectrum;
00101 }
00102
00103
00118
00119 muse_mask *
00120 muse_sky_create_skymask(muse_image *aImage, double aMinFraction, double aFraction,
00121 const char *aQCPrefix)
00122 {
00123 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, NULL);
00124
00125
00126
00127
00128
00129 aFraction = aMinFraction + aFraction * (1-aMinFraction);
00130
00131
00132 muse_image_reject_from_dq(aImage);
00133 double t0 = muse_cplimage_get_percentile(aImage->data, aMinFraction);
00134 double t1 = muse_cplimage_get_percentile(aImage->data, aFraction);
00135 cpl_msg_info(__func__, "Creating sky mask for pixels between minimum (%g) and"
00136 " threshold (%g)", t0, t1);
00137
00138
00139 muse_mask *selectedRegions = muse_mask_new();
00140 selectedRegions->mask = cpl_mask_threshold_image_create(aImage->data, t0, t1);
00141 cpl_mask_not(selectedRegions->mask);
00142 cpl_mask_or(selectedRegions->mask, cpl_image_get_bpm(aImage->data));
00143 cpl_mask_not(selectedRegions->mask);
00144
00145
00146 selectedRegions->header = cpl_propertylist_duplicate(aImage->header);
00147 char keyword[KEYWORD_LENGTH];
00148 snprintf(keyword, KEYWORD_LENGTH, "%s THRESHOLD", aQCPrefix);
00149 cpl_propertylist_append_double(selectedRegions->header, keyword, t1);
00150
00151 return selectedRegions;
00152 }
00153
00154
00167
00168 cpl_error_code
00169 muse_sky_save_continuum(muse_processing *aProcessing,
00170 const cpl_table *aContinuum, cpl_propertylist *aHeader)
00171 {
00172 cpl_ensure_code(aProcessing && aContinuum && aHeader, CPL_ERROR_NULL_INPUT);
00173 cpl_frame *frame = muse_processing_new_frame(aProcessing, -1, aHeader,
00174 MUSE_TAG_SKY_CONT,
00175 CPL_FRAME_TYPE_TABLE);
00176 cpl_ensure_code(frame, CPL_ERROR_ILLEGAL_INPUT);
00177 const char *filename = cpl_frame_get_filename(frame);
00178 cpl_error_code rc = cpl_propertylist_save(aHeader, filename, CPL_IO_CREATE);
00179 rc = muse_cpltable_append_file(aContinuum, filename,
00180 "CONTINUUM", muse_fluxspectrum_def);
00181 if (rc == CPL_ERROR_NONE) {
00182 #pragma omp critical(muse_processing_output_frames)
00183 cpl_frameset_insert(aProcessing->outframes, frame);
00184 } else {
00185 cpl_frame_delete(frame);
00186 }
00187 return rc;
00188 }
00189