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
00031 #include <muse.h>
00032 #include "muse_scipost_z.h"
00033
00034
00035
00036
00037
00038
00050
00051 static void
00052 muse_scipost_offsets_scale(muse_pixtable *aPT, const cpl_table *aOffsets,
00053 const char *aPurpose)
00054 {
00055 if (!aPT || !aOffsets) {
00056 return;
00057 }
00058 if (!aPT->header) {
00059 return;
00060 }
00061 cpl_msg_info(__func__, "Applying offsets to %s...", aPurpose);
00062 cpl_msg_indent_more();
00063 double ra = muse_pfits_get_ra(aPT->header),
00064 dec = muse_pfits_get_dec(aPT->header),
00065 *offsets = muse_xcombine_find_offsets(aOffsets,
00066 muse_pfits_get_dateobs(aPT->header));
00067 char keyword[KEYWORD_LENGTH], comment[KEYWORD_LENGTH];
00068 if (offsets) {
00069 if (isfinite(offsets[0]) && isfinite(offsets[1])) {
00070 ra -= offsets[0];
00071 dec -= offsets[1];
00072 cpl_msg_debug(__func__, "Applying coordinate offsets to exposure: %e/%e"
00073 " deg", offsets[0], offsets[1]);
00074
00075 cpl_errorstate state = cpl_errorstate_get();
00076 cpl_propertylist_update_double(aPT->header, "RA", ra);
00077 if (!cpl_errorstate_is_equal(state)) {
00078 cpl_errorstate_set(state);
00079 cpl_propertylist_update_float(aPT->header, "RA", ra);
00080 }
00081 cpl_propertylist_set_comment(aPT->header, "RA", "offset applied!");
00082 state = cpl_errorstate_get();
00083 cpl_propertylist_update_double(aPT->header, "DEC", dec);
00084 if (!cpl_errorstate_is_equal(state)) {
00085 cpl_errorstate_set(state);
00086 cpl_propertylist_update_float(aPT->header, "DEC", dec);
00087 }
00088 cpl_propertylist_set_comment(aPT->header, "DEC", "offset applied!");
00089
00090 snprintf(keyword, KEYWORD_LENGTH, MUSE_HDR_OFFSETi_DRA, 1);
00091 snprintf(comment, KEYWORD_LENGTH, MUSE_HDR_OFFSETi_DRA_C, offsets[0] * 3600.);
00092 cpl_propertylist_append_double(aPT->header, keyword, offsets[0]);
00093 cpl_propertylist_set_comment(aPT->header, keyword, comment);
00094 snprintf(keyword, KEYWORD_LENGTH, MUSE_HDR_OFFSETi_DDEC, 1);
00095 snprintf(comment, KEYWORD_LENGTH, MUSE_HDR_OFFSETi_DDEC_C, offsets[1] * 3600.);
00096 cpl_propertylist_append_double(aPT->header, keyword, offsets[1]);
00097 cpl_propertylist_set_comment(aPT->header, keyword, comment);
00098 }
00099 if (isnormal(offsets[2])) {
00100
00101 cpl_msg_debug(__func__, "Scaling flux of exposure by %g.", offsets[2]);
00102 muse_pixtable_flux_multiply(aPT, offsets[2]);
00103
00104 snprintf(keyword, KEYWORD_LENGTH, MUSE_HDR_FLUX_SCALEi, 1);
00105 cpl_propertylist_append_double(aPT->header, keyword, offsets[2]);
00106 cpl_propertylist_set_comment(aPT->header, keyword, MUSE_HDR_FLUX_SCALEi_C);
00107 }
00108
00109 snprintf(keyword, KEYWORD_LENGTH, MUSE_HDR_OFFSETi_DATEOBS, 1);
00110 snprintf(comment, KEYWORD_LENGTH, MUSE_HDR_OFFSETi_DATEOBS_C, 1);
00111 cpl_propertylist_append_string(aPT->header, keyword,
00112 muse_pfits_get_dateobs(aPT->header));
00113 cpl_propertylist_set_comment(aPT->header, keyword, comment);
00114 }
00115 cpl_free(offsets);
00116 cpl_msg_indent_less();
00117 }
00118
00119
00135
00136 int
00137 muse_scipost_compute(muse_processing *aProcessing,
00138 muse_scipost_params_t *aParams)
00139 {
00140 const char *savevalid = "cube,skymodel,individual,positioned,combined,stacked";
00141 if (!muse_postproc_check_save_param(aParams->save, savevalid)) {
00142 return -1;
00143 }
00144 muse_postproc_properties *prop = muse_postproc_properties_new(MUSE_POSTPROC_SCIPOST);
00145
00146 prop->lambdamin = aParams->lambdamin;
00147 prop->lambdamax = aParams->lambdamax;
00148 prop->lambdaref = aParams->lambdaref;
00149 prop->darcheck = MUSE_POSTPROC_DARCHECK_NONE;
00150 if (aParams->darcheck == MUSE_SCIPOST_PARAM_DARCHECK_CHECK) {
00151 prop->darcheck = MUSE_POSTPROC_DARCHECK_CHECK;
00152 } else if (aParams->darcheck == MUSE_SCIPOST_PARAM_DARCHECK_CORRECT) {
00153 prop->darcheck = MUSE_POSTPROC_DARCHECK_CORRECT;
00154 }
00155 prop->rvtype = muse_rvcorrect_select_type(aParams->rvcorr_s);
00156
00157 prop->response = muse_table_load(aProcessing, MUSE_TAG_STD_RESPONSE, 0);
00158 prop->extinction = muse_table_load(aProcessing, MUSE_TAG_EXTINCT_TABLE, 0);
00159 prop->telluric = muse_table_load(aProcessing, MUSE_TAG_STD_TELLURIC, 0);
00160
00161 if (aParams->astrometry) {
00162 prop->wcs = muse_propertylist_load(aProcessing, MUSE_TAG_ASTROMETRY_WCS);
00163 if (!prop->wcs) {
00164
00165 cpl_msg_warning(__func__, "Using default MUSE WFM astrometry, output "
00166 "world coordinates will be inaccurate!");
00167 prop->wcs = muse_wcs_create_default();
00168 }
00169 }
00170
00171 const struct {
00172 int par;
00173 muse_postproc_skymethod postproc;
00174 } skymethod[] = {
00175 { MUSE_SCIPOST_PARAM_SKYMETHOD_NONE, MUSE_POSTPROC_SKYMETHOD_NONE },
00176 { MUSE_SCIPOST_PARAM_SKYMETHOD_SUBTRACT_MODEL, MUSE_POSTPROC_SKYMETHOD_NONE },
00177 { MUSE_SCIPOST_PARAM_SKYMETHOD_MODEL, MUSE_POSTPROC_SKYMETHOD_MODEL },
00178 { MUSE_SCIPOST_PARAM_SKYMETHOD_SIMPLE, MUSE_POSTPROC_SKYMETHOD_SIMPLE },
00179 { MUSE_SCIPOST_PARAM_SKYMETHOD_INVALID_VALUE, MUSE_POSTPROC_SKYMETHOD_MODEL },
00180 };
00181 prop->skymethod = MUSE_POSTPROC_SKYMETHOD_MODEL;
00182 int i_method;
00183 for (i_method = 0;
00184 skymethod[i_method].par != MUSE_SCIPOST_PARAM_SKYMETHOD_INVALID_VALUE;
00185 i_method++) {
00186 if (skymethod[i_method].par == aParams->skymethod) {
00187 prop->skymethod = skymethod[i_method].postproc;
00188 break;
00189 }
00190 }
00191 prop->skymodel_params.fraction = aParams->skymodel_fraction;
00192 prop->skymodel_params.ignore = aParams->skymodel_ignore;
00193 prop->skymodel_params.sampling = aParams->skymodel_sampling;
00194 prop->skymodel_params.csampling = aParams->skymodel_csampling;
00195
00196 cpl_array *crarray = muse_cplarray_new_from_delimited_string(aParams->sky_crsigma, ",");
00197 if (cpl_array_get_size(crarray) < 2) {
00198 prop->skymodel_params.crsigmac = 15.;
00199 prop->skymodel_params.crsigmas = 0.;
00200 cpl_msg_warning(__func__, "Less than two values given by sky_crsigma "
00201 "parameter, using defaults (%.3f.,%.3f)!",
00202 prop->skymodel_params.crsigmac, prop->skymodel_params.crsigmas);
00203 } else {
00204 prop->skymodel_params.crsigmac = cpl_array_get_string(crarray, 0)
00205 ? atof(cpl_array_get_string(crarray, 0)) : 15.;
00206 prop->skymodel_params.crsigmas = cpl_array_get_string(crarray, 1)
00207 ? atof(cpl_array_get_string(crarray, 1)) : 0.;
00208 }
00209 cpl_array_delete(crarray);
00210
00211 #ifdef USE_LSF_PARAMS
00212 cpl_errorstate prestate = cpl_errorstate_get();
00213 #endif
00214 if (aParams->skymethod == MUSE_SCIPOST_PARAM_SKYMETHOD_SUBTRACT_MODEL) {
00215 prop->lsf_cube = muse_lsf_cube_load_all(aProcessing);
00216 if (prop->lsf_cube != NULL) {
00217 prop->sky_lines = muse_sky_lines_load(aProcessing);
00218 #ifdef USE_LSF_PARAMS
00219 } else {
00220 prop-> lsf_params = muse_processing_lsf_params_load(aProcessing, 0);
00221 if (prop->lsf_params != NULL) {
00222 cpl_errorstate_set(prestate);
00223 prop->sky_lines = muse_sky_lines_load(aProcessing);
00224 }
00225 #endif
00226 }
00227 prop->sky_continuum = muse_sky_continuum_load(aProcessing);
00228 } else if (aParams->skymethod == MUSE_SCIPOST_PARAM_SKYMETHOD_MODEL) {
00229 prop->lsf_cube = muse_lsf_cube_load_all(aProcessing);
00230 if (prop->lsf_cube == NULL) {
00231 #ifdef USE_LSF_PARAMS
00232 prop->lsf_params = muse_processing_lsf_params_load(aProcessing, 0);
00233 if (prop->lsf_params != NULL) {
00234 cpl_errorstate_set(prestate);
00235 } else {
00236 #endif
00237 cpl_msg_error(__func__, "Missing required LSF frames for sky model");
00238 #ifdef USE_LSF_PARAMS
00239 }
00240 #endif
00241 }
00242 prop->sky_lines = muse_sky_lines_load(aProcessing);
00243 if (prop->sky_lines == NULL) {
00244 cpl_msg_error(__func__, "Missing required sky lines frame for sky model");
00245 }
00246 if (((prop->lsf_cube == NULL)
00247 #ifdef USE_LSF_PARAMS
00248 && (prop->lsf_params == NULL)
00249 #endif
00250 )
00251 || (prop->sky_lines == NULL)) {
00252 muse_postproc_properties_delete(prop);
00253 return -1;
00254 }
00255 prop->sky_continuum = muse_sky_continuum_load(aProcessing);
00256 prop->sky_mask = muse_processing_mask_load(aProcessing, MUSE_TAG_SKY_MASK);
00257 } else if (aParams->skymethod == MUSE_SCIPOST_PARAM_SKYMETHOD_SIMPLE) {
00258
00259 prop->sky_mask = muse_processing_mask_load(aProcessing, MUSE_TAG_SKY_MASK);
00260 }
00261
00262
00263 prop->exposures = muse_processing_sort_exposures(aProcessing);
00264 if (!prop->exposures) {
00265 cpl_msg_error(__func__, "no science exposures found in input");
00266 muse_postproc_properties_delete(prop);
00267 return -1;
00268 }
00269 int nexposures = cpl_table_get_nrow(prop->exposures);
00270
00271
00272 cpl_table *offsets = muse_table_load(aProcessing, MUSE_TAG_OFFSET_LIST, 0);
00273 if (offsets && muse_cpltable_check(offsets, muse_offset_list_def) != CPL_ERROR_NONE) {
00274 cpl_msg_warning(__func__, "Input %s has unexpected format, proceeding "
00275 "without offset and flux scales!", MUSE_TAG_OFFSET_LIST);
00276 cpl_table_delete(offsets);
00277 offsets = NULL;
00278 }
00279
00280
00281
00282 muse_pixtable **pixtables = cpl_calloc(nexposures + 1, sizeof(muse_pixtable *));
00283 int i;
00284 for (i = 0; i < nexposures; i++) {
00285 muse_postproc_sky_outputs *skyout = cpl_calloc(1, sizeof(muse_postproc_sky_outputs));
00286 pixtables[i] = muse_postproc_process_exposure(prop, i, skyout);
00287 if (!pixtables[i]) {
00288 int i2;
00289 for (i2 = 0; i2 <= i; i2++) {
00290 muse_pixtable_delete(pixtables[i2]);
00291 }
00292 cpl_free(pixtables);
00293 muse_postproc_properties_delete(prop);
00294 cpl_table_delete(offsets);
00295 return -1;
00296 }
00297
00298 if (strstr(aParams->save, "skymodel")) {
00299 if (skyout->mask) {
00300 muse_processing_save_mask(aProcessing, -1, skyout->mask, MUSE_TAG_SKY_MASK);
00301 }
00302 if (skyout->spectrum) {
00303 cpl_propertylist *header = cpl_propertylist_duplicate(pixtables[i]->header);
00304 cpl_propertylist_erase_regexp(header, MUSE_HDR_PT_REGEXP, 0);
00305 muse_processing_save_table(aProcessing, -1, skyout->spectrum, header,
00306 MUSE_TAG_SKY_SPECTRUM, MUSE_TABLE_TYPE_CPL);
00307 cpl_propertylist_delete(header);
00308 }
00309 if (skyout->lines) {
00310 cpl_propertylist *header = cpl_propertylist_duplicate(pixtables[i]->header);
00311 cpl_propertylist_erase_regexp(header, MUSE_HDR_PT_REGEXP, 0);
00312 muse_sky_qc_lines(header, skyout->lines, "ESO QC SCIPOST");
00313 muse_sky_lines_save(aProcessing, skyout->lines, header);
00314 cpl_propertylist_delete(header);
00315 }
00316 if (skyout->continuum) {
00317 cpl_propertylist *header = cpl_propertylist_duplicate(pixtables[i]->header);
00318 cpl_propertylist_erase_regexp(header, MUSE_HDR_PT_REGEXP, 0);
00319 muse_sky_qc_continuum(header, skyout->continuum, "ESO QC SCIPOST");
00320 muse_sky_save_continuum(aProcessing, skyout->continuum, header);
00321 cpl_propertylist_delete(header);
00322 }
00323 }
00324 muse_mask_delete(skyout->mask);
00325 cpl_table_delete(skyout->spectrum);
00326 cpl_table_delete(skyout->lines);
00327 cpl_table_delete(skyout->continuum);
00328 cpl_free(skyout);
00329
00330 if (strstr(aParams->save, "individual")) {
00331 muse_processing_save_table(aProcessing, -1, pixtables[i], NULL,
00332 MUSE_TAG_PIXTABLE_REDUCED,
00333 MUSE_TABLE_TYPE_PIXTABLE);
00334 }
00335 if (strstr(aParams->save, "positioned")) {
00336
00337
00338 muse_pixtable *pt = muse_pixtable_duplicate(pixtables[i]);
00339
00340
00341 muse_scipost_offsets_scale(pt, offsets,
00342 "positioned pixel table for saving");
00343 muse_wcs_position_celestial(pt, muse_pfits_get_ra(pt->header),
00344 muse_pfits_get_dec(pt->header));
00345 muse_processing_save_table(aProcessing, -1, pt, NULL,
00346 MUSE_TAG_PIXTABLE_POSITIONED,
00347 MUSE_TABLE_TYPE_PIXTABLE);
00348 muse_pixtable_delete(pt);
00349 }
00350 }
00351 muse_postproc_properties_delete(prop);
00352
00353
00354 muse_pixtable *bigpixtable = NULL;
00355 if (nexposures > 1) {
00356 muse_xcombine_types weight = muse_postproc_get_weight_type(aParams->weight_s);
00357 cpl_error_code rc = muse_xcombine_weights(pixtables, weight);
00358 if (rc != CPL_ERROR_NONE) {
00359 cpl_msg_error(__func__, "weighting the pixel tables didn't work: %s",
00360 cpl_error_get_message());
00361 for (i = 0; i < nexposures; i++) {
00362 muse_pixtable_delete(pixtables[i]);
00363 }
00364 cpl_free(pixtables);
00365 cpl_table_delete(offsets);
00366 return -1;
00367 }
00368
00369 bigpixtable = muse_xcombine_tables(pixtables, offsets);
00370 if (!bigpixtable) {
00371 cpl_msg_error(__func__, "combining the pixel tables didn't work: %s",
00372 cpl_error_get_message());
00373 for (i = 0; i < nexposures; i++) {
00374 muse_pixtable_delete(pixtables[i]);
00375 }
00376 cpl_free(pixtables);
00377 cpl_table_delete(offsets);
00378 return -1;
00379 }
00380 } else {
00381 bigpixtable = pixtables[0];
00382
00383 cpl_msg_indent_more();
00384 muse_scipost_offsets_scale(bigpixtable, offsets,
00385 "single pixel table for resampling");
00386 cpl_msg_indent_less();
00387 muse_wcs_position_celestial(bigpixtable,
00388 muse_pfits_get_ra(bigpixtable->header),
00389 muse_pfits_get_dec(bigpixtable->header));
00390 }
00391 cpl_free(pixtables);
00392 cpl_table_delete(offsets);
00393
00394 cpl_error_code rc = CPL_ERROR_NONE;
00395 if (strstr(aParams->save, "cube")) {
00396 muse_resampling_type resample
00397 = muse_postproc_get_resampling_type(aParams->resample_s);
00398 muse_resampling_params *rp = muse_resampling_params_new(resample);
00399 rp->dx = aParams->dx;
00400 rp->dy = aParams->dy;
00401 rp->dlambda = aParams->dlambda;
00402 rp->crtype = muse_postproc_get_cr_type(aParams->crtype_s);
00403 rp->crsigma = aParams->crsigma;
00404 rp->ld = aParams->ld;
00405 rp->rc = aParams->rc;
00406 rp->pfx = aParams->pixfrac;
00407 rp->pfy = aParams->pixfrac;
00408 rp->pfl = aParams->pixfrac;
00409 cpl_propertylist *outwcs = muse_postproc_cube_load_output_wcs(aProcessing);
00410 muse_resampling_params_set_wcs(rp, outwcs);
00411 cpl_propertylist_delete(outwcs);
00412 muse_cube_type format = muse_postproc_get_cube_format(aParams->format_s);
00413 rc = muse_postproc_cube_resample_and_collapse(aProcessing, bigpixtable,
00414 format, rp, aParams->filter);
00415 muse_resampling_params_delete(rp);
00416 }
00417 if (strstr(aParams->save, "combined")) {
00418 muse_processing_save_table(aProcessing, -1, bigpixtable, NULL,
00419 MUSE_TAG_PIXTABLE_COMBINED,
00420 MUSE_TABLE_TYPE_PIXTABLE);
00421 }
00422 if (strstr(aParams->save, "stacked")) {
00423 cpl_msg_debug(__func__, "additional output as column-stacked image");
00424 muse_image *img = muse_resampling_image(bigpixtable,
00425 MUSE_RESAMPLE_WEIGHTED_RENKA,
00426 aParams->dx, aParams->dlambda);
00427 muse_processing_save_image(aProcessing, -1, img, MUSE_TAG_OBJECT_RESAMPLED);
00428 muse_image_delete(img);
00429 }
00430
00431 muse_pixtable_delete(bigpixtable);
00432
00433
00434 return rc == CPL_ERROR_NONE ? 0 : -1;
00435 }