35 #include "muse_astrometry_z.h"
56 static const char *muse_astrometry_help =
57 "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.";
59 static const char *muse_astrometry_help_esorex =
60 "\n\nInput frames for raw frame tag \"PIXTABLE_ASTROMETRY\":\n"
61 "\n Frame tag Type Req #Fr Description"
62 "\n -------------------- ---- --- --- ------------"
63 "\n PIXTABLE_ASTROMETRY raw Y Pixel table of an astrometric field"
64 "\n ASTROMETRY_REFERENCE calib Y 1 Reference table of known objects for astrometry"
65 "\n EXTINCT_TABLE calib . 1 Atmospheric extinction table"
66 "\n STD_RESPONSE calib . 1 Response curve as derived from standard star(s)"
67 "\n STD_TELLURIC calib . 1 Telluric absorption as derived from standard star(s)"
68 "\n\nProduct frames for raw frame tag \"PIXTABLE_ASTROMETRY\":\n"
69 "\n Frame tag Level Description"
70 "\n -------------------- -------- ------------"
71 "\n DATACUBE_ASTROMETRY final Reduced astrometry field exposure"
72 "\n ASTROMETRY_WCS final Astrometric solution";
83 static cpl_recipeconfig *
84 muse_astrometry_new_recipeconfig(
void)
86 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
89 tag =
"PIXTABLE_ASTROMETRY";
90 cpl_recipeconfig_set_tag(recipeconfig, tag, 1, -1);
91 cpl_recipeconfig_set_input(recipeconfig, tag,
"ASTROMETRY_REFERENCE", 1, 1);
92 cpl_recipeconfig_set_input(recipeconfig, tag,
"EXTINCT_TABLE", -1, 1);
93 cpl_recipeconfig_set_input(recipeconfig, tag,
"STD_RESPONSE", -1, 1);
94 cpl_recipeconfig_set_input(recipeconfig, tag,
"STD_TELLURIC", -1, 1);
95 cpl_recipeconfig_set_output(recipeconfig, tag,
"DATACUBE_ASTROMETRY");
96 cpl_recipeconfig_set_output(recipeconfig, tag,
"ASTROMETRY_WCS");
112 static cpl_error_code
113 muse_astrometry_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
115 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
116 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
117 if (!strcmp(aFrametag,
"DATACUBE_ASTROMETRY")) {
120 "[pix] Position of source k in x-direction in combined frame");
123 "[pix] Position of source k in y-direction in combined frame");
126 "[arcsec] FWHM of source k in x-direction in combined frame");
129 "[arcsec] FWHM of source k in y-direction in combined frame");
130 }
else if (!strcmp(aFrametag,
"ASTROMETRY_WCS")) {
133 "Number of stars identified for the astrometric solution");
136 "[arcsec] Computed scale in x-direction");
139 "[arcsec] Computed scale in y-direction");
142 "[deg] Computed angle in x-direction");
145 "[deg] Computed angle in y-direction");
148 "[arcsec] Median residuals of astrometric fit in x-direction");
151 "[arcsec] Median residuals of astrometric fit in y-direction");
153 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
154 return CPL_ERROR_ILLEGAL_INPUT;
156 return CPL_ERROR_NONE;
169 static cpl_frame_level
170 muse_astrometry_get_frame_level(
const char *aFrametag)
173 return CPL_FRAME_LEVEL_NONE;
175 if (!strcmp(aFrametag,
"DATACUBE_ASTROMETRY")) {
176 return CPL_FRAME_LEVEL_FINAL;
178 if (!strcmp(aFrametag,
"ASTROMETRY_WCS")) {
179 return CPL_FRAME_LEVEL_FINAL;
181 return CPL_FRAME_LEVEL_NONE;
195 muse_astrometry_get_frame_mode(
const char *aFrametag)
200 if (!strcmp(aFrametag,
"DATACUBE_ASTROMETRY")) {
203 if (!strcmp(aFrametag,
"ASTROMETRY_WCS")) {
221 muse_astrometry_create(cpl_plugin *aPlugin)
225 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
226 recipe = (cpl_recipe *)aPlugin;
234 muse_astrometry_new_recipeconfig(),
235 muse_astrometry_prepare_header,
236 muse_astrometry_get_frame_level,
237 muse_astrometry_get_frame_mode);
242 cpl_msg_set_time_on();
246 recipe->parameters = cpl_parameterlist_new();
251 p = cpl_parameter_new_enum(
"muse.muse_astrometry.centroid",
253 "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.",
254 "muse.muse_astrometry",
255 (
const char *)
"moffat",
257 (
const char *)
"gaussian",
258 (
const char *)
"moffat",
259 (
const char *)
"box");
260 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"centroid");
261 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"centroid");
263 cpl_parameterlist_append(recipe->parameters, p);
266 p = cpl_parameter_new_value(
"muse.muse_astrometry.detsigma",
268 "Source detection sigma level to use.",
269 "muse.muse_astrometry",
271 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"detsigma");
272 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"detsigma");
274 cpl_parameterlist_append(recipe->parameters, p);
277 p = cpl_parameter_new_value(
"muse.muse_astrometry.radius",
279 "Initial radius in pixels for pattern matching identification in the astrometric field.",
280 "muse.muse_astrometry",
282 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"radius");
283 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"radius");
285 cpl_parameterlist_append(recipe->parameters, p);
288 p = cpl_parameter_new_value(
"muse.muse_astrometry.faccuracy",
290 "Factor of initial accuracy relative to mean positional accuracy of the measured positions to use for pattern matching.",
291 "muse.muse_astrometry",
293 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"faccuracy");
294 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"faccuracy");
296 cpl_parameterlist_append(recipe->parameters, p);
299 p = cpl_parameter_new_value(
"muse.muse_astrometry.niter",
301 "Number of iterations of the astrometric fit.",
302 "muse.muse_astrometry",
304 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"niter");
305 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"niter");
307 cpl_parameterlist_append(recipe->parameters, p);
310 p = cpl_parameter_new_value(
"muse.muse_astrometry.rejsigma",
312 "Rejection sigma level of the astrometric fit.",
313 "muse.muse_astrometry",
315 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"rejsigma");
316 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"rejsigma");
318 cpl_parameterlist_append(recipe->parameters, p);
321 p = cpl_parameter_new_value(
"muse.muse_astrometry.rotcenter",
323 "Center of rotation of the instrument, given as two comma-separated floating point values in pixels.",
324 "muse.muse_astrometry",
325 (
const char *)
"-0.01,-1.20");
326 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"rotcenter");
327 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"rotcenter");
329 cpl_parameterlist_append(recipe->parameters, p);
332 p = cpl_parameter_new_value(
"muse.muse_astrometry.lambdamin",
334 "Cut off the data below this wavelength after loading the pixel table(s).",
335 "muse.muse_astrometry",
337 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamin");
338 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamin");
340 cpl_parameterlist_append(recipe->parameters, p);
343 p = cpl_parameter_new_value(
"muse.muse_astrometry.lambdamax",
345 "Cut off the data above this wavelength after loading the pixel table(s).",
346 "muse.muse_astrometry",
348 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamax");
349 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamax");
351 cpl_parameterlist_append(recipe->parameters, p);
354 p = cpl_parameter_new_value(
"muse.muse_astrometry.lambdaref",
356 "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.",
357 "muse.muse_astrometry",
359 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdaref");
360 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdaref");
362 cpl_parameterlist_append(recipe->parameters, p);
365 p = cpl_parameter_new_enum(
"muse.muse_astrometry.darcheck",
367 "Carry out a check of the theoretical DAR correction using source centroiding. If \"correct\" it will also apply an empirical correction.",
368 "muse.muse_astrometry",
369 (
const char *)
"none",
371 (
const char *)
"none",
372 (
const char *)
"check",
373 (
const char *)
"correct");
374 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"darcheck");
375 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"darcheck");
377 cpl_parameterlist_append(recipe->parameters, p);
397 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
398 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
401 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.centroid");
402 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
403 aParams->
centroid_s = cpl_parameter_get_string(p);
405 (!strcasecmp(aParams->
centroid_s,
"gaussian")) ? MUSE_ASTROMETRY_PARAM_CENTROID_GAUSSIAN :
406 (!strcasecmp(aParams->
centroid_s,
"moffat")) ? MUSE_ASTROMETRY_PARAM_CENTROID_MOFFAT :
407 (!strcasecmp(aParams->
centroid_s,
"box")) ? MUSE_ASTROMETRY_PARAM_CENTROID_BOX :
408 MUSE_ASTROMETRY_PARAM_CENTROID_INVALID_VALUE;
409 cpl_ensure_code(aParams->
centroid != MUSE_ASTROMETRY_PARAM_CENTROID_INVALID_VALUE,
410 CPL_ERROR_ILLEGAL_INPUT);
412 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.detsigma");
413 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
414 aParams->
detsigma = cpl_parameter_get_double(p);
416 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.radius");
417 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
418 aParams->
radius = cpl_parameter_get_double(p);
420 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.faccuracy");
421 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
422 aParams->
faccuracy = cpl_parameter_get_double(p);
424 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.niter");
425 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
426 aParams->
niter = cpl_parameter_get_int(p);
428 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.rejsigma");
429 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
430 aParams->
rejsigma = cpl_parameter_get_double(p);
432 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.rotcenter");
433 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
434 aParams->
rotcenter = cpl_parameter_get_string(p);
436 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.lambdamin");
437 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
438 aParams->
lambdamin = cpl_parameter_get_double(p);
440 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.lambdamax");
441 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
442 aParams->
lambdamax = cpl_parameter_get_double(p);
444 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.lambdaref");
445 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
446 aParams->
lambdaref = cpl_parameter_get_double(p);
448 p = cpl_parameterlist_find(aParameters,
"muse.muse_astrometry.darcheck");
449 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
450 aParams->
darcheck_s = cpl_parameter_get_string(p);
452 (!strcasecmp(aParams->
darcheck_s,
"none")) ? MUSE_ASTROMETRY_PARAM_DARCHECK_NONE :
453 (!strcasecmp(aParams->
darcheck_s,
"check")) ? MUSE_ASTROMETRY_PARAM_DARCHECK_CHECK :
454 (!strcasecmp(aParams->
darcheck_s,
"correct")) ? MUSE_ASTROMETRY_PARAM_DARCHECK_CORRECT :
455 MUSE_ASTROMETRY_PARAM_DARCHECK_INVALID_VALUE;
456 cpl_ensure_code(aParams->
darcheck != MUSE_ASTROMETRY_PARAM_DARCHECK_INVALID_VALUE,
457 CPL_ERROR_ILLEGAL_INPUT);
471 muse_astrometry_exec(cpl_plugin *aPlugin)
473 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
476 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
477 cpl_msg_set_threadid_on();
479 cpl_frameset *usedframes = cpl_frameset_new(),
480 *outframes = cpl_frameset_new();
482 muse_astrometry_params_fill(¶ms, recipe->parameters);
484 cpl_errorstate prestate = cpl_errorstate_get();
488 int rc = muse_astrometry_compute(proc, ¶ms);
489 cpl_frameset_join(usedframes, proc->
usedframes);
490 cpl_frameset_join(outframes, proc->
outframes);
493 if (!cpl_errorstate_is_equal(prestate)) {
497 cpl_msg_set_level(CPL_MSG_INFO);
508 cpl_frameset_join(recipe->frames, usedframes);
509 cpl_frameset_join(recipe->frames, outframes);
510 cpl_frameset_delete(usedframes);
511 cpl_frameset_delete(outframes);
524 muse_astrometry_destroy(cpl_plugin *aPlugin)
528 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
529 recipe = (cpl_recipe *)aPlugin;
535 cpl_parameterlist_delete(recipe->parameters);
552 cpl_plugin_get_info(cpl_pluginlist *aList)
554 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
555 cpl_plugin *plugin = &recipe->interface;
559 helptext = cpl_sprintf(
"%s%s", muse_astrometry_help,
560 muse_astrometry_help_esorex);
562 helptext = cpl_sprintf(
"%s", muse_astrometry_help);
566 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
567 CPL_PLUGIN_TYPE_RECIPE,
569 "Compute an astrometric solution.",
574 muse_astrometry_create,
575 muse_astrometry_exec,
576 muse_astrometry_destroy);
577 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.
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).
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.