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 <string.h>
00030 #include <math.h>
00031
00032 #include <muse.h>
00033 #include "muse_create_sky_z.h"
00034
00035
00036
00037
00038 static muse_pixtable *
00039 muse_create_sky_load_pixtable(muse_processing *aProcessing,
00040 muse_create_sky_params_t *aParams)
00041 {
00042 muse_pixtable *pixtable = NULL;
00043
00044
00045 cpl_table *exposures = muse_processing_sort_exposures(aProcessing);
00046 if (!exposures) {
00047 cpl_msg_error(__func__, "no science exposures found in input");
00048 return NULL;
00049 }
00050 int nexposures = cpl_table_get_nrow(exposures);
00051 if (nexposures != 1) {
00052 cpl_msg_error(__func__, "More than one exposure (%i) in sky creation",
00053 nexposures);
00054 }
00055
00056
00057 int i;
00058 for (i = 0; i < nexposures; i++) {
00059 cpl_table *thisexp = cpl_table_extract(exposures, i, 1);
00060 muse_pixtable *p = muse_pixtable_load_merge_channels(thisexp,
00061 aParams->lambdamin,
00062 aParams->lambdamax);
00063 cpl_table_delete(thisexp);
00064 if (p == NULL) {
00065 muse_pixtable_delete(pixtable);
00066 pixtable = NULL;
00067 break;
00068 }
00069
00070 cpl_propertylist_erase_regexp(p->header, "ESO QC ", 0);
00071 if (pixtable == NULL) {
00072 pixtable = p;
00073 } else {
00074 cpl_table_insert(pixtable->table, p->table,
00075 cpl_table_get_nrow(pixtable->table));
00076 muse_pixtable_delete(p);
00077 }
00078 }
00079 cpl_table_delete(exposures);
00080
00081 if ((pixtable != NULL) && (muse_pixtable_is_skysub(pixtable) == CPL_TRUE)) {
00082 cpl_msg_error(__func__, "Pixel table already sky subtracted");
00083 muse_pixtable_delete(pixtable);
00084 pixtable = NULL;
00085 }
00086
00087 cpl_table *response = muse_table_load(aProcessing, MUSE_TAG_STD_RESPONSE, 0);
00088 cpl_table *extinction = muse_table_load(aProcessing, MUSE_TAG_EXTINCT_TABLE, 0);
00089 cpl_table *telluric = muse_table_load(aProcessing, MUSE_TAG_STD_TELLURIC, 0);
00090
00091 if ((pixtable != NULL) && (response != NULL)) {
00092 if (muse_pixtable_is_fluxcal(pixtable) == CPL_TRUE) {
00093 cpl_msg_error(__func__,
00094 "Pixel table already flux calibrated. Dont specify %s, %s, %s",
00095 MUSE_TAG_STD_RESPONSE, MUSE_TAG_EXTINCT_TABLE,
00096 MUSE_TAG_STD_TELLURIC);
00097 muse_pixtable_delete(pixtable);
00098 pixtable = NULL;
00099 } else {
00100 cpl_error_code rc = muse_flux_calibrate(pixtable, response, extinction, telluric);
00101 if (rc != CPL_ERROR_NONE) {
00102 cpl_msg_error(__func__, "while muse_flux_calibrate");
00103 muse_pixtable_delete(pixtable);
00104 pixtable = NULL;
00105 }
00106 }
00107 }
00108
00109 cpl_table_delete(response);
00110 cpl_table_delete(extinction);
00111 cpl_table_delete(telluric);
00112
00113 if ((pixtable != NULL) && (muse_pixtable_is_fluxcal(pixtable) != CPL_TRUE)) {
00114 cpl_msg_error(__func__, "Pixel table not flux calibrated");
00115 muse_pixtable_delete(pixtable);
00116 pixtable = NULL;
00117 }
00118
00119 if (pixtable != NULL) {
00120 cpl_table_and_selected_int(pixtable->table, MUSE_PIXTABLE_DQ,
00121 CPL_NOT_EQUAL_TO, EURO3D_GOODPIXEL);
00122 cpl_table_erase_selected(pixtable->table);
00123
00124
00125 if (muse_pfits_get_mode(pixtable->header) <= MUSE_MODE_WFM_AO_N) {
00126 cpl_msg_debug(__func__, "WFM detected: starting DAR correction");
00127 cpl_error_code rc = muse_dar_correct(pixtable, aParams->lambdaref);
00128 cpl_msg_debug(__func__, "DAR correction returned rc=%d: %s", rc,
00129 rc != CPL_ERROR_NONE ? cpl_error_get_message() : "");
00130 }
00131 }
00132
00133 return pixtable;
00134 }
00135
00136
00146
00147 static muse_image *
00148 muse_create_sky_whitelight_image(muse_pixtable *aPixtable, double aCRSigma)
00149 {
00150 cpl_boolean usegrid = getenv("MUSE_COLLAPSE_PIXTABLE")
00151 && atoi(getenv("MUSE_COLLAPSE_PIXTABLE")) > 0;
00152 muse_resampling_type type = usegrid ? MUSE_RESAMPLE_NONE
00153 : MUSE_RESAMPLE_WEIGHTED_DRIZZLE;
00154 muse_resampling_params *params = muse_resampling_params_new(type);
00155 if (aCRSigma > 0.) {
00156 params->crtype = MUSE_RESAMPLING_CRSTATS_MEDIAN;
00157 params->crsigma = aCRSigma;
00158 }
00159 muse_pixgrid *grid = NULL;
00160 muse_datacube *cube = muse_resampling_cube(aPixtable, params,
00161 usegrid ? &grid : NULL);
00162 if (cube == NULL) {
00163 cpl_msg_error(__func__, "Could not create cube for whitelight image");
00164 muse_resampling_params_delete(params);
00165 muse_pixgrid_delete(grid);
00166 return NULL;
00167 }
00168 muse_image *image = NULL;
00169 cpl_table *fwhite = muse_table_load_filter(NULL, "white");
00170 if (usegrid) {
00171 params->method = MUSE_RESAMPLE_WEIGHTED_DRIZZLE;
00172 image = muse_resampling_collapse_pixgrid(aPixtable, grid,
00173 cube, fwhite, params);
00174 } else {
00175 image = muse_datacube_collapse(cube, fwhite);
00176 }
00177 muse_resampling_params_delete(params);
00178 muse_pixgrid_delete(grid);
00179 muse_datacube_delete(cube);
00180 cpl_table_delete(fwhite);
00181 return image;
00182 }
00183
00184
00191
00192 int
00193 muse_create_sky_compute(muse_processing *aProcessing,
00194 muse_create_sky_params_t *aParams)
00195 {
00196 cpl_array *crarray = muse_cplarray_new_from_delimited_string(aParams->crsigma, ",");
00197 double crsigmac = 15.,
00198 crsigmas = 0.;
00199 if (cpl_array_get_size(crarray) < 2) {
00200 cpl_msg_warning(__func__, "Less than two values given by crsigma "
00201 "parameter, using defaults (%.3f.,%.3f)!", crsigmac,
00202 crsigmas);
00203 } else {
00204 crsigmac = cpl_array_get_string(crarray, 0)
00205 ? atof(cpl_array_get_string(crarray, 0)) : 15.;
00206 crsigmas = cpl_array_get_string(crarray, 1)
00207 ? atof(cpl_array_get_string(crarray, 1)) : 0.;
00208 }
00209 cpl_array_delete(crarray);
00210
00211 muse_pixtable *pixtable = muse_create_sky_load_pixtable(aProcessing, aParams);
00212 if (pixtable == NULL) {
00213 cpl_msg_error(__func__, "Could not load pixel table");
00214 return -1;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224 muse_mask *smask = muse_processing_mask_load(aProcessing, MUSE_TAG_SKY_MASK);
00225 if (smask) {
00226 cpl_table_select_all(pixtable->table);
00227 muse_pixtable_and_selected_mask(pixtable, smask);
00228 muse_mask_delete(smask);
00229 }
00230
00231 muse_image *whitelight = muse_create_sky_whitelight_image(pixtable, crsigmac);
00232 if (whitelight == NULL) {
00233 cpl_msg_error(__func__, "Could not create whitelight image");
00234 return -1;
00235 }
00236 muse_processing_save_image(aProcessing, -1, whitelight, MUSE_TAG_IMAGE_FOV);
00237
00238 muse_mask *sky_mask = muse_sky_create_skymask(whitelight, aParams->ignore,
00239 aParams->fraction,
00240 "ESO QC SKY");
00241 muse_processing_save_mask(aProcessing, -1, sky_mask, MUSE_TAG_SKY_MASK);
00242
00243 cpl_table_select_all(pixtable->table);
00244 muse_pixtable_and_selected_mask(pixtable, sky_mask);
00245 cpl_table_not_selected(pixtable->table);
00246 cpl_table_erase_selected(pixtable->table);
00247 muse_image_delete(whitelight);
00248 muse_mask_delete(sky_mask);
00249
00250
00251 cpl_table *spectrum = muse_resampling_spectrum_iterate(pixtable,
00252 aParams->sampling,
00253 0., crsigmas, 1);
00254 if (spectrum == NULL) {
00255 muse_pixtable_delete(pixtable);
00256 return -1;
00257 }
00258 muse_processing_save_table(aProcessing, -1, spectrum, pixtable->header,
00259 MUSE_TAG_SKY_SPECTRUM, MUSE_TABLE_TYPE_CPL);
00260
00261 cpl_table *lines = muse_sky_lines_load(aProcessing);
00262 if (lines != NULL) {
00263 double lambda_low = cpl_table_get_column_min(spectrum, "lambda");
00264 double lambda_high = cpl_table_get_column_max(spectrum, "lambda");
00265 muse_sky_lines_set_range(lines, lambda_low-5, lambda_high+5);
00266 }
00267
00268 cpl_table *continuum = muse_sky_continuum_load(aProcessing);
00269
00270
00271
00272
00273
00274
00275
00276 cpl_errorstate prestate = cpl_errorstate_get();
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 muse_lsf_cube **lsfCube = muse_lsf_cube_load_all(aProcessing);
00287 if (lsfCube != NULL) {
00288 cpl_image *lsfImage = muse_lsf_average_cube_all(lsfCube, pixtable);
00289 muse_wcs *lsfWCS = muse_lsf_cube_get_wcs_all(lsfCube);
00290 muse_lsf_fold_rectangle(lsfImage, lsfWCS, aParams->sampling);
00291
00292 cpl_msg_info(__func__, "Creating master sky spectrum using fits to lines "
00293 "(fluxes) and residual continuum");
00294
00295
00296 muse_sky_lines_fit(spectrum, lines, lsfImage, lsfWCS);
00297 if (!cpl_errorstate_is_equal(prestate)) {
00298 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00299 cpl_errorstate_set(prestate);
00300 }
00301
00302 if (continuum == NULL) {
00303 continuum = muse_sky_continuum_create(spectrum, lines, lsfImage, lsfWCS,
00304 aParams->csampling);
00305 }
00306
00307 muse_lsf_cube_delete_all(lsfCube);
00308 cpl_image_delete(lsfImage);
00309 #ifdef USE_LSF_PARAMS
00310 } else {
00311 cpl_errorstate_set(prestate);
00312 muse_lsf_params **lsfParams = muse_processing_lsf_params_load(aProcessing, 0);
00313 if (lsfParams != NULL) {
00314
00315
00316 muse_sky_lines_fit_old(spectrum, lines);
00317 if (!cpl_errorstate_is_equal(prestate)) {
00318 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00319 cpl_errorstate_set(prestate);
00320 }
00321
00322 if (continuum == NULL) {
00323 muse_sky_subtract_lines_old(pixtable, lines, lsfParams);
00324 continuum = muse_resampling_spectrum(pixtable, aParams->csampling);
00325 cpl_table_erase_column(continuum, "stat");
00326 cpl_table_erase_column(continuum, "dq");
00327 cpl_table_name_column(continuum, "data", "flux");
00328 }
00329
00330 muse_lsf_params_delete_all(lsfParams);
00331 } else {
00332 cpl_msg_error(__func__, "Could not load LSF. Continuum is not created.");
00333 }
00334 #endif
00335 }
00336
00337 cpl_propertylist *header = cpl_propertylist_new();
00338 muse_sky_qc_lines(header, lines, "ESO QC SKY");
00339 muse_sky_lines_save(aProcessing, lines, header);
00340 cpl_propertylist_delete(header);
00341
00342 header = cpl_propertylist_new();
00343 muse_sky_qc_continuum(header, continuum, "ESO QC SKY");
00344 muse_sky_save_continuum(aProcessing, continuum, header);
00345 cpl_propertylist_delete(header);
00346
00347
00348 cpl_table_delete(spectrum);
00349 cpl_table_delete(lines);
00350 cpl_table_delete(continuum);
00351 muse_pixtable_delete(pixtable);
00352 return cpl_errorstate_is_equal(prestate) ? 0 : -1;
00353 }
00354