GIRAFFE Pipeline Reference Manual

giwavecalibration.c
1 /* $Id$
2  *
3  * This file is part of the GIRAFFE Pipeline
4  * Copyright (C) 2002-2006 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$
23  * $Date$
24  * $Revision$
25  * $Name$
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31 
32 #include <math.h>
33 
34 #include <cxtypes.h>
35 #include <cxmessages.h>
36 
37 #include <cpl_recipe.h>
38 #include <cpl_plugininfo.h>
39 #include <cpl_parameterlist.h>
40 #include <cpl_frameset.h>
41 #include <cpl_propertylist.h>
42 
43 #include "gialias.h"
44 #include "gierror.h"
45 #include "giframe.h"
46 #include "giwindow.h"
47 #include "gifibers.h"
48 #include "gislitgeometry.h"
49 #include "gipsfdata.h"
50 #include "gifiberutils.h"
51 #include "gibias.h"
52 #include "giextract.h"
53 #include "giqclog.h"
54 #include "giutils.h"
55 #include "giwlcalibration.h"
56 #include "girebinning.h"
57 #include "gisgcalibration.h"
58 
59 
60 static cxint giwavecalibration(cpl_parameterlist* config, cpl_frameset* set);
61 static cxint giqcwavecalibration(cpl_frameset* set);
62 
63 
64 /*
65  * Create the recipe instance, i.e. setup the parameter list for this
66  * recipe and make it availble to the application using the interface.
67  */
68 
69 static cxint
70 giwavecalibration_create(cpl_plugin* plugin)
71 {
72 
73  cpl_recipe* recipe = (cpl_recipe*)plugin;
74 
75  cpl_parameter* p;
76 
77 
78  giraffe_error_init();
79 
80 
81  /*
82  * We have to provide the option we accept to the application. We
83  * need to setup our parameter list and hook it into the recipe
84  * interface.
85  */
86 
87  recipe->parameters = cpl_parameterlist_new();
88  cx_assert(recipe->parameters != NULL);
89 
90  /*
91  * Fill the parameter list.
92  */
93 
94  /* Bias Removal */
95 
96  giraffe_bias_config_add(recipe->parameters);
97 
98  /* Flat Fielding */
99  /* Not Yet Implemented */
100 
101  /* Spectrum Extraction */
102 
103  giraffe_extract_config_add(recipe->parameters);
104 
105  /* Wavelength Calibration */
106 
107  giraffe_wlcalibration_config_add(recipe->parameters);
108 
109  /* Arc-lamp spectrum rebinning */
110 
111  p = cpl_parameter_new_value("giraffe.wcal.rebin",
112  CPL_TYPE_BOOL,
113  "Rebin extracted arc-lamp spectra.",
114  "giraffe.wcal",
115  TRUE);
116 
117  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-rebin");
118  cpl_parameterlist_append(recipe->parameters, p);
119 
120  giraffe_rebin_config_add(recipe->parameters);
121 
122  /* Slit geometry calibration */
123 
124  p = cpl_parameter_new_value("giraffe.wcal.slitgeometry",
125  CPL_TYPE_BOOL,
126  "Controls the slit geometry calibration.",
127  "giraffe.wcal",
128  FALSE);
129 
130  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcal-slit");
131  cpl_parameterlist_append(recipe->parameters, p);
132 
133  giraffe_sgcalibration_config_add(recipe->parameters);
134 
135  return 0;
136 
137 }
138 
139 /*
140  * Execute the plugin instance given by the interface.
141  */
142 
143 static cxint
144 giwavecalibration_exec(cpl_plugin* plugin)
145 {
146 
147  cpl_recipe* recipe = (cpl_recipe*)plugin;
148 
149  cxint status = 0;
150 
151 
152  if (recipe->parameters == NULL || recipe->frames == NULL) {
153  return 1;
154  }
155 
156  status = giwavecalibration(recipe->parameters, recipe->frames);
157 
158  if (status != 0) {
159  return 1;
160  }
161 
162  status = giqcwavecalibration(recipe->frames);
163 
164  if (status != 0) {
165  return 1;
166  }
167 
168  return 0;
169 
170 }
171 
172 
173 static cxint
174 giwavecalibration_destroy(cpl_plugin* plugin)
175 {
176 
177  cpl_recipe* recipe = (cpl_recipe*)plugin;
178 
179 
180  /*
181  * We just destroy what was created during the plugin initialization
182  * phase, i.e. the parameter list. The frame set is managed by the
183  * application which called us, so we must not touch it,
184  */
185 
186  cpl_parameterlist_delete(recipe->parameters); recipe->parameters = NULL;
187 
188  giraffe_error_clear();
189 
190  return 0;
191 
192 }
193 
194 /*
195  * The actual recipe starts here.
196  */
197 
198 static cxint
199 giwavecalibration(cpl_parameterlist* config, cpl_frameset* set)
200 {
201 
202  const cxchar* const fctid = "giwavecalibration";
203 
204 
205  const cxchar* filename = NULL;
206 
207  cxbool rebin = FALSE;
208  cxbool slitgeometry = FALSE;
209 
210  cxint status = 0;
211  cxint narcspectrum = 0;
212 
213  const cpl_propertylist* properties = NULL;
214 
215  cpl_frame* arcspec_frame = NULL;
216  cpl_frame* bpixel_frame = NULL;
217  cpl_frame* mbias_frame = NULL;
218  cpl_frame* mlocy_frame = NULL;
219  cpl_frame* mlocw_frame = NULL;
220  cpl_frame* psfdata_frame = NULL;
221  cpl_frame* slight_frame = NULL;
222  cpl_frame* grating_frame = NULL;
223  cpl_frame* slitgeo_frame = NULL;
224  cpl_frame* lines_frame = NULL;
225  cpl_frame* wcal_frame = NULL;
226  cpl_frame* ldata_frame = NULL;
227  cpl_frame* scal_frame = NULL;
228  cpl_frame* sext_frame = NULL;
229 
230  cpl_parameter* p = NULL;
231 
232  cpl_matrix* biasareas = NULL;
233 
234  GiImage* arcspectrum = NULL;
235  GiImage* bsarcspectrum = NULL;
236  GiImage* slight = NULL;
237  GiImage* mbias = NULL;
238  GiImage* bpixel = NULL;
239 
240  GiLocalization* localization = NULL;
241  GiExtraction* extraction = NULL;
242  GiRebinning* rebinning = NULL;
243  GiWCalData* wlsolution = NULL;
244 
245  GiTable* fibers = NULL;
246  GiTable* grating = NULL;
247  GiTable* slitgeo = NULL;
248  GiTable* wavelengths = NULL;
249  GiTable* wcal_initial = NULL;
250 
251 // GiWcalSolution* wcal_solution = NULL;
252 
253  GiBiasConfig* bias_config = NULL;
254  GiExtractConfig* extract_config = NULL;
255  GiWCalConfig* wcal_config = NULL;
256 
257  GiFrameCreator creator = NULL;
258 
259  GiRecipeInfo info = {(cxchar*)fctid, 1, NULL};
260 
261  GiGroupInfo groups[] = {
262  {GIFRAME_ARC_SPECTRUM, CPL_FRAME_GROUP_RAW},
263  {GIFRAME_BADPIXEL_MAP, CPL_FRAME_GROUP_CALIB},
264  {GIFRAME_BIAS_MASTER, CPL_FRAME_GROUP_CALIB},
265  {GIFRAME_SCATTERED_LIGHT_MODEL, CPL_FRAME_GROUP_CALIB},
266  {GIFRAME_LOCALIZATION_CENTROID, CPL_FRAME_GROUP_CALIB},
267  {GIFRAME_LOCALIZATION_WIDTH, CPL_FRAME_GROUP_CALIB},
268  {GIFRAME_PSF_CENTROID, CPL_FRAME_GROUP_CALIB},
269  {GIFRAME_PSF_WIDTH, CPL_FRAME_GROUP_CALIB},
270  {GIFRAME_PSF_DATA, CPL_FRAME_GROUP_CALIB},
271  {GIFRAME_WAVELENGTH_SOLUTION, CPL_FRAME_GROUP_CALIB},
272  {GIFRAME_SLITSETUP, CPL_FRAME_GROUP_CALIB},
273  {GIFRAME_SLITMASTER, CPL_FRAME_GROUP_CALIB},
274  {GIFRAME_GRATING, CPL_FRAME_GROUP_CALIB},
275  {GIFRAME_LINE_CATALOG, CPL_FRAME_GROUP_CALIB},
276  {GIFRAME_LINE_MASK, CPL_FRAME_GROUP_CALIB},
277  {NULL, CPL_FRAME_GROUP_NONE}
278  };
279 
280 
281 
282  if (!config) {
283  cpl_msg_error(fctid, "Invalid parameter list! Aborting ...");
284  return 1;
285  }
286 
287  if (!set) {
288  cpl_msg_error(fctid, "Invalid frame set! Aborting ...");
289  return 1;
290  }
291 
292  p = cpl_parameterlist_find(config, "giraffe.wcal.rebin");
293 
294  if (p != NULL) {
295  rebin = cpl_parameter_get_bool(p);
296  }
297 
298  p = cpl_parameterlist_find(config, "giraffe.wcal.slitgeometry");
299 
300  if (p != NULL) {
301  slitgeometry = cpl_parameter_get_bool(p);
302  }
303 
304  status = giraffe_frameset_set_groups(set, groups);
305 
306  if (status != 0) {
307  cpl_msg_error(fctid, "Setting frame group information failed!");
308  return 1;
309  }
310 
311 
312  /*************************************************************************
313  Preprocessing
314  *************************************************************************/
315 
316  cpl_msg_info(fctid, "Recipe Step : Initialization");
317 
318  /*
319  * Verify the frame set contents
320  */
321 
322  narcspectrum = cpl_frameset_count_tags(set, GIFRAME_ARC_SPECTRUM);
323 
324  if (narcspectrum > 1) {
325  cpl_msg_error(fctid, "Only one arc spectrum frame allowed! "
326  "Aborting...");
327  return 1;
328  }
329  else if (narcspectrum < 1) {
330  cpl_msg_error(fctid, "Arc spectrum frame is missing! "
331  "Aborting...");
332  return 1;
333  }
334 
335  arcspec_frame = cpl_frameset_find(set, GIFRAME_ARC_SPECTRUM);
336  bpixel_frame = cpl_frameset_find(set, GIFRAME_BADPIXEL_MAP);
337 
338  if (!bpixel_frame) {
339  cpl_msg_info(fctid, "No bad pixel map present in frame set.");
340  }
341 
342  mbias_frame = cpl_frameset_find(set, GIFRAME_BIAS_MASTER);
343 
344  if (!mbias_frame) {
345  cpl_msg_info(fctid, "No master bias present in frame set.");
346  }
347 
348  mlocy_frame = cpl_frameset_find(set, GIFRAME_PSF_CENTROID);
349 
350  if (mlocy_frame == NULL) {
351 
352  mlocy_frame = cpl_frameset_find(set, GIFRAME_LOCALIZATION_CENTROID);
353 
354  if (mlocy_frame == NULL) {
355  cpl_msg_info(fctid, "No master localization (centroid position) "
356  "present in frame set. Aborting ...");
357  return 1;
358  }
359 
360  }
361 
362  mlocw_frame = cpl_frameset_find(set, GIFRAME_PSF_WIDTH);
363 
364  if (mlocw_frame == NULL) {
365 
366  mlocw_frame = cpl_frameset_find(set, GIFRAME_LOCALIZATION_WIDTH);
367 
368  if (mlocw_frame == NULL) {
369  cpl_msg_info(fctid, "No master localization (spectrum width) "
370  "present in frame set. Aborting ...");
371  return 1;
372  }
373 
374  }
375 
376  psfdata_frame = cpl_frameset_find(set, GIFRAME_PSF_DATA);
377 
378  if (!psfdata_frame) {
379  cpl_msg_info(fctid, "No PSF profile parameters present in frame set.");
380  }
381 
382  slight_frame = cpl_frameset_find(set, GIFRAME_SCATTERED_LIGHT_MODEL);
383 
384  if (!slight_frame) {
385  cpl_msg_info(fctid, "No scattered light model present in frame set.");
386  }
387 
388  grating_frame = cpl_frameset_find(set, GIFRAME_GRATING);
389 
390  if (!grating_frame) {
391  cpl_msg_error(fctid, "No grating table present in frame set, "
392  "aborting...");
393  return 1;
394  }
395 
396  slitgeo_frame = giraffe_get_slitgeometry(set);
397 
398  if (!slitgeo_frame) {
399  cpl_msg_error(fctid, "No slit geometry table present in frame "
400  "set, aborting...");
401  return 1;
402  }
403 
404  lines_frame = cpl_frameset_find(set, GIFRAME_LINE_CATALOG);
405 
406  if (!lines_frame) {
407  cpl_msg_error(fctid, "No wavelength table present in frame set, "
408  "aborting...");
409  return 1;
410  }
411 
412  wcal_frame = cpl_frameset_find(set, GIFRAME_WAVELENGTH_SOLUTION);
413 
414  if (!wcal_frame) {
415  cpl_msg_info(fctid, "No wavelength solution present in frame set.");
416  }
417 
418  scal_frame = cpl_frameset_find(set, GIFRAME_LINE_MASK);
419 
420  if (!scal_frame) {
421 
422  if (slitgeometry == TRUE) {
423  cpl_msg_error(fctid, "No line mask present in frame "
424  "set. Aborting ...");
425  return 1;
426  }
427  else {
428  cpl_msg_info(fctid, "No slit geometry mask present in frame "
429  "set.");
430  }
431 
432  }
433 
434 
435  /*************************************************************************
436  Processing
437  *************************************************************************/
438 
439  /*
440  * Load bad pixel map if it is present in the frame set.
441  */
442 
443  if (bpixel_frame) {
444 
445  filename = cpl_frame_get_filename(bpixel_frame);
446 
447  bpixel = giraffe_image_new(CPL_TYPE_INT);
448  status = giraffe_image_load(bpixel, filename, 0);
449 
450  if (status) {
451  cpl_msg_error(fctid, "Cannot load bad pixel map from '%s'. "
452  "Aborting ...", filename);
453 
454  giraffe_image_delete(bpixel);
455  return 1;
456  }
457  }
458 
459 
460  /*
461  * Load arc spectrum
462  */
463 
464  status = 0;
465  filename = cpl_frame_get_filename(arcspec_frame);
466 
467  arcspectrum = giraffe_image_new(CPL_TYPE_DOUBLE);
468  status = giraffe_image_load(arcspectrum, filename, 0);
469 
470  if (status) {
471  cpl_msg_error(fctid, "Cannot load arc spectrum from '%s'. "
472  "Aborting...", filename);
473 
474  giraffe_image_delete(bpixel);
475  giraffe_image_delete(arcspectrum);
476  return 1;
477  }
478 
479 
480  /*
481  * Prepare bias subtraction
482  */
483 
484  cpl_msg_info(fctid, "Recipe Step : Bias Removal");
485 
486  bias_config = giraffe_bias_config_create(config);
487 
488  /*
489  * Setup user defined areas to use for the bias computation
490  */
491 
492  if (bias_config->method == GIBIAS_METHOD_MASTER ||
493  bias_config->method == GIBIAS_METHOD_ZMASTER) {
494 
495  if (!mbias_frame) {
496  cpl_msg_error(fctid, "Missing master bias frame! Selected bias "
497  "removal method requires a master bias "
498  "frame!");
499 
500  giraffe_image_delete(bpixel);
501  giraffe_image_delete(arcspectrum);
502  giraffe_bias_config_destroy(bias_config);
503 
504  return 1;
505  }
506  else {
507 
508  status = 0;
509  filename = cpl_frame_get_filename(mbias_frame);
510 
511  mbias = giraffe_image_new(CPL_TYPE_DOUBLE);
512  status = giraffe_image_load(mbias, filename, 0);
513 
514  if (status) {
515  cpl_msg_error(fctid, "Cannot load master bias from '%s'. "
516  "Aborting ...", filename);
517 
518  giraffe_image_delete(bpixel);
519  giraffe_image_delete(arcspectrum);
520  giraffe_image_delete(mbias);
521  giraffe_bias_config_destroy(bias_config);
522 
523  return 1;
524  }
525  }
526  }
527 
528 
529  /*
530  * Compute and remove the bias from the stacked flat field frame.
531  */
532 
533  bsarcspectrum = giraffe_image_new(CPL_TYPE_DOUBLE);
534 
535  status = giraffe_bias_remove(bsarcspectrum, arcspectrum, mbias, bpixel,
536  biasareas, bias_config);
537 
538  giraffe_image_delete(arcspectrum);
539  arcspectrum = NULL;
540 
541  if (mbias) {
542  giraffe_image_delete(mbias);
543  mbias = NULL;
544  }
545 
546  giraffe_bias_config_destroy(bias_config);
547  bias_config = NULL;
548 
549  if (status) {
550  cpl_msg_error(fctid, "Bias removal failed. Aborting ...");
551 
552  giraffe_image_delete(bpixel);
553  giraffe_image_delete(bsarcspectrum);
554  return 1;
555  }
556 
557 
558  /*
559  * Determine fiber setup
560  */
561 
562  cpl_msg_info(fctid, "Recipe Step : Fiber Setup");
563 
564  cpl_msg_info(fctid, "Building fiber setup for frame '%s'.",
565  cpl_frame_get_filename(arcspec_frame));
566 
567  fibers = giraffe_fibers_setup(arcspec_frame, mlocy_frame);
568 
569  if (!fibers) {
570  cpl_msg_error(fctid, "Cannot create fiber setup for frame '%s'! "
571  "Aborting ...", cpl_frame_get_filename(arcspec_frame));
572 
573  giraffe_image_delete(bpixel);
574  giraffe_image_delete(bsarcspectrum);
575 
576  return 1;
577  }
578 
579  cpl_msg_info(fctid, "Fiber reference setup taken from localization "
580  "frame '%s'.", cpl_frame_get_filename(mlocy_frame));
581 
582 
583  /*
584  * Load spectrum localization.
585  */
586 
587  localization = giraffe_localization_new();
588 
589  filename = cpl_frame_get_filename(mlocy_frame);
590  status = 0;
591 
592  localization->locy = giraffe_image_new(CPL_TYPE_DOUBLE);
593  status = giraffe_image_load(localization->locy, filename, 0);
594 
595  if (status) {
596  cpl_msg_error(fctid, "Cannot load localization (centroid "
597  "position) frame from '%s'. Aborting ...",
598  filename);
599 
600  giraffe_localization_destroy(localization);
601  giraffe_image_delete(bpixel);
602  giraffe_image_delete(bsarcspectrum);
603  giraffe_table_delete(fibers);
604 
605  return 1;
606 
607  }
608 
609 
610  filename = cpl_frame_get_filename(mlocw_frame);
611  status = 0;
612 
613  localization->locw = giraffe_image_new(CPL_TYPE_DOUBLE);
614  status = giraffe_image_load(localization->locw, filename, 0);
615 
616  if (status) {
617  cpl_msg_error(fctid, "Cannot load localization (spectrum width) "
618  "frame from '%s'. Aborting ...", filename);
619 
620  giraffe_localization_destroy(localization);
621  giraffe_image_delete(bpixel);
622  giraffe_image_delete(bsarcspectrum);
623  giraffe_table_delete(fibers);
624 
625  return 1;
626 
627  }
628 
629 
630  /*
631  * Perform spectrum extraction on the master flat field.
632  */
633 
634  cpl_msg_info(fctid, "Recipe Step : Spectrum Extraction");
635 
636  if (slight_frame) {
637 
638  filename = cpl_frame_get_filename(slight_frame);
639  status = 0;
640 
641  slight = giraffe_image_new(CPL_TYPE_DOUBLE);
642  status = giraffe_image_load(slight, filename, 0);
643 
644  if (status) {
645  cpl_msg_error(fctid, "Cannot load scattered light model from "
646  "'%s'. Aborting ...", filename);
647 
648  giraffe_image_delete(bpixel);
649  giraffe_image_delete(bsarcspectrum);
650  giraffe_table_delete(fibers);
651  giraffe_localization_destroy(localization);
652  giraffe_image_delete(slight);
653 
654  return 1;
655 
656  }
657 
658  }
659 
660  extract_config = giraffe_extract_config_create(config);
661 
662  if ((extract_config->emethod == GIEXTRACT_OPTIMAL) ||
663  (extract_config->emethod == GIEXTRACT_HORNE)) {
664 
665  if (psfdata_frame == NULL) {
666 
667  const cxchar* emethod = "Optimal";
668 
669  if (extract_config->emethod == GIEXTRACT_HORNE) {
670  emethod = "Horne";
671  }
672 
673  cpl_msg_error(fctid, "%s spectrum extraction requires PSF "
674  "profile data. Aborting ...", emethod);
675 
676  giraffe_extract_config_destroy(extract_config);
677  extract_config = NULL;
678 
679  if (slight != NULL) {
680  giraffe_image_delete(slight);
681  slight = NULL;
682  }
683 
684  giraffe_localization_destroy(localization);
685  localization = NULL;
686 
687  if (bpixel) {
688  giraffe_image_delete(bpixel);
689  bpixel = NULL;
690  }
691 
692  giraffe_table_delete(fibers);
693  fibers = NULL;
694 
695  giraffe_image_delete(bsarcspectrum);
696  bsarcspectrum = NULL;
697 
698  return 1;
699 
700  }
701  else {
702 
703  filename = cpl_frame_get_filename(psfdata_frame);
704  status = 0;
705 
706  localization->psf = giraffe_psfdata_new();
707  status = giraffe_psfdata_load(localization->psf, filename);
708 
709  if (status) {
710  cpl_msg_error(fctid, "Cannot load PSF profile data frame from "
711  "'%s'. Aborting ...", filename);
712 
713  giraffe_extract_config_destroy(extract_config);
714  extract_config = NULL;
715 
716  if (slight != NULL) {
717  giraffe_image_delete(slight);
718  slight = NULL;
719  }
720 
721  giraffe_localization_destroy(localization);
722  localization = NULL;
723 
724  if (bpixel) {
725  giraffe_image_delete(bpixel);
726  bpixel = NULL;
727  }
728 
729  giraffe_table_delete(fibers);
730  fibers = NULL;
731 
732  giraffe_image_delete(bsarcspectrum);
733  bsarcspectrum = NULL;
734 
735  return 1;
736 
737  }
738 
739  }
740 
741  }
742 
743 
744  extraction = giraffe_extraction_new();
745 
746  status = giraffe_extract_spectra(extraction, bsarcspectrum, fibers,
747  localization, bpixel, slight,
748  extract_config);
749 
750  if (status) {
751  cpl_msg_error(fctid, "Spectrum extraction failed! Aborting ...");
752 
753  giraffe_image_delete(bpixel);
754  giraffe_image_delete(bsarcspectrum);
755  giraffe_table_delete(fibers);
756  giraffe_localization_destroy(localization);
757  giraffe_image_delete(slight);
758  giraffe_extract_config_destroy(extract_config);
759  giraffe_extraction_destroy(extraction);
760 
761  return 1;
762  }
763 
764  giraffe_image_delete(slight);
765  slight = NULL;
766 
767  giraffe_image_delete(bpixel);
768  bpixel = NULL;
769 
770  giraffe_image_delete(bsarcspectrum);
771  bsarcspectrum = NULL;
772 
773  giraffe_extract_config_destroy(extract_config);
774  extract_config = NULL;
775 
776  /*
777  * Save the spectrum extraction results and register them as
778  * products.
779  */
780 
781  cpl_msg_info(fctid, "Writing extracted spectra ...");
782 
783  /* Extracted spectra */
784 
785  giraffe_image_add_info(extraction->spectra, &info, set);
786 
787  sext_frame = giraffe_frame_create_image(extraction->spectra,
788  GIFRAME_ARC_LAMP_EXTSPECTRA,
789  CPL_FRAME_LEVEL_INTERMEDIATE,
790  TRUE, TRUE);
791 
792  if (sext_frame == NULL) {
793  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
794 
795  giraffe_table_delete(fibers);
796 
797  giraffe_localization_destroy(localization);
798  giraffe_extraction_destroy(extraction);
799 
800  return 1;
801  }
802 
803  status = giraffe_fiberlist_attach(sext_frame, fibers);
804 
805  if (status) {
806  cpl_msg_error(fctid, "Cannot attach fiber setup to local file '%s'! "
807  "Aborting ...", cpl_frame_get_filename(sext_frame));
808 
809  cpl_frame_delete(sext_frame);
810 
811  giraffe_table_delete(fibers);
812 
813  giraffe_localization_destroy(localization);
814  giraffe_extraction_destroy(extraction);
815 
816  return 1;
817  }
818 
819  cpl_frameset_insert(set, sext_frame);
820 
821  /* Extracted spectra errors */
822 
823  giraffe_image_add_info(extraction->error, &info, set);
824 
825  sext_frame = giraffe_frame_create_image(extraction->error,
826  GIFRAME_ARC_LAMP_EXTERRORS,
827  CPL_FRAME_LEVEL_INTERMEDIATE,
828  TRUE, TRUE);
829 
830  if (sext_frame == NULL) {
831  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
832 
833  giraffe_table_delete(fibers);
834 
835  giraffe_localization_destroy(localization);
836  giraffe_extraction_destroy(extraction);
837 
838  return 1;
839  }
840 
841  status = giraffe_fiberlist_attach(sext_frame, fibers);
842 
843  if (status) {
844  cpl_msg_error(fctid, "Cannot attach fiber setup to local file '%s'! "
845  "Aborting ...", cpl_frame_get_filename(sext_frame));
846 
847  cpl_frame_delete(sext_frame);
848 
849  giraffe_table_delete(fibers);
850 
851  giraffe_localization_destroy(localization);
852  giraffe_extraction_destroy(extraction);
853 
854  return 1;
855  }
856 
857  cpl_frameset_insert(set, sext_frame);
858 
859  /* Extracted spectra pixels */
860 
861  if (extraction->npixels != NULL) {
862 
863  giraffe_image_add_info(extraction->npixels, &info, set);
864 
865  sext_frame = giraffe_frame_create_image(extraction->npixels,
866  GIFRAME_ARC_LAMP_EXTPIXELS,
867  CPL_FRAME_LEVEL_INTERMEDIATE,
868  TRUE, TRUE);
869 
870  if (sext_frame == NULL) {
871  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
872 
873  giraffe_table_delete(fibers);
874 
875  giraffe_localization_destroy(localization);
876  giraffe_extraction_destroy(extraction);
877 
878  return 1;
879  }
880 
881  status = giraffe_fiberlist_attach(sext_frame, fibers);
882 
883  if (status) {
884  cpl_msg_error(fctid, "Cannot attach fiber setup to local file '%s'! "
885  "Aborting ...", cpl_frame_get_filename(sext_frame));
886 
887  cpl_frame_delete(sext_frame);
888 
889  giraffe_table_delete(fibers);
890 
891  giraffe_localization_destroy(localization);
892  giraffe_extraction_destroy(extraction);
893 
894  return 1;
895  }
896 
897  cpl_frameset_insert(set, sext_frame);
898 
899  }
900 
901  /* Extracted spectra centroids */
902 
903  giraffe_image_add_info(extraction->centroid, &info, set);
904 
905  sext_frame = giraffe_frame_create_image(extraction->centroid,
906  GIFRAME_ARC_LAMP_EXTTRACE,
907  CPL_FRAME_LEVEL_INTERMEDIATE,
908  TRUE, TRUE);
909 
910  if (sext_frame == NULL) {
911  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
912 
913  giraffe_table_delete(fibers);
914 
915  giraffe_localization_destroy(localization);
916  giraffe_extraction_destroy(extraction);
917 
918  return 1;
919  }
920 
921  status = giraffe_fiberlist_attach(sext_frame, fibers);
922 
923  if (status) {
924  cpl_msg_error(fctid, "Cannot attach fiber setup to local file '%s'! "
925  "Aborting ...", cpl_frame_get_filename(sext_frame));
926 
927  cpl_frame_delete(sext_frame);
928 
929  giraffe_table_delete(fibers);
930 
931  giraffe_localization_destroy(localization);
932  giraffe_extraction_destroy(extraction);
933 
934  return 1;
935  }
936 
937  cpl_frameset_insert(set, sext_frame);
938 
939  /* Extraction model spectra */
940 
941  if (extraction->model != NULL) {
942 
943  giraffe_image_add_info(extraction->model, &info, set);
944 
945  sext_frame = giraffe_frame_create_image(extraction->model,
946  GIFRAME_ARC_LAMP_EXTMODEL,
947  CPL_FRAME_LEVEL_FINAL,
948  TRUE, TRUE);
949 
950  if (sext_frame == NULL) {
951  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
952 
953  giraffe_table_delete(fibers);
954 
955  giraffe_localization_destroy(localization);
956  giraffe_extraction_destroy(extraction);
957 
958  return 1;
959  }
960 
961  status = giraffe_fiberlist_attach(sext_frame, fibers);
962 
963  if (status != 0) {
964  cpl_msg_error(fctid, "Cannot attach fiber setup to local file '%s'! "
965  "Aborting ...", cpl_frame_get_filename(sext_frame));
966 
967  cpl_frame_delete(sext_frame);
968 
969  giraffe_table_delete(fibers);
970 
971  giraffe_localization_destroy(localization);
972  giraffe_extraction_destroy(extraction);
973 
974  return 1;
975  }
976 
977  cpl_frameset_insert(set, sext_frame);
978 
979  }
980 
981  /*
982  * Perform Wavelength Calibration
983  */
984 
985  cpl_msg_info(fctid, "Recipe Step : Wavelength Calibration");
986 
987  filename = cpl_frame_get_filename(grating_frame);
988  status = 0;
989 
990  grating = giraffe_table_new();
991  status = giraffe_table_load(grating, filename, 1, NULL);
992 
993  if (status) {
994  cpl_msg_error(fctid, "Cannot load grating table from '%s'. "
995  "Aborting ...", filename);
996 
997  giraffe_table_delete(fibers);
998  giraffe_localization_destroy(localization);
999  giraffe_extraction_destroy(extraction);
1000 
1001  return 1;
1002  }
1003 
1004 
1005  filename = cpl_frame_get_filename(slitgeo_frame);
1006 
1007  slitgeo = giraffe_slitgeometry_load(fibers, filename, 1, NULL);
1008 
1009  if (slitgeo == NULL) {
1010  cpl_msg_error(fctid, "Cannot load slit geometry table from '%s'. "
1011  "Aborting ...", filename);
1012 
1013  giraffe_table_delete(fibers);
1014  giraffe_localization_destroy(localization);
1015  giraffe_extraction_destroy(extraction);
1016  giraffe_table_delete(grating);
1017 
1018  return 1;
1019  }
1020  else {
1021 
1022  /*
1023  * Check whether the contains the positions for all fibers
1024  * provided by the fiber setup. If this is not the case
1025  * this is an error.
1026  */
1027 
1028  if (giraffe_fiberlist_compare(slitgeo, fibers) != 1) {
1029  cpl_msg_error(fctid, "Slit geometry data from '%s' is not "
1030  "applicable for current fiber setup! "
1031  "Aborting ...", filename);
1032 
1033  giraffe_table_delete(slitgeo);
1034  giraffe_table_delete(fibers);
1035  giraffe_localization_destroy(localization);
1036  giraffe_extraction_destroy(extraction);
1037  giraffe_table_delete(grating);
1038 
1039  return 1;
1040  }
1041 
1042  }
1043 
1044 
1045  filename = cpl_frame_get_filename(lines_frame);
1046  status = 0;
1047 
1048  wavelengths = giraffe_table_new();
1049  status = giraffe_table_load(wavelengths, filename, 1, NULL);
1050 
1051  if (status) {
1052  cpl_msg_error(fctid, "Cannot load arc-line data from '%s'. "
1053  "Aborting ...", filename);
1054 
1055  giraffe_table_delete(fibers);
1056  giraffe_localization_destroy(localization);
1057  giraffe_extraction_destroy(extraction);
1058  giraffe_table_delete(grating);
1059  giraffe_table_delete(slitgeo);
1060 
1061  return 1;
1062 
1063  }
1064 
1065  if (wcal_frame != NULL) {
1066 
1067  wcal_initial = giraffe_table_new();
1068 
1069  filename = cpl_frame_get_filename(wcal_frame);
1070  status = giraffe_table_load(wcal_initial, filename, 1, NULL);
1071 
1072  if (status) {
1073  cpl_msg_error(fctid, "Cannot load initial wavelength solution "
1074  "from '%s'. Aborting ...", filename);
1075 
1076  giraffe_table_delete(wcal_initial);
1077 
1078  giraffe_table_delete(fibers);
1079  giraffe_localization_destroy(localization);
1080  giraffe_extraction_destroy(extraction);
1081  giraffe_table_delete(grating);
1082  giraffe_table_delete(slitgeo);
1083 
1084  return 1;
1085 
1086  }
1087 
1088  }
1089 
1090  wcal_config = giraffe_wlcalibration_config_create(config);
1091  cx_assert(wcal_config != NULL);
1092 
1093  wlsolution = giraffe_wcaldata_new();
1094 
1095  status = giraffe_calibrate_wavelength(wlsolution, extraction,
1096  localization, fibers, slitgeo,
1097  grating, wavelengths, wcal_initial,
1098  wcal_config);
1099 
1100  if (status) {
1101  cpl_msg_error(fctid, "Error during wavelength calibration, "
1102  "aborting...");
1103 
1104  giraffe_table_delete(fibers);
1105  giraffe_localization_destroy(localization);
1106  giraffe_extraction_destroy(extraction);
1107  giraffe_table_delete(grating);
1108  giraffe_table_delete(slitgeo);
1109  giraffe_table_delete(wavelengths);
1110  giraffe_table_delete(wcal_initial);
1111 
1112  giraffe_wcaldata_delete(wlsolution);
1114 
1115  return 1;
1116 
1117  }
1118 
1120  wcal_config = NULL;
1121 
1122  giraffe_table_delete(wcal_initial);
1123  wcal_initial = NULL;
1124 
1125  giraffe_table_delete(wavelengths);
1126  wavelengths = NULL;
1127 
1128 
1129  /*
1130  * Save and register the wavelength calibration results.
1131  */
1132 
1133  /* Coefficients of the x-residuals fit */
1134 
1135  giraffe_table_add_info(wlsolution->coeffs, &info, set);
1136 
1137  wcal_frame = giraffe_frame_create_table(wlsolution->coeffs,
1138  GIFRAME_WAVELENGTH_SOLUTION,
1139  CPL_FRAME_LEVEL_FINAL,
1140  TRUE, TRUE);
1141 
1142  if (wcal_frame == NULL) {
1143 
1144  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
1145 
1146  giraffe_table_delete(fibers);
1147  giraffe_localization_destroy(localization);
1148  giraffe_extraction_destroy(extraction);
1149  giraffe_table_delete(grating);
1150  giraffe_table_delete(slitgeo);
1151 
1152  giraffe_wcaldata_delete(wlsolution);
1153 
1154  return 1;
1155 
1156  }
1157 
1158  cpl_frameset_insert(set, wcal_frame);
1159 
1160  /* Lines data */
1161 
1162  properties = giraffe_table_get_properties(wlsolution->coeffs);
1163  creator = (GiFrameCreator)giraffe_linedata_writer;
1164 
1165  ldata_frame = giraffe_frame_create(GIFRAME_LINE_DATA,
1166  CPL_FRAME_LEVEL_FINAL,
1167  properties, wlsolution->linedata,
1168  NULL,
1169  creator);
1170 
1171  if (ldata_frame == NULL) {
1172 
1173  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
1174 
1175  giraffe_table_delete(fibers);
1176  giraffe_localization_destroy(localization);
1177  giraffe_extraction_destroy(extraction);
1178  giraffe_table_delete(grating);
1179  giraffe_table_delete(slitgeo);
1180 
1181  giraffe_wcaldata_delete(wlsolution);
1182 
1183  properties = NULL;
1184 
1185  return 1;
1186 
1187  }
1188 
1189  properties = NULL;
1190 
1191  giraffe_linedata_delete(wlsolution->linedata);
1192  wlsolution->linedata = NULL;
1193 
1194  cpl_frameset_insert(set, ldata_frame);
1195 
1196 
1197  /*
1198  * Optional slit geometry calibration. Note that this step requires a
1199  * rebinned arc-lamp frame as input!
1200  */
1201 
1202  if (slitgeometry == TRUE) {
1203 
1204  cpl_frame* slit_frame = NULL;
1205 
1206  GiSGCalConfig* scal_config = NULL;
1207 
1208  GiTable* mask = NULL;
1209  GiTable* slit = NULL;
1210 
1211 
1212  cpl_msg_info(fctid, "Calibrating slit geometry ...");
1213 
1214  scal_config = giraffe_sgcalibration_config_create(config);
1215 
1216 
1217  filename = cpl_frame_get_filename(scal_frame);
1218 
1219  mask = giraffe_table_new();
1220  status = giraffe_table_load(mask, filename, 1, NULL);
1221 
1222  if (status != 0) {
1223  cpl_msg_error(fctid, "Cannot load slit geometry mask from '%s'. "
1224  "Aborting ...", filename);
1225 
1227 
1228  giraffe_table_delete(mask);
1229 
1230  giraffe_wcaldata_delete(wlsolution);
1231 
1232  giraffe_localization_destroy(localization);
1233  giraffe_extraction_destroy(extraction);
1234 
1235  giraffe_table_delete(fibers);
1236  giraffe_table_delete(grating);
1237  giraffe_table_delete(slitgeo);
1238 
1239  return 1;
1240 
1241  }
1242 
1243  slit = giraffe_table_new();
1244 
1245  status = giraffe_calibrate_slit(slit, extraction, localization, fibers,
1246  wlsolution->coeffs, slitgeo, grating,
1247  mask, scal_config);
1248 
1249  if (status != 0) {
1250  cpl_msg_error(fctid, "Slit geometry calibration failed! "
1251  "Aborting ...");
1252 
1254 
1255  giraffe_table_delete(slit);
1256  giraffe_table_delete(mask);
1257 
1258  giraffe_wcaldata_delete(wlsolution);
1259 
1260  giraffe_localization_destroy(localization);
1261  giraffe_extraction_destroy(extraction);
1262 
1263  giraffe_table_delete(fibers);
1264  giraffe_table_delete(grating);
1265  giraffe_table_delete(slitgeo);
1266 
1267  return 1;
1268 
1269  }
1270 
1271 
1272  /*
1273  * Save and register the slit geometry calibration results.
1274  */
1275 
1276 
1277  giraffe_table_add_info(slit, &info, set);
1278 
1279  slit_frame = giraffe_slitgeometry_save(slit);
1280 
1281  if (!slit_frame) {
1282 
1283  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
1284 
1286 
1287  giraffe_table_delete(slit);
1288  giraffe_table_delete(mask);
1289 
1290  giraffe_wcaldata_delete(wlsolution);
1291 
1292  giraffe_localization_destroy(localization);
1293  giraffe_extraction_destroy(extraction);
1294 
1295  giraffe_table_delete(fibers);
1296  giraffe_table_delete(grating);
1297  giraffe_table_delete(slitgeo);
1298 
1299  return 1;
1300  }
1301 
1302  cpl_frameset_insert(set, slit_frame);
1303 
1304  giraffe_table_delete(mask);
1306 
1307 
1308  /*
1309  * Replace the slit geometry table with the new one.
1310  */
1311 
1312  giraffe_table_delete(slitgeo);
1313  slitgeo = slit;
1314 
1315  }
1316 
1317 
1318  /*
1319  * Optional rebinning of the previously extracted arc-lamp spectra.
1320  */
1321 
1322  if (rebin == TRUE) {
1323 
1324  cpl_frame* rbin_frame = NULL;
1325 
1326  GiRebinConfig* rebin_config;
1327 
1328 
1329  cpl_msg_info(fctid, "Recipe Step : Spectrum Rebinning");
1330 
1331  rebin_config = giraffe_rebin_config_create(config);
1332 
1333  rebinning = giraffe_rebinning_new();
1334 
1335  status = giraffe_rebin_spectra(rebinning, extraction, fibers,
1336  localization, grating, slitgeo,
1337  wlsolution->coeffs, rebin_config);
1338 
1339  if (status) {
1340  cpl_msg_error(fctid, "Rebinning of arc-lamp spectra failed! "
1341  "Aborting...");
1342 
1343  giraffe_wcaldata_delete(wlsolution);
1344 
1345  giraffe_rebinning_destroy(rebinning);
1346  giraffe_localization_destroy(localization);
1347  giraffe_extraction_destroy(extraction);
1348 
1349  giraffe_table_delete(grating);
1350  giraffe_table_delete(slitgeo);
1351  giraffe_table_delete(fibers);
1352 
1353  giraffe_rebin_config_destroy(rebin_config);
1354 
1355  return 1;
1356 
1357  }
1358 
1359  giraffe_rebin_config_destroy(rebin_config);
1360 
1361  /*
1362  * Save and register the results of the spectrum rebinning.
1363  */
1364 
1365  /* Rebinned spectra */
1366 
1367  giraffe_image_add_info(rebinning->spectra, &info, set);
1368 
1369  rbin_frame = giraffe_frame_create_image(rebinning->spectra,
1370  GIFRAME_ARC_LAMP_RBNSPECTRA,
1371  CPL_FRAME_LEVEL_FINAL,
1372  TRUE, TRUE);
1373 
1374  if (rbin_frame == NULL) {
1375 
1376  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
1377 
1378  giraffe_wcaldata_delete(wlsolution);
1379 
1380  giraffe_rebinning_destroy(rebinning);
1381  giraffe_localization_destroy(localization);
1382  giraffe_extraction_destroy(extraction);
1383 
1384  giraffe_table_delete(grating);
1385  giraffe_table_delete(slitgeo);
1386  giraffe_table_delete(fibers);
1387 
1388  return 1;
1389 
1390  }
1391 
1392  status = giraffe_fiberlist_attach(rbin_frame, fibers);
1393 
1394  if (status) {
1395  cpl_msg_error(fctid, "Cannot attach fiber setup to local "
1396  "file '%s'! Aborting ...",
1397  cpl_frame_get_filename(rbin_frame));
1398 
1399  giraffe_wcaldata_delete(wlsolution);
1400 
1401  giraffe_rebinning_destroy(rebinning);
1402  giraffe_localization_destroy(localization);
1403  giraffe_extraction_destroy(extraction);
1404 
1405  giraffe_table_delete(grating);
1406  giraffe_table_delete(slitgeo);
1407  giraffe_table_delete(fibers);
1408 
1409  cpl_frame_delete(rbin_frame);
1410 
1411  return 1;
1412 
1413  }
1414 
1415  cpl_frameset_insert(set, rbin_frame);
1416 
1417  /* Rebinned spectra errors */
1418 
1419  giraffe_image_add_info(rebinning->errors, &info, set);
1420 
1421  rbin_frame = giraffe_frame_create_image(rebinning->errors,
1422  GIFRAME_ARC_LAMP_RBNERRORS,
1423  CPL_FRAME_LEVEL_FINAL,
1424  TRUE, TRUE);
1425 
1426  if (rbin_frame == NULL) {
1427 
1428  cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
1429 
1430  giraffe_wcaldata_delete(wlsolution);
1431 
1432  giraffe_rebinning_destroy(rebinning);
1433  giraffe_localization_destroy(localization);
1434  giraffe_extraction_destroy(extraction);
1435 
1436  giraffe_table_delete(grating);
1437  giraffe_table_delete(slitgeo);
1438  giraffe_table_delete(fibers);
1439 
1440  return 1;
1441 
1442  }
1443 
1444  status = giraffe_fiberlist_attach(rbin_frame, fibers);
1445 
1446  if (status) {
1447 
1448  cpl_msg_error(fctid, "Cannot attach fiber setup to local "
1449  "file '%s'! Aborting ...",
1450  cpl_frame_get_filename(rbin_frame));
1451 
1452  giraffe_wcaldata_delete(wlsolution);
1453 
1454  giraffe_rebinning_destroy(rebinning);
1455  giraffe_localization_destroy(localization);
1456  giraffe_extraction_destroy(extraction);
1457 
1458  giraffe_table_delete(grating);
1459  giraffe_table_delete(slitgeo);
1460  giraffe_table_delete(fibers);
1461 
1462  cpl_frame_delete(rbin_frame);
1463 
1464  return 1;
1465 
1466  }
1467 
1468  cpl_frameset_insert(set, rbin_frame);
1469 
1470  }
1471 
1472 
1473  /*
1474  * Postprocessing
1475  */
1476 
1477  giraffe_table_delete(fibers);
1478  fibers = NULL;
1479 
1480  giraffe_localization_destroy(localization);
1481  localization = NULL;
1482 
1483  giraffe_extraction_destroy(extraction);
1484  extraction = NULL;
1485 
1486  if (rebinning != NULL) {
1487  giraffe_rebinning_destroy(rebinning);
1488  rebinning = NULL;
1489  }
1490 
1491  giraffe_table_delete(grating);
1492  grating = NULL;
1493 
1494  giraffe_table_delete(slitgeo);
1495  slitgeo = NULL;
1496 
1497  giraffe_wcaldata_delete(wlsolution);
1498  wlsolution = NULL;
1499 
1500  return 0;
1501 
1502 }
1503 
1504 
1505 static cxint
1506 giqcwavecalibration(cpl_frameset* set)
1507 {
1508 
1509  const cxchar* const fctid = "giqcwavecalibration";
1510 
1511 
1512  cxint i = 0;
1513  cxint j = 0;
1514  cxint nx = 0;
1515  cxint ny = 0;
1516  cxint npixel = 0;
1517  cxint nsaturated = 0;
1518  cxint status = 0;
1519 
1520  const cxdouble rmsscale = 3.;
1521  const cxdouble saturation = 60000.;
1522  const cxdouble* pixels = NULL;
1523 
1524  cxdouble efficiency[2] = {0., 0.};
1525  cxdouble wlcenter = 0.;
1526  cxdouble mean = 0.;
1527  cxdouble rms = 0.;
1528  cxdouble pixel2nm = 1.;
1529  cxdouble fwhm_domain[2] = {0., 100.};
1530  cxdouble* _tdata = NULL;
1531 
1532  cpl_propertylist* properties = NULL;
1533  cpl_propertylist* qclog = NULL;
1534 
1535  cpl_frame* rframe = NULL;
1536  cpl_frame* pframe = NULL;
1537 
1538  const cpl_image* _rimage = NULL;
1539  const cpl_image* _pimage = NULL;
1540 
1541  cpl_image* _test = NULL;
1542  cpl_image* _test0 = NULL;
1543  cpl_image* _test1 = NULL;
1544 
1545  cpl_table* _ptable = NULL;
1546 
1547  GiImage* rimage = NULL;
1548  GiImage* pimage = NULL;
1549 
1550  GiTable* ptable = NULL;
1551 
1552  GiLineData* plines = NULL;
1553 
1554  GiPaf* qc = NULL;
1555 
1556  GiWindow w;
1557 
1558 
1559 
1560  cpl_msg_info(fctid, "Computing QC1 parameters ...");
1561 
1562 
1563  /*
1564  * Compute lamp efficiencies from the rebinned frame if
1565  * it is available. If not the efficiencies are set to 0.
1566  */
1567 
1568  pframe = giraffe_get_frame(set, GIFRAME_ARC_LAMP_EXTSPECTRA,
1569  CPL_FRAME_GROUP_PRODUCT);
1570 
1571  if (pframe == NULL) {
1572 
1573  cpl_msg_warning(fctid, "Product '%s' not found.",
1574  GIFRAME_ARC_LAMP_EXTSPECTRA);
1575 
1576  cpl_msg_warning(fctid, "Setting lamp efficiencies (%s, %s) to 0.",
1577  GIALIAS_QCLAMP, GIALIAS_QCLAMP_SIMCAL);
1578 
1579  efficiency[0] = 0.;
1580  efficiency[1] = 0.;
1581 
1582  }
1583 
1584 
1585  pimage = giraffe_image_new(CPL_TYPE_DOUBLE);
1586  status = giraffe_image_load(pimage, cpl_frame_get_filename(pframe), 0);
1587 
1588  if (status != 0) {
1589  cpl_msg_error(fctid, "Could not load extracted spectra '%s'!",
1590  cpl_frame_get_filename(pframe));
1591 
1592  giraffe_image_delete(pimage);
1593  pimage = NULL;
1594 
1595  giraffe_paf_delete(qc);
1596  qc = NULL;
1597 
1598  return 1;
1599  }
1600 
1601  _pimage = giraffe_image_get(pimage);
1602  cx_assert(_pimage != NULL);
1603 
1604 
1605  ptable = giraffe_table_new();
1606  status = giraffe_table_load(ptable, cpl_frame_get_filename(pframe), 1,
1607  NULL);
1608 
1609  if (status != 0) {
1610  cpl_msg_error(fctid, "Could not load extracted spectra fiber setup!");
1611 
1612  giraffe_table_delete(ptable);
1613  ptable = NULL;
1614 
1615  giraffe_image_delete(pimage);
1616  pimage = NULL;
1617 
1618  giraffe_paf_delete(qc);
1619  qc = NULL;
1620 
1621  return 1;
1622  }
1623 
1624  _ptable = giraffe_table_get(ptable);
1625  cx_assert(_ptable != NULL);
1626 
1627  if (cpl_table_has_column(_ptable, "RP") == FALSE) {
1628 
1629  cpl_msg_warning(fctid, "Column 'RP' not found in fiber setup table!");
1630  cpl_msg_warning(fctid, "Setting lamp efficiencies (%s, %s) to 0.",
1631  GIALIAS_QCLAMP, GIALIAS_QCLAMP_SIMCAL);
1632 
1633  efficiency[0] = 0.;
1634  efficiency[1] = 0.;
1635 
1636  }
1637  else {
1638 
1639  properties = giraffe_image_get_properties(pimage);
1640  cx_assert(properties != NULL);
1641 
1642  if (cpl_propertylist_has(properties, GIALIAS_EXPTIME) == FALSE) {
1643 
1644  cpl_msg_warning(fctid, "Property '%s' not found in '%s'.",
1645  GIALIAS_EXPTIME, cpl_frame_get_filename(rframe));
1646  cpl_msg_warning(fctid, "Setting lamp efficiencies (%s, %s) to 0.",
1647  GIALIAS_QCLAMP, GIALIAS_QCLAMP_SIMCAL);
1648 
1649  efficiency[0] = 0.;
1650  efficiency[1] = 0.;
1651 
1652  }
1653  else {
1654 
1655  cxint fiber = 0;
1656  cxint nb = cpl_image_get_size_y(_pimage);
1657  cxint nf[2] = {0, 0};
1658 
1659  cxdouble exptime = cpl_propertylist_get_double(properties,
1660  GIALIAS_EXPTIME);
1661  cxdouble* _sum = NULL;
1662 
1663  cpl_image* sum = NULL;
1664 
1665 
1666  sum = cpl_image_collapse_create(_pimage, 0);
1667  _sum = cpl_image_get_data_double(sum);
1668 
1669  for (fiber = 0; fiber < cpl_table_get_nrow(_ptable); ++fiber) {
1670 
1671  cxint rp = cpl_table_get_int(_ptable, "RP", fiber, NULL);
1672 
1673  if (rp == -1) {
1674  efficiency[1] += _sum[fiber];
1675  ++nf[1];
1676  }
1677  else {
1678  efficiency[0] += _sum[fiber];
1679  ++nf[0];
1680  }
1681 
1682  }
1683 
1684  _sum = NULL;
1685 
1686  cpl_image_delete(sum);
1687  sum = NULL;
1688 
1689  if (nf[0] == 0) {
1690  cpl_msg_warning(fctid, "No OzPoz fibers found in the "
1691  "current fiber setup.");
1692  cpl_msg_warning(fctid, "Setting lamp efficiency (%s) to 0.",
1693  GIALIAS_QCLAMP);
1694  efficiency[0] = 0.;
1695  }
1696  else {
1697  efficiency[0] /= nf[0] * nb * exptime;
1698  }
1699 
1700  if (nf[1] == 0) {
1701  cpl_msg_warning(fctid, "No simultaneous calibration fibers "
1702  "found in the current fiber setup.");
1703  cpl_msg_warning(fctid, "Setting lamp efficiency (%s) to 0.",
1704  GIALIAS_QCLAMP_SIMCAL);
1705  efficiency[1] = 0.;
1706  }
1707  else {
1708  efficiency[1] /= nf[1] * nb * exptime;
1709  }
1710 
1711  }
1712 
1713  properties = NULL;
1714 
1715  }
1716 
1717  _ptable = NULL;
1718  _pimage = NULL;
1719 
1720  giraffe_table_delete(ptable);
1721  ptable = NULL;
1722 
1723  giraffe_image_delete(pimage);
1724  pimage = NULL;
1725 
1726 
1727  /*
1728  * Load first raw image as reference
1729  */
1730 
1731  rframe = cpl_frameset_find(set, GIFRAME_ARC_SPECTRUM);
1732 
1733  if (rframe == NULL) {
1734  cpl_msg_error(fctid, "Missing raw frame (%s)", GIFRAME_ARC_SPECTRUM);
1735 
1736  giraffe_paf_delete(qc);
1737  qc = NULL;
1738 
1739  return 1;
1740  }
1741 
1742  cpl_msg_info(fctid, "Processing reference frame '%s' (%s)",
1743  cpl_frame_get_filename(rframe), cpl_frame_get_tag(rframe));
1744 
1745  rimage = giraffe_image_new(CPL_TYPE_DOUBLE);
1746  status = giraffe_image_load(rimage, cpl_frame_get_filename(rframe), 0);
1747 
1748  if (status != 0) {
1749 
1750  cpl_msg_error(fctid, "Could not load arc-lamp spectra '%s'!",
1751  cpl_frame_get_filename(rframe));
1752 
1753  giraffe_image_delete(rimage);
1754  rimage = NULL;
1755 
1756  giraffe_paf_delete(qc);
1757  qc = NULL;
1758 
1759  return 1;
1760 
1761  }
1762 
1763  _rimage = giraffe_image_get(rimage);
1764  cx_assert(_rimage != NULL);
1765 
1766 
1767  /*
1768  * Compute mean level of the first raw frame and count the number
1769  * of saturated pixels.
1770  */
1771 
1772  properties = giraffe_image_get_properties(rimage);
1773  cx_assert(properties != NULL);
1774 
1775  if (cpl_propertylist_has(properties, GIALIAS_OVSCX)) {
1776 
1777  cxint _ox = cpl_propertylist_get_int(properties, GIALIAS_OVSCX);
1778  cxint _nx = cpl_image_get_size_x(_rimage) - 2 * CX_MAX(0, _ox) - 1;
1779 
1780  w.x0 = CX_MAX(0, _ox) + 1;
1781  w.x1 = w.x0 + _nx;
1782 
1783  }
1784 
1785  if (cpl_propertylist_has(properties, GIALIAS_OVSCY)) {
1786 
1787  cxint _oy = cpl_propertylist_get_int(properties, GIALIAS_OVSCY);
1788  cxint _ny = cpl_image_get_size_y(_rimage) - 2 * CX_MAX(0, _oy) - 1;
1789 
1790  w.y0 = CX_MAX(0, _oy) + 1;
1791  w.y1 = w.y0 + _ny;
1792 
1793  }
1794 
1795  mean = cpl_image_get_mean_window(_rimage, w.x0, w.y0, w.x1, w.y1);
1796 
1797  pixels = cpl_image_get_data_const(_rimage);
1798  npixel = cpl_image_get_size_x(_rimage) * cpl_image_get_size_y(_rimage);
1799 
1800  for (i = 0; i < npixel; i++) {
1801  if (pixels[i] > saturation) {
1802  ++nsaturated;
1803  }
1804  }
1805 
1806 
1807  /*
1808  * Process dispersion solution
1809  */
1810 
1811  qc = giraffe_qclog_open(0);
1812 
1813  if (qc == NULL) {
1814  cpl_msg_error(fctid, "Cannot create QC1 log!");
1815 
1816  giraffe_image_delete(rimage);
1817  rimage = NULL;
1818 
1819  return 1;
1820  }
1821 
1822  qclog = giraffe_paf_get_properties(qc);
1823  cx_assert(qclog != NULL);
1824 
1825  pframe = giraffe_get_frame(set, GIFRAME_WAVELENGTH_SOLUTION,
1826  CPL_FRAME_GROUP_PRODUCT);
1827 
1828  if (pframe == NULL) {
1829  cpl_msg_error(fctid, "Missing product frame (%s)",
1830  GIFRAME_WAVELENGTH_SOLUTION);
1831 
1832  giraffe_paf_delete(qc);
1833  qc = NULL;
1834 
1835  giraffe_image_delete(rimage);
1836  rimage = NULL;
1837 
1838  return 1;
1839  }
1840 
1841  cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
1842  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
1843 
1844  ptable = giraffe_table_new();
1845  status = giraffe_table_load(ptable, cpl_frame_get_filename(pframe), 1,
1846  NULL);
1847 
1848  if (status != 0) {
1849  cpl_msg_error(fctid, "Could not load dispersion solution '%s'!",
1850  cpl_frame_get_filename(pframe));
1851 
1852  giraffe_table_delete(ptable);
1853  ptable = NULL;
1854 
1855  giraffe_image_delete(rimage);
1856  rimage = NULL;
1857 
1858  giraffe_paf_delete(qc);
1859  qc = NULL;
1860 
1861  return 1;
1862  }
1863 
1864  properties = giraffe_image_get_properties(rimage);
1865  cx_assert(properties != NULL);
1866 
1867  giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
1868  giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
1869  giraffe_propertylist_copy(qclog, "INS.EXP.MODE", properties,
1870  GIALIAS_SETUPNAME);
1871  giraffe_propertylist_copy(qclog, "INS.SLIT.NAME", properties,
1872  GIALIAS_SLITNAME);
1873  giraffe_propertylist_copy(qclog, "INS.GRAT.NAME", properties,
1874  GIALIAS_GRATNAME);
1875  giraffe_propertylist_copy(qclog, "INS.GRAT.WLEN", properties,
1876  GIALIAS_GRATWLEN);
1877  giraffe_propertylist_copy(qclog, "INS.GRAT.ENC", properties,
1878  GIALIAS_GRATPOS);
1879 
1880  cpl_propertylist_update_string(qclog, "PRO.CATG",
1881  cpl_frame_get_tag(pframe));
1882  cpl_propertylist_set_comment(qclog, "PRO.CATG",
1883  "Pipeline product category");
1884 
1885  properties = giraffe_table_get_properties(ptable);
1886  cx_assert(properties != NULL);
1887 
1888  giraffe_propertylist_copy(qclog, "PRO.WSOL.RMS", properties,
1889  GIALIAS_WSOL_RMS);
1890  giraffe_propertylist_copy(qclog, "PRO.WSOL.NLINES", properties,
1891  GIALIAS_WSOL_NLINES);
1892  giraffe_propertylist_copy(qclog, "PRO.WSOL.NACCEPT", properties,
1893  GIALIAS_WSOL_NACCEPT);
1894  giraffe_propertylist_copy(qclog, "PRO.WSOL.NREJECT", properties,
1895  GIALIAS_WSOL_NREJECT);
1896  giraffe_propertylist_copy(qclog, "PRO.SLIT.NFIBRES", properties,
1897  GIALIAS_NFIBERS);
1898 
1899 
1900  giraffe_table_delete(ptable);
1901  ptable = NULL;
1902 
1903  giraffe_qclog_close(qc);
1904  qc = NULL;
1905 
1906 
1907  /*
1908  * Process rebinned arc-lamp spectrum
1909  */
1910 
1911  qc = giraffe_qclog_open(1);
1912 
1913  if (qc == NULL) {
1914  cpl_msg_error(fctid, "Cannot create QC1 log!");
1915  return 1;
1916  }
1917 
1918  qclog = giraffe_paf_get_properties(qc);
1919  cx_assert(qclog != NULL);
1920 
1921  pframe = giraffe_get_frame(set, GIFRAME_ARC_LAMP_RBNSPECTRA,
1922  CPL_FRAME_GROUP_PRODUCT);
1923 
1924  if (pframe == NULL) {
1925  cpl_msg_error(fctid, "Missing product frame (%s)",
1926  GIFRAME_ARC_LAMP_RBNSPECTRA);
1927 
1928  giraffe_image_delete(rimage);
1929  rimage = NULL;
1930 
1931  giraffe_paf_delete(qc);
1932  qc = NULL;
1933 
1934  return 1;
1935  }
1936 
1937  cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
1938  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
1939 
1940  pimage = giraffe_image_new(CPL_TYPE_DOUBLE);
1941  status = giraffe_image_load(pimage, cpl_frame_get_filename(pframe), 0);
1942 
1943  if (status != 0) {
1944  cpl_msg_error(fctid, "Could not load rebinned arc-lamp spectra '%s'!",
1945  cpl_frame_get_filename(pframe));
1946 
1947  giraffe_image_delete(pimage);
1948  pimage = NULL;
1949 
1950  giraffe_image_delete(rimage);
1951  rimage = NULL;
1952 
1953  giraffe_paf_delete(qc);
1954  qc = NULL;
1955 
1956  return 1;
1957  }
1958 
1959  ptable = giraffe_table_new();
1960  status = giraffe_table_load(ptable, cpl_frame_get_filename(pframe), 1,
1961  NULL);
1962 
1963  if (status != 0) {
1964  cpl_msg_error(fctid, "Could not load rebinned arc-lamp spectra '%s'!",
1965  cpl_frame_get_filename(pframe));
1966 
1967  giraffe_table_delete(ptable);
1968  ptable = NULL;
1969 
1970  giraffe_image_delete(pimage);
1971  pimage = NULL;
1972 
1973  giraffe_image_delete(rimage);
1974  rimage = NULL;
1975 
1976  giraffe_paf_delete(qc);
1977  qc = NULL;
1978 
1979  return 1;
1980  }
1981 
1982  properties = giraffe_image_get_properties(rimage);
1983  cx_assert(properties != NULL);
1984 
1985  giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
1986  giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
1987  giraffe_propertylist_copy(qclog, "INS.EXP.MODE", properties,
1988  GIALIAS_SETUPNAME);
1989  giraffe_propertylist_copy(qclog, "INS.SLIT.NAME", properties,
1990  GIALIAS_SLITNAME);
1991  giraffe_propertylist_copy(qclog, "INS.GRAT.NAME", properties,
1992  GIALIAS_GRATNAME);
1993  giraffe_propertylist_copy(qclog, "INS.GRAT.WLEN", properties,
1994  GIALIAS_GRATWLEN);
1995 
1996  cpl_propertylist_update_string(qclog, "PRO.CATG",
1997  cpl_frame_get_tag(pframe));
1998  cpl_propertylist_set_comment(qclog, "PRO.CATG",
1999  "Pipeline product category");
2000 
2001  properties = giraffe_image_get_properties(pimage);
2002  cx_assert(properties != NULL);
2003 
2004  giraffe_propertylist_copy(qclog, "PRO.DATAAVG", properties,
2005  GIALIAS_DATAMEAN);
2006  giraffe_propertylist_copy(qclog, "PRO.DATARMS", properties,
2007  GIALIAS_DATASIG);
2008  giraffe_propertylist_copy(qclog, "PRO.DATAMED", properties,
2009  GIALIAS_DATAMEDI);
2010  giraffe_propertylist_copy(qclog, "PRO.SLIT.NFIBRES", properties,
2011  GIALIAS_NFIBERS);
2012 
2013 
2014  cpl_propertylist_update_double(properties, GIALIAS_QCMEAN, mean);
2015  cpl_propertylist_set_comment(properties, GIALIAS_QCMEAN, "Mean level of "
2016  "first raw frame");
2017 
2018  giraffe_propertylist_copy(qclog, "QC.OUT1.MEAN.RAW", properties,
2019  GIALIAS_QCMEAN);
2020 
2021 
2022  cpl_propertylist_update_int(properties, GIALIAS_QCNSAT, nsaturated);
2023  cpl_propertylist_set_comment(properties, GIALIAS_QCNSAT, "Number of "
2024  "saturated pixels in the first raw frame");
2025 
2026  giraffe_propertylist_copy(qclog, "QC.OUT1.NSAT.RAW", properties,
2027  GIALIAS_QCNSAT);
2028 
2029 
2030  /*
2031  * Calibration lamp monitoring
2032  */
2033 
2034  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP, efficiency[0]);
2035  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP,
2036  "Calibration lamp efficiency");
2037 
2038  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC", properties,
2039  GIALIAS_QCLAMP);
2040 
2041  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP_SIMCAL,
2042  efficiency[1]);
2043  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP_SIMCAL,
2044  "SIMCAL lamp efficiency");
2045 
2046  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC1", properties,
2047  GIALIAS_QCLAMP_SIMCAL);
2048 
2049 
2050  /* Compute rebinned emission line straightness. */
2051 
2052  _pimage = giraffe_image_get(pimage);
2053 
2054  _test = cpl_image_duplicate(_pimage);
2055  _tdata = cpl_image_get_data(_test);
2056 
2057  nx = cpl_image_get_size_x(_test);
2058  ny = cpl_image_get_size_y(_test);
2059 
2060  for (i = 0; i < nx * ny; i++) {
2061  _tdata[i] = _tdata[i] > 0. ? log(_tdata[i]) : 0.;
2062  }
2063 
2064  _tdata = NULL;
2065 
2066  _test0 = cpl_image_extract(_test, 4, 1, 4, ny);
2067 
2068  _test1 = cpl_image_collapse_create(_test, 1);
2069  cpl_image_divide_scalar(_test1, nx);
2070 
2071  cpl_image_delete(_test);
2072  _test = NULL;
2073 
2074 
2075  _test = cpl_image_subtract_create(_test0, _test1);
2076 
2077  cpl_image_delete(_test0);
2078  _test0 = NULL;
2079 
2080  cpl_image_delete(_test1);
2081  _test1 = NULL;
2082 
2083 
2084  _tdata = cpl_image_get_data(_test);
2085 
2086  rms = 0;
2087 
2088  for (i = 0; i < ny; i++) {
2089  _tdata[i] = exp(_tdata[i]);
2090  rms += pow(_tdata[i], 2.);
2091  }
2092 
2093  rms = sqrt(rms / (ny - 1));
2094 
2095  cpl_image_delete(_test);
2096  _test = NULL;
2097 
2098  cpl_propertylist_update_double(properties, GIALIAS_QCRBRMS, rms);
2099  cpl_propertylist_set_comment(properties, GIALIAS_QCRBRMS,
2100  "RMS of rebinned arc-lamp spectra");
2101 
2102  giraffe_propertylist_copy(qclog, "QC.WSOL.REBIN.RMS", properties,
2103  GIALIAS_QCRBRMS);
2104 
2105 
2106  status = giraffe_image_save(pimage, cpl_frame_get_filename(pframe));
2107 
2108  if (status != 0) {
2109  cpl_msg_error(fctid, "Could not save rebinned arc-lamp spectra "
2110  "'%s'!", cpl_frame_get_filename(pframe));
2111 
2112  giraffe_table_delete(ptable);
2113  ptable = NULL;
2114 
2115  giraffe_image_delete(pimage);
2116  pimage = NULL;
2117 
2118  giraffe_image_delete(rimage);
2119  rimage = NULL;
2120 
2121  giraffe_paf_delete(qc);
2122  qc = NULL;
2123 
2124  return 1;
2125  }
2126 
2127  status = giraffe_table_attach(ptable, cpl_frame_get_filename(pframe),
2128  1, NULL);
2129 
2130  if (status != 0) {
2131  cpl_msg_error(fctid, "Could not save rebinned arc-lamp spectra "
2132  "'%s'!", cpl_frame_get_filename(pframe));
2133 
2134  giraffe_table_delete(ptable);
2135  ptable = NULL;
2136 
2137  giraffe_image_delete(pimage);
2138  pimage = NULL;
2139 
2140  giraffe_image_delete(rimage);
2141  rimage = NULL;
2142 
2143  giraffe_paf_delete(qc);
2144  qc = NULL;
2145 
2146  return 1;
2147  }
2148 
2149  giraffe_image_delete(pimage);
2150  pimage = NULL;
2151 
2152  giraffe_table_delete(ptable);
2153  ptable = NULL;
2154 
2155  giraffe_qclog_close(qc);
2156  qc = NULL;
2157 
2158 
2159  /*
2160  * Process line data
2161  */
2162 
2163  qc = giraffe_qclog_open(2);
2164 
2165  if (qc == NULL) {
2166  cpl_msg_error(fctid, "Cannot create QC1 log!");
2167  return 1;
2168  }
2169 
2170  qclog = giraffe_paf_get_properties(qc);
2171  cx_assert(qclog != NULL);
2172 
2173  pframe = giraffe_get_frame(set, GIFRAME_LINE_DATA,
2174  CPL_FRAME_GROUP_PRODUCT);
2175 
2176  if (pframe == NULL) {
2177  cpl_msg_error(fctid, "Missing product frame (%s)",
2178  GIFRAME_LINE_DATA);
2179 
2180  giraffe_image_delete(rimage);
2181  rimage = NULL;
2182 
2183  giraffe_paf_delete(qc);
2184  qc = NULL;
2185 
2186  return 1;
2187  }
2188 
2189  cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
2190  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
2191 
2192 
2193  /*
2194  * Load line data
2195  */
2196 
2197  plines = giraffe_linedata_new();
2198 
2199  status = giraffe_linedata_load(plines, cpl_frame_get_filename(pframe));
2200 
2201  if (status != 0) {
2202  cpl_msg_error(fctid, "Could not load line data '%s'!",
2203  cpl_frame_get_filename(pframe));
2204 
2205  giraffe_linedata_delete(plines);
2206  plines = NULL;
2207 
2208  giraffe_image_delete(rimage);
2209  rimage = NULL;
2210 
2211  giraffe_paf_delete(qc);
2212  qc = NULL;
2213 
2214  return 1;
2215  }
2216 
2217  properties = giraffe_image_get_properties(rimage);
2218  cx_assert(properties != NULL);
2219 
2220  giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
2221  giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
2222  giraffe_propertylist_copy(qclog, "INS.EXP.MODE", properties,
2223  GIALIAS_SETUPNAME);
2224  giraffe_propertylist_copy(qclog, "INS.SLIT.NAME", properties,
2225  GIALIAS_SLITNAME);
2226  giraffe_propertylist_copy(qclog, "INS.GRAT.NAME", properties,
2227  GIALIAS_GRATNAME);
2228  giraffe_propertylist_copy(qclog, "INS.GRAT.WLEN", properties,
2229  GIALIAS_GRATWLEN);
2230 
2231  cpl_propertylist_update_string(qclog, "PRO.CATG",
2232  cpl_frame_get_tag(pframe));
2233  cpl_propertylist_set_comment(qclog, "PRO.CATG",
2234  "Pipeline product category");
2235 
2236 
2237  _pimage = giraffe_linedata_get_data(plines, "FWHM");
2238 
2239  if (_pimage == NULL) {
2240  cpl_msg_error(fctid, "FWHM line data not found!");
2241 
2242  giraffe_linedata_delete(plines);
2243  plines = NULL;
2244 
2245  giraffe_image_delete(rimage);
2246  rimage = NULL;
2247 
2248  giraffe_paf_delete(qc);
2249  qc = NULL;
2250 
2251  return 1;
2252  }
2253 
2254  nx = cpl_image_get_size_x(_pimage);
2255  ny = cpl_image_get_size_y(_pimage);
2256 
2257  pixels = cpl_image_get_data_const(_pimage);
2258 
2259  for (j = 0; j < 2; ++j) {
2260 
2261  register cxint ndata = nx * ny;
2262 
2263  npixel = 0;
2264  mean = 0.;
2265  rms = 0.;
2266 
2267  for (i = 0; i < ndata; ++i) {
2268 
2269  if ((pixels[i] >= fwhm_domain[0]) &&
2270  (pixels[i] < fwhm_domain[1])) {
2271  mean += pixels[i];
2272  ++npixel;
2273  }
2274 
2275  }
2276 
2277  if (npixel == 0) {
2278  cpl_msg_error(fctid, "All line FWHM data are invalid!");
2279 
2280  giraffe_linedata_delete(plines);
2281  plines = NULL;
2282 
2283  giraffe_image_delete(rimage);
2284  rimage = NULL;
2285 
2286  giraffe_paf_delete(qc);
2287  qc = NULL;
2288 
2289  return 1;
2290  }
2291 
2292  mean /= npixel;
2293 
2294  for (i = 0; i < ndata; ++i) {
2295 
2296  if ((pixels[i] >= fwhm_domain[0]) &&
2297  (pixels[i] < fwhm_domain[1])) {
2298  rms += pow(pixels[i] - mean, 2.);
2299  }
2300 
2301  }
2302 
2303  if (npixel > 1) {
2304  rms = sqrt(rms / (npixel - 1));
2305  }
2306 
2307  fwhm_domain[0] = CX_MAX(mean - rmsscale * rms, 0.);
2308  fwhm_domain[1] = CX_MIN(mean + rmsscale * rms, 100.);
2309 
2310  }
2311 
2312 
2313  properties = cpl_propertylist_load(cpl_frame_get_filename(pframe), 0);
2314  cx_assert(properties != NULL);
2315 
2316  if (cpl_propertylist_has(properties, GIALIAS_GRATWLEN) == FALSE) {
2317  cpl_msg_error(fctid, "Grating central wavelength property '%s' not "
2318  "found!", GIALIAS_GRATWLEN);
2319 
2320  cpl_propertylist_delete(properties);
2321  properties = NULL;
2322 
2323  giraffe_linedata_delete(plines);
2324  plines = NULL;
2325 
2326  giraffe_image_delete(rimage);
2327  rimage = NULL;
2328 
2329  giraffe_paf_delete(qc);
2330  qc = NULL;
2331 
2332  return 1;
2333  }
2334 
2335  if (cpl_propertylist_has(properties, GIALIAS_WSOL_SCALE) == FALSE) {
2336  cpl_msg_error(fctid, "Line data property '%s' not found!",
2337  GIALIAS_WSOL_SCALE);
2338 
2339  cpl_propertylist_delete(properties);
2340  properties = NULL;
2341 
2342  giraffe_linedata_delete(plines);
2343  plines = NULL;
2344 
2345  giraffe_image_delete(rimage);
2346  rimage = NULL;
2347 
2348  giraffe_paf_delete(qc);
2349  qc = NULL;
2350 
2351  return 1;
2352  }
2353 
2354  wlcenter = cpl_propertylist_get_double(properties, GIALIAS_GRATWLEN);
2355  pixel2nm = cpl_propertylist_get_double(properties, GIALIAS_WSOL_SCALE);
2356 
2357  mean *= pixel2nm;
2358  rms *= pixel2nm;
2359 
2360  cpl_propertylist_update_double(properties, GIALIAS_QCRESOLAVG, mean);
2361  cpl_propertylist_set_comment(properties, GIALIAS_QCRESOLAVG,
2362  "Average line FWHM [nm]");
2363 
2364  cpl_propertylist_update_double(properties, GIALIAS_QCRESOLRMS, rms);
2365  cpl_propertylist_set_comment(properties, GIALIAS_QCRESOLRMS,
2366  "RMS of line FWHM [nm]");
2367 
2368  cpl_propertylist_update_int(properties, GIALIAS_QCRESOLTOT, nx * ny);
2369  cpl_propertylist_set_comment(properties, GIALIAS_QCRESOLTOT,
2370  "Total number of lines available for FWHM RMS "
2371  "computation");
2372 
2373  cpl_propertylist_update_int(properties, GIALIAS_QCRESOLLIN, npixel);
2374  cpl_propertylist_set_comment(properties, GIALIAS_QCRESOLLIN,
2375  "Number of lines used for FWHM RMS "
2376  "computation");
2377 
2378  cpl_propertylist_update_double(properties, GIALIAS_QCRESOLPWR,
2379  wlcenter / mean);
2380  cpl_propertylist_set_comment(properties, GIALIAS_QCRESOLPWR,
2381  "Resolving power");
2382 
2383  giraffe_propertylist_copy(qclog, "QC.RESOL.MEAN", properties,
2384  GIALIAS_QCRESOLAVG);
2385  giraffe_propertylist_copy(qclog, "QC.RESOL.RMS", properties,
2386  GIALIAS_QCRESOLRMS);
2387  giraffe_propertylist_copy(qclog, "QC.RESOL.NTOTAL", properties,
2388  GIALIAS_QCRESOLTOT);
2389  giraffe_propertylist_copy(qclog, "QC.RESOL.NLINES", properties,
2390  GIALIAS_QCRESOLLIN);
2391  giraffe_propertylist_copy(qclog, "QC.RESOL.POWER", properties,
2392  GIALIAS_QCRESOLPWR);
2393 
2394 
2395  status = giraffe_linedata_save(plines, properties,
2396  cpl_frame_get_filename(pframe));
2397 
2398  if (status != 0) {
2399  cpl_msg_error(fctid, "Could not save line data "
2400  "'%s'!", cpl_frame_get_filename(pframe));
2401 
2402  cpl_propertylist_delete(properties);
2403  properties = NULL;
2404 
2405  giraffe_linedata_delete(plines);
2406  plines = NULL;
2407 
2408  giraffe_image_delete(rimage);
2409  rimage = NULL;
2410 
2411  giraffe_paf_delete(qc);
2412  qc = NULL;
2413 
2414  return 1;
2415  }
2416 
2417  cpl_propertylist_delete(properties);
2418  properties = NULL;
2419 
2420  giraffe_qclog_close(qc);
2421  qc = NULL;
2422 
2423 
2424  /*
2425  * Cleanup
2426  */
2427 
2428  giraffe_image_delete(rimage);
2429 
2430  return 0;
2431 
2432 }
2433 
2434 
2435 /*
2436  * Build table of contents, i.e. the list of available plugins, for
2437  * this module. This function is exported.
2438  */
2439 
2440 int
2441 cpl_plugin_get_info(cpl_pluginlist* list)
2442 {
2443 
2444  cpl_recipe* recipe = cx_calloc(1, sizeof *recipe);
2445  cpl_plugin* plugin = &recipe->interface;
2446 
2447  cpl_plugin_init(plugin,
2448  CPL_PLUGIN_API,
2449  GIRAFFE_BINARY_VERSION,
2450  CPL_PLUGIN_TYPE_RECIPE,
2451  "giwavecalibration",
2452  "Compute dispersion solution from an arc-lamp spectrum.",
2453  "For detailed information please refer to the "
2454  "GIRAFFE pipeline user manual.\nIt is available at "
2455  "http://www.eso.org/pipelines.",
2456  "Giraffe Pipeline",
2457  PACKAGE_BUGREPORT,
2459  giwavecalibration_create,
2460  giwavecalibration_exec,
2461  giwavecalibration_destroy);
2462 
2463  cpl_pluginlist_append(list, plugin);
2464 
2465  return 0;
2466 
2467 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.12.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Mon Mar 24 2014 11:43:53 by doxygen 1.8.2 written by Dimitri van Heesch, © 1997-2004