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 ((const char *)message != NULL) 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 ((const char *)message != NULL) 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
00309
00310
00311
00312
00313 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00314 cpl_msg_indent_more();
00315
00316 slit_margin = dfs_get_parameter_int(parlist,
00317 "fors.fors_detect_objects.slit_margin",
00318 NULL);
00319 if (slit_margin < 0)
00320 fors_detect_objects_exit("Value must be zero or positive");
00321
00322 ext_radius = dfs_get_parameter_int(parlist,
00323 "fors.fors_detect_objects.ext_radius",
00324 NULL);
00325 if (ext_radius < 0)
00326 fors_detect_objects_exit("Value must be zero or positive");
00327
00328 cont_radius = dfs_get_parameter_int(parlist,
00329 "fors.fors_detect_objects.cont_radius",
00330 NULL);
00331 if (cont_radius < 0)
00332 fors_detect_objects_exit("Value must be zero or positive");
00333
00334 if (cpl_error_get_code())
00335 fors_detect_objects_exit("Failure reading configuration parameters");
00336
00337
00338 cpl_msg_indent_less();
00339 cpl_msg_info(recipe, "Check input set-of-frames:");
00340 cpl_msg_indent_more();
00341
00342 nframes = scimxu = cpl_frameset_count_tags(frameset, "MAPPED_SCI_MXU");
00343 nframes += scimos = cpl_frameset_count_tags(frameset, "MAPPED_SCI_MOS");
00344 nframes += scilss = cpl_frameset_count_tags(frameset, "MAPPED_SCI_LSS");
00345 nframes += stdmxu = cpl_frameset_count_tags(frameset, "MAPPED_STD_MXU");
00346 nframes += stdmos = cpl_frameset_count_tags(frameset, "MAPPED_STD_MOS");
00347 nframes += stdlss = cpl_frameset_count_tags(frameset, "MAPPED_STD_LSS");
00348
00349 if (nframes == 0) {
00350 fors_detect_objects_exit("Missing input scientific spectra");
00351 }
00352 if (nframes > 1) {
00353 cpl_msg_error(recipe, "Too many input scientific spectra (%d > 1)",
00354 nframes);
00355 fors_detect_objects_exit(NULL);
00356 }
00357
00358 if (scimxu) {
00359 input_tag = "MAPPED_SCI_MXU";
00360 outpt_tag = "OBJECT_TABLE_SCI_MXU";
00361 slit_location_tag = "SLIT_LOCATION_MXU";
00362 }
00363 else if (scimos) {
00364 input_tag = "MAPPED_SCI_MOS";
00365 outpt_tag = "OBJECT_TABLE_SCI_MOS";
00366 slit_location_tag = "SLIT_LOCATION_MOS";
00367 }
00368 else if (scilss) {
00369 input_tag = "MAPPED_SCI_LSS";
00370 outpt_tag = "OBJECT_TABLE_SCI_LSS";
00371 slit_location_tag = "SLIT_LOCATION_LSS";
00372 }
00373 else if (stdmxu) {
00374 input_tag = "MAPPED_STD_MXU";
00375 outpt_tag = "OBJECT_TABLE_SCI_MXU";
00376 slit_location_tag = "SLIT_LOCATION_MXU";
00377 }
00378 else if (stdmos) {
00379 input_tag = "MAPPED_STD_MOS";
00380 outpt_tag = "OBJECT_TABLE_SCI_MOS";
00381 slit_location_tag = "SLIT_LOCATION_MOS";
00382 }
00383 else if (stdlss) {
00384 input_tag = "MAPPED_STD_LSS";
00385 outpt_tag = "OBJECT_TABLE_SCI_LSS";
00386 slit_location_tag = "SLIT_LOCATION_LSS";
00387 }
00388
00389 if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
00390 cpl_msg_warning(cpl_func,"Input frames are not from the same grism");
00391
00392 if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
00393 cpl_msg_warning(cpl_func,"Input frames are not from the same filter");
00394
00395 if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
00396 cpl_msg_warning(cpl_func,"Input frames are not from the same chip");
00397
00398 header = dfs_load_header(frameset, input_tag, 0);
00399 if (header == NULL)
00400 fors_detect_objects_exit("Cannot load scientific frame header");
00401
00402 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00403 if (instrume == NULL)
00404 fors_detect_objects_exit("Missing keyword INSTRUME in reference frame "
00405 "header");
00406
00407 if (instrume[4] == '1')
00408 snprintf(version, 80, "%s/%s", "fors1", VERSION);
00409 if (instrume[4] == '2')
00410 snprintf(version, 80, "%s/%s", "fors2", VERSION);
00411
00412 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
00413
00414 cpl_propertylist_delete(header); header = NULL;
00415
00416 if (cpl_error_get_code() != CPL_ERROR_NONE)
00417 fors_detect_objects_exit("Missing keyword ESO DET OUT1 CONAD in "
00418 "scientific frame header");
00419
00420 cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain);
00421
00422
00423 cpl_msg_indent_less();
00424 cpl_msg_info(recipe, "Load input frames...");
00425 cpl_msg_indent_more();
00426
00427 mapped = dfs_load_image(frameset, input_tag, CPL_TYPE_FLOAT, 0, 0);
00428 if (mapped == NULL)
00429 fors_detect_objects_exit("Cannot load input scientific frame");
00430
00431 slits = dfs_load_table(frameset, slit_location_tag, 1);
00432 if (slits == NULL)
00433 fors_detect_objects_exit("Cannot load slits location table");
00434
00435 cpl_msg_indent_less();
00436 cpl_msg_info(recipe, "Object detection...");
00437 cpl_msg_indent_more();
00438
00439 mos_clean_cosmics(mapped, gain, -1., -1.);
00440 dummy = mos_detect_objects(mapped, slits, slit_margin,
00441 ext_radius, cont_radius);
00442
00443 cpl_image_delete(mapped); mapped = NULL;
00444 cpl_image_delete(dummy); dummy = NULL;
00445
00446 if (dfs_save_table(frameset, slits, outpt_tag, NULL, parlist,
00447 recipe, version))
00448 fors_detect_objects_exit(NULL);
00449
00450 cpl_table_delete(slits); slits = NULL;
00451
00452 return 0;
00453 }