35 #include "muse_astrometry_z.h" 65 static const char *muse_astrometry_help =
66 "Merge pixel tables from all IFUs, apply correction for differential atmospheric refraction, optionally apply flux calibration and telluric correction (if the necessary input data was given), and resample the data from all exposures into a datacube. Use the cube to detect objects which are then matched to their reference positions from which a two-dimensional WCS solution is computed. The main output is the ASTROMETRY_WCS file which is a bare FITS header containing the world coordinate solution. The secondary product is DATACUBE_ASTROMETRY, it is not needed for further processing but can be used for verification and debugging. It contains the reconstructed cube and two images created from it in further FITS extensions: a white-light image and the special image created from the central planes of the cube used to detect and centroid the stars (as well as its variance).";
68 static const char *muse_astrometry_help_esorex =
69 "\n\nInput frames for raw frame tag \"PIXTABLE_ASTROMETRY\":\n" 70 "\n Frame tag Type Req #Fr Description" 71 "\n -------------------- ---- --- --- ------------" 72 "\n PIXTABLE_ASTROMETRY raw Y Pixel table of an astrometric field" 73 "\n ASTROMETRY_REFERENCE calib Y 1 Reference table of known objects for astrometry" 74 "\n EXTINCT_TABLE calib . 1 Atmospheric extinction table" 75 "\n STD_RESPONSE calib . 1 Response curve as derived from standard star(s)" 76 "\n STD_TELLURIC calib . 1 Telluric absorption as derived from standard star(s)" 77 "\n\nProduct frames for raw frame tag \"PIXTABLE_ASTROMETRY\":\n" 78 "\n Frame tag Level Description" 79 "\n -------------------- -------- ------------" 80 "\n DATACUBE_ASTROMETRY final Reduced astrometry field exposure" 81 "\n ASTROMETRY_WCS final Astrometric solution";
92 static cpl_recipeconfig *
93 muse_astrometry_new_recipeconfig(
void)
95 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
97 cpl_recipeconfig_set_tag(recipeconfig,
"PIXTABLE_ASTROMETRY", 1, -1);
98 cpl_recipeconfig_set_input(recipeconfig,
"PIXTABLE_ASTROMETRY",
"ASTROMETRY_REFERENCE", 1, 1);
99 cpl_recipeconfig_set_input(recipeconfig,
"PIXTABLE_ASTROMETRY",
"EXTINCT_TABLE", -1, 1);
100 cpl_recipeconfig_set_input(recipeconfig,
"PIXTABLE_ASTROMETRY",
"STD_RESPONSE", -1, 1);
101 cpl_recipeconfig_set_input(recipeconfig,
"PIXTABLE_ASTROMETRY",
"STD_TELLURIC", -1, 1);
102 cpl_recipeconfig_set_output(recipeconfig,
"PIXTABLE_ASTROMETRY",
"DATACUBE_ASTROMETRY");
103 cpl_recipeconfig_set_output(recipeconfig,
"PIXTABLE_ASTROMETRY",
"ASTROMETRY_WCS");
119 static cpl_error_code
120 muse_astrometry_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
122 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
123 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
124 if (!strcmp(aFrametag,
"DATACUBE_ASTROMETRY")) {
127 "Number of detected sources in output cube.");
130 "[Angstrom] Wavelength of plane in combined cube that was used for object detection.");
133 "[pix] Position of source k in x-direction in output cube. If the FWHM measurement fails, this value will be -1.");
136 "[pix] Position of source k in y-direction in output cube. If the FWHM measurement fails, this value will be -1.");
139 "[arcsec] FWHM of source k in x-direction in output cube. If the FWHM measurement fails, this value will be -1.");
142 "[arcsec] FWHM of source k in y-direction in output cube. If the FWHM measurement fails, this value will be -1.");
145 "Number of detected sources with valid FWHM in output cube.");
148 "[arcsec] Median FWHM of all sources with valid FWHM measurement (in x- and y-direction) in output cube. If less than three sources with valid FWHM are detected, this value is zero.");
151 "[arcsec] Median absolute deviation of the FWHM of all sources with valid FWHM measurement (in x- and y-direction) in output cube. If less than three sources with valid FWHM are detected, this value is zero.");
152 }
else if (!strcmp(aFrametag,
"ASTROMETRY_WCS")) {
155 "Number of stars identified for the astrometric solution");
158 "[arcsec] Computed scale in x-direction");
161 "[arcsec] Computed scale in y-direction");
164 "[deg] Computed angle in x-direction");
167 "[deg] Computed angle in y-direction");
170 "[arcsec] Median residuals of astrometric fit in x-direction");
173 "[arcsec] Median residuals of astrometric fit in y-direction");
175 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
176 return CPL_ERROR_ILLEGAL_INPUT;
178 return CPL_ERROR_NONE;
191 static cpl_frame_level
192 muse_astrometry_get_frame_level(
const char *aFrametag)
195 return CPL_FRAME_LEVEL_NONE;
197 if (!strcmp(aFrametag,
"DATACUBE_ASTROMETRY")) {
198 return CPL_FRAME_LEVEL_FINAL;
200 if (!strcmp(aFrametag,
"ASTROMETRY_WCS")) {
201 return CPL_FRAME_LEVEL_FINAL;
203 return CPL_FRAME_LEVEL_NONE;
217 muse_astrometry_get_frame_mode(
const char *aFrametag)
222 if (!strcmp(aFrametag,
"DATACUBE_ASTROMETRY")) {
225 if (!strcmp(aFrametag,
"ASTROMETRY_WCS")) {
243 muse_astrometry_create(cpl_plugin *aPlugin)
247 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
248 recipe = (cpl_recipe *)aPlugin;
256 muse_astrometry_new_recipeconfig(),
257 muse_astrometry_prepare_header,
258 muse_astrometry_get_frame_level,
259 muse_astrometry_get_frame_mode);
264 cpl_msg_set_time_on();
268 recipe->parameters = cpl_parameterlist_new();
273 p = cpl_parameter_new_enum(
"muse.muse_astrometry.centroid",
275 "Centroiding method to use for objects in the field of view. \"gaussian\" and \"moffat\" use 2D fits to derive the centroid, \"box\" is a simple centroid in a square box.",
276 "muse.muse_astrometry",
277 (
const char *)
"moffat",
279 (
const char *)
"gaussian",
280 (
const char *)
"moffat",
281 (
const char *)
"box");
282 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"centroid");
283 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"centroid");
285 cpl_parameterlist_append(recipe->parameters, p);
288 p = cpl_parameter_new_value(
"muse.muse_astrometry.detsigma",
290 "Source detection sigma level to use. If this is negative, values between its absolute and 1.0 are tested with a stepsize of 0.1, to find an optimal solution.",
291 "muse.muse_astrometry",
293 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"detsigma");
294 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"detsigma");
296 cpl_parameterlist_append(recipe->parameters, p);
299 p = cpl_parameter_new_value(
"muse.muse_astrometry.radius",
301 "Initial radius in pixels for pattern matching identification in the astrometric field.",
302 "muse.muse_astrometry",
304 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"radius");
305 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"radius");
307 cpl_parameterlist_append(recipe->parameters, p);
310 p = cpl_parameter_new_value(
"muse.muse_astrometry.faccuracy",
312 "Factor of initial accuracy relative to mean positional accuracy of the measured positions to use for pattern matching.",
313 "muse.muse_astrometry",
315 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"faccuracy");
316 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"faccuracy");
318 cpl_parameterlist_append(recipe->parameters, p);
321 p = cpl_parameter_new_value(
"muse.muse_astrometry.niter",
323 "Number of iterations of the astrometric fit.",
324 "muse.muse_astrometry",
326 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"niter");
327 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"niter");
329 cpl_parameterlist_append(recipe->parameters, p);
332 p = cpl_parameter_new_value(
"muse.muse_astrometry.rejsigma",
334 "Rejection sigma level of the astrometric fit.",
335 "muse.muse_astrometry",
337 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"rejsigma");
338 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"rejsigma");
340 cpl_parameterlist_append(recipe->parameters, p);
343 p = cpl_parameter_new_value(
"muse.muse_astrometry.rotcenter",
345 "Center of rotation of the instrument, given as two comma-separated floating point values in pixels.",
346 "muse.muse_astrometry",
347 (
const char *)
"-0.01,-1.20");
348 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"rotcenter");
349 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"rotcenter");
351 cpl_parameterlist_append(recipe->parameters, p);
354 p = cpl_parameter_new_value(
"muse.muse_astrometry.lambdamin",
356 "Cut off the data below this wavelength after loading the pixel table(s).",
357 "muse.muse_astrometry",
359 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamin");
360 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamin");
362 cpl_parameterlist_append(recipe->parameters, p);
365 p = cpl_parameter_new_value(
"muse.muse_astrometry.lambdamax",
367 "Cut off the data above this wavelength after loading the pixel table(s).",
368 "muse.muse_astrometry",
370 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamax");
371 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamax");
373 cpl_parameterlist_append(recipe->parameters, p);
376 p = cpl_parameter_new_value(
"muse.muse_astrometry.lambdaref",
378 "Reference wavelength used for correction of differential atmospheric refraction. The R-band (peak wavelength ~7000 Angstrom) that is usually used for guiding, is close to the central wavelength of MUSE, so a value of 7000.0 Angstrom should be used if nothing else is known. A value less than zero switches DAR correction off.",
379 "muse.muse_astrometry",
381 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdaref");
382 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdaref");
384 cpl_parameterlist_append(recipe->parameters, p);
387 p = cpl_parameter_new_enum(
"muse.muse_astrometry.darcheck",
389 "Carry out a check of the theoretical DAR correction using source centroiding. If \"correct\" it will also apply an empirical correction.",
390 "muse.muse_astrometry",
391 (
const char *)
"none",
393 (
const char *)
"none",
394 (
const char *)
"check",
395 (
const char *)
"correct");
396 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"darcheck");
397 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"darcheck");
399 cpl_parameterlist_append(recipe->parameters, p);
419 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
420 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
423 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.centroid");
424 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
425 aParams->
centroid_s = cpl_parameter_get_string(p);
427 (!strcasecmp(aParams->
centroid_s,
"gaussian")) ? MUSE_ASTROMETRY_PARAM_CENTROID_GAUSSIAN :
428 (!strcasecmp(aParams->
centroid_s,
"moffat")) ? MUSE_ASTROMETRY_PARAM_CENTROID_MOFFAT :
429 (!strcasecmp(aParams->
centroid_s,
"box")) ? MUSE_ASTROMETRY_PARAM_CENTROID_BOX :
430 MUSE_ASTROMETRY_PARAM_CENTROID_INVALID_VALUE;
431 cpl_ensure_code(aParams->
centroid != MUSE_ASTROMETRY_PARAM_CENTROID_INVALID_VALUE,
432 CPL_ERROR_ILLEGAL_INPUT);
434 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.detsigma");
435 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
436 aParams->
detsigma = cpl_parameter_get_double(p);
438 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.radius");
439 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
440 aParams->
radius = cpl_parameter_get_double(p);
442 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.faccuracy");
443 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
444 aParams->
faccuracy = cpl_parameter_get_double(p);
446 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.niter");
447 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
448 aParams->
niter = cpl_parameter_get_int(p);
450 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.rejsigma");
451 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
452 aParams->
rejsigma = cpl_parameter_get_double(p);
454 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.rotcenter");
455 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
456 aParams->
rotcenter = cpl_parameter_get_string(p);
458 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.lambdamin");
459 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
460 aParams->
lambdamin = cpl_parameter_get_double(p);
462 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.lambdamax");
463 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
464 aParams->
lambdamax = cpl_parameter_get_double(p);
466 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.lambdaref");
467 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
468 aParams->
lambdaref = cpl_parameter_get_double(p);
470 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.darcheck");
471 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
472 aParams->
darcheck_s = cpl_parameter_get_string(p);
474 (!strcasecmp(aParams->
darcheck_s,
"none")) ? MUSE_ASTROMETRY_PARAM_DARCHECK_NONE :
475 (!strcasecmp(aParams->
darcheck_s,
"check")) ? MUSE_ASTROMETRY_PARAM_DARCHECK_CHECK :
476 (!strcasecmp(aParams->
darcheck_s,
"correct")) ? MUSE_ASTROMETRY_PARAM_DARCHECK_CORRECT :
477 MUSE_ASTROMETRY_PARAM_DARCHECK_INVALID_VALUE;
478 cpl_ensure_code(aParams->
darcheck != MUSE_ASTROMETRY_PARAM_DARCHECK_INVALID_VALUE,
479 CPL_ERROR_ILLEGAL_INPUT);
493 muse_astrometry_exec(cpl_plugin *aPlugin)
495 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
499 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
500 cpl_msg_set_threadid_on();
502 cpl_frameset *usedframes = cpl_frameset_new(),
503 *outframes = cpl_frameset_new();
505 muse_astrometry_params_fill(¶ms, recipe->parameters);
507 cpl_errorstate prestate = cpl_errorstate_get();
511 int rc = muse_astrometry_compute(proc, ¶ms);
512 cpl_frameset_join(usedframes, proc->
usedframes);
513 cpl_frameset_join(outframes, proc->
outframes);
516 if (!cpl_errorstate_is_equal(prestate)) {
520 cpl_msg_set_level(CPL_MSG_INFO);
531 cpl_frameset_join(recipe->frames, usedframes);
532 cpl_frameset_join(recipe->frames, outframes);
533 cpl_frameset_delete(usedframes);
534 cpl_frameset_delete(outframes);
547 muse_astrometry_destroy(cpl_plugin *aPlugin)
551 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
552 recipe = (cpl_recipe *)aPlugin;
558 cpl_parameterlist_delete(recipe->parameters);
575 cpl_plugin_get_info(cpl_pluginlist *aList)
577 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
578 cpl_plugin *plugin = &recipe->interface;
582 helptext = cpl_sprintf(
"%s%s", muse_astrometry_help,
583 muse_astrometry_help_esorex);
585 helptext = cpl_sprintf(
"%s", muse_astrometry_help);
589 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
590 CPL_PLUGIN_TYPE_RECIPE,
592 "Compute an astrometric solution.",
597 muse_astrometry_create,
598 muse_astrometry_exec,
599 muse_astrometry_destroy);
600 cpl_pluginlist_append(aList, plugin);
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
double rejsigma
Rejection sigma level of the astrometric fit.
double lambdaref
Reference wavelength used for correction of differential atmospheric refraction. The R-band (peak wav...
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
cpl_frameset * usedframes
muse_processing * muse_processing_new(const char *aName, cpl_recipe *aRecipe)
Create a new processing structure.
const char * muse_get_license(void)
Get the pipeline copyright and license.
double radius
Initial radius in pixels for pattern matching identification in the astrometric field.
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
int centroid
Centroiding method to use for objects in the field of view. "gaussian" and "moffat" use 2D fits to de...
void muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
Dump some CPL errors.
void muse_processinginfo_delete(cpl_recipe *)
Clear all information from the processing info and from the recipe config.
const char * centroid_s
Centroiding method to use for objects in the field of view. "gaussian" and "moffat" use 2D fits to de...
int niter
Number of iterations of the astrometric fit.
const char * darcheck_s
Carry out a check of the theoretical DAR correction using source centroiding. If "correct" it will al...
double detsigma
Source detection sigma level to use. If this is negative, values between its absolute and 1...
cpl_error_code muse_cplframeset_erase_duplicate(cpl_frameset *aFrames)
Erase all duplicate frames from a frameset.
cpl_error_code muse_cplframeset_erase_all(cpl_frameset *aFrames)
Erase all frames in a frameset.
const char * rotcenter
Center of rotation of the instrument, given as two comma-separated floating point values in pixels...
Structure to hold the parameters of the muse_astrometry recipe.
void muse_processinginfo_register(cpl_recipe *, cpl_recipeconfig *, muse_processing_prepare_header_func *, muse_processing_get_frame_level_func *, muse_processing_get_frame_mode_func *)
Register extended functionalities for MUSE recipes.
double lambdamax
Cut off the data above this wavelength after loading the pixel table(s).
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.
double faccuracy
Factor of initial accuracy relative to mean positional accuracy of the measured positions to use for ...
int darcheck
Carry out a check of the theoretical DAR correction using source centroiding. If "correct" it will al...
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.