FORS Pipeline Reference Manual  4.12.5
fors_normalise_flat.c
1 /* $Id: fors_normalise_flat.c,v 1.10 2013/09/09 12:24:55 cgarcia Exp $
2  *
3  * This file is part of the FORS Data Reduction Pipeline
4  * Copyright (C) 2002-2010 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22  * $Author: cgarcia $
23  * $Date: 2013/09/09 12:24:55 $
24  * $Revision: 1.10 $
25  * $Name: $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include <math.h>
33 #include <cpl.h>
34 #include <moses.h>
35 #include <fors_dfs.h>
36 #include <fors_flat_normalise.h>
37 
38 static int fors_normalise_flat_create(cpl_plugin *);
39 static int fors_normalise_flat_exec(cpl_plugin *);
40 static int fors_normalise_flat_destroy(cpl_plugin *);
41 static int fors_normalise_flat(cpl_parameterlist *, cpl_frameset *);
42 
43 static char fors_normalise_flat_description[] =
44 "This recipe is used to normalise a master flat field frame dividing it\n"
45 "by its large scale illumination trend. This recipe can be applied both\n"
46 "to generic multi-slit (MOS/MXU) and to long slit exposures (either LSS, or\n"
47 "LSS-like MOS/MXU), even if different normalisation methods are applied in\n"
48 "such different cases. The input master flat field image is the product\n"
49 "of the recipe fors_flat. The input spectral curvature table, product of\n"
50 "the recipe fors_detect_spectra, is only required in the case of multi-slit\n"
51 "data.\n"
52 "\n"
53 "In the case of multi-slit data, the flat field spectra are spatially\n"
54 "rectified, heavily smoothed, and then mapped back on the CCD. Then the\n"
55 "master flat image is divided by its smoothed counterpart. The smoothing\n"
56 "may be obtained either by applying a running median filter of specified\n"
57 "sizes, or by polynomial fitting along the dispersion direction performed\n"
58 "independently for each row of the spatially remapped spectra.\n"
59 "\n"
60 "In the case of long-slit data, the smoothing can still be obtained either\n"
61 "by applying a running median filter or by polynomial fitting, but the\n"
62 "polynomial fitting will be performed along the spatial direction, for\n"
63 "each column of the spectrum.\n"
64 "\n"
65 "In the table below the MXU acronym can be alternatively read as MOS or\n"
66 "LSS.\n\n"
67 "Input files:\n\n"
68 " DO category: Type: Explanation: Required:\n"
69 " MASTER_SCREEN_FLAT_MXU Calib Master flat frame Y\n"
70 " CURV_COEFF_MXU Calib Spectral curvature .\n"
71 " SLIT_LOCATION_MXU Calib Spectral curvature .\n"
72 " GRISM_TABLE Calib Grism table .\n\n"
73 "Output files:\n\n"
74 " DO category: Data type: Explanation:\n"
75 " MASTER_NORM_FLAT_MXU FITS image Normalised flat field\n\n";
76 
77 #define fors_normalise_flat_exit(message) \
78 { \
79 if (message) cpl_msg_error(recipe, message); \
80 cpl_image_delete(master_flat); \
81 cpl_image_delete(spatial); \
82 cpl_image_delete(coordinate); \
83 cpl_image_delete(smo_flat); \
84 cpl_table_delete(grism_table); \
85 cpl_table_delete(maskslits); \
86 cpl_table_delete(slits); \
87 cpl_table_delete(polytraces); \
88 cpl_propertylist_delete(header); \
89 cpl_msg_indent_less(); \
90 return -1; \
91 }
92 
93 #define fors_normalise_flat_exit_memcheck(message) \
94 { \
95 if (message) cpl_msg_info(recipe, message); \
96 printf("free master_flat (%p)\n", master_flat); \
97 cpl_image_delete(master_flat); \
98 printf("free spatial (%p)\n", spatial); \
99 cpl_image_delete(spatial); \
100 printf("free coordinate (%p)\n", coordinate); \
101 cpl_image_delete(coordinate); \
102 printf("free smo_flat (%p)\n", smo_flat); \
103 cpl_image_delete(smo_flat); \
104 printf("free grism_table (%p)\n", grism_table); \
105 cpl_table_delete(grism_table); \
106 printf("free maskslits (%p)\n", maskslits); \
107 cpl_table_delete(maskslits); \
108 printf("free slits (%p)\n", slits); \
109 cpl_table_delete(slits); \
110 printf("free polytraces (%p)\n", polytraces); \
111 cpl_table_delete(polytraces); \
112 printf("free header (%p)\n", header); \
113 cpl_propertylist_delete(header); \
114 cpl_msg_indent_less(); \
115 return 0; \
116 }
117 
118 
130 int cpl_plugin_get_info(cpl_pluginlist *list)
131 {
132  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
133  cpl_plugin *plugin = &recipe->interface;
134 
135  cpl_plugin_init(plugin,
136  CPL_PLUGIN_API,
137  FORS_BINARY_VERSION,
138  CPL_PLUGIN_TYPE_RECIPE,
139  "fors_normalise_flat",
140  "Normalise master flat spectrum",
141  fors_normalise_flat_description,
142  "Carlo Izzo",
143  PACKAGE_BUGREPORT,
144  "This file is currently part of the FORS Instrument Pipeline\n"
145  "Copyright (C) 2002-2010 European Southern Observatory\n\n"
146  "This program is free software; you can redistribute it and/or modify\n"
147  "it under the terms of the GNU General Public License as published by\n"
148  "the Free Software Foundation; either version 2 of the License, or\n"
149  "(at your option) any later version.\n\n"
150  "This program is distributed in the hope that it will be useful,\n"
151  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
152  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
153  "GNU General Public License for more details.\n\n"
154  "You should have received a copy of the GNU General Public License\n"
155  "along with this program; if not, write to the Free Software Foundation,\n"
156  "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
157  fors_normalise_flat_create,
158  fors_normalise_flat_exec,
159  fors_normalise_flat_destroy);
160 
161  cpl_pluginlist_append(list, plugin);
162 
163  return 0;
164 }
165 
166 
177 static int fors_normalise_flat_create(cpl_plugin *plugin)
178 {
179  cpl_recipe *recipe;
180  cpl_parameter *p;
181 
182  /*
183  * Check that the plugin is part of a valid recipe
184  */
185 
186  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
187  recipe = (cpl_recipe *)plugin;
188  else
189  return -1;
190 
191  /*
192  * Create the (empty) parameters list in the cpl_recipe object
193  */
194 
195  recipe->parameters = cpl_parameterlist_new();
196 
197  /*
198  * Dispersion
199  */
200 
201  p = cpl_parameter_new_value("fors.fors_normalise_flat.dispersion",
202  CPL_TYPE_DOUBLE,
203  "Expected spectral dispersion (Angstrom/pixel)",
204  "fors.fors_normalise_flat",
205  0.0);
206  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
207  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
208  cpl_parameterlist_append(recipe->parameters, p);
209 
210  /*
211  * Start wavelength for spectral extraction
212  */
213 
214  p = cpl_parameter_new_value("fors.fors_normalise_flat.startwavelength",
215  CPL_TYPE_DOUBLE,
216  "Start wavelength in spectral extraction",
217  "fors.fors_normalise_flat",
218  0.0);
219  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
220  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
221  cpl_parameterlist_append(recipe->parameters, p);
222 
223  /*
224  * End wavelength for spectral extraction
225  */
226 
227  p = cpl_parameter_new_value("fors.fors_normalise_flat.endwavelength",
228  CPL_TYPE_DOUBLE,
229  "End wavelength in spectral extraction",
230  "fors.fors_normalise_flat",
231  0.0);
232  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
233  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
234  cpl_parameterlist_append(recipe->parameters, p);
235 
236  /*
237  * Number of knots in flat field fitting splines along spatial direction
238  */
239 
240  p = cpl_parameter_new_value("fors.fors_normalise_flat.spa_polydegree",
241  CPL_TYPE_INT,
242  "Polynomial degree for the flat field fitting "
243  "along spatial direction",
244  "fors.fors_normalise_flat",
245  -1);
246  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "spa_polydegree");
247  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
248  cpl_parameterlist_append(recipe->parameters, p);
249 
250  /*
251  * Smooth box radius for flat field along spatial direction
252  * (if spa_knots < 0)
253  */
254 
255  p = cpl_parameter_new_value("fors.fors_normalise_flat.sradius",
256  CPL_TYPE_INT,
257  "Smooth box radius for flat field along "
258  "spatial direction (used if spa_knots < 0)",
259  "fors.fors_normalise_flat",
260  10);
261  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sradius");
262  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
263  cpl_parameterlist_append(recipe->parameters, p);
264 
265  /*
266  * Number of knots in flat field fitting splines along dispersion direction
267  */
268 
269  p = cpl_parameter_new_value("fors.fors_normalise_flat.disp_nknots",
270  CPL_TYPE_INT,
271  "Number of knots in flat field fitting "
272  "splines along dispersion direction",
273  "fors.fors_normalise_flat",
274  -1);
275  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "disp_nknots");
276  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
277  cpl_parameterlist_append(recipe->parameters, p);
278 
279  /*
280  * Smooth box radius for flat field along dispersion direction
281  */
282 
283  p = cpl_parameter_new_value("fors.fors_normalise_flat.dradius",
284  CPL_TYPE_INT,
285  "Smooth box radius for flat field along "
286  "dispersion direction (if disp_knots < 0)",
287  "fors.fors_normalise_flat",
288  10);
289  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dradius");
290  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
291  cpl_parameterlist_append(recipe->parameters, p);
292 
293  /*
294  * Threshold percentage for flat spline fitting with respect to the maximum
295  */
296 
297  p = cpl_parameter_new_value("fors.fors_normalise_flat.splfit_threshold",
298  CPL_TYPE_DOUBLE,
299  "Threshold percentage for flat spline fitting"
300  "with respect to the maximum",
301  "fors.fors_normalise_flat",
302  0.01);
303  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "splfit_threshold");
304  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
305  cpl_parameterlist_append(recipe->parameters, p);
306 
307  return 0;
308 }
309 
310 
319 static int fors_normalise_flat_exec(cpl_plugin *plugin)
320 {
321  cpl_recipe *recipe;
322 
323  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
324  recipe = (cpl_recipe *)plugin;
325  else
326  return -1;
327 
328  /* Issue a banner */
330 
331  return fors_normalise_flat(recipe->parameters, recipe->frames);
332 }
333 
334 
343 static int fors_normalise_flat_destroy(cpl_plugin *plugin)
344 {
345  cpl_recipe *recipe;
346 
347  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
348  recipe = (cpl_recipe *)plugin;
349  else
350  return -1;
351 
352  cpl_parameterlist_delete(recipe->parameters);
353 
354  return 0;
355 }
356 
357 
367 static int fors_normalise_flat(cpl_parameterlist *parlist,
368  cpl_frameset *frameset)
369 {
370 
371  const char *recipe = "fors_normalise_flat";
372 
373 
374  /*
375  * Input parameters
376  */
377 
378  double dispersion;
379  double startwavelength;
380  double endwavelength;
381  int spa_polyorder;
382  int disp_nknots;
383  int sradius;
384  int dradius;
385  float splfit_threshold;
386 
387  /*
388  * CPL objects
389  */
390 
391  cpl_image *master_flat = NULL;
392  cpl_image *smo_flat = NULL;
393  cpl_image *coordinate = NULL;
394  cpl_image *spatial = NULL;
395  cpl_table *grism_table = NULL;
396  cpl_table *slits = NULL;
397  cpl_table *polytraces = NULL;
398  cpl_table *maskslits = NULL;
399  cpl_propertylist *header = NULL;
400 
401  /*
402  * Auxiliary variables
403  */
404 
405  char version[80];
406  const char *master_flat_tag;
407  const char *master_norm_flat_tag;
408  const char *slit_location_tag;
409  const char *curv_coeff_tag;
410  int mxu, mos, lss;
411  int nflat;
412  int rebin;
413  int nx, ny;
414  int treat_as_lss;
415  double reference;
416  double mxpos;
417 
418  char *instrume = NULL;
419 
420 
421  cpl_msg_set_indentation(2);
422 
423 
424  /*
425  * Get configuration parameters
426  */
427 
428  cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
429  cpl_msg_indent_more();
430 
431  if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
432  fors_normalise_flat_exit("Too many in input: GRISM_TABLE");
433 
434  grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
435 
436  dispersion = dfs_get_parameter_double(parlist,
437  "fors.fors_normalise_flat.dispersion", grism_table);
438 
439  if (dispersion <= 0.0)
440  fors_normalise_flat_exit("Invalid spectral dispersion value");
441 
442  startwavelength = dfs_get_parameter_double(parlist,
443  "fors.fors_normalise_flat.startwavelength", grism_table);
444  if (startwavelength > 1.0)
445  if (startwavelength < 3000.0 || startwavelength > 13000.0)
446  fors_normalise_flat_exit("Invalid wavelength");
447 
448  endwavelength = dfs_get_parameter_double(parlist,
449  "fors.fors_normalise_flat.endwavelength", grism_table);
450  if (endwavelength > 1.0) {
451  if (endwavelength < 3000.0 || endwavelength > 13000.0)
452  fors_normalise_flat_exit("Invalid wavelength");
453  if (startwavelength < 1.0)
454  fors_normalise_flat_exit("Invalid wavelength interval");
455  }
456 
457  if (startwavelength > 1.0)
458  if (endwavelength - startwavelength <= 0.0)
459  fors_normalise_flat_exit("Invalid wavelength interval");
460 
461  spa_polyorder = dfs_get_parameter_int(parlist,
462  "fors.fors_normalise_flat.spa_polydegree", NULL);
463  disp_nknots = dfs_get_parameter_int(parlist,
464  "fors.fors_normalise_flat.disp_nknots", NULL);
465  sradius = dfs_get_parameter_int(parlist,
466  "fors.fors_normalise_flat.sradius", NULL);
467  dradius = dfs_get_parameter_int(parlist,
468  "fors.fors_normalise_flat.dradius", NULL);
469  splfit_threshold = dfs_get_parameter_double(parlist,
470  "fors.fors_normalise_flat.splfit_threshold", NULL);
471 
472  if (sradius < 1 || dradius < 1)
473  fors_normalise_flat_exit("Invalid smoothing box radius");
474 
475  cpl_table_delete(grism_table); grism_table = NULL;
476 
477  if (cpl_error_get_code())
478  fors_normalise_flat_exit("Failure reading the configuration "
479  "parameters");
480 
481 
482  cpl_msg_indent_less();
483  cpl_msg_info(recipe, "Check input set-of-frames:");
484  cpl_msg_indent_more();
485 
486  nflat = mxu = cpl_frameset_count_tags(frameset, "MASTER_SCREEN_FLAT_MXU");
487  nflat += mos = cpl_frameset_count_tags(frameset, "MASTER_SCREEN_FLAT_MOS");
488  nflat += lss = cpl_frameset_count_tags(frameset, "MASTER_SCREEN_FLAT_LSS");
489 
490  if (nflat == 0) {
491  fors_normalise_flat_exit("Missing input master flat field frame");
492  }
493  if (nflat > 1) {
494  cpl_msg_error(recipe, "Too many input flat frames (%d > 1)", nflat);
495  fors_normalise_flat_exit(NULL);
496  }
497 
498  if (mxu) {
499  master_flat_tag = "MASTER_SCREEN_FLAT_MXU";
500  master_norm_flat_tag = "MASTER_NORM_FLAT_MXU";
501  slit_location_tag = "SLIT_LOCATION_MXU";
502  curv_coeff_tag = "CURV_COEFF_MXU";
503  }
504  else if (mos) {
505  master_flat_tag = "MASTER_SCREEN_FLAT_MOS";
506  master_norm_flat_tag = "MASTER_NORM_FLAT_MOS";
507  slit_location_tag = "SLIT_LOCATION_MOS";
508  curv_coeff_tag = "CURV_COEFF_MOS";
509  }
510  else if (lss) {
511  master_flat_tag = "MASTER_SCREEN_FLAT_LSS";
512  master_norm_flat_tag = "MASTER_NORM_FLAT_LSS";
513  }
514 
515  header = dfs_load_header(frameset, master_flat_tag, 0);
516 
517  if (mos || mxu) {
518  int nslits_out_det = 0;
519  if (mos)
520  maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
521  else
522  maskslits = mos_load_slits_fors_mxu(header);
523 
524  /*
525  * Check if all slits have the same X offset: in such case,
526  * treat the observation as a long-slit one!
527  */
528 
529  treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det);
530 
531  cpl_table_delete(maskslits); maskslits = NULL;
532 
533  if (treat_as_lss)
534  cpl_msg_warning(recipe, "All MOS slits have the same offset: %.2f\n"
535  "The LSS data reduction strategy is applied!",
536  mxpos);
537  }
538 
539  if (!(lss || treat_as_lss)) {
540  if (cpl_frameset_count_tags(frameset, curv_coeff_tag) == 0) {
541  cpl_msg_error(recipe, "Missing input: %s", curv_coeff_tag);
542  fors_normalise_flat_exit(NULL);
543  }
544 
545  if (cpl_frameset_count_tags(frameset, curv_coeff_tag) > 1) {
546  cpl_msg_error(recipe, "Too many in input: %s", curv_coeff_tag);
547  fors_normalise_flat_exit(NULL);
548  }
549 
550  if (cpl_frameset_count_tags(frameset, slit_location_tag) == 0) {
551  cpl_msg_error(recipe, "Missing input: %s", slit_location_tag);
552  fors_normalise_flat_exit(NULL);
553  }
554 
555  if (cpl_frameset_count_tags(frameset, slit_location_tag) > 1) {
556  cpl_msg_error(recipe, "Too many in input: %s", slit_location_tag);
557  fors_normalise_flat_exit(NULL);
558  }
559  }
560 
561  if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
562  fors_normalise_flat_exit("Input frames are not from the same grism");
563 
564  if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
565  fors_normalise_flat_exit("Input frames are not from the same filter");
566 
567  if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
568  fors_normalise_flat_exit("Input frames are not from the same chip");
569 
570 
571  /*
572  * Get the reference wavelength and the rebin factor along the
573  * dispersion direction from the master flat frame
574  */
575 
576  if (header == NULL)
577  fors_normalise_flat_exit("Cannot load master flat frame header");
578 
579  instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
580  if (instrume == NULL)
581  fors_normalise_flat_exit("Missing keyword INSTRUME in master "
582  "flat header");
583 
584  if (instrume[4] == '1')
585  snprintf(version, 80, "%s/%s", "fors1", VERSION);
586  if (instrume[4] == '2')
587  snprintf(version, 80, "%s/%s", "fors2", VERSION);
588 
589  reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
590 
591  if (cpl_error_get_code() != CPL_ERROR_NONE)
592  fors_normalise_flat_exit("Missing keyword ESO INS GRIS1 WLEN "
593  "in master flat frame header");
594 
595  if (reference < 3000.0) /* Perhaps in nanometers... */
596  reference *= 10;
597 
598  if (reference < 3000.0 || reference > 13000.0) {
599  cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
600  "keyword ESO INS GRIS1 WLEN in master flat header",
601  reference);
602  fors_normalise_flat_exit(NULL);
603  }
604 
605  cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
606 
607  rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
608 
609  if (cpl_error_get_code() != CPL_ERROR_NONE)
610  fors_normalise_flat_exit("Missing keyword ESO DET WIN1 BINX "
611  "in master flat header");
612 
613  if (rebin != 1) {
614  dispersion *= rebin;
615  cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
616  "working dispersion used is %f A/pixel", rebin,
617  dispersion);
618  }
619 
620 
621  cpl_msg_indent_less();
622  cpl_msg_info(recipe, "Load input frames...");
623  cpl_msg_indent_more();
624 
625  master_flat = dfs_load_image(frameset, master_flat_tag,
626  CPL_TYPE_FLOAT, 0, 0);
627  if (master_flat == NULL)
628  fors_normalise_flat_exit("Cannot load master flat field frame");
629 
630 
631  cpl_msg_indent_less();
632  cpl_msg_info(recipe, "Perform flat field normalisation...");
633  cpl_msg_indent_more();
634 
635  if (lss || treat_as_lss) {
636 
637  /* FIXME:
638  * The LSS data calibration is still dirty: it doesn't apply
639  * any spatial rectification, and only in future an external
640  * spectral curvature model would be provided in input. Here
641  * and there temporary solutions are adpted, such as accepting
642  * the preliminary wavelength calibration.
643  */
644 
645  /*
646  * Flat field normalisation is done directly on the master flat
647  * field (without spatial rectification first). The spectral
648  * curvature model may be provided in input, in future releases.
649  */
650 
651  smo_flat = mos_lssflat_normalise(master_flat,
652  sradius, dradius,
653  spa_polyorder, disp_nknots,
654  splfit_threshold);
655 
656  cpl_image_delete(smo_flat); smo_flat = NULL; /* It may be a product */
657 
658  if (dfs_save_image(frameset, master_flat, master_norm_flat_tag,
659  header, parlist, recipe, version))
660  fors_normalise_flat_exit(NULL);
661 
662  cpl_propertylist_delete(header); header = NULL;
663  cpl_image_delete(master_flat); master_flat = NULL;
664 
665  return 0;
666  }
667 
668 
669  /*
670  * This is the generic MOS/MXU handling
671  */
672 
673  slits = dfs_load_table(frameset, slit_location_tag, 1);
674  if (slits == NULL)
675  fors_normalise_flat_exit("Cannot load slits location table");
676 
677  polytraces = dfs_load_table(frameset, curv_coeff_tag, 1);
678  if (slits == NULL)
679  fors_normalise_flat_exit("Cannot load spectral curvature table");
680 
681  nx = cpl_image_get_size_x(master_flat);
682  ny = cpl_image_get_size_y(master_flat);
683 
684  coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
685  spatial = mos_spatial_calibration(master_flat, slits, polytraces,
686  reference,
687  startwavelength, endwavelength,
688  dispersion, 0, coordinate);
689 
690  cpl_image_delete(spatial); spatial = NULL;
691 
692  smo_flat = mos_mosflat_normalise(master_flat, coordinate, slits, polytraces,
693  reference, startwavelength, endwavelength,
694  dispersion, sradius, dradius,
695  spa_polyorder, disp_nknots, splfit_threshold);
696 
697  cpl_image_delete(smo_flat); smo_flat = NULL; /* It may be a product */
698  cpl_image_delete(coordinate); coordinate = NULL;
699  cpl_table_delete(polytraces); polytraces = NULL;
700  cpl_table_delete(slits); slits = NULL;
701 
702  if (dfs_save_image(frameset, master_flat, master_norm_flat_tag,
703  header, parlist, recipe, version))
704  fors_normalise_flat_exit(NULL);
705 
706  cpl_propertylist_delete(header); header = NULL;
707  cpl_image_delete(master_flat); master_flat = NULL;
708 
709  return 0;
710 }
cpl_image * mos_spatial_calibration(cpl_image *spectra, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion, int flux, cpl_image *calibration)
Spatial remapping of CCD spectra eliminating the spectral curvature.
Definition: moses.c:8264
void fors_print_banner(void)
Issue a banner with the pipeline version.
Definition: fors_utils.c:92
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.
Definition: fors_bias.c:62
cpl_image * dfs_load_image(cpl_frameset *frameset, const char *category, cpl_type type, int ext, int calib)
Loading image data of given category.
Definition: fors_dfs.c:845
cpl_propertylist * dfs_load_header(cpl_frameset *frameset, const char *category, int ext)
Loading header associated to data of given category.
Definition: fors_dfs.c:951
cpl_table * mos_load_slits_fors_mxu(cpl_propertylist *header)
Create slit location table from FITS header of FORS2-MXU data.
Definition: moses.c:14561
cpl_table * mos_load_slits_fors_mos(cpl_propertylist *header, int *nslits_out_det)
Create slit location table from FITS header of FORS1/2 MOS data.
Definition: moses.c:14801
int dfs_equal_keyword(cpl_frameset *frameset, const char *keyword)
Saving table data of given category.
Definition: fors_dfs.c:1685
int dfs_save_image(cpl_frameset *frameset, const cpl_image *image, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving image data of given category.
Definition: fors_dfs.c:1447
cpl_table * dfs_load_table(cpl_frameset *frameset, const char *category, int ext)
Loading table data of given category.
Definition: fors_dfs.c:901
int dfs_get_parameter_int(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe integer parameter value.
Definition: fors_dfs.c:392
Definition: list.c:74
double dfs_get_parameter_double(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe double parameter value.
Definition: fors_dfs.c:489