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_detect_objects_create(cpl_plugin *);
00038 static int fors_detect_objects_exec(cpl_plugin *);
00039 static int fors_detect_objects_destroy(cpl_plugin *);
00040 static int fors_detect_objects(cpl_parameterlist *, cpl_frameset *);
00041
00042 static char fors_detect_objects_description[] =
00043 "This recipe is used to detect scientific objects spectra on a resampled\n"
00044 "image produced with recipe fors_resample. Please refer to the FORS\n"
00045 "Pipeline User's Manual for more details on object detection.\n"
00046 "\n"
00047 "In the table below the MXU acronym can be alternatively read as MOS and\n"
00048 "LSS, and SCI as STD.\n\n"
00049 "Input files:\n\n"
00050 " DO category: Type: Explanation: Required:\n"
00051 " MAPPED_SCI_MXU Calib Resampled slit spectra Y\n"
00052 " SLIT_LOCATION_MXU Calib Slit location on image Y\n"
00053 "Output files:\n\n"
00054 " DO category: Data type: Explanation:\n"
00055 " OBJECT_TABLE_SCI_MXU FITS table Object positions in slit spectra\n\n";
00056
00057 #define fors_detect_objects_exit(message) \
00058 { \
00059 if (message) cpl_msg_error(recipe, message); \
00060 cpl_image_delete(dummy); \
00061 cpl_image_delete(mapped); \
00062 cpl_table_delete(slits); \
00063 cpl_propertylist_delete(header); \
00064 cpl_msg_indent_less(); \
00065 return -1; \
00066 }
00067
00068 #define fors_detect_objects_exit_memcheck(message) \
00069 { \
00070 if (message) cpl_msg_info(recipe, message); \
00071 printf("free dummy (%p)\n", dummy); \
00072 cpl_image_delete(dummy); \
00073 printf("free mapped (%p)\n", mapped); \
00074 cpl_image_delete(mapped); \
00075 printf("free slits (%p)\n", slits); \
00076 cpl_table_delete(slits); \
00077 printf("free header (%p)\n", header); \
00078 cpl_propertylist_delete(header); \
00079 cpl_msg_indent_less(); \
00080 return 0; \
00081 }
00082
00083
00095 int cpl_plugin_get_info(cpl_pluginlist *list)
00096 {
00097 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
00098 cpl_plugin *plugin = &recipe->interface;
00099
00100 cpl_plugin_init(plugin,
00101 CPL_PLUGIN_API,
00102 FORS_BINARY_VERSION,
00103 CPL_PLUGIN_TYPE_RECIPE,
00104 "fors_detect_objects",
00105 "Detect objects in slit spectra",
00106 fors_detect_objects_description,
00107 "Carlo Izzo",
00108 PACKAGE_BUGREPORT,
00109 "This file is currently part of the FORS Instrument Pipeline\n"
00110 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
00111 "This program is free software; you can redistribute it and/or modify\n"
00112 "it under the terms of the GNU General Public License as published by\n"
00113 "the Free Software Foundation; either version 2 of the License, or\n"
00114 "(at your option) any later version.\n\n"
00115 "This program is distributed in the hope that it will be useful,\n"
00116 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00117 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00118 "GNU General Public License for more details.\n\n"
00119 "You should have received a copy of the GNU General Public License\n"
00120 "along with this program; if not, write to the Free Software Foundation,\n"
00121 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
00122 fors_detect_objects_create,
00123 fors_detect_objects_exec,
00124 fors_detect_objects_destroy);
00125
00126 cpl_pluginlist_append(list, plugin);
00127
00128 return 0;
00129 }
00130
00131
00142 static int fors_detect_objects_create(cpl_plugin *plugin)
00143 {
00144 cpl_recipe *recipe;
00145 cpl_parameter *p;
00146
00147
00148
00149
00150
00151 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00152 recipe = (cpl_recipe *)plugin;
00153 else
00154 return -1;
00155
00156
00157
00158
00159
00160 recipe->parameters = cpl_parameterlist_new();
00161
00162
00163
00164
00165
00166 p = cpl_parameter_new_value("fors.fors_detect_objects.slit_margin",
00167 CPL_TYPE_INT,
00168 "Number of pixels to exclude at each slit "
00169 "in object detection and extraction",
00170 "fors.fors_detect_objects",
00171 3);
00172 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "slit_margin");
00173 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00174 cpl_parameterlist_append(recipe->parameters, p);
00175
00176
00177
00178
00179
00180 p = cpl_parameter_new_value("fors.fors_detect_objects.ext_radius",
00181 CPL_TYPE_INT,
00182 "Maximum extraction radius for detected "
00183 "objects (pixel)",
00184 "fors.fors_detect_objects",
00185 6);
00186 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ext_radius");
00187 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00188 cpl_parameterlist_append(recipe->parameters, p);
00189
00190
00191
00192
00193
00194 p = cpl_parameter_new_value("fors.fors_detect_objects.cont_radius",
00195 CPL_TYPE_INT,
00196 "Minimum distance at which two objects "
00197 "of equal luminosity do not contaminate "
00198 "each other (pixel)",
00199 "fors.fors_detect_objects",
00200 0);
00201 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cont_radius");
00202 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00203 cpl_parameterlist_append(recipe->parameters, p);
00204
00205 return 0;
00206 }
00207
00208
00217 static int fors_detect_objects_exec(cpl_plugin *plugin)
00218 {
00219 cpl_recipe *recipe;
00220
00221 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00222 recipe = (cpl_recipe *)plugin;
00223 else
00224 return -1;
00225
00226 return fors_detect_objects(recipe->parameters, recipe->frames);
00227 }
00228
00229
00238 static int fors_detect_objects_destroy(cpl_plugin *plugin)
00239 {
00240 cpl_recipe *recipe;
00241
00242 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00243 recipe = (cpl_recipe *)plugin;
00244 else
00245 return -1;
00246
00247 cpl_parameterlist_delete(recipe->parameters);
00248
00249 return 0;
00250 }
00251
00252
00262 static int fors_detect_objects(cpl_parameterlist *parlist,
00263 cpl_frameset *frameset)
00264 {
00265
00266 const char *recipe = "fors_detect_objects";
00267
00268
00269
00270
00271
00272
00273 int slit_margin;
00274 int ext_radius;
00275 int cont_radius;
00276
00277
00278
00279
00280
00281 cpl_image *mapped = NULL;
00282 cpl_image *dummy = NULL;
00283 cpl_table *slits = NULL;
00284 cpl_propertylist *header = NULL;
00285
00286
00287
00288
00289
00290 char version[80];
00291 const char *slit_location_tag;
00292 const char *input_tag;
00293 const char *outpt_tag;
00294 int nframes;
00295 double gain;
00296 int scimxu;
00297 int scimos;
00298 int scilss;
00299 int stdmxu;
00300 int stdmos;
00301 int stdlss;
00302
00303 char *instrume = NULL;
00304
00305
00306 cpl_msg_set_indentation(2);
00307
00308 if (dfs_files_dont_exist(frameset))
00309 fors_detect_objects_exit(NULL);
00310
00311
00312
00313
00314
00315
00316 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00317 cpl_msg_indent_more();
00318
00319 slit_margin = dfs_get_parameter_int(parlist,
00320 "fors.fors_detect_objects.slit_margin",
00321 NULL);
00322 if (slit_margin < 0)
00323 fors_detect_objects_exit("Value must be zero or positive");
00324
00325 ext_radius = dfs_get_parameter_int(parlist,
00326 "fors.fors_detect_objects.ext_radius",
00327 NULL);
00328 if (ext_radius < 0)
00329 fors_detect_objects_exit("Value must be zero or positive");
00330
00331 cont_radius = dfs_get_parameter_int(parlist,
00332 "fors.fors_detect_objects.cont_radius",
00333 NULL);
00334 if (cont_radius < 0)
00335 fors_detect_objects_exit("Value must be zero or positive");
00336
00337 if (cpl_error_get_code())
00338 fors_detect_objects_exit("Failure reading configuration parameters");
00339
00340
00341 cpl_msg_indent_less();
00342 cpl_msg_info(recipe, "Check input set-of-frames:");
00343 cpl_msg_indent_more();
00344
00345 nframes = scimxu = cpl_frameset_count_tags(frameset, "MAPPED_SCI_MXU");
00346 nframes += scimos = cpl_frameset_count_tags(frameset, "MAPPED_SCI_MOS");
00347 nframes += scilss = cpl_frameset_count_tags(frameset, "MAPPED_SCI_LSS");
00348 nframes += stdmxu = cpl_frameset_count_tags(frameset, "MAPPED_STD_MXU");
00349 nframes += stdmos = cpl_frameset_count_tags(frameset, "MAPPED_STD_MOS");
00350 nframes += stdlss = cpl_frameset_count_tags(frameset, "MAPPED_STD_LSS");
00351
00352 if (nframes == 0) {
00353 fors_detect_objects_exit("Missing input scientific spectra");
00354 }
00355 if (nframes > 1) {
00356 cpl_msg_error(recipe, "Too many input scientific spectra (%d > 1)",
00357 nframes);
00358 fors_detect_objects_exit(NULL);
00359 }
00360
00361 if (scimxu) {
00362 input_tag = "MAPPED_SCI_MXU";
00363 outpt_tag = "OBJECT_TABLE_SCI_MXU";
00364 slit_location_tag = "SLIT_LOCATION_MXU";
00365 }
00366 else if (scimos) {
00367 input_tag = "MAPPED_SCI_MOS";
00368 outpt_tag = "OBJECT_TABLE_SCI_MOS";
00369 slit_location_tag = "SLIT_LOCATION_MOS";
00370 }
00371 else if (scilss) {
00372 input_tag = "MAPPED_SCI_LSS";
00373 outpt_tag = "OBJECT_TABLE_SCI_LSS";
00374 slit_location_tag = "SLIT_LOCATION_LSS";
00375 }
00376 else if (stdmxu) {
00377 input_tag = "MAPPED_STD_MXU";
00378 outpt_tag = "OBJECT_TABLE_SCI_MXU";
00379 slit_location_tag = "SLIT_LOCATION_MXU";
00380 }
00381 else if (stdmos) {
00382 input_tag = "MAPPED_STD_MOS";
00383 outpt_tag = "OBJECT_TABLE_SCI_MOS";
00384 slit_location_tag = "SLIT_LOCATION_MOS";
00385 }
00386 else if (stdlss) {
00387 input_tag = "MAPPED_STD_LSS";
00388 outpt_tag = "OBJECT_TABLE_SCI_LSS";
00389 slit_location_tag = "SLIT_LOCATION_LSS";
00390 }
00391
00392 if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
00393 fors_detect_objects_exit("Input frames are not from the same grism");
00394
00395 if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
00396 fors_detect_objects_exit("Input frames are not from the same filter");
00397
00398 if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
00399 fors_detect_objects_exit("Input frames are not from the same chip");
00400
00401 header = dfs_load_header(frameset, input_tag, 0);
00402 if (header == NULL)
00403 fors_detect_objects_exit("Cannot load scientific frame header");
00404
00405 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00406 if (instrume == NULL)
00407 fors_detect_objects_exit("Missing keyword INSTRUME in reference frame "
00408 "header");
00409
00410 if (instrume[4] == '1')
00411 snprintf(version, 80, "%s/%s", "fors1", VERSION);
00412 if (instrume[4] == '2')
00413 snprintf(version, 80, "%s/%s", "fors2", VERSION);
00414
00415 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
00416
00417 cpl_propertylist_delete(header); header = NULL;
00418
00419 if (cpl_error_get_code() != CPL_ERROR_NONE)
00420 fors_detect_objects_exit("Missing keyword ESO DET OUT1 CONAD in "
00421 "scientific frame header");
00422
00423 cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain);
00424
00425
00426 cpl_msg_indent_less();
00427 cpl_msg_info(recipe, "Load input frames...");
00428 cpl_msg_indent_more();
00429
00430 mapped = dfs_load_image(frameset, input_tag, CPL_TYPE_FLOAT, 0, 0);
00431 if (mapped == NULL)
00432 fors_detect_objects_exit("Cannot load input scientific frame");
00433
00434 slits = dfs_load_table(frameset, slit_location_tag, 1);
00435 if (slits == NULL)
00436 fors_detect_objects_exit("Cannot load slits location table");
00437
00438 cpl_msg_indent_less();
00439 cpl_msg_info(recipe, "Object detection...");
00440 cpl_msg_indent_more();
00441
00442 mos_clean_cosmics(mapped, gain, -1., -1.);
00443 dummy = mos_detect_objects(mapped, slits, slit_margin,
00444 ext_radius, cont_radius);
00445
00446 cpl_image_delete(mapped); mapped = NULL;
00447 cpl_image_delete(dummy); dummy = NULL;
00448
00449 if (dfs_save_table(frameset, slits, outpt_tag, NULL, parlist,
00450 recipe, version))
00451 fors_detect_objects_exit(NULL);
00452
00453 cpl_table_delete(slits); slits = NULL;
00454
00455 return 0;
00456 }