00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032 #include <math.h>
00033 #include <cpl.h>
00034 #include <moses.h>
00035 #include <fors_dfs.h>
00036
00037 static int fors_subtract_sky_lss_create(cpl_plugin *);
00038 static int fors_subtract_sky_lss_exec(cpl_plugin *);
00039 static int fors_subtract_sky_lss_destroy(cpl_plugin *);
00040 static int fors_subtract_sky_lss(cpl_parameterlist *, cpl_frameset *);
00041
00042 static char fors_subtract_sky_lss_description[] =
00043 "This recipe is used to subtract the sky from wavelength calibrated\n"
00044 "scientific spectra produced by the recipe fors_resample. A simple median\n"
00045 "signal level is subtracted from each image column.\n"
00046 "In the table below the MXU acronym can be read alternatively as MOS\n"
00047 "and LSS, depending on the instrument mode of the input data. The acronym\n"
00048 "SCI may be read STD in case of standard stars observations.\n"
00049 "Note that only LSS or LSS-like MOS/MXU data are to be processed by this\n"
00050 "recipe.\n\n"
00051 "Input files:\n\n"
00052 " DO category: Type: Explanation: Required:\n"
00053 " MAPPED_ALL_SCI_MXU Raw Scientific exposure Y\n\n"
00054 "Output files:\n\n"
00055 " DO category: Data type: Explanation:\n"
00056 " MAPPED_SCI_MXU FITS image Rectified scientific spectra\n"
00057 " MAPPED_SKY_SCI_MXU FITS image Rectified sky spectra\n\n";
00058
00059 #define fors_subtract_sky_lss_exit(message) \
00060 { \
00061 if (message) cpl_msg_error(recipe, message); \
00062 cpl_image_delete(skymap); \
00063 cpl_image_delete(sky); \
00064 cpl_image_delete(spectra); \
00065 cpl_propertylist_delete(header); \
00066 cpl_msg_indent_less(); \
00067 return -1; \
00068 }
00069
00070
00071 #define fors_subtract_sky_lss_exit_memcheck(message) \
00072 { \
00073 if (message) cpl_msg_info(recipe, message); \
00074 cpl_image_delete(skymap); \
00075 cpl_image_delete(sky); \
00076 cpl_image_delete(spectra); \
00077 cpl_propertylist_delete(header); \
00078 cpl_msg_indent_less(); \
00079 return 0; \
00080 }
00081
00082
00094 int cpl_plugin_get_info(cpl_pluginlist *list)
00095 {
00096 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
00097 cpl_plugin *plugin = &recipe->interface;
00098
00099 cpl_plugin_init(plugin,
00100 CPL_PLUGIN_API,
00101 FORS_BINARY_VERSION,
00102 CPL_PLUGIN_TYPE_RECIPE,
00103 "fors_subtract_sky_lss",
00104 "Subtract sky from calibrated long slit exposure",
00105 fors_subtract_sky_lss_description,
00106 "Carlo Izzo",
00107 PACKAGE_BUGREPORT,
00108 "This file is currently part of the FORS Instrument Pipeline\n"
00109 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
00110 "This program is free software; you can redistribute it and/or modify\n"
00111 "it under the terms of the GNU General Public License as published by\n"
00112 "the Free Software Foundation; either version 2 of the License, or\n"
00113 "(at your option) any later version.\n\n"
00114 "This program is distributed in the hope that it will be useful,\n"
00115 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00116 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00117 "GNU General Public License for more details.\n\n"
00118 "You should have received a copy of the GNU General Public License\n"
00119 "along with this program; if not, write to the Free Software Foundation,\n"
00120 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
00121 fors_subtract_sky_lss_create,
00122 fors_subtract_sky_lss_exec,
00123 fors_subtract_sky_lss_destroy);
00124
00125 cpl_pluginlist_append(list, plugin);
00126
00127 return 0;
00128 }
00129
00130
00141 static int fors_subtract_sky_lss_create(cpl_plugin *plugin)
00142 {
00143 cpl_recipe *recipe;
00144
00145
00146
00147
00148
00149
00150
00151
00152 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00153 recipe = (cpl_recipe *)plugin;
00154 else
00155 return -1;
00156
00157
00158
00159
00160
00161 recipe->parameters = cpl_parameterlist_new();
00162
00163 return 0;
00164 }
00165
00166
00175 static int fors_subtract_sky_lss_exec(cpl_plugin *plugin)
00176 {
00177 cpl_recipe *recipe;
00178
00179 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00180 recipe = (cpl_recipe *)plugin;
00181 else
00182 return -1;
00183
00184 return fors_subtract_sky_lss(recipe->parameters, recipe->frames);
00185 }
00186
00187
00196 static int fors_subtract_sky_lss_destroy(cpl_plugin *plugin)
00197 {
00198 cpl_recipe *recipe;
00199
00200 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00201 recipe = (cpl_recipe *)plugin;
00202 else
00203 return -1;
00204
00205 cpl_parameterlist_delete(recipe->parameters);
00206
00207 return 0;
00208 }
00209
00210
00220 static int fors_subtract_sky_lss(cpl_parameterlist *parlist,
00221 cpl_frameset *frameset)
00222 {
00223
00224 const char *recipe = "fors_subtract_sky_lss";
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 cpl_image *spectra = NULL;
00236 cpl_image *skymap = NULL;
00237 cpl_image *sky = NULL;
00238 cpl_table *maskslits = NULL;
00239
00240 cpl_propertylist *header = NULL;
00241
00242
00243
00244
00245
00246 char version[80];
00247 char *instrume = NULL;
00248 const char *mapped_science_tag;
00249 const char *mapped_science_sky_tag;
00250 const char *mapped_sky_tag;
00251 int mxu, mos, lss;
00252 int treat_as_lss = 0;
00253 int nslits;
00254 int nscience;
00255 double *xpos;
00256 double mxpos;
00257 int nx, ny;
00258 int standard;
00259 float *data;
00260 float *sdata;
00261 int i, j;
00262
00263
00264 snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
00265
00266 cpl_msg_set_indentation(2);
00267
00268 if (dfs_files_dont_exist(frameset))
00269 fors_subtract_sky_lss_exit(NULL);
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 cpl_msg_indent_less();
00281 cpl_msg_info(recipe, "Check input set-of-frames:");
00282 cpl_msg_indent_more();
00283
00284 mxu = cpl_frameset_count_tags(frameset, "MAPPED_ALL_SCI_MXU");
00285 mos = cpl_frameset_count_tags(frameset, "MAPPED_ALL_SCI_MOS");
00286 lss = cpl_frameset_count_tags(frameset, "MAPPED_ALL_SCI_LSS");
00287 standard = 0;
00288
00289 if (mxu + mos + lss == 0) {
00290 mxu = cpl_frameset_count_tags(frameset, "MAPPED_ALL_STD_MXU");
00291 mos = cpl_frameset_count_tags(frameset, "MAPPED_ALL_STD_MOS");
00292 lss = cpl_frameset_count_tags(frameset, "MAPPED_ALL_STD_LSS");
00293 standard = 1;
00294 }
00295
00296 if (mxu + mos + lss == 0)
00297 fors_subtract_sky_lss_exit("Missing input scientific frame");
00298
00299 nscience = mxu + mos + lss;
00300
00301 if (nscience > 1)
00302 fors_subtract_sky_lss_exit("More than one scientific frame in input");
00303
00304 if (mxu) {
00305 if (standard) {
00306 cpl_msg_info(recipe, "MXU data found");
00307 mapped_science_tag = "MAPPED_STD_MXU";
00308 mapped_science_sky_tag = "MAPPED_ALL_STD_MXU";
00309 mapped_sky_tag = "MAPPED_SKY_STD_MXU";
00310 }
00311 else {
00312 cpl_msg_info(recipe, "MXU data found");
00313 mapped_science_tag = "MAPPED_SCI_MXU";
00314 mapped_science_sky_tag = "MAPPED_ALL_SCI_MXU";
00315 mapped_sky_tag = "MAPPED_SKY_SCI_MXU";
00316 }
00317 }
00318
00319 if (lss) {
00320 if (standard) {
00321 cpl_msg_info(recipe, "LSS data found");
00322 mapped_science_tag = "MAPPED_STD_LSS";
00323 mapped_science_sky_tag = "MAPPED_ALL_STD_LSS";
00324 mapped_sky_tag = "MAPPED_SKY_STD_LSS";
00325 }
00326 else {
00327 cpl_msg_info(recipe, "LSS data found");
00328 mapped_science_tag = "MAPPED_SCI_LSS";
00329 mapped_science_sky_tag = "MAPPED_ALL_SCI_LSS";
00330 mapped_sky_tag = "MAPPED_SKY_SCI_LSS";
00331 }
00332 }
00333
00334 if (mos) {
00335 if (standard) {
00336 cpl_msg_info(recipe, "MOS data found");
00337 mapped_science_tag = "MAPPED_STD_MOS";
00338 mapped_science_sky_tag = "MAPPED_ALL_STD_MOS";
00339 mapped_sky_tag = "MAPPED_SKY_STD_MOS";
00340 }
00341 else {
00342 cpl_msg_info(recipe, "MOS data found");
00343 mapped_science_tag = "MAPPED_SCI_MOS";
00344 mapped_science_sky_tag = "MAPPED_ALL_SCI_MOS";
00345 mapped_sky_tag = "MAPPED_SKY_SCI_MOS";
00346 }
00347 }
00348
00349
00350
00351
00352
00353 cpl_msg_info(recipe, "Load mapped scientific exposure...");
00354 cpl_msg_indent_more();
00355
00356 spectra = dfs_load_image(frameset, mapped_science_sky_tag,
00357 CPL_TYPE_FLOAT, 0, 0);
00358
00359 if (spectra == NULL)
00360 fors_subtract_sky_lss_exit("Cannot load input frame");
00361
00362 header = dfs_load_header(frameset, mapped_science_sky_tag, 0);
00363
00364 if (header == NULL)
00365 fors_subtract_sky_lss_exit("Cannot load input frame header");
00366
00367 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00368 if (instrume == NULL)
00369 fors_subtract_sky_lss_exit("Missing keyword INSTRUME in scientific header");
00370 instrume = cpl_strdup(instrume);
00371
00372 if (instrume[4] == '1')
00373 snprintf(version, 80, "%s/%s", "fors1", VERSION);
00374 if (instrume[4] == '2')
00375 snprintf(version, 80, "%s/%s", "fors2", VERSION);
00376
00377 cpl_free(instrume); instrume = NULL;
00378
00379 cpl_msg_indent_less();
00380
00381 if (mos || mxu) {
00382 if (mos)
00383 maskslits = mos_load_slits_fors_mos(header);
00384 else
00385 maskslits = mos_load_slits_fors_mxu(header);
00386
00387
00388
00389
00390
00391
00392 mxpos = cpl_table_get_column_median(maskslits, "xtop");
00393 xpos = cpl_table_get_data_double(maskslits, "xtop");
00394 nslits = cpl_table_get_nrow(maskslits);
00395
00396 treat_as_lss = 1;
00397 for (i = 0; i < nslits; i++) {
00398 if (fabs(mxpos-xpos[i]) > 0.01) {
00399 treat_as_lss = 0;
00400 break;
00401 }
00402 }
00403
00404 cpl_table_delete(maskslits); maskslits = NULL;
00405
00406 if (treat_as_lss)
00407 cpl_msg_info(recipe, "All MOS slits have the same offset: %.2f\n"
00408 "The LSS data reduction strategy is applied.",
00409 mxpos);
00410 else
00411 fors_subtract_sky_lss_exit("This recipe can only be used "
00412 "with LSS-like data");
00413 }
00414
00415 nx = cpl_image_get_size_x(spectra);
00416 ny = cpl_image_get_size_y(spectra);
00417
00418 skymap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00419 sky = cpl_image_collapse_median_create(spectra, 0, 0, 1);
00420
00421 data = cpl_image_get_data(skymap);
00422
00423 for (i = 0; i < ny; i++) {
00424 sdata = cpl_image_get_data(sky);
00425 for (j = 0; j < nx; j++) {
00426 *data++ = *sdata++;
00427 }
00428 }
00429
00430 cpl_image_delete(sky); sky = NULL;
00431 cpl_image_subtract(spectra, skymap);
00432
00433 if (dfs_save_image(frameset, skymap, mapped_sky_tag, header,
00434 parlist, recipe, version))
00435 fors_subtract_sky_lss_exit(NULL);
00436
00437 cpl_image_delete(skymap); skymap = NULL;
00438
00439 if (dfs_save_image(frameset, spectra, mapped_science_tag, header,
00440 parlist, recipe, version))
00441 fors_subtract_sky_lss_exit(NULL);
00442
00443 cpl_image_delete(spectra); spectra = NULL;
00444
00445 cpl_propertylist_delete(header); header = NULL;
00446
00447 if (cpl_error_get_code()) {
00448 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
00449 fors_subtract_sky_lss_exit(NULL);
00450 }
00451 else
00452 return 0;
00453 }