00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028
00029
00030
00031 #include <string.h>
00032 #include <strings.h>
00033 #include <cpl.h>
00034
00035 #include "muse_geometry_z.h"
00036
00037
00071
00074
00075
00076
00077 static const char *muse_geometry_help =
00078 "Processing first works separately on each IFU of the raw input data (in parallel): it trims the raw data and records the overscan statistics, subtracts the bias and converts them from adu to count. Optionally, the dark can be subtracted and the data can be divided by the flat-field. The data of all input mask exposures is then averaged. The averaged image together with the trace mask and wavelength calibration as well as the line catalog are used to detect spots. The detection windows are used to measure the spots on all images of the sequence, the result is saved, with information on the measured PSF, in the spots tables. Then properties of all slices are computed, first separately on each IFU to determine the peak position of the mask for each slice and its angle, subsequently the width and horizontal position. Then, the result of all IFUs is analyzed together to produce a refined horizontal position, applying global shifts to each IFU as needed. The vertical position is then determined using the known slice ordering on the sky; the relative peak positions are put into sequence, taking into account the vertical offsets of the pinholes in the mask. The table is then cleaned up from intermediate debug data. If the --smooth parameter is set to a positive value, it is used to do a sigma-clipped smoothing within each slicer stack, for a more regular appearance of the output table. The table is then saved. As a last optional step, additional raw input data is reduced using the newly geometry to produce an image of the field of view. If these exposures contain smooth features, they can be used as a visual check of the quality of the geometrical calibration.";
00079
00080 static const char *muse_geometry_help_esorex =
00081 "\n\nInput frames for raw frame tag \"MASK\":\n"
00082 "\n Frame tag Type Req #Fr Description"
00083 "\n -------------------- ---- --- --- ------------"
00084 "\n MASK raw Y >=50 The full exposure sequence of raw multi-pinhole mask images"
00085 "\n MASTER_BIAS calib Y 1 Master bias"
00086 "\n MASTER_DARK calib . 1 Master dark"
00087 "\n MASTER_FLAT calib . 1 Master flat"
00088 "\n TRACE_TABLE calib Y 1 Trace table"
00089 "\n WAVECAL_TABLE calib Y 1 Wavelength calibration table"
00090 "\n LINE_CATALOG calib Y 1 List of arc lines"
00091 "\n BADPIX_TABLE calib . 1 Known bad pixels"
00092 "\n MASK_CHECK calib . Some other optional raw frame, ideally a trace mask exposure or something else with smooth features."
00093 "\n\nProduct frames for raw frame tag \"MASK\":\n"
00094 "\n Frame tag Level Description"
00095 "\n -------------------- -------- ------------"
00096 "\n MASK_REDUCED final Reduced pinhole mask images"
00097 "\n MASK_COMBINED final Combined pinhole mask image"
00098 "\n SPOTS_TABLE final Measurements of all detected spots on all input images."
00099 "\n GEOMETRY_UNSMOOTHED final Relative positions of the slices in the field of view (unsmoothed)"
00100 "\n GEOMETRY_TABLE final Relative positions of the slices in the field of view"
00101 "\n GEOMETRY_CUBE final Cube of the field of view to check the geometry calibration. It is restricted to the wavelength range given in the parameters and contains an integrated image (\"white\") over this range."
00102 "\n GEOMETRY_CHECK final Optional field of view image to check the geometry calibration, integrated over the wavelength range given in the parameters.";
00103
00104
00112
00113 static cpl_recipeconfig *
00114 muse_geometry_new_recipeconfig(void)
00115 {
00116 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
00117
00118 cpl_recipeconfig_set_tag(recipeconfig, "MASK", 50, -1);
00119 cpl_recipeconfig_set_input(recipeconfig, "MASK", "MASTER_BIAS", 1, 1);
00120 cpl_recipeconfig_set_input(recipeconfig, "MASK", "MASTER_DARK", -1, 1);
00121 cpl_recipeconfig_set_input(recipeconfig, "MASK", "MASTER_FLAT", -1, 1);
00122 cpl_recipeconfig_set_input(recipeconfig, "MASK", "TRACE_TABLE", 1, 1);
00123 cpl_recipeconfig_set_input(recipeconfig, "MASK", "WAVECAL_TABLE", 1, 1);
00124 cpl_recipeconfig_set_input(recipeconfig, "MASK", "LINE_CATALOG", 1, 1);
00125 cpl_recipeconfig_set_input(recipeconfig, "MASK", "BADPIX_TABLE", -1, 1);
00126 cpl_recipeconfig_set_input(recipeconfig, "MASK", "MASK_CHECK", -1, -1);
00127 cpl_recipeconfig_set_output(recipeconfig, "MASK", "MASK_REDUCED");
00128 cpl_recipeconfig_set_output(recipeconfig, "MASK", "MASK_COMBINED");
00129 cpl_recipeconfig_set_output(recipeconfig, "MASK", "SPOTS_TABLE");
00130 cpl_recipeconfig_set_output(recipeconfig, "MASK", "GEOMETRY_UNSMOOTHED");
00131 cpl_recipeconfig_set_output(recipeconfig, "MASK", "GEOMETRY_TABLE");
00132 cpl_recipeconfig_set_output(recipeconfig, "MASK", "GEOMETRY_CUBE");
00133
00134 return recipeconfig;
00135 }
00136
00137
00147
00148 static cpl_error_code
00149 muse_geometry_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
00150 {
00151 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
00152 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
00153 if (!strcmp(aFrametag, "MASK_REDUCED")) {
00154 } else if (!strcmp(aFrametag, "MASK_COMBINED")) {
00155 } else if (!strcmp(aFrametag, "SPOTS_TABLE")) {
00156 muse_processing_prepare_property(aHeader, "ESO QC GEO EXP[0-9]+ FWHM MEAN",
00157 CPL_TYPE_FLOAT,
00158 "[pix] Average FWHM of all bright spots in exposure k.");
00159 muse_processing_prepare_property(aHeader, "ESO QC GEO EXP[0-9]+ FWHM MEDIAN",
00160 CPL_TYPE_FLOAT,
00161 "[pix] Median FWHM of all bright spots in exposure k.");
00162 muse_processing_prepare_property(aHeader, "ESO QC GEO EXP[0-9]+ FWHM STDEV",
00163 CPL_TYPE_FLOAT,
00164 "[pix] Standard deviation of FWHM of all bright spots in exposure k.");
00165 muse_processing_prepare_property(aHeader, "ESO QC GEO FWHM MEAN",
00166 CPL_TYPE_FLOAT,
00167 "[pix] Average of the average FWHM of all bright spots in all exposures.");
00168 muse_processing_prepare_property(aHeader, "ESO QC GEO FWHM STDEV",
00169 CPL_TYPE_FLOAT,
00170 "[pix] Standard deviation of the average FWHM of all bright spots in all exposures.");
00171 } else if (!strcmp(aFrametag, "GEOMETRY_UNSMOOTHED")) {
00172 } else if (!strcmp(aFrametag, "GEOMETRY_TABLE")) {
00173 muse_processing_prepare_property(aHeader, "ESO QC GEO IFU[0-9]+ ANGLE",
00174 CPL_TYPE_FLOAT,
00175 "[deg] Angle of the mask with respect to the slicer system, computed as median angle of all slices of this IFU for which the measurement could be made.");
00176 muse_processing_prepare_property(aHeader, "ESO QC GEO IFU[0-9]+ WLEN[0-9]+",
00177 CPL_TYPE_FLOAT,
00178 "[Angstrom] Nominal wavelength of arc line l.");
00179 muse_processing_prepare_property(aHeader, "ESO QC GEO IFU[0-9]+ WLEN[0-9]+ FLUX MEAN",
00180 CPL_TYPE_FLOAT,
00181 "Average integrated flux in all spots at reference wavelength l.");
00182 muse_processing_prepare_property(aHeader, "ESO QC GEO IFU[0-9]+ WLEN[0-9]+ FLUX MEDIAN",
00183 CPL_TYPE_FLOAT,
00184 "Median integrated flux in all spots at reference wavelength l.");
00185 muse_processing_prepare_property(aHeader, "ESO QC GEO IFU[0-9]+ WLEN[0-9]+ FLUX STDEV",
00186 CPL_TYPE_FLOAT,
00187 "Standard deviation of integrated flux in all spots at reference wavelength l.");
00188 muse_processing_prepare_property(aHeader, "ESO QC GEO IFU[0-9]+ GAPPOS MEAN",
00189 CPL_TYPE_FLOAT,
00190 "[pix] Average position of the central gap between the 12 slices of IFU m.");
00191 muse_processing_prepare_property(aHeader, "ESO QC GEO MASK ANGLE",
00192 CPL_TYPE_FLOAT,
00193 "[deg] Angle of the mask with respect to the slicer system, computed as median angle of all slices of all IFUs for which the measurement could be made.");
00194 muse_processing_prepare_property(aHeader, "ESO QC GEO GAPPOS MEAN",
00195 CPL_TYPE_FLOAT,
00196 "[pix] Average of all mean central gap positions of all IFUs for which the measurement could be made.");
00197 muse_processing_prepare_property(aHeader, "ESO QC GEO GAPPOS STDEV",
00198 CPL_TYPE_FLOAT,
00199 "[pix] Standard deviation of all mean central gap positions of all IFUs for which the measurement could be made.");
00200 muse_processing_prepare_property(aHeader, "ESO QC GEO SMOOTH NX",
00201 CPL_TYPE_INT,
00202 "Number of slices that were changed with respect to x position by smoothing. Gets set to -1 if smoothing is inactive.");
00203 muse_processing_prepare_property(aHeader, "ESO QC GEO SMOOTH NY",
00204 CPL_TYPE_INT,
00205 "Number of slices that were changed with respect to y position by smoothing. Gets set to -1 if smoothing is inactive.");
00206 muse_processing_prepare_property(aHeader, "ESO QC GEO SMOOTH NANGLE",
00207 CPL_TYPE_INT,
00208 "Number of slices that were changed with respect to angle by smoothing. Gets set to -1 if smoothing is inactive.");
00209 muse_processing_prepare_property(aHeader, "ESO QC GEO SMOOTH NWIDTH",
00210 CPL_TYPE_INT,
00211 "Number of slices that were changed with respect to width by smoothing. Gets set to -1 if smoothing is inactive.");
00212 } else if (!strcmp(aFrametag, "GEOMETRY_CUBE")) {
00213 } else if (!strcmp(aFrametag, "GEOMETRY_CHECK")) {
00214 } else {
00215 cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
00216 return CPL_ERROR_ILLEGAL_INPUT;
00217 }
00218 return CPL_ERROR_NONE;
00219 }
00220
00221
00230
00231 static cpl_frame_level
00232 muse_geometry_get_frame_level(const char *aFrametag)
00233 {
00234 if (!aFrametag) {
00235 return CPL_FRAME_LEVEL_NONE;
00236 }
00237 if (!strcmp(aFrametag, "MASK_REDUCED")) {
00238 return CPL_FRAME_LEVEL_FINAL;
00239 }
00240 if (!strcmp(aFrametag, "MASK_COMBINED")) {
00241 return CPL_FRAME_LEVEL_FINAL;
00242 }
00243 if (!strcmp(aFrametag, "SPOTS_TABLE")) {
00244 return CPL_FRAME_LEVEL_FINAL;
00245 }
00246 if (!strcmp(aFrametag, "GEOMETRY_UNSMOOTHED")) {
00247 return CPL_FRAME_LEVEL_FINAL;
00248 }
00249 if (!strcmp(aFrametag, "GEOMETRY_TABLE")) {
00250 return CPL_FRAME_LEVEL_FINAL;
00251 }
00252 if (!strcmp(aFrametag, "GEOMETRY_CUBE")) {
00253 return CPL_FRAME_LEVEL_FINAL;
00254 }
00255 if (!strcmp(aFrametag, "GEOMETRY_CHECK")) {
00256 return CPL_FRAME_LEVEL_FINAL;
00257 }
00258 return CPL_FRAME_LEVEL_NONE;
00259 }
00260
00261
00270
00271 static muse_frame_mode
00272 muse_geometry_get_frame_mode(const char *aFrametag)
00273 {
00274 if (!aFrametag) {
00275 return MUSE_FRAME_MODE_ALL;
00276 }
00277 if (!strcmp(aFrametag, "MASK_REDUCED")) {
00278 return MUSE_FRAME_MODE_ALL;
00279 }
00280 if (!strcmp(aFrametag, "MASK_COMBINED")) {
00281 return MUSE_FRAME_MODE_MASTER;
00282 }
00283 if (!strcmp(aFrametag, "SPOTS_TABLE")) {
00284 return MUSE_FRAME_MODE_MASTER;
00285 }
00286 if (!strcmp(aFrametag, "GEOMETRY_UNSMOOTHED")) {
00287 return MUSE_FRAME_MODE_MASTER;
00288 }
00289 if (!strcmp(aFrametag, "GEOMETRY_TABLE")) {
00290 return MUSE_FRAME_MODE_MASTER;
00291 }
00292 if (!strcmp(aFrametag, "GEOMETRY_CUBE")) {
00293 return MUSE_FRAME_MODE_MASTER;
00294 }
00295 if (!strcmp(aFrametag, "GEOMETRY_CHECK")) {
00296 return MUSE_FRAME_MODE_ALL;
00297 }
00298 return MUSE_FRAME_MODE_ALL;
00299 }
00300
00301
00311
00312 static int
00313 muse_geometry_create(cpl_plugin *aPlugin)
00314 {
00315
00316 cpl_recipe *recipe;
00317 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
00318 recipe = (cpl_recipe *)aPlugin;
00319 } else {
00320 return -1;
00321 }
00322
00323
00324
00325 muse_processinginfo_register(recipe,
00326 muse_geometry_new_recipeconfig(),
00327 muse_geometry_prepare_header,
00328 muse_geometry_get_frame_level,
00329 muse_geometry_get_frame_mode);
00330
00331
00332
00333 if (muse_cplframework() == MUSE_CPLFRAMEWORK_ESOREX) {
00334 cpl_msg_set_time_on();
00335 }
00336
00337
00338 recipe->parameters = cpl_parameterlist_new();
00339
00340 cpl_parameter *p;
00341
00342
00343 p = cpl_parameter_new_range("muse.muse_geometry.ifu1",
00344 CPL_TYPE_INT,
00345 "First IFU to analyze.",
00346 "muse.muse_geometry",
00347 (int)1,
00348 (int)1,
00349 (int)24);
00350 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ifu1");
00351 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifu1");
00352
00353 cpl_parameterlist_append(recipe->parameters, p);
00354
00355
00356 p = cpl_parameter_new_range("muse.muse_geometry.ifu2",
00357 CPL_TYPE_INT,
00358 "Last IFU to analyze.",
00359 "muse.muse_geometry",
00360 (int)24,
00361 (int)1,
00362 (int)24);
00363 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ifu2");
00364 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifu2");
00365
00366 cpl_parameterlist_append(recipe->parameters, p);
00367
00368
00369 p = cpl_parameter_new_value("muse.muse_geometry.sigma",
00370 CPL_TYPE_DOUBLE,
00371 "Sigma detection level for spot detection, in terms of median deviation above the median.",
00372 "muse.muse_geometry",
00373 (double)2.2);
00374 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "sigma");
00375 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma");
00376
00377 cpl_parameterlist_append(recipe->parameters, p);
00378
00379
00380 p = cpl_parameter_new_enum("muse.muse_geometry.centroid",
00381 CPL_TYPE_STRING,
00382 "Type of centroiding and FWHM determination to use for all spot measurements: simple barycenter method or using a Gaussian fit.",
00383 "muse.muse_geometry",
00384 (const char *)"gaussian",
00385 2,
00386 (const char *)"barycenter",
00387 (const char *)"gaussian");
00388 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "centroid");
00389 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "centroid");
00390
00391 cpl_parameterlist_append(recipe->parameters, p);
00392
00393
00394 p = cpl_parameter_new_value("muse.muse_geometry.smooth",
00395 CPL_TYPE_DOUBLE,
00396 "Use this sigma-level cut for smoothing of the output table within each slicer stack. Set to non-positive value to deactivate smoothing.",
00397 "muse.muse_geometry",
00398 (double)1.5);
00399 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "smooth");
00400 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "smooth");
00401
00402 cpl_parameterlist_append(recipe->parameters, p);
00403
00404
00405 p = cpl_parameter_new_value("muse.muse_geometry.lambdamin",
00406 CPL_TYPE_DOUBLE,
00407 "When passing any MASK_CHECK frames in the input, use this lower wavelength cut before reconstructing the image.",
00408 "muse.muse_geometry",
00409 (double)6800.);
00410 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lambdamin");
00411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lambdamin");
00412
00413 cpl_parameterlist_append(recipe->parameters, p);
00414
00415
00416 p = cpl_parameter_new_value("muse.muse_geometry.lambdamax",
00417 CPL_TYPE_DOUBLE,
00418 "When passing any MASK_CHECK frames in the input, use this upper wavelength cut before reconstructing the image.",
00419 "muse.muse_geometry",
00420 (double)7200.);
00421 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lambdamax");
00422 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lambdamax");
00423
00424 cpl_parameterlist_append(recipe->parameters, p);
00425
00426 return 0;
00427 }
00428
00429
00440
00441 static int
00442 muse_geometry_params_fill(muse_geometry_params_t *aParams, cpl_parameterlist *aParameters)
00443 {
00444 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
00445 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
00446 cpl_parameter *p;
00447
00448 p = cpl_parameterlist_find(aParameters, "muse.muse_geometry.ifu1");
00449 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00450 aParams->ifu1 = cpl_parameter_get_int(p);
00451
00452 p = cpl_parameterlist_find(aParameters, "muse.muse_geometry.ifu2");
00453 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00454 aParams->ifu2 = cpl_parameter_get_int(p);
00455
00456 p = cpl_parameterlist_find(aParameters, "muse.muse_geometry.sigma");
00457 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00458 aParams->sigma = cpl_parameter_get_double(p);
00459
00460 p = cpl_parameterlist_find(aParameters, "muse.muse_geometry.centroid");
00461 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00462 aParams->centroid_s = cpl_parameter_get_string(p);
00463 aParams->centroid =
00464 (!strcasecmp(aParams->centroid_s, "barycenter")) ? MUSE_GEOMETRY_PARAM_CENTROID_BARYCENTER :
00465 (!strcasecmp(aParams->centroid_s, "gaussian")) ? MUSE_GEOMETRY_PARAM_CENTROID_GAUSSIAN :
00466 MUSE_GEOMETRY_PARAM_CENTROID_INVALID_VALUE;
00467 cpl_ensure_code(aParams->centroid != MUSE_GEOMETRY_PARAM_CENTROID_INVALID_VALUE,
00468 CPL_ERROR_ILLEGAL_INPUT);
00469
00470 p = cpl_parameterlist_find(aParameters, "muse.muse_geometry.smooth");
00471 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00472 aParams->smooth = cpl_parameter_get_double(p);
00473
00474 p = cpl_parameterlist_find(aParameters, "muse.muse_geometry.lambdamin");
00475 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00476 aParams->lambdamin = cpl_parameter_get_double(p);
00477
00478 p = cpl_parameterlist_find(aParameters, "muse.muse_geometry.lambdamax");
00479 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00480 aParams->lambdamax = cpl_parameter_get_double(p);
00481
00482 return 0;
00483 }
00484
00485
00492
00493 static int
00494 muse_geometry_exec(cpl_plugin *aPlugin)
00495 {
00496 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
00497 return -1;
00498 }
00499 muse_processing_recipeinfo(aPlugin);
00500 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
00501 cpl_msg_set_threadid_on();
00502
00503 cpl_frameset *usedframes = cpl_frameset_new(),
00504 *outframes = cpl_frameset_new();
00505 muse_geometry_params_t params;
00506 muse_geometry_params_fill(¶ms, recipe->parameters);
00507
00508 cpl_errorstate prestate = cpl_errorstate_get();
00509
00510 muse_processing *proc = muse_processing_new("muse_geometry",
00511 recipe);
00512 int rc = muse_geometry_compute(proc, ¶ms);
00513 cpl_frameset_join(usedframes, proc->usedframes);
00514 cpl_frameset_join(outframes, proc->outframes);
00515 muse_processing_delete(proc);
00516
00517 if (!cpl_errorstate_is_equal(prestate)) {
00518
00519 cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
00520
00521 cpl_msg_set_level(CPL_MSG_INFO);
00522 }
00523
00524 muse_cplframeset_erase_duplicate(usedframes);
00525 muse_cplframeset_erase_duplicate(outframes);
00526
00527
00528
00529
00530
00531 muse_cplframeset_erase_all(recipe->frames);
00532 cpl_frameset_join(recipe->frames, usedframes);
00533 cpl_frameset_join(recipe->frames, outframes);
00534 cpl_frameset_delete(usedframes);
00535 cpl_frameset_delete(outframes);
00536 return rc;
00537 }
00538
00539
00546
00547 static int
00548 muse_geometry_destroy(cpl_plugin *aPlugin)
00549 {
00550
00551 cpl_recipe *recipe;
00552 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
00553 recipe = (cpl_recipe *)aPlugin;
00554 } else {
00555 return -1;
00556 }
00557
00558
00559 cpl_parameterlist_delete(recipe->parameters);
00560 muse_processinginfo_delete(recipe);
00561 return 0;
00562 }
00563
00564
00574
00575 int
00576 cpl_plugin_get_info(cpl_pluginlist *aList)
00577 {
00578 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00579 cpl_plugin *plugin = &recipe->interface;
00580
00581 char *helptext;
00582 if (muse_cplframework() == MUSE_CPLFRAMEWORK_ESOREX) {
00583 helptext = cpl_sprintf("%s%s", muse_geometry_help,
00584 muse_geometry_help_esorex);
00585 } else {
00586 helptext = cpl_sprintf("%s", muse_geometry_help);
00587 }
00588
00589
00590 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
00591 CPL_PLUGIN_TYPE_RECIPE,
00592 "muse_geometry",
00593 "Compute relative location of the slices within the field of view and measure the instrumental PSF on the detectors.",
00594 helptext,
00595 "Peter Weilbacher",
00596 "usd-help@eso.org",
00597 muse_get_license(),
00598 muse_geometry_create,
00599 muse_geometry_exec,
00600 muse_geometry_destroy);
00601 cpl_pluginlist_append(aList, plugin);
00602 cpl_free(helptext);
00603
00604 return 0;
00605 }
00606