GIRAFFE Pipeline Reference Manual

gimasterflat.c
1 /*
2  * This file is part of the GIRAFFE Pipeline
3  * Copyright (C) 2002-2019 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23 
24 #include <math.h>
25 
26 #include <cxslist.h>
27 #include <cxmessages.h>
28 #include <cxmemory.h>
29 
30 #include <cpl_recipe.h>
31 #include <cpl_plugininfo.h>
32 #include <cpl_parameterlist.h>
33 #include <cpl_frameset.h>
34 #include <cpl_msg.h>
35 
36 #include "gialias.h"
37 #include "gierror.h"
38 #include "giframe.h"
39 #include "giimage.h"
40 #include "giwindow.h"
41 #include "gifibers.h"
42 #include "gifiberutils.h"
43 #include "gislitgeometry.h"
44 #include "gibias.h"
45 #include "gidark.h"
46 #include "gilocalize.h"
47 #include "gipsf.h"
48 #include "giextract.h"
49 #include "gitransmission.h"
50 #include "gislight.h"
51 #include "giqclog.h"
52 #include "giutils.h"
53 
54 
55 static cxint gimasterflat(cpl_parameterlist* config, cpl_frameset* set);
56 static cxint giqcmasterflat(cpl_frameset* set);
57 
58 
59 /*
60  * Create the recipe instance, i.e. setup the parameter list for this
61  * recipe and make it availble to the application using the interface.
62  */
63 
64 static cxint
65 gimasterflat_create(cpl_plugin* plugin)
66 {
67 
68  cpl_recipe* recipe = (cpl_recipe*)plugin;
69 
70  cpl_parameter* p;
71 
72 
73  giraffe_error_init();
74 
75 
76  /*
77  * We have to provide the option we accept to the application. We
78  * need to setup our parameter list and hook it into the recipe
79  * interface.
80  */
81 
82  recipe->parameters = cpl_parameterlist_new();
83  cx_assert(recipe->parameters != NULL);
84 
85 
86  /*
87  * Fill the parameter list.
88  */
89 
90  /* Fiber selection */
91 
92  giraffe_fibers_config_add(recipe->parameters);
93 
94  /* Bias removal */
95 
96  giraffe_bias_config_add(recipe->parameters);
97 
98  /* Dark subtraction */
99 
100  /* TBD */
101 
102  /* Spectrum localization */
103 
104  giraffe_localize_config_add(recipe->parameters);
105 
106  /* PSF fitting (accurate localization) */
107 
108  giraffe_psf_config_add(recipe->parameters);
109 
110  /* Spectrum extraction */
111 
112  giraffe_extract_config_add(recipe->parameters);
113 
114  /* Relative fiber transmission correction */
115 
116  p = cpl_parameter_new_value("giraffe.masterflat.transmission",
117  CPL_TYPE_BOOL,
118  "Controls the relative fiber transmission "
119  "computation.",
120  "giraffe.masterflat",
121  TRUE);
122 
123  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "transmission");
124  cpl_parameterlist_append(recipe->parameters, p);
125 
126  giraffe_transmission_config_add(recipe->parameters);
127 
128 
129  p = cpl_parameter_new_value("giraffe.masterflat.slight",
130  CPL_TYPE_BOOL,
131  "Controls the scattered light model "
132  "computation.",
133  "giraffe.masterflat",
134  FALSE);
135  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "slight");
136  cpl_parameterlist_append(recipe->parameters, p);
137 
138  giraffe_slight_config_add(recipe->parameters);
139 
140  return 0;
141 
142 }
143 
144 
145 /*
146  * Execute the plugin instance given by the interface.
147  */
148 
149 static cxint
150 gimasterflat_exec(cpl_plugin* plugin)
151 {
152 
153  cpl_recipe* recipe = (cpl_recipe*)plugin;
154 
155  cxint status = 0;
156 
157 
158  if (recipe->parameters == NULL || recipe->frames == NULL) {
159  return 1;
160  }
161 
162  status = gimasterflat(recipe->parameters, recipe->frames);
163 
164  if (status != 0) {
165  return 1;
166  }
167 
168  status = giqcmasterflat(recipe->frames);
169 
170  if (status != 0) {
171  return 1;
172  }
173 
174  return 0;
175 
176 }
177 
178 
179 static cxint
180 gimasterflat_destroy(cpl_plugin* plugin)
181 {
182 
183  cpl_recipe* recipe = (cpl_recipe*)plugin;
184 
185 
186  /*
187  * We just destroy what was created during the plugin initialization
188  * phase, i.e. the parameter list. The frame set is managed by the
189  * application which called us, so we must not touch it,
190  */
191 
192  cpl_parameterlist_delete(recipe->parameters);
193 
194  giraffe_error_clear();
195 
196  return 0;
197 
198 }
199 
200 
201 /*
202  * The actual recipe starts here.
203  */
204 
205 static cxint
206 gimasterflat(cpl_parameterlist* config, cpl_frameset* set)
207 {
208 
209  const cxchar* const _id = "gimasterflat";
210 
211 
212  cxbool transmission = FALSE;
213  cxbool slmodel = FALSE;
214 
215  cxint status = 0;
216  cxint nflats;
217 
218  cxlong i;
219 
220  cxdouble exptime = 0.;
221  cxdouble mean = 0.;
222 
223  cx_slist* flats = NULL;
224 
225  cpl_parameter* p = NULL;
226 
227  cpl_propertylist* properties = NULL;
228 
229  cpl_matrix* biasareas = NULL;
230 
231  cpl_frame* flat_frame = NULL;
232  cpl_frame* mbias_frame = NULL;
233  cpl_frame* mdark_frame = NULL;
234  cpl_frame* bpixel_frame = NULL;
235  cpl_frame* slight_frame = NULL;
236  cpl_frame* mlocy_frame = NULL;
237  cpl_frame* mlocw_frame = NULL;
238  cpl_frame* mlpsf_frame = NULL;
239  cpl_frame* mflat_frame = NULL;
240  cpl_frame* sloc_frame = NULL;
241  cpl_frame* ploc_frame = NULL;
242  cpl_frame* sext_frame = NULL;
243  cpl_frame* slit_frame = NULL;
244  cpl_frame* grating_frame = NULL;
245  cpl_frame* wcal_frame = NULL;
246 
247  GiImage* bpixel = NULL;
248  GiImage* mbias = NULL;
249  GiImage* mdark = NULL;
250  GiImage* slight = NULL;
251  GiImage* sflat = NULL;
252  GiImage* mflat = NULL;
253 
254  GiTable* fibers = NULL;
255  GiTable* grating = NULL;
256  GiTable* slitgeometry = NULL;
257  GiTable* wlsolution = NULL;
258 
259  GiLocalization* sloc = NULL;
260  GiLocalization* ploc = NULL;
261  GiLocalization* mloc = NULL;
262 
263  GiExtraction* extraction = NULL;
264 
265  GiBiasConfig* bias_config = NULL;
266 
267  GiFibersConfig* fibers_config = NULL;
268 
269  GiLocalizeConfig* localize_config = NULL;
270 
271  GiPsfConfig* psf_config = NULL;
272 
273  GiExtractConfig* extract_config = NULL;
274 
275  GiTransmissionConfig* transmission_config = NULL;
276 
277  GiRecipeInfo info = {(cxchar*)_id, 1, NULL, config};
278 
279  GiGroupInfo groups[] = {
280  {GIFRAME_FIBER_FLAT, CPL_FRAME_GROUP_RAW},
281  {GIFRAME_BADPIXEL_MAP, CPL_FRAME_GROUP_CALIB},
282  {GIFRAME_BIAS_MASTER, CPL_FRAME_GROUP_CALIB},
283  {GIFRAME_DARK_MASTER, CPL_FRAME_GROUP_CALIB},
284  {GIFRAME_SCATTERED_LIGHT_MODEL, CPL_FRAME_GROUP_CALIB},
285  {GIFRAME_LOCALIZATION_CENTROID, CPL_FRAME_GROUP_CALIB},
286  {GIFRAME_LOCALIZATION_WIDTH, CPL_FRAME_GROUP_CALIB},
287  {GIFRAME_PSF_DATA, CPL_FRAME_GROUP_CALIB},
288  {GIFRAME_WAVELENGTH_SOLUTION, CPL_FRAME_GROUP_CALIB},
289  {GIFRAME_SLITSETUP, CPL_FRAME_GROUP_CALIB},
290  {GIFRAME_SLITMASTER, CPL_FRAME_GROUP_CALIB},
291  {GIFRAME_GRATING, CPL_FRAME_GROUP_CALIB},
292  {NULL, CPL_FRAME_GROUP_NONE}
293  };
294 
295 
296 
297  if (!config) {
298  cpl_msg_error(_id, "Invalid parameter list! Aborting ...");
299  return 1;
300  }
301 
302  if (!set) {
303  cpl_msg_error(_id, "Invalid frame set! Aborting ...");
304  return 1;
305  }
306 
307  status = giraffe_frameset_set_groups(set, groups);
308 
309  if (status != 0) {
310  cpl_msg_error(_id, "Setting frame group information failed!");
311  return 1;
312  }
313 
314 
315  p = cpl_parameterlist_find(config, "giraffe.masterflat.transmission");
316 
317  if (p != NULL) {
318  transmission = cpl_parameter_get_bool(p);
319  }
320 
321  p = cpl_parameterlist_find(config, "giraffe.masterflat.slight");
322 
323  if (p != NULL) {
324  slmodel = cpl_parameter_get_bool(p);
325  }
326 
327 
328  /*
329  * Verify the frame set contents
330  */
331 
332  nflats = cpl_frameset_count_tags(set, GIFRAME_FIBER_FLAT);
333 
334  if (nflats < 1) {
335  cpl_msg_error(_id, "Too few (%d) raw frames (%s) present in "
336  "frame set! Aborting ...", nflats, GIFRAME_FIBER_FLAT);
337  return 1;
338  }
339 
340 
341  bpixel_frame = cpl_frameset_find(set, GIFRAME_BADPIXEL_MAP);
342 
343  if (!bpixel_frame) {
344  cpl_msg_info(_id, "No bad pixel map present in frame set.");
345  }
346 
347  mbias_frame = cpl_frameset_find(set, GIFRAME_BIAS_MASTER);
348 
349  if (!mbias_frame) {
350  cpl_msg_info(_id, "No master bias present in frame set.");
351  }
352 
353  mdark_frame = cpl_frameset_find(set, GIFRAME_DARK_MASTER);
354 
355  if (!mdark_frame) {
356  cpl_msg_info(_id, "No master dark present in frame set.");
357  }
358 
359  mlocy_frame = cpl_frameset_find(set, GIFRAME_LOCALIZATION_CENTROID);
360 
361  if (!mlocy_frame) {
362  cpl_msg_info(_id, "No master localization (centroid position) "
363  "present in frame set.");
364  }
365 
366  mlocw_frame = cpl_frameset_find(set, GIFRAME_LOCALIZATION_WIDTH);
367 
368  if (!mlocw_frame) {
369  cpl_msg_info(_id, "No master localization (spectrum width) "
370  "present in frame set.");
371  }
372 
373  mlpsf_frame = cpl_frameset_find(set, GIFRAME_PSF_DATA);
374 
375  if (!mlpsf_frame) {
376  cpl_msg_info(_id, "No master localization (PSF parameters) "
377  "present in frame set.");
378  }
379 
380  slight_frame = cpl_frameset_find(set, GIFRAME_SCATTERED_LIGHT_MODEL);
381 
382  if (!slight_frame) {
383  cpl_msg_info(_id, "No scattered light model present in frame set.");
384  }
385 
386  grating_frame = cpl_frameset_find(set, GIFRAME_GRATING);
387 
388  if (!grating_frame) {
389  cpl_msg_info(_id, "No grating data present in frame set. "
390  "Aborting ...");
391  return 1;
392  }
393 
394  slit_frame = giraffe_get_slitgeometry(set);
395 
396  if (!slit_frame) {
397  cpl_msg_info(_id, "No slitgeometry present in frame set. "
398  "Aborting ...");
399  return 1;
400  }
401 
402  wcal_frame = cpl_frameset_find(set, GIFRAME_WAVELENGTH_SOLUTION);
403 
404  if (!wcal_frame) {
405  cpl_msg_info(_id, "No wavelength solution present in frame set.");
406  }
407 
408 
409  /*
410  * Load raw images
411  */
412 
413  flats = cx_slist_new();
414 
415  flat_frame = cpl_frameset_find(set, GIFRAME_FIBER_FLAT);
416 
417  for (i = 0; i < nflats; i++) {
418 
419  const cxchar* filename = cpl_frame_get_filename(flat_frame);
420 
421  GiImage* raw = giraffe_image_new(CPL_TYPE_DOUBLE);
422 
423 
424  status = giraffe_image_load(raw, filename, 0);
425 
426  if (status) {
427  cpl_msg_error(_id, "Cannot load raw flat from '%s'. "
428  "Aborting ...", filename);
429 
430  cx_slist_destroy(flats, (cx_free_func) giraffe_image_delete);
431 
432  return 1;
433  }
434 
435  cx_slist_push_back(flats, raw);
436 
437  flat_frame = cpl_frameset_find(set, NULL);
438 
439  }
440 
441 
442  /*
443  * Create a stacked flat field from the list of raw images. Each raw
444  * image is disposed when it is no longer needed.
445  */
446 
447  // FIXME: For the moment we just do a simple averaging of all flats
448  // in the list, until the image combination is ported.
449 
450  cpl_msg_info(_id, "Averaging flat field frames ...");
451 
452  nflats = (cxint)cx_slist_size(flats);
453  sflat = cx_slist_pop_front(flats);
454 
455  properties = giraffe_image_get_properties(sflat);
456  cx_assert(properties != NULL);
457 
458  exptime = cpl_propertylist_get_double(properties, GIALIAS_EXPTIME);
459 
460  for (i = 1; i < nflats; i++) {
461 
462  cpl_propertylist* _properties;
463 
464  GiImage* flat = cx_slist_pop_front(flats);
465 
466 
467  cpl_image_add(giraffe_image_get(sflat), giraffe_image_get(flat));
468 
469  _properties = giraffe_image_get_properties(flat);
470  cx_assert(_properties != NULL);
471 
472  exptime += cpl_propertylist_get_double(_properties, GIALIAS_EXPTIME);
473 
474  giraffe_image_delete(flat);
475 
476  }
477 
478  cpl_image_divide_scalar(giraffe_image_get(sflat), nflats);
479 
480  cx_assert(cx_slist_empty(flats));
481  cx_slist_delete(flats);
482  flats = NULL;
483 
484 
485  /*
486  * Update stacked flat field properties
487  */
488 
489  cpl_msg_info(_id, "Updating stacked flat field image properties ...");
490 
491  cpl_propertylist_update_double(properties, GIALIAS_EXPTIME,
492  exptime / nflats);
493 
494  cpl_propertylist_update_double(properties, GIALIAS_EXPTTOT, exptime);
495  cpl_propertylist_set_comment(properties, GIALIAS_EXPTTOT,
496  "Total exposure time of all frames "
497  "combined");
498 
499  cpl_propertylist_update_int(properties, GIALIAS_DATANCOM, nflats);
500  cpl_propertylist_set_comment(properties, GIALIAS_DATANCOM, "Number of "
501  "frames combined");
502 
503  cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
504 
505 
506  /*
507  * Prepare for bias subtraction
508  */
509 
510  bias_config = giraffe_bias_config_create(config);
511 
512  if (bias_config->method == GIBIAS_METHOD_MASTER ||
513  bias_config->method == GIBIAS_METHOD_ZMASTER) {
514 
515  if (!mbias_frame) {
516  cpl_msg_error(_id, "Missing master bias frame! Selected bias "
517  "removal method requires a master bias frame!");
518 
519  giraffe_bias_config_destroy(bias_config);
520  giraffe_image_delete(sflat);
521 
522  return 1;
523  }
524  else {
525  const cxchar* filename = cpl_frame_get_filename(mbias_frame);
526 
527 
528  mbias = giraffe_image_new(CPL_TYPE_DOUBLE);
529  status = giraffe_image_load(mbias, filename, 0);
530 
531  if (status) {
532  cpl_msg_error(_id, "Cannot load master bias from '%s'. "
533  "Aborting ...", filename);
534 
535  giraffe_bias_config_destroy(bias_config);
536  giraffe_image_delete(sflat);
537 
538  return 1;
539  }
540  }
541  }
542 
543 
544  /*
545  * Load bad pixel map if it is present in the frame set.
546  */
547 
548  if (bpixel_frame) {
549 
550  const cxchar* filename = cpl_frame_get_filename(bpixel_frame);
551 
552 
553  bpixel = giraffe_image_new(CPL_TYPE_INT);
554  status = giraffe_image_load(bpixel, filename, 0);
555 
556  if (status) {
557  cpl_msg_error(_id, "Cannot load bad pixel map from '%s'. "
558  "Aborting ...", filename);
559 
560  if (mbias != NULL) {
561  giraffe_image_delete(mbias);
562  mbias = NULL;
563  }
564 
565  giraffe_bias_config_destroy(bias_config);
566  giraffe_image_delete(sflat);
567 
568  return 1;
569  }
570 
571  }
572 
573 
574  /*
575  * Compute and remove the bias from the stacked flat field frame.
576  */
577 
578  mflat = giraffe_image_new(CPL_TYPE_DOUBLE);
579 
580  status = giraffe_bias_remove(mflat, sflat, mbias, bpixel, biasareas,
581  bias_config);
582 
583  giraffe_image_delete(sflat);
584  sflat = NULL;
585 
586  giraffe_image_delete(mbias);
587  mbias = NULL;
588 
589  giraffe_bias_config_destroy(bias_config);
590 
591  if (status) {
592  cpl_msg_error(_id, "Bias removal failed. Aborting ...");
593 
594  giraffe_image_delete(mflat);
595  mflat = NULL;
596 
597  if (bpixel != NULL) {
598  giraffe_image_delete(bpixel);
599  bpixel = NULL;
600  }
601 
602  return 1;
603  }
604 
605 
606  /*
607  * Load master dark if it is present in the frame set and correct
608  * the master flat field for the dark current.
609  */
610 
611  if (mdark_frame) {
612 
613  const cxchar* filename = cpl_frame_get_filename(mdark_frame);
614 
615  GiDarkConfig dark_config = {GIDARK_METHOD_ZMASTER, 0.};
616 
617 
618  mdark = giraffe_image_new(CPL_TYPE_DOUBLE);
619  status = giraffe_image_load(mdark, filename, 0);
620 
621  if (status != 0) {
622  cpl_msg_error(_id, "Cannot load master dark from '%s'. "
623  "Aborting ...", filename);
624 
625  giraffe_image_delete(mflat);
626  mflat = NULL;
627 
628  if (bpixel != NULL) {
629  giraffe_image_delete(bpixel);
630  bpixel = NULL;
631  }
632 
633  return 1;
634  }
635 
636  status = giraffe_subtract_dark(mflat, mdark, bpixel, NULL,
637  &dark_config);
638 
639  if (status != 0) {
640  cpl_msg_error(_id, "Dark subtraction failed! Aborting ...");
641 
642  giraffe_image_delete(mdark);
643  mdark = NULL;
644 
645  giraffe_image_delete(mflat);
646  mflat = NULL;
647 
648  if (bpixel != NULL) {
649  giraffe_image_delete(bpixel);
650  bpixel = NULL;
651  }
652 
653  return 1;
654  }
655 
656  giraffe_image_delete(mdark);
657  mdark = NULL;
658 
659  }
660 
661 
662  /*
663  * Update master flat field properties, save the master flat field frame
664  * and register it as product.
665  */
666 
667  cpl_msg_info(_id, "Writing master flat field image ...");
668 
669  giraffe_image_add_info(mflat, &info, set);
670 
671  mflat_frame = giraffe_frame_create_image(mflat,
672  GIFRAME_FIBER_FLAT_MASTER,
673  CPL_FRAME_LEVEL_FINAL,
674  TRUE, TRUE);
675 
676  if (mflat_frame == NULL) {
677  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
678 
679  giraffe_image_delete(mflat);
680 
681  if (bpixel) {
682  giraffe_image_delete(bpixel);
683  }
684 
685  return 1;
686  }
687 
688  cpl_frameset_insert(set, mflat_frame);
689 
690 
691  /*
692  * Determine fiber setup
693  */
694 
695  cpl_msg_info(_id, "Recipe Step: Fiber setup");
696 
697  fibers_config = giraffe_fibers_config_create(config);
698  flat_frame = cpl_frameset_find(set, GIFRAME_FIBER_FLAT);
699 
700  cpl_msg_info(_id, "Building fiber setup for frame '%s'.",
701  cpl_frame_get_filename(flat_frame));
702 
703  if (mlocy_frame == NULL) {
704 
705  GiTable *active_fibers = NULL;
706 
707  if (slit_frame != NULL) {
708 
709  const cxchar *tag = cpl_frame_get_tag(slit_frame);
710  const cxchar *filename = cpl_frame_get_filename(slit_frame);
711 
712  if (strcmp(tag, GIFRAME_SLITSETUP) == 0) {
713 
714  active_fibers = giraffe_table_new();
715  status = giraffe_table_load(active_fibers,
716  cpl_frame_get_filename(slit_frame),
717  1, "SLIT_GEOMETRY_SETUP");
718 
719  if (status) {
720  cpl_msg_error(_id, "Cannot load expected fiber setup from "
721  "slit geometry '%s'! Aborting ...", filename);
722 
723  giraffe_table_delete(active_fibers);
724  giraffe_image_delete(mflat);
725 
726  if (bpixel) {
727  giraffe_image_delete(bpixel);
728  }
729 
730  giraffe_fibers_config_destroy(fibers_config);
731 
732  return 1;
733  }
734  }
735  }
736 
737  fibers = giraffe_fibers_select(flat_frame, active_fibers,
738  fibers_config);
739 
740  if (!fibers) {
741  cpl_msg_error(_id, "Cannot determine fiber setup from flat "
742  "field frame '%s'! Aborting ...",
743  cpl_frame_get_filename(flat_frame));
744 
745  giraffe_table_delete(active_fibers);
746  giraffe_image_delete(mflat);
747 
748  if (bpixel) {
749  giraffe_image_delete(bpixel);
750  }
751 
752  giraffe_fibers_config_destroy(fibers_config);
753 
754  return 1;
755  }
756 
757  giraffe_table_delete(active_fibers);
758  active_fibers = NULL;
759 
760  cpl_msg_info(_id, "Fiber setup taken from flat field frame '%s'.",
761  cpl_frame_get_filename(flat_frame));
762 
763  }
764  else {
765 
766  cpl_msg_info(_id, "Fiber reference setup taken from localization "
767  "frame '%s'.", cpl_frame_get_filename(mlocy_frame));
768 
769  fibers = giraffe_fibers_setup(flat_frame, mlocy_frame);
770 
771  if (!fibers) {
772  cpl_msg_error(_id, "Cannot create fiber setup for frame '%s'! "
773  "Aborting ...", cpl_frame_get_filename(flat_frame));
774 
775  giraffe_image_delete(mflat);
776 
777  if (bpixel) {
778  giraffe_image_delete(bpixel);
779  }
780 
781  giraffe_fibers_config_destroy(fibers_config);
782 
783  return 1;
784  }
785 
786  }
787 
788  giraffe_fibers_config_destroy(fibers_config);
789 
790 
791  /*
792  * Perform spectrum localization on the created master flat field.
793  */
794 
795  if (mlocy_frame != NULL) {
796 
797  const cxchar* filename = cpl_frame_get_filename(mlocy_frame);
798 
799 
800  mloc = giraffe_localization_new();
801  mloc->locy = giraffe_image_new(CPL_TYPE_DOUBLE);
802  status = giraffe_image_load(mloc->locy, filename, 0);
803 
804  if (status) {
805  cpl_msg_error(_id, "Cannot load master localization centroids "
806  "from '%s'. Aborting ...", filename);
807 
808  giraffe_localization_delete(mloc);
809  mloc = NULL;
810 
811  giraffe_table_delete(fibers);
812  giraffe_image_delete(mflat);
813 
814  if (bpixel) {
815  giraffe_image_delete(bpixel);
816  }
817 
818  giraffe_localize_config_destroy(localize_config);
819 
820  return 1;
821  }
822 
823  }
824 
825  localize_config = giraffe_localize_config_create(config);
826 
827  if (localize_config->full == FALSE) {
828 
829  // FIXME: For the time being just release the memory acquired.
830  // In future the master localization has to be loaded here
831  // and its completeness has to be checked.
832 
833  cpl_msg_error(_id, "Localization computation using only SIWC spectra "
834  "is not yet supported! Aborting ...");
835 
836  giraffe_table_delete(fibers);
837  giraffe_image_delete(mflat);
838 
839  if (bpixel) {
840  giraffe_image_delete(bpixel);
841  }
842 
843  giraffe_localize_config_destroy(localize_config);
844 
845  return 1;
846 
847  }
848 
849  sloc = giraffe_localization_new();
850 
851  status = giraffe_localize_spectra(sloc, mflat, fibers, mloc,
852  bpixel, localize_config);
853 
854  if (status) {
855  cpl_msg_error(_id, "Spectrum localization failed! Aborting ...");
856 
857 
858  giraffe_localization_destroy(sloc);
859 
860  if (mloc) {
861  giraffe_localization_destroy(mloc);
862  }
863 
864  giraffe_table_delete(fibers);
865  giraffe_image_delete(mflat);
866 
867  if (bpixel) {
868  giraffe_image_delete(bpixel);
869  }
870 
871  giraffe_localize_config_destroy(localize_config);
872 
873  return 1;
874  }
875 
876  giraffe_localize_config_destroy(localize_config);
877 
878  if (mloc != NULL) {
879  giraffe_localization_destroy(mloc);
880  }
881 
882 
883  /*
884  * Save the computed localization and register its components as
885  * products.
886  */
887 
888  cpl_msg_info(_id, "Writing fiber localization ...");
889 
890 
891  /* Localization centroids */
892 
893  giraffe_image_add_info(sloc->locy, &info, set);
894 
895  sloc_frame = giraffe_frame_create_image(sloc->locy,
896  GIFRAME_LOCALIZATION_CENTROID,
897  CPL_FRAME_LEVEL_FINAL,
898  TRUE, TRUE);
899 
900  if (sloc_frame == NULL) {
901  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
902 
903  giraffe_localization_destroy(sloc);
904 
905  giraffe_table_delete(fibers);
906  giraffe_image_delete(mflat);
907 
908  if (bpixel) {
909  giraffe_image_delete(bpixel);
910  }
911 
912  return 1;
913  }
914 
915  status = giraffe_fiberlist_attach(sloc_frame, fibers);
916 
917  if (status) {
918  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
919  "Aborting ...", cpl_frame_get_filename(sloc_frame));
920 
921  cpl_frame_delete(sloc_frame);
922 
923  giraffe_localization_destroy(sloc);
924 
925  giraffe_table_delete(fibers);
926  giraffe_image_delete(mflat);
927 
928  if (bpixel) {
929  giraffe_image_delete(bpixel);
930  }
931 
932  return 1;
933  }
934 
935  cpl_frameset_insert(set, sloc_frame);
936 
937 
938  /* Localization half-width */
939 
940  giraffe_image_add_info(sloc->locw, &info, set);
941 
942  sloc_frame = giraffe_frame_create_image(sloc->locw,
943  GIFRAME_LOCALIZATION_WIDTH,
944  CPL_FRAME_LEVEL_FINAL,
945  TRUE, TRUE);
946 
947  if (sloc_frame == NULL) {
948  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
949 
950  giraffe_localization_destroy(sloc);
951 
952  giraffe_table_delete(fibers);
953  giraffe_image_delete(mflat);
954 
955  if (bpixel) {
956  giraffe_image_delete(bpixel);
957  }
958 
959  return 1;
960  }
961 
962  status = giraffe_fiberlist_attach(sloc_frame, fibers);
963 
964  if (status) {
965  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
966  "Aborting ...", cpl_frame_get_filename(sloc_frame));
967 
968  cpl_frame_delete(sloc_frame);
969 
970  giraffe_localization_destroy(sloc);
971 
972  giraffe_table_delete(fibers);
973  giraffe_image_delete(mflat);
974 
975  if (bpixel) {
976  giraffe_image_delete(bpixel);
977  }
978 
979  return 1;
980  }
981 
982  cpl_frameset_insert(set, sloc_frame);
983 
984  /* Localization fit coefficients */
985 
986  if (sloc->locc) {
987 
988  giraffe_table_add_info(sloc->locc, &info, set);
989 
990  sloc_frame = giraffe_frame_create_table(sloc->locc,
991  GIFRAME_LOCALIZATION_FIT,
992  CPL_FRAME_LEVEL_FINAL,
993  TRUE, TRUE);
994 
995  if (sloc_frame == NULL) {
996  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
997 
998  giraffe_localization_destroy(sloc);
999 
1000  giraffe_table_delete(fibers);
1001  giraffe_image_delete(mflat);
1002 
1003  if (bpixel) {
1004  giraffe_image_delete(bpixel);
1005  }
1006 
1007  return 1;
1008  }
1009  }
1010 
1011  cpl_frameset_insert(set, sloc_frame);
1012 
1013 
1014  /*
1015  * Remove the reference index from the fiber setup, since the just
1016  * created localization is now used as position reference of the fibers.
1017  */
1018 
1020 
1021 
1022  /*
1023  * Compute localization mask from the PSF profile of the fibers
1024  */
1025 
1026  psf_config = giraffe_psf_config_create(config);
1027 
1028  if (psf_config == NULL) {
1029  cpl_msg_error(_id, "Invalid fiber profile fit configuration!");
1030 
1031  giraffe_localization_destroy(sloc);
1032  sloc = NULL;
1033 
1034  giraffe_table_delete(fibers);
1035  fibers = NULL;
1036 
1037  giraffe_image_delete(mflat);
1038  mflat = NULL;
1039 
1040  if (bpixel != NULL) {
1041  giraffe_image_delete(bpixel);
1042  bpixel = NULL;
1043  }
1044 
1045  return 1;
1046 
1047  }
1048 
1049  ploc = giraffe_localization_new();
1050 
1051  status = giraffe_compute_fiber_profiles(ploc, mflat, fibers, sloc,
1052  bpixel, psf_config);
1053 
1054  if (status != 0) {
1055  cpl_msg_error(_id, "Fiber profile computation failed! Aborting ...");
1056 
1057  giraffe_localization_destroy(ploc);
1058  ploc = NULL;
1059 
1060  giraffe_psf_config_destroy(psf_config);
1061  psf_config = NULL;
1062 
1063  giraffe_localization_destroy(sloc);
1064  sloc = NULL;
1065 
1066  giraffe_table_delete(fibers);
1067  fibers = NULL;
1068 
1069  giraffe_image_delete(mflat);
1070  mflat = NULL;
1071 
1072  if (bpixel != NULL) {
1073  giraffe_image_delete(bpixel);
1074  bpixel = NULL;
1075  }
1076 
1077  return 1;
1078 
1079  }
1080 
1081  giraffe_psf_config_destroy(psf_config);
1082  psf_config = NULL;
1083 
1084  giraffe_localization_destroy(sloc);
1085  sloc = NULL;
1086 
1087 
1088  /*
1089  * Save the computed fiber traces and register its components as
1090  * products.
1091  */
1092 
1093  cpl_msg_info(_id, "Writing fiber traces ...");
1094 
1095 
1096  /* Fiber profile centroids */
1097 
1098  giraffe_image_add_info(ploc->locy, &info, set);
1099 
1100  ploc_frame = giraffe_frame_create_image(ploc->locy,
1101  GIFRAME_PSF_CENTROID,
1102  CPL_FRAME_LEVEL_FINAL,
1103  TRUE, TRUE);
1104 
1105  if (ploc_frame == NULL) {
1106  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1107 
1108  giraffe_localization_destroy(ploc);
1109  ploc = NULL;
1110 
1111  giraffe_table_delete(fibers);
1112  fibers = NULL;
1113 
1114  giraffe_image_delete(mflat);
1115  mflat = NULL;
1116 
1117  if (bpixel != NULL) {
1118  giraffe_image_delete(bpixel);
1119  bpixel = NULL;
1120  }
1121 
1122  return 1;
1123  }
1124 
1125  status = giraffe_fiberlist_attach(ploc_frame, fibers);
1126 
1127  if (status != 0) {
1128  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
1129  "Aborting ...", cpl_frame_get_filename(ploc_frame));
1130 
1131  cpl_frame_delete(ploc_frame);
1132 
1133  giraffe_localization_destroy(ploc);
1134  ploc = NULL;
1135 
1136  giraffe_table_delete(fibers);
1137  fibers = NULL;
1138 
1139  giraffe_image_delete(mflat);
1140  mflat = NULL;
1141 
1142  if (bpixel != NULL) {
1143  giraffe_image_delete(bpixel);
1144  bpixel = NULL;
1145  }
1146 
1147  return 1;
1148  }
1149 
1150  cpl_frameset_insert(set, ploc_frame);
1151 
1152 
1153  /* Fiber profile widths */
1154 
1155  giraffe_image_add_info(ploc->locw, &info, set);
1156 
1157  ploc_frame = giraffe_frame_create_image(ploc->locw,
1158  GIFRAME_PSF_WIDTH,
1159  CPL_FRAME_LEVEL_FINAL,
1160  TRUE, TRUE);
1161 
1162  if (ploc_frame == NULL) {
1163  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1164 
1165  giraffe_localization_destroy(ploc);
1166  ploc = NULL;
1167 
1168  giraffe_table_delete(fibers);
1169  fibers = NULL;
1170 
1171  giraffe_image_delete(mflat);
1172  mflat = NULL;
1173 
1174  if (bpixel != NULL) {
1175  giraffe_image_delete(bpixel);
1176  bpixel = NULL;
1177  }
1178 
1179  return 1;
1180  }
1181 
1182  status = giraffe_fiberlist_attach(ploc_frame, fibers);
1183 
1184  if (status != 0) {
1185  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
1186  "Aborting ...", cpl_frame_get_filename(ploc_frame));
1187 
1188  cpl_frame_delete(ploc_frame);
1189 
1190  giraffe_localization_destroy(ploc);
1191  ploc = NULL;
1192 
1193  giraffe_table_delete(fibers);
1194  fibers = NULL;
1195 
1196  giraffe_image_delete(mflat);
1197  mflat = NULL;
1198 
1199  if (bpixel != NULL) {
1200  giraffe_image_delete(bpixel);
1201  bpixel = NULL;
1202  }
1203 
1204  return 1;
1205  }
1206 
1207  cpl_frameset_insert(set, ploc_frame);
1208 
1209 
1210  /* Fiber profile centroid and widths fit coefficients */
1211 
1212  giraffe_table_add_info(ploc->locc, &info, set);
1213 
1214  ploc_frame = giraffe_frame_create_table(ploc->locc,
1215  GIFRAME_PSF_FIT,
1216  CPL_FRAME_LEVEL_FINAL,
1217  TRUE, TRUE);
1218 
1219  if (ploc_frame == NULL) {
1220  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1221 
1222  giraffe_localization_destroy(ploc);
1223  ploc = NULL;
1224 
1225  giraffe_table_delete(fibers);
1226  fibers = NULL;
1227 
1228  giraffe_image_delete(mflat);
1229  mflat = NULL;
1230 
1231  if (bpixel != NULL) {
1232  giraffe_image_delete(bpixel);
1233  bpixel = NULL;
1234  }
1235 
1236  return 1;
1237  }
1238 
1239  status = giraffe_fiberlist_attach(ploc_frame, fibers);
1240 
1241  if (status != 0) {
1242  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
1243  "Aborting ...", cpl_frame_get_filename(ploc_frame));
1244 
1245  cpl_frame_delete(ploc_frame);
1246 
1247  giraffe_localization_destroy(ploc);
1248  ploc = NULL;
1249 
1250  giraffe_table_delete(fibers);
1251  fibers = NULL;
1252 
1253  giraffe_image_delete(mflat);
1254  mflat = NULL;
1255 
1256  if (bpixel != NULL) {
1257  giraffe_image_delete(bpixel);
1258  bpixel = NULL;
1259  }
1260 
1261  return 1;
1262  }
1263 
1264  cpl_frameset_insert(set, ploc_frame);
1265 
1266 
1267  if (ploc->psf) {
1268 
1269  GiFrameCreator creator = (GiFrameCreator) giraffe_psfdata_save;
1270 
1271  properties = giraffe_image_get_properties(ploc->locy);
1272 
1273  ploc_frame = giraffe_frame_create(GIFRAME_PSF_DATA,
1274  CPL_FRAME_LEVEL_FINAL,
1275  properties, ploc->psf,
1276  NULL,
1277  creator);
1278 
1279  if (ploc_frame == NULL) {
1280  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1281 
1282  giraffe_localization_destroy(ploc);
1283  ploc = NULL;
1284 
1285  giraffe_table_delete(fibers);
1286  fibers = NULL;
1287 
1288  giraffe_image_delete(mflat);
1289  mflat = NULL;
1290 
1291  if (bpixel != NULL) {
1292  giraffe_image_delete(bpixel);
1293  bpixel = NULL;
1294  }
1295 
1296  return 1;
1297  }
1298 
1299  status = giraffe_fiberlist_attach(ploc_frame, fibers);
1300 
1301  if (status != 0) {
1302  cpl_msg_error(_id, "Cannot attach fiber setup to local "
1303  "file '%s'! Aborting ...",
1304  cpl_frame_get_filename(ploc_frame));
1305 
1306  cpl_frame_delete(ploc_frame);
1307 
1308  giraffe_localization_destroy(ploc);
1309  ploc = NULL;
1310 
1311  giraffe_table_delete(fibers);
1312  fibers = NULL;
1313 
1314  giraffe_image_delete(mflat);
1315  mflat = NULL;
1316 
1317  if (bpixel != NULL) {
1318  giraffe_image_delete(bpixel);
1319  bpixel = NULL;
1320  }
1321 
1322  return 1;
1323  }
1324 
1325  cpl_frameset_insert(set, ploc_frame);
1326 
1327  }
1328 
1329 
1330  /*
1331  * Optional scattered light model computation
1332  */
1333 
1334  // FIXME: Check whether scattered light modeling code should stay here!
1335 
1336  if (slmodel == TRUE) {
1337 
1338  cpl_frame* slmodel_frame = NULL;
1339 
1340  GiSLightConfig* slight_config = NULL;
1341 
1342 
1343  cpl_msg_info(_id, "Computing scattered light model ...");
1344 
1345  slight_config = giraffe_slight_config_create(config);
1346 
1347  if (slight_config == NULL) {
1348  cpl_msg_error(_id, "Invalid scattered light model "
1349  "configuration!");
1350 
1351  giraffe_table_delete(fibers);
1352  giraffe_image_delete(mflat);
1353 
1354  if (bpixel) {
1355  giraffe_image_delete(bpixel);
1356  }
1357 
1358  giraffe_localization_destroy(ploc);
1359  ploc = NULL;
1360 
1361  return 1;
1362 
1363  }
1364 
1365  slight = giraffe_image_new(CPL_TYPE_DOUBLE);
1366 
1367  status = giraffe_adjust_scattered_light(slight, mflat, ploc,
1368  bpixel, NULL, slight_config);
1369 
1370  if (status != 0) {
1371  cpl_msg_error(_id, "Scattered light model computation failed! "
1372  "Aborting ...");
1373 
1374  giraffe_image_delete(slight);
1375 
1376  giraffe_slight_config_destroy(slight_config);
1377 
1378  giraffe_table_delete(fibers);
1379  giraffe_image_delete(mflat);
1380 
1381  if (bpixel != NULL) {
1382  giraffe_image_delete(bpixel);
1383  bpixel = NULL;
1384  }
1385 
1386  giraffe_localization_destroy(ploc);
1387  ploc = NULL;
1388 
1389  return 1;
1390  }
1391 
1392 
1393  giraffe_slight_config_destroy(slight_config);
1394  slight_config = NULL;
1395 
1396 
1397  /*
1398  * Save scattered light model
1399  */
1400 
1401  cpl_msg_info(_id, "Writing scattered light model ...");
1402 
1403  giraffe_image_add_info(slight, &info, set);
1404 
1405  slmodel_frame =
1407  GIFRAME_SCATTERED_LIGHT_MODEL,
1408  CPL_FRAME_LEVEL_FINAL,
1409  TRUE, TRUE);
1410 
1411  if (slmodel_frame == NULL) {
1412  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1413 
1414  giraffe_image_delete(slight);
1415 
1416  giraffe_table_delete(fibers);
1417  giraffe_image_delete(mflat);
1418 
1419  if (bpixel != NULL) {
1420  giraffe_image_delete(bpixel);
1421  bpixel = NULL;
1422  }
1423 
1424  giraffe_localization_destroy(ploc);
1425  ploc = NULL;
1426 
1427  return 1;
1428  }
1429 
1430  cpl_frameset_insert(set, slmodel_frame);
1431 
1432  giraffe_image_delete(slight);
1433  slight = NULL;
1434 
1435  }
1436 
1437 
1438  /*
1439  * Perform spectrum extraction on the master flat field.
1440  */
1441 
1442  cpl_msg_info(_id, "Extracting spectra ...");
1443 
1444  if (slight_frame != NULL) {
1445 
1446  const cxchar* filename = cpl_frame_get_filename(slight_frame);
1447 
1448 
1449  slight = giraffe_image_new(CPL_TYPE_DOUBLE);
1450  status = giraffe_image_load(slight, filename, 0);
1451 
1452  if (status != 0) {
1453  cpl_msg_error(_id, "Cannot load scattered light model from '%s'. "
1454  "Aborting ...", filename);
1455 
1456  giraffe_image_delete(slight);
1457 
1458  giraffe_table_delete(fibers);
1459  giraffe_image_delete(mflat);
1460 
1461  if (bpixel != NULL) {
1462  giraffe_image_delete(bpixel);
1463  bpixel = NULL;
1464  }
1465 
1466  giraffe_localization_destroy(ploc);
1467  ploc = NULL;
1468 
1469  return 1;
1470 
1471  }
1472 
1473  }
1474 
1475  extract_config = giraffe_extract_config_create(config);
1476 
1477  extraction = giraffe_extraction_new();
1478 
1479  status = giraffe_extract_spectra(extraction, mflat, fibers,
1480  ploc, bpixel, slight,
1481  extract_config);
1482 
1483  if (status != 0) {
1484  cpl_msg_error(_id, "Spectrum extraction failed! Aborting ...");
1485 
1486  giraffe_extraction_destroy(extraction);
1487 
1488  giraffe_image_delete(slight);
1489 
1490  giraffe_localization_destroy(ploc);
1491  ploc = NULL;
1492 
1493  giraffe_table_delete(fibers);
1494  giraffe_image_delete(mflat);
1495 
1496  if (bpixel != NULL) {
1497  giraffe_image_delete(bpixel);
1498  bpixel = NULL;
1499  }
1500 
1501  giraffe_extract_config_destroy(extract_config);
1502 
1503  return 1;
1504  }
1505 
1506  giraffe_image_delete(slight);
1507  giraffe_image_delete(mflat);
1508 
1509  if (bpixel != NULL) {
1510  giraffe_image_delete(bpixel);
1511  bpixel = NULL;
1512  }
1513 
1514  giraffe_extract_config_destroy(extract_config);
1515 
1516 
1517  /*
1518  * Normalize extracted spectra and errors
1519  */
1520 
1521  mean = cpl_image_get_mean(giraffe_image_get(extraction->spectra));
1522 
1523  cpl_image_divide_scalar(giraffe_image_get(extraction->spectra), mean);
1524 
1525  properties = giraffe_image_get_properties(extraction->spectra);
1526  cpl_propertylist_update_double(properties, GIALIAS_FLAT_SCALE, mean);
1527  cpl_propertylist_set_comment(properties, GIALIAS_FLAT_SCALE,
1528  "Flat field scale factor");
1529 
1530 
1531  cpl_image_divide_scalar(giraffe_image_get(extraction->error), mean);
1532 
1533  properties = giraffe_image_get_properties(extraction->error);
1534  cpl_propertylist_update_double(properties, GIALIAS_FLAT_SCALE, mean);
1535  cpl_propertylist_set_comment(properties, GIALIAS_FLAT_SCALE,
1536  "Flat field scale factor");
1537 
1538 
1539  /*
1540  * Compute relative fiber transmission correction.
1541  */
1542 
1543  if (transmission == TRUE) {
1544 
1545  const cxchar* filename = NULL;
1546 
1547 
1548  transmission_config = giraffe_transmission_config_create(config);
1549 
1550  cpl_msg_info(_id, "Computing relative fiber transmission ...");
1551 
1552  filename = cpl_frame_get_filename(grating_frame);
1553 
1554  grating = giraffe_table_new();
1555  status = giraffe_table_load(grating, filename, 1, NULL);
1556 
1557  if (status != 0) {
1558  cpl_msg_error(_id, "Cannot load grating data from '%s'. "
1559  "Aborting ...", filename);
1560 
1561  giraffe_table_delete(grating);
1562 
1563  giraffe_transmission_config_destroy(transmission_config);
1564 
1565  giraffe_extraction_destroy(extraction);
1566 
1567  giraffe_localization_destroy(ploc);
1568  ploc = NULL;
1569 
1570  giraffe_table_delete(fibers);
1571 
1572  return 1;
1573  }
1574 
1575 
1576  filename = cpl_frame_get_filename(slit_frame);
1577 
1578  slitgeometry = giraffe_slitgeometry_load(fibers, filename, 1, NULL);
1579 
1580  if (slitgeometry == NULL) {
1581  cpl_msg_error(_id, "Cannot load slit geometry data from '%s'. "
1582  "Aborting ...", filename);
1583 
1584  giraffe_table_delete(grating);
1585 
1586  giraffe_transmission_config_destroy(transmission_config);
1587 
1588  giraffe_extraction_destroy(extraction);
1589 
1590  giraffe_localization_destroy(ploc);
1591  ploc = NULL;
1592 
1593  giraffe_table_delete(fibers);
1594 
1595  return 1;
1596  }
1597  else {
1598 
1599  /*
1600  * Check whether the contains the positions for all fibers
1601  * provided by the fiber setup. If this is not the case
1602  * this is an error.
1603  */
1604 
1605  if (giraffe_fiberlist_compare(slitgeometry, fibers) != 1) {
1606  cpl_msg_error(_id, "Slit geometry data from '%s' is not "
1607  "applicable for current fiber setup! "
1608  "Aborting ...", filename);
1609 
1610  giraffe_table_delete(slitgeometry);
1611  giraffe_table_delete(grating);
1612 
1613  giraffe_transmission_config_destroy(transmission_config);
1614 
1615  giraffe_extraction_destroy(extraction);
1616 
1617  giraffe_localization_destroy(ploc);
1618  ploc = NULL;
1619 
1620  giraffe_table_delete(fibers);
1621 
1622  return 1;
1623  }
1624 
1625  }
1626 
1627 
1628  if (wcal_frame != NULL) {
1629 
1630  filename = cpl_frame_get_filename(wcal_frame);
1631 
1632  cpl_msg_info(_id, "Loading wavelength solution from '%s'",
1633  filename);
1634 
1635  wlsolution = giraffe_table_new();
1636  status = giraffe_table_load(wlsolution, filename, 1, NULL);
1637 
1638  if (status != 0) {
1639  cpl_msg_error(_id, "Cannot load wavelength solution from "
1640  "'%s'. Aborting ...", filename);
1641 
1642  giraffe_table_delete(wlsolution);
1643  giraffe_table_delete(slitgeometry);
1644  giraffe_table_delete(grating);
1645 
1646  giraffe_transmission_config_destroy(transmission_config);
1647 
1648  giraffe_extraction_destroy(extraction);
1649 
1650  giraffe_localization_destroy(ploc);
1651  ploc = NULL;
1652 
1653  giraffe_table_delete(fibers);
1654 
1655  return 1;
1656  }
1657 
1658  }
1659 
1660 
1661  status = giraffe_transmission_compute(extraction, fibers,
1662  ploc, wlsolution,
1663  grating, slitgeometry);
1664 
1665  if (status != 0) {
1666  cpl_msg_error(_id, "Relative transmission computation failed! "
1667  "Aborting ...");
1668 
1669  if (wlsolution != NULL) {
1670  giraffe_table_delete(wlsolution);
1671  wlsolution = NULL;
1672  }
1673 
1674  giraffe_table_delete(slitgeometry);
1675  giraffe_table_delete(grating);
1676 
1677  giraffe_transmission_config_destroy(transmission_config);
1678 
1679  giraffe_extraction_destroy(extraction);
1680 
1681  giraffe_localization_destroy(ploc);
1682  ploc = NULL;
1683 
1684  giraffe_table_delete(fibers);
1685 
1686  return 1;
1687  }
1688 
1689  if (wlsolution != NULL) {
1690  giraffe_table_delete(wlsolution);
1691  wlsolution = NULL;
1692  }
1693 
1694  giraffe_table_delete(slitgeometry);
1695  giraffe_table_delete(grating);
1696 
1697  giraffe_transmission_config_destroy(transmission_config);
1698 
1699  }
1700 
1701  giraffe_localization_destroy(ploc);
1702  ploc = NULL;
1703 
1704 
1705  /*
1706  * Save the spectrum extraction results and register them as
1707  * products.
1708  */
1709 
1710  cpl_msg_info(_id, "Writing extracted spectra ...");
1711 
1712  /* Extracted spectra */
1713 
1714  giraffe_image_add_info(extraction->spectra, &info, set);
1715 
1716  sext_frame = giraffe_frame_create_image(extraction->spectra,
1717  GIFRAME_FIBER_FLAT_EXTSPECTRA,
1718  CPL_FRAME_LEVEL_FINAL,
1719  TRUE, TRUE);
1720 
1721  if (sext_frame == NULL) {
1722  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1723 
1724  giraffe_extraction_destroy(extraction);
1725  giraffe_table_delete(fibers);
1726 
1727  return 1;
1728  }
1729 
1730  status = giraffe_fiberlist_attach(sext_frame, fibers);
1731 
1732  if (status != 0) {
1733  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
1734  "Aborting ...", cpl_frame_get_filename(sext_frame));
1735 
1736  cpl_frame_delete(sext_frame);
1737 
1738  giraffe_extraction_destroy(extraction);
1739  giraffe_table_delete(fibers);
1740 
1741  return 1;
1742  }
1743 
1744  cpl_frameset_insert(set, sext_frame);
1745 
1746  /* Extracted spectra errors */
1747 
1748  giraffe_image_add_info(extraction->error, &info, set);
1749 
1750  sext_frame = giraffe_frame_create_image(extraction->error,
1751  GIFRAME_FIBER_FLAT_EXTERRORS,
1752  CPL_FRAME_LEVEL_FINAL,
1753  TRUE, TRUE);
1754 
1755  if (sext_frame == NULL) {
1756  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1757 
1758  giraffe_extraction_destroy(extraction);
1759  giraffe_table_delete(fibers);
1760 
1761  return 1;
1762  }
1763 
1764  status = giraffe_fiberlist_attach(sext_frame, fibers);
1765 
1766  if (status != 0) {
1767  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
1768  "Aborting ...", cpl_frame_get_filename(sext_frame));
1769 
1770  cpl_frame_delete(sext_frame);
1771 
1772  giraffe_extraction_destroy(extraction);
1773  giraffe_table_delete(fibers);
1774 
1775  return 1;
1776  }
1777 
1778  cpl_frameset_insert(set, sext_frame);
1779 
1780  /* Extracted spectra pixels */
1781 
1782  if (extraction->npixels != NULL) {
1783 
1784  giraffe_image_add_info(extraction->npixels, &info, set);
1785 
1786  sext_frame = giraffe_frame_create_image(extraction->npixels,
1787  GIFRAME_FIBER_FLAT_EXTPIXELS,
1788  CPL_FRAME_LEVEL_FINAL,
1789  TRUE, TRUE);
1790 
1791  if (sext_frame == NULL) {
1792  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1793 
1794  giraffe_extraction_destroy(extraction);
1795  giraffe_table_delete(fibers);
1796 
1797  return 1;
1798  }
1799 
1800  status = giraffe_fiberlist_attach(sext_frame, fibers);
1801 
1802  if (status != 0) {
1803  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
1804  "Aborting ...", cpl_frame_get_filename(sext_frame));
1805 
1806  cpl_frame_delete(sext_frame);
1807 
1808  giraffe_extraction_destroy(extraction);
1809  giraffe_table_delete(fibers);
1810 
1811  return 1;
1812  }
1813 
1814  cpl_frameset_insert(set, sext_frame);
1815 
1816  }
1817 
1818  /* Extracted spectra centroids */
1819 
1820  giraffe_image_add_info(extraction->centroid, &info, set);
1821 
1822  sext_frame = giraffe_frame_create_image(extraction->centroid,
1823  GIFRAME_FIBER_FLAT_EXTTRACE,
1824  CPL_FRAME_LEVEL_FINAL,
1825  TRUE, TRUE);
1826 
1827  if (sext_frame == NULL) {
1828  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1829 
1830  giraffe_extraction_destroy(extraction);
1831  giraffe_table_delete(fibers);
1832 
1833  return 1;
1834  }
1835 
1836  status = giraffe_fiberlist_attach(sext_frame, fibers);
1837 
1838  if (status != 0) {
1839  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
1840  "Aborting ...", cpl_frame_get_filename(sext_frame));
1841 
1842  cpl_frame_delete(sext_frame);
1843 
1844  giraffe_extraction_destroy(extraction);
1845  giraffe_table_delete(fibers);
1846 
1847  return 1;
1848  }
1849 
1850  cpl_frameset_insert(set, sext_frame);
1851 
1852  /* Extraction model spectra */
1853 
1854  if (extraction->model != NULL) {
1855 
1856  giraffe_image_add_info(extraction->model, &info, set);
1857 
1858  sext_frame = giraffe_frame_create_image(extraction->model,
1859  GIFRAME_FIBER_FLAT_EXTMODEL,
1860  CPL_FRAME_LEVEL_FINAL,
1861  TRUE, TRUE);
1862 
1863  if (sext_frame == NULL) {
1864  cpl_msg_error(_id, "Cannot create local file! Aborting ...");
1865 
1866  giraffe_extraction_destroy(extraction);
1867  giraffe_table_delete(fibers);
1868 
1869  return 1;
1870  }
1871 
1872  status = giraffe_fiberlist_attach(sext_frame, fibers);
1873 
1874  if (status != 0) {
1875  cpl_msg_error(_id, "Cannot attach fiber setup to local file '%s'! "
1876  "Aborting ...", cpl_frame_get_filename(sext_frame));
1877 
1878  cpl_frame_delete(sext_frame);
1879 
1880  giraffe_extraction_destroy(extraction);
1881  giraffe_table_delete(fibers);
1882 
1883  return 1;
1884  }
1885 
1886  cpl_frameset_insert(set, sext_frame);
1887 
1888  }
1889 
1890 
1891  /*
1892  * Cleanup
1893  */
1894 
1895  giraffe_extraction_destroy(extraction);
1896  giraffe_table_delete(fibers);
1897 
1898  return 0;
1899 
1900 }
1901 
1902 
1903 static cxint
1904 giqcmasterflat(cpl_frameset* set)
1905 {
1906 
1907  const cxchar* const fctid = "giqcmasterflat";
1908 
1909 
1910  cxint i = 0;
1911  cxint nx = 0;
1912  cxint ny = 0;
1913  cxint npixel = 0;
1914  cxint nsaturated = 0;
1915  cxint status = 0;
1916 
1917  const cxdouble saturation = 60000.;
1918  const cxdouble* pixels = NULL;
1919  cxdouble efficiency[2] = {0., 0.};
1920  cxdouble scale = 1.;
1921  cxdouble mean = 0.;
1922  cxdouble rms = 0.;
1923  cxdouble diff = 0.;
1924  cxdouble* _pdata = NULL;
1925  cxdouble* _tdata = NULL;
1926 
1927  cpl_propertylist* properties = NULL;
1928  cpl_propertylist* qclog = NULL;
1929 
1930  cpl_frame* rframe = NULL;
1931  cpl_frame* pframe = NULL;
1932 
1933  cpl_image* _rimage = NULL;
1934  cpl_image* _pimage = NULL;
1935  cpl_image* _test = NULL;
1936 
1937  cpl_table* _ptable = NULL;
1938 
1939  GiImage* rimage = NULL;
1940  GiImage* pimage = NULL;
1941 
1942  GiTable* ptable = NULL;
1943 
1944  GiPaf* qc = NULL;
1945 
1946  GiWindow w = {0, 0, 0, 0};
1947 
1948 
1949 
1950  cpl_msg_info(fctid, "Computing QC1 parameters ...");
1951 
1952  qc = giraffe_qclog_open(0);
1953 
1954  if (qc == NULL) {
1955  cpl_msg_error(fctid, "Cannot create QC1 log!");
1956  return 1;
1957  }
1958 
1959  qclog = giraffe_paf_get_properties(qc);
1960  cx_assert(qclog != NULL);
1961 
1962 
1963  /*
1964  * Compute lamp efficiencies from the rebinned frame if
1965  * it is available. If not the efficiencies are set to 0.
1966  */
1967 
1968  pframe = giraffe_get_frame(set, GIFRAME_FIBER_FLAT_EXTSPECTRA,
1969  CPL_FRAME_GROUP_PRODUCT);
1970 
1971  if (pframe == NULL) {
1972 
1973  cpl_msg_warning(fctid, "Product '%s' not found.",
1974  GIFRAME_FIBER_FLAT_EXTSPECTRA);
1975 
1976  cpl_msg_warning(fctid, "Setting lamp efficiencies (%s, %s) to 0.",
1977  GIALIAS_QCLAMP, GIALIAS_QCLAMP_SIMCAL);
1978 
1979  efficiency[0] = 0.;
1980  efficiency[1] = 0.;
1981 
1982  }
1983 
1984 
1985  pimage = giraffe_image_new(CPL_TYPE_DOUBLE);
1986  status = giraffe_image_load(pimage, cpl_frame_get_filename(pframe), 0);
1987 
1988  if (status != 0) {
1989  cpl_msg_error(fctid, "Could not load extracted spectra '%s'!",
1990  cpl_frame_get_filename(pframe));
1991 
1992  giraffe_image_delete(pimage);
1993  pimage = NULL;
1994 
1995  giraffe_paf_delete(qc);
1996  qc = NULL;
1997 
1998  return 1;
1999  }
2000 
2001  _pimage = giraffe_image_get(pimage);
2002  cx_assert(_pimage != NULL);
2003 
2004 
2005  ptable = giraffe_table_new();
2006  status = giraffe_table_load(ptable, cpl_frame_get_filename(pframe), 1,
2007  NULL);
2008 
2009  if (status != 0) {
2010  cpl_msg_error(fctid, "Could not load extracted spectra fiber setup!");
2011 
2012  giraffe_table_delete(ptable);
2013  ptable = NULL;
2014 
2015  giraffe_image_delete(pimage);
2016  pimage = NULL;
2017 
2018  giraffe_paf_delete(qc);
2019  qc = NULL;
2020 
2021  return 1;
2022  }
2023 
2024  _ptable = giraffe_table_get(ptable);
2025  cx_assert(_ptable != NULL);
2026 
2027  if (cpl_table_has_column(_ptable, "RP") == FALSE) {
2028 
2029  cpl_msg_warning(fctid, "Column 'RP' not found in fiber setup table!");
2030  cpl_msg_warning(fctid, "Setting lamp efficiencies (%s, %s) to 0.",
2031  GIALIAS_QCLAMP, GIALIAS_QCLAMP_SIMCAL);
2032 
2033  efficiency[0] = 0.;
2034  efficiency[1] = 0.;
2035 
2036  }
2037  else {
2038 
2039  properties = giraffe_image_get_properties(pimage);
2040  cx_assert(properties != NULL);
2041 
2042  if (cpl_propertylist_has(properties, GIALIAS_EXPTIME) == FALSE) {
2043 
2044  cpl_msg_warning(fctid, "Property '%s' not found in '%s'.",
2045  GIALIAS_EXPTIME, cpl_frame_get_filename(rframe));
2046  cpl_msg_warning(fctid, "Setting lamp efficiencies (%s, %s) to 0.",
2047  GIALIAS_QCLAMP, GIALIAS_QCLAMP_SIMCAL);
2048 
2049  efficiency[0] = 0.;
2050  efficiency[1] = 0.;
2051 
2052  }
2053  else {
2054 
2055  cxbool scaled = cpl_propertylist_has(properties,
2056  GIALIAS_FLAT_SCALE);
2057 
2058  cxint fiber = 0;
2059  cxint nb = cpl_image_get_size_y(_pimage);
2060  cxint nf[2] = {0, 0};
2061 
2062  cxdouble exptime = cpl_propertylist_get_double(properties,
2063  GIALIAS_EXPTIME);
2064  cxdouble* _sum = NULL;
2065 
2066  cpl_image* sum = NULL;
2067 
2068 
2069  if (scaled == TRUE) {
2070 
2071  scale = cpl_propertylist_get_double(properties,
2072  GIALIAS_FLAT_SCALE);
2073  cpl_image_multiply_scalar(_pimage, scale);
2074 
2075 
2076  }
2077 
2078  sum = cpl_image_collapse_create(_pimage, 0);
2079  _sum = cpl_image_get_data_double(sum);
2080 
2081  for (fiber = 0; fiber < cpl_table_get_nrow(_ptable); ++fiber) {
2082 
2083  cxint rp = cpl_table_get_int(_ptable, "RP", fiber, NULL);
2084 
2085  if (rp == -1) {
2086  efficiency[1] += _sum[fiber];
2087  ++nf[1];
2088  }
2089  else {
2090  efficiency[0] += _sum[fiber];
2091  ++nf[0];
2092  }
2093 
2094  }
2095 
2096  _sum = NULL;
2097 
2098  cpl_image_delete(sum);
2099  sum = NULL;
2100 
2101  if (nf[0] == 0) {
2102  cpl_msg_warning(fctid, "No OzPoz fibers found in the "
2103  "current fiber setup.");
2104  cpl_msg_warning(fctid, "Setting lamp efficiency (%s) to 0.",
2105  GIALIAS_QCLAMP);
2106  efficiency[0] = 0.;
2107  }
2108  else {
2109  efficiency[0] /= nf[0] * nb * exptime;
2110  }
2111 
2112  if (nf[1] == 0) {
2113  cpl_msg_warning(fctid, "No simultaneous calibration fibers "
2114  "found in the current fiber setup.");
2115  cpl_msg_warning(fctid, "Setting lamp efficiency (%s) to 0.",
2116  GIALIAS_QCLAMP_SIMCAL);
2117  efficiency[1] = 0.;
2118  }
2119  else {
2120  efficiency[1] /= nf[1] * nb * exptime;
2121  }
2122 
2123  }
2124 
2125  properties = NULL;
2126 
2127  }
2128 
2129  _ptable = NULL;
2130  _pimage = NULL;
2131 
2132  giraffe_table_delete(ptable);
2133  ptable = NULL;
2134 
2135  giraffe_image_delete(pimage);
2136  pimage = NULL;
2137 
2138 
2139  /*
2140  * Process master flat field
2141  */
2142 
2143 
2144  pframe = giraffe_get_frame(set, GIFRAME_FIBER_FLAT_MASTER,
2145  CPL_FRAME_GROUP_PRODUCT);
2146 
2147  if (pframe == NULL) {
2148  cpl_msg_error(fctid, "Missing product frame (%s)",
2149  GIFRAME_FIBER_FLAT_MASTER);
2150 
2151  giraffe_paf_delete(qc);
2152  qc = NULL;
2153 
2154  return 1;
2155  }
2156 
2157  cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
2158  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
2159 
2160  pimage = giraffe_image_new(CPL_TYPE_DOUBLE);
2161  status = giraffe_image_load(pimage, cpl_frame_get_filename(pframe), 0);
2162 
2163  if (status != 0) {
2164  cpl_msg_error(fctid, "Could not load master flat field '%s'!",
2165  cpl_frame_get_filename(pframe));
2166 
2167  giraffe_image_delete(pimage);
2168  pimage = NULL;
2169 
2170  giraffe_paf_delete(qc);
2171  qc = NULL;
2172 
2173  return 1;
2174  }
2175 
2176 
2177  /*
2178  * Load first raw image as reference
2179  */
2180 
2181  rframe = cpl_frameset_find(set, GIFRAME_FIBER_FLAT);
2182 
2183  if (rframe == NULL) {
2184  cpl_msg_error(fctid, "Missing raw frame (%s)", GIFRAME_FIBER_FLAT);
2185 
2186  giraffe_image_delete(pimage);
2187  pimage = NULL;
2188 
2189  giraffe_paf_delete(qc);
2190  qc = NULL;
2191 
2192  return 1;
2193  }
2194 
2195  rimage = giraffe_image_new(CPL_TYPE_DOUBLE);
2196  status = giraffe_image_load(rimage, cpl_frame_get_filename(rframe), 0);
2197 
2198  if (status != 0) {
2199 
2200  cpl_msg_error(fctid, "Could not load flat field '%s'!",
2201  cpl_frame_get_filename(rframe));
2202 
2203  giraffe_image_delete(rimage);
2204  rimage = NULL;
2205 
2206  giraffe_image_delete(pimage);
2207  pimage = NULL;
2208 
2209  giraffe_paf_delete(qc);
2210  qc = NULL;
2211 
2212  return 1;
2213 
2214  }
2215 
2216  _rimage = giraffe_image_get(rimage);
2217  cx_assert(_rimage != NULL);
2218 
2219  properties = giraffe_image_get_properties(rimage);
2220  cx_assert(properties != NULL);
2221 
2222  giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
2223  giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
2224  giraffe_propertylist_copy(qclog, "INS.EXP.MODE", properties,
2225  GIALIAS_SETUPNAME);
2226  giraffe_propertylist_copy(qclog, "INS.SLIT.NAME", properties,
2227  GIALIAS_SLITNAME);
2228  giraffe_propertylist_copy(qclog, "INS.GRAT.WLEN", properties,
2229  GIALIAS_GRATWLEN);
2230  giraffe_propertylist_copy(qclog, "DPR.TYPE", properties, GIALIAS_DPRTYPE);
2231 
2232  cpl_propertylist_update_string(qclog, "PRO.CATG",
2233  cpl_frame_get_tag(pframe));
2234  cpl_propertylist_set_comment(qclog, "PRO.CATG",
2235  "Pipeline product category");
2236 
2237  properties = giraffe_image_get_properties(pimage);
2238  cx_assert(properties != NULL);
2239 
2240  giraffe_propertylist_copy(qclog, "PRO.DATAAVG", properties,
2241  GIALIAS_DATAMEAN);
2242  giraffe_propertylist_copy(qclog, "PRO.DATARMS", properties,
2243  GIALIAS_DATASIG);
2244  giraffe_propertylist_copy(qclog, "PRO.DATAMED", properties,
2245  GIALIAS_DATAMEDI);
2246  giraffe_propertylist_copy(qclog, "PRO.DATANCOM", properties,
2247  GIALIAS_DATANCOM);
2248 
2249 
2250  /*
2251  * Compute mean level of the first raw frame and count the number
2252  * of saturated pixels.
2253  */
2254 
2255  properties = giraffe_image_get_properties(rimage);
2256  cx_assert(properties != NULL);
2257 
2258  if (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE) {
2259 
2260  cxint _ox = cpl_propertylist_get_int(properties, GIALIAS_OVSCX);
2261  cxint _nx = cpl_image_get_size_x(_rimage) - 2 * CX_MAX(0, _ox) - 1;
2262 
2263  w.x0 = CX_MAX(0, _ox) + 1;
2264  w.x1 = w.x0 + _nx;
2265 
2266  }
2267 
2268  if (cpl_propertylist_has(properties, GIALIAS_OVSCY) == TRUE) {
2269 
2270  cxint _oy = cpl_propertylist_get_int(properties, GIALIAS_OVSCY);
2271  cxint _ny = cpl_image_get_size_y(_rimage) - 2 * CX_MAX(0, _oy) - 1;
2272 
2273  w.y0 = CX_MAX(0, _oy) + 1;
2274  w.y1 = w.y0 + _ny;
2275 
2276  }
2277 
2278  mean = cpl_image_get_mean_window(_rimage, w.x0, w.y0, w.x1, w.y1);
2279 
2280  pixels = cpl_image_get_data(_rimage);
2281  npixel = cpl_image_get_size_x(_rimage) * cpl_image_get_size_y(_rimage);
2282 
2283  for (i = 0; i < npixel; i++) {
2284  if (pixels[i] > saturation) {
2285  ++nsaturated;
2286  }
2287  }
2288 
2289 
2290  properties = giraffe_image_get_properties(pimage);
2291  cx_assert(properties != NULL);
2292 
2293  cpl_propertylist_update_double(properties, GIALIAS_QCMEAN, mean);
2294  cpl_propertylist_set_comment(properties, GIALIAS_QCMEAN, "Mean level of "
2295  "first raw frame");
2296 
2297  giraffe_propertylist_copy(qclog, "QC.OUT1.MEAN.RAW", properties,
2298  GIALIAS_QCMEAN);
2299 
2300 
2301  cpl_propertylist_update_int(properties, GIALIAS_QCNSAT, nsaturated);
2302  cpl_propertylist_set_comment(properties, GIALIAS_QCNSAT, "Number of "
2303  "saturated pixels in the first raw frame");
2304 
2305  giraffe_propertylist_copy(qclog, "QC.OUT1.NSAT.RAW", properties,
2306  GIALIAS_QCNSAT);
2307 
2308 
2309  /*
2310  * Calibration lamp monitoring
2311  */
2312 
2313  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP, efficiency[0]);
2314  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP,
2315  "Calibration lamp efficiency");
2316 
2317  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC", properties,
2318  GIALIAS_QCLAMP);
2319 
2320  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP_SIMCAL,
2321  efficiency[1]);
2322  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP_SIMCAL,
2323  "SIMCAL lamp efficiency");
2324 
2325  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC1", properties,
2326  GIALIAS_QCLAMP_SIMCAL);
2327 
2328 
2329  /*
2330  * Write QC1 log and save updated master flat field.
2331  */
2332 
2333  giraffe_image_save(pimage, cpl_frame_get_filename(pframe));
2334 
2335  giraffe_image_delete(pimage);
2336  pimage = NULL;
2337 
2338  giraffe_qclog_close(qc);
2339  qc = NULL;
2340 
2341 
2342  /*
2343  * Process fiber localization centroid
2344  */
2345 
2346  qc = giraffe_qclog_open(1);
2347 
2348  if (qc == NULL) {
2349  cpl_msg_error(fctid, "Cannot create QC1 log!");
2350 
2351  giraffe_image_delete(rimage);
2352  rimage = NULL;
2353 
2354  return 1;
2355  }
2356 
2357  qclog = giraffe_paf_get_properties(qc);
2358  cx_assert(qclog != NULL);
2359 
2360  pframe = giraffe_get_frame(set, GIFRAME_LOCALIZATION_CENTROID,
2361  CPL_FRAME_GROUP_PRODUCT);
2362 
2363  if (pframe == NULL) {
2364  cpl_msg_error(fctid, "Missing product frame (%s)",
2365  GIFRAME_LOCALIZATION_CENTROID);
2366 
2367  giraffe_paf_delete(qc);
2368  qc = NULL;
2369 
2370  giraffe_image_delete(rimage);
2371  rimage = NULL;
2372 
2373  return 1;
2374  }
2375 
2376  cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
2377  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
2378 
2379 
2380  pimage = giraffe_image_new(CPL_TYPE_DOUBLE);
2381  status = giraffe_image_load(pimage, cpl_frame_get_filename(pframe), 0);
2382 
2383  if (status != 0) {
2384  cpl_msg_error(fctid, "Could not load localization centroids '%s'!",
2385  cpl_frame_get_filename(pframe));
2386 
2387  giraffe_image_delete(pimage);
2388  pimage = NULL;
2389 
2390  giraffe_image_delete(rimage);
2391  rimage = NULL;
2392 
2393  giraffe_paf_delete(qc);
2394  qc = NULL;
2395 
2396  return 1;
2397  }
2398 
2399  ptable = giraffe_table_new();
2400  status = giraffe_table_load(ptable, cpl_frame_get_filename(pframe), 1,
2401  NULL);
2402 
2403  if (status != 0) {
2404  cpl_msg_error(fctid, "Could not load localization centroids '%s'!",
2405  cpl_frame_get_filename(pframe));
2406 
2407  giraffe_table_delete(ptable);
2408  ptable = NULL;
2409 
2410  giraffe_image_delete(pimage);
2411  pimage = NULL;
2412 
2413  giraffe_image_delete(rimage);
2414  rimage = NULL;
2415 
2416  giraffe_paf_delete(qc);
2417  qc = NULL;
2418 
2419  return 1;
2420  }
2421 
2422  properties = giraffe_image_get_properties(rimage);
2423  cx_assert(properties != NULL);
2424 
2425  giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
2426  giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
2427  giraffe_propertylist_copy(qclog, "INS.EXP.MODE", properties,
2428  GIALIAS_SETUPNAME);
2429  giraffe_propertylist_copy(qclog, "INS.SLIT.NAME", properties,
2430  GIALIAS_SLITNAME);
2431  giraffe_propertylist_copy(qclog, "INS.GRAT.WLEN", properties,
2432  GIALIAS_GRATWLEN);
2433  giraffe_propertylist_copy(qclog, "DPR.TYPE", properties, GIALIAS_DPRTYPE);
2434 
2435  cpl_propertylist_update_string(qclog, "PRO.CATG",
2436  cpl_frame_get_tag(pframe));
2437  cpl_propertylist_set_comment(qclog, "PRO.CATG",
2438  "Pipeline product category");
2439 
2440  properties = giraffe_image_get_properties(pimage);
2441  cx_assert(properties != NULL);
2442 
2443  giraffe_propertylist_copy(qclog, "PRO.DATAAVG", properties,
2444  GIALIAS_DATAMEAN);
2445  giraffe_propertylist_copy(qclog, "PRO.DATARMS", properties,
2446  GIALIAS_DATASIG);
2447  giraffe_propertylist_copy(qclog, "PRO.DATAMED", properties,
2448  GIALIAS_DATAMEDI);
2449  giraffe_propertylist_copy(qclog, "PRO.DATANCOM", properties,
2450  GIALIAS_DATANCOM);
2451  giraffe_propertylist_copy(qclog, "PRO.SLIT.NFIBRES", properties,
2452  GIALIAS_NFIBERS);
2453 
2454 
2455  /*
2456  * Calibration lamp monitoring
2457  */
2458 
2459  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP, efficiency[0]);
2460  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP,
2461  "Calibration lamp efficiency");
2462 
2463  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC", properties,
2464  GIALIAS_QCLAMP);
2465 
2466  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP_SIMCAL,
2467  efficiency[1]);
2468  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP_SIMCAL,
2469  "SIMCAL lamp efficiency");
2470 
2471  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC1", properties,
2472  GIALIAS_QCLAMP_SIMCAL);
2473 
2474 
2475  /* Fiber signal curvature RMS */
2476 
2477  _pimage = giraffe_image_get(pimage);
2478 
2479  _test = cpl_image_collapse_create(_pimage, 0);
2480  cpl_image_divide_scalar(_test, cpl_image_get_size_y(_pimage));
2481 
2482  _pdata = cpl_image_get_data(_pimage);
2483  _tdata = cpl_image_get_data(_test);
2484 
2485  rms = 0.;
2486 
2487  nx = cpl_image_get_size_x(_pimage);
2488  ny = cpl_image_get_size_y(_pimage);
2489 
2490  for (i = 0; i < nx; i++) {
2491 
2492  cxint j;
2493 
2494  cxdouble _rms = 0.;
2495 
2496 
2497  for (j = 0; j < ny; j++) {
2498  _rms += pow(_pdata[j * nx + i] - _tdata[i], 2.);
2499  }
2500 
2501  rms += sqrt(_rms / (ny - 1));
2502 
2503  }
2504 
2505  rms /= nx;
2506 
2507  cpl_image_delete(_test);
2508  _test = NULL;
2509 
2510  cpl_propertylist_update_double(properties, GIALIAS_QCLCRMS, rms);
2511  cpl_propertylist_set_comment(properties, GIALIAS_QCLCRMS,
2512  "Mean fibre signal curvature");
2513 
2514  giraffe_propertylist_copy(qclog, "QC.FIBRE.CENTROID.RMS", properties,
2515  GIALIAS_QCLCRMS);
2516 
2517 
2518  /* Difference of fiber signal curvature */
2519 
2520  diff = 0.;
2521 
2522  for (i = 0; i < nx; i++) {
2523 
2524  cxdouble min = cpl_image_get_min_window(_pimage,
2525  i + 1, 1, i + 1, ny);
2526  cxdouble max = cpl_image_get_max_window(_pimage,
2527  i + 1, 1, i + 1, ny);
2528 
2529  diff += max - min;
2530 
2531  }
2532 
2533  diff /= nx;
2534 
2535  cpl_propertylist_update_double(properties, GIALIAS_QCLCDIFF, diff);
2536  cpl_propertylist_set_comment(properties, GIALIAS_QCLCDIFF,
2537  "Mean difference of fibre signal "
2538  "curvature");
2539 
2540  giraffe_propertylist_copy(qclog, "QC.FIBRE.CENTROID.DIFF", properties,
2541  GIALIAS_QCLCDIFF);
2542 
2543 
2544  status = giraffe_image_save(pimage, cpl_frame_get_filename(pframe));
2545 
2546  if (status != 0) {
2547  cpl_msg_error(fctid, "Could not save localization centroids '%s'!",
2548  cpl_frame_get_filename(pframe));
2549 
2550  giraffe_table_delete(ptable);
2551  ptable = NULL;
2552 
2553  giraffe_image_delete(pimage);
2554  pimage = NULL;
2555 
2556  giraffe_image_delete(rimage);
2557  rimage = NULL;
2558 
2559  giraffe_paf_delete(qc);
2560  qc = NULL;
2561 
2562  return 1;
2563  }
2564 
2565  status = giraffe_table_attach(ptable, cpl_frame_get_filename(pframe),
2566  1, NULL);
2567 
2568  if (status != 0) {
2569  cpl_msg_error(fctid, "Could not save localization centroids '%s'!",
2570  cpl_frame_get_filename(pframe));
2571 
2572  giraffe_table_delete(ptable);
2573  ptable = NULL;
2574 
2575  giraffe_image_delete(pimage);
2576  pimage = NULL;
2577 
2578  giraffe_image_delete(rimage);
2579  rimage = NULL;
2580 
2581  giraffe_paf_delete(qc);
2582  qc = NULL;
2583 
2584  return 1;
2585  }
2586 
2587  giraffe_image_delete(pimage);
2588  pimage = NULL;
2589 
2590  giraffe_table_delete(ptable);
2591  ptable = NULL;
2592 
2593  giraffe_qclog_close(qc);
2594  qc = NULL;
2595 
2596 
2597  /*
2598  * Process fiber localization width
2599  */
2600 
2601  qc = giraffe_qclog_open(2);
2602 
2603  if (qc == NULL) {
2604  cpl_msg_error(fctid, "Cannot create QC1 log!");
2605 
2606  giraffe_image_delete(rimage);
2607  rimage = NULL;
2608 
2609  return 1;
2610  }
2611 
2612  qclog = giraffe_paf_get_properties(qc);
2613  cx_assert(qclog != NULL);
2614 
2615  pframe = giraffe_get_frame(set, GIFRAME_LOCALIZATION_WIDTH,
2616  CPL_FRAME_GROUP_PRODUCT);
2617 
2618  if (pframe == NULL) {
2619  cpl_msg_error(fctid, "Missing product frame (%s)",
2620  GIFRAME_LOCALIZATION_WIDTH);
2621 
2622  giraffe_paf_delete(qc);
2623  qc = NULL;
2624 
2625  giraffe_image_delete(rimage);
2626  rimage = NULL;
2627 
2628  return 1;
2629  }
2630 
2631  cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
2632  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
2633 
2634 
2635  pimage = giraffe_image_new(CPL_TYPE_DOUBLE);
2636  status = giraffe_image_load(pimage, cpl_frame_get_filename(pframe), 0);
2637 
2638  if (status != 0) {
2639  cpl_msg_error(fctid, "Could not load localization widths '%s'!",
2640  cpl_frame_get_filename(pframe));
2641 
2642  giraffe_image_delete(pimage);
2643  pimage = NULL;
2644 
2645  giraffe_image_delete(rimage);
2646  rimage = NULL;
2647 
2648  giraffe_paf_delete(qc);
2649  qc = NULL;
2650 
2651  return 1;
2652  }
2653 
2654  ptable = giraffe_table_new();
2655  status = giraffe_table_load(ptable, cpl_frame_get_filename(pframe), 1,
2656  NULL);
2657 
2658  if (status != 0) {
2659  cpl_msg_error(fctid, "Could not load localization widths '%s'!",
2660  cpl_frame_get_filename(pframe));
2661 
2662  giraffe_table_delete(ptable);
2663  ptable = NULL;
2664 
2665  giraffe_image_delete(pimage);
2666  pimage = NULL;
2667 
2668  giraffe_image_delete(rimage);
2669  rimage = NULL;
2670 
2671  giraffe_paf_delete(qc);
2672  qc = NULL;
2673 
2674  return 1;
2675  }
2676 
2677  properties = giraffe_image_get_properties(rimage);
2678  cx_assert(properties != NULL);
2679 
2680  giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
2681  giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
2682  giraffe_propertylist_copy(qclog, "INS.EXP.MODE", properties,
2683  GIALIAS_SETUPNAME);
2684  giraffe_propertylist_copy(qclog, "INS.SLIT.NAME", properties,
2685  GIALIAS_SLITNAME);
2686  giraffe_propertylist_copy(qclog, "INS.GRAT.WLEN", properties,
2687  GIALIAS_GRATWLEN);
2688  giraffe_propertylist_copy(qclog, "DPR.TYPE", properties, GIALIAS_DPRTYPE);
2689 
2690  cpl_propertylist_update_string(qclog, "PRO.CATG",
2691  cpl_frame_get_tag(pframe));
2692  cpl_propertylist_set_comment(qclog, "PRO.CATG",
2693  "Pipeline product category");
2694 
2695  properties = giraffe_image_get_properties(pimage);
2696  cx_assert(properties != NULL);
2697 
2698  giraffe_propertylist_copy(qclog, "PRO.DATAAVG", properties,
2699  GIALIAS_DATAMEAN);
2700  giraffe_propertylist_copy(qclog, "PRO.DATARMS", properties,
2701  GIALIAS_DATASIG);
2702  giraffe_propertylist_copy(qclog, "PRO.DATAMED", properties,
2703  GIALIAS_DATAMEDI);
2704  giraffe_propertylist_copy(qclog, "PRO.DATANCOM", properties,
2705  GIALIAS_DATANCOM);
2706  giraffe_propertylist_copy(qclog, "PRO.SLIT.NFIBRES", properties,
2707  GIALIAS_NFIBERS);
2708 
2709 
2710  /*
2711  * Calibration lamp monitoring
2712  */
2713 
2714  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP, efficiency[0]);
2715  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP,
2716  "Calibration lamp efficiency");
2717 
2718  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC", properties,
2719  GIALIAS_QCLAMP);
2720 
2721  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP_SIMCAL,
2722  efficiency[1]);
2723  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP_SIMCAL,
2724  "SIMCAL lamp efficiency");
2725 
2726  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC1", properties,
2727  GIALIAS_QCLAMP_SIMCAL);
2728 
2729 
2730  /* Compute fiber width statistics, i.e. the mean width and its RMS */
2731 
2732  _pimage = giraffe_image_get(pimage);
2733 
2734  _test = cpl_image_collapse_create(_pimage, 0);
2735  cpl_image_divide_scalar(_test, cpl_image_get_size_y(_pimage));
2736 
2737  _pdata = cpl_image_get_data(_pimage);
2738  _tdata = cpl_image_get_data(_test);
2739 
2740  mean = 0.;
2741  rms = 0.;
2742 
2743  nx = cpl_image_get_size_x(_pimage);
2744  ny = cpl_image_get_size_y(_pimage);
2745 
2746  for (i = 0; i < nx; i++) {
2747 
2748  cxint j;
2749 
2750  cxdouble _rms = 0.;
2751 
2752 
2753  for (j = 0; j < ny; j++) {
2754  _rms += pow(_pdata[j * nx + i] - _tdata[i], 2.);
2755  }
2756 
2757  mean += _tdata[i];
2758  rms += sqrt(_rms / (ny - 1));
2759 
2760  }
2761 
2762  mean /= nx;
2763  rms /= nx;
2764 
2765  cpl_image_delete(_test);
2766  _test = NULL;
2767 
2768 
2769  cpl_propertylist_update_double(properties, GIALIAS_QCLWAVG, mean);
2770  cpl_propertylist_set_comment(properties, GIALIAS_QCLWAVG,
2771  "Mean fibre half width");
2772 
2773  giraffe_propertylist_copy(qclog, "QC.FIBRE.WIDTH.MEAN", properties,
2774  GIALIAS_QCLWAVG);
2775 
2776  cpl_propertylist_update_double(properties, GIALIAS_QCLWRMS, rms);
2777  cpl_propertylist_set_comment(properties, GIALIAS_QCLWRMS,
2778  "RMS of fibre half width");
2779 
2780  giraffe_propertylist_copy(qclog, "QC.FIBRE.WIDTH.RMS", properties,
2781  GIALIAS_QCLWRMS);
2782 
2783 
2784  status = giraffe_image_save(pimage, cpl_frame_get_filename(pframe));
2785 
2786  if (status != 0) {
2787  cpl_msg_error(fctid, "Could not save localization widths '%s'!",
2788  cpl_frame_get_filename(pframe));
2789 
2790  giraffe_table_delete(ptable);
2791  ptable = NULL;
2792 
2793  giraffe_image_delete(pimage);
2794  pimage = NULL;
2795 
2796  giraffe_image_delete(rimage);
2797  rimage = NULL;
2798 
2799  giraffe_paf_delete(qc);
2800  qc = NULL;
2801 
2802  return 1;
2803  }
2804 
2805  status = giraffe_table_attach(ptable, cpl_frame_get_filename(pframe),
2806  1, NULL);
2807 
2808  if (status != 0) {
2809  cpl_msg_error(fctid, "Could not save localization widths '%s'!",
2810  cpl_frame_get_filename(pframe));
2811 
2812  giraffe_table_delete(ptable);
2813  ptable = NULL;
2814 
2815  giraffe_image_delete(pimage);
2816  pimage = NULL;
2817 
2818  giraffe_image_delete(rimage);
2819  rimage = NULL;
2820 
2821  giraffe_paf_delete(qc);
2822  qc = NULL;
2823 
2824  return 1;
2825  }
2826 
2827  giraffe_image_delete(pimage);
2828  pimage = NULL;
2829 
2830  giraffe_table_delete(ptable);
2831  ptable = NULL;
2832 
2833  giraffe_qclog_close(qc);
2834  qc = NULL;
2835 
2836 
2837  /*
2838  * Process extracted flat field spectra
2839  */
2840 
2841  qc = giraffe_qclog_open(3);
2842 
2843  if (qc == NULL) {
2844  cpl_msg_error(fctid, "Cannot create QC1 log!");
2845 
2846  giraffe_image_delete(rimage);
2847  rimage = NULL;
2848 
2849  return 1;
2850  }
2851 
2852  qclog = giraffe_paf_get_properties(qc);
2853  cx_assert(qclog != NULL);
2854 
2855  pframe = giraffe_get_frame(set, GIFRAME_FIBER_FLAT_EXTSPECTRA,
2856  CPL_FRAME_GROUP_PRODUCT);
2857 
2858  if (pframe == NULL) {
2859  cpl_msg_error(fctid, "Missing product frame (%s)",
2860  GIFRAME_FIBER_FLAT_EXTSPECTRA);
2861 
2862  giraffe_paf_delete(qc);
2863  qc = NULL;
2864 
2865  giraffe_image_delete(rimage);
2866  rimage = NULL;
2867 
2868  return 1;
2869  }
2870 
2871  cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
2872  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
2873 
2874 
2875  pimage = giraffe_image_new(CPL_TYPE_DOUBLE);
2876  status = giraffe_image_load(pimage, cpl_frame_get_filename(pframe), 0);
2877 
2878  if (status != 0) {
2879  cpl_msg_error(fctid, "Could not load extracted flat field spectra "
2880  "'%s'!", cpl_frame_get_filename(pframe));
2881 
2882  giraffe_image_delete(pimage);
2883  pimage = NULL;
2884 
2885  giraffe_image_delete(rimage);
2886  rimage = NULL;
2887 
2888  giraffe_paf_delete(qc);
2889  qc = NULL;
2890 
2891  return 1;
2892  }
2893 
2894  ptable = giraffe_table_new();
2895  status = giraffe_table_load(ptable, cpl_frame_get_filename(pframe), 1,
2896  NULL);
2897 
2898  if (status != 0) {
2899  cpl_msg_error(fctid, "Could not load extracted flat field spectra "
2900  "'%s'!", cpl_frame_get_filename(pframe));
2901 
2902  giraffe_table_delete(ptable);
2903  ptable = NULL;
2904 
2905  giraffe_image_delete(pimage);
2906  pimage = NULL;
2907 
2908  giraffe_image_delete(rimage);
2909  rimage = NULL;
2910 
2911  giraffe_paf_delete(qc);
2912  qc = NULL;
2913 
2914  return 1;
2915  }
2916 
2917  properties = giraffe_image_get_properties(rimage);
2918  cx_assert(properties != NULL);
2919 
2920  giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
2921  giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
2922  giraffe_propertylist_copy(qclog, "INS.EXP.MODE", properties,
2923  GIALIAS_SETUPNAME);
2924  giraffe_propertylist_copy(qclog, "INS.SLIT.NAME", properties,
2925  GIALIAS_SLITNAME);
2926  giraffe_propertylist_copy(qclog, "INS.GRAT.WLEN", properties,
2927  GIALIAS_GRATWLEN);
2928  giraffe_propertylist_copy(qclog, "DPR.TYPE", properties, GIALIAS_DPRTYPE);
2929 
2930  cpl_propertylist_update_string(qclog, "PRO.CATG",
2931  cpl_frame_get_tag(pframe));
2932  cpl_propertylist_set_comment(qclog, "PRO.CATG",
2933  "Pipeline product category");
2934 
2935  properties = giraffe_image_get_properties(pimage);
2936  cx_assert(properties != NULL);
2937 
2938  giraffe_propertylist_copy(qclog, "PRO.DATAAVG", properties,
2939  GIALIAS_DATAMEAN);
2940  giraffe_propertylist_copy(qclog, "PRO.DATARMS", properties,
2941  GIALIAS_DATASIG);
2942  giraffe_propertylist_copy(qclog, "PRO.DATAMED", properties,
2943  GIALIAS_DATAMEDI);
2944  giraffe_propertylist_copy(qclog, "PRO.DATANCOM", properties,
2945  GIALIAS_DATANCOM);
2946  giraffe_propertylist_copy(qclog, "PRO.SLIT.NFIBRES", properties,
2947  GIALIAS_NFIBERS);
2948 
2949 
2950  /*
2951  * Calibration lamp monitoring
2952  */
2953 
2954  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP, efficiency[0]);
2955  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP,
2956  "Calibration lamp efficiency");
2957 
2958  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC", properties,
2959  GIALIAS_QCLAMP);
2960 
2961  cpl_propertylist_update_double(properties, GIALIAS_QCLAMP_SIMCAL,
2962  efficiency[1]);
2963  cpl_propertylist_set_comment(properties, GIALIAS_QCLAMP_SIMCAL,
2964  "SIMCAL lamp efficiency");
2965 
2966  giraffe_propertylist_copy(qclog, "QC.LAMP.EFFIC1", properties,
2967  GIALIAS_QCLAMP_SIMCAL);
2968 
2969 
2970  _ptable = giraffe_table_get(ptable);
2971 
2972  if (cpl_table_has_column(_ptable, "TRANSMISSION") == FALSE) {
2973  cpl_msg_warning(fctid, "Relative fiber transmission not available! "
2974  "QC parameter computation skipped.");
2975  }
2976  else {
2977 
2978  const cxdouble low = 0.5;
2979  const cxdouble high = 2.0;
2980 
2981  cxint nf = 0;
2982 
2983  cxdouble t = 0.;
2984  cxdouble dt = 0.;
2985 
2986  cpl_table* ttable = NULL;
2987 
2988 
2989  rms = 0.;
2990 
2991  cpl_table_unselect_all(_ptable);
2992 
2993  cpl_table_or_selected_int(_ptable, "RP", CPL_GREATER_THAN, 0);
2994  cpl_table_and_selected_double(_ptable, "TRANSMISSION",
2995  CPL_GREATER_THAN, low);
2996  cpl_table_and_selected_double(_ptable, "TRANSMISSION",
2997  CPL_LESS_THAN, high);
2998 
2999  ttable = cpl_table_extract_selected(_ptable);
3000 
3001  nf = cpl_table_get_nrow(ttable);
3002  if (ttable == NULL || nf <= 0) {
3003  cpl_msg_warning(fctid, "No fiber found within transmission "
3004  "range ]%.2f, %.2f[", low, high);
3005 
3006  }
3007  else {
3008 
3009  t = cpl_table_get_column_median(ttable, "TRANSMISSION");
3010 
3011  if (nf > 1) {
3012 
3013  for (i = 0; i < cpl_table_get_nrow(ttable); i++) {
3014 
3015  cxdouble _t = cpl_table_get_double(ttable,
3016  "TRANSMISSION", i, NULL);
3017  rms += pow(_t - t, 2.);
3018 
3019  }
3020 
3021  rms = sqrt(rms / (cpl_table_get_nrow(ttable) - 1));
3022 
3023  }
3024  else {
3025  rms = 0.;
3026  }
3027 
3028 
3029  }
3030 
3031  if (!cpl_table_has_column(_ptable, "DTRANSMISSION")) {
3032  cpl_msg_warning(fctid, "Relative fiber transmission error not "
3033  "available! QC parameter computation skipped.");
3034  }
3035  else {
3036 
3037  cx_assert(cpl_table_has_column(ttable, "DTRANSMISSION") != 0);
3038  dt = cpl_table_get_column_median(ttable, "DTRANSMISSION");
3039 
3040  }
3041 
3042  cpl_table_delete(ttable);
3043  ttable = NULL;
3044 
3045 
3046  cpl_propertylist_update_double(properties, GIALIAS_QCTRMED, t);
3047  cpl_propertylist_set_comment(properties, GIALIAS_QCTRMED, "Median of "
3048  "relative fibre transmission");
3049 
3050  giraffe_propertylist_copy(qclog, "QC.FIBRE.TRANS.MEDIAN", properties,
3051  GIALIAS_QCTRMED);
3052 
3053 
3054  cpl_propertylist_update_double(properties, GIALIAS_QCTRRMS, rms);
3055  cpl_propertylist_set_comment(properties, GIALIAS_QCTRRMS, "RMS of "
3056  "relative fibre transmission");
3057 
3058  giraffe_propertylist_copy(qclog, "QC.FIBRE.TRANS.RMS", properties,
3059  GIALIAS_QCTRRMS);
3060 
3061 
3062  cpl_propertylist_update_double(properties, GIALIAS_QCTRERR, dt);
3063  cpl_propertylist_set_comment(properties, GIALIAS_QCTRERR, "Median of "
3064  "relative fibre transmission error");
3065 
3066  giraffe_propertylist_copy(qclog, "QC.FIBRE.TRANS.ERROR", properties,
3067  GIALIAS_QCTRERR);
3068 
3069 
3070  //FIXME: Check whether this number is useful!
3071 #if 0
3072  cpl_propertylist_update_int(properties, GIALIAS_QCTRNF, nf);
3073  cpl_propertylist_set_comment(properties, GIALIAS_QCTRNF, "Number "
3074  "of fibres used for median transmission computation.");
3075 
3076  giraffe_propertylist_copy(qclog, "QC.FIBRE.TRANS.NFIBRES",
3077  properties, GIALIAS_QCTRNF);
3078 #endif
3079  cpl_msg_debug(fctid, "%d fibers used for median transmission "
3080  "computation.", nf);
3081 
3082  }
3083 
3084  status = giraffe_image_save(pimage, cpl_frame_get_filename(pframe));
3085 
3086  if (status != 0) {
3087  cpl_msg_error(fctid, "Could not save extracted flat field spectra "
3088  "'%s'!", cpl_frame_get_filename(pframe));
3089 
3090  giraffe_table_delete(ptable);
3091  ptable = NULL;
3092 
3093  giraffe_image_delete(pimage);
3094  pimage = NULL;
3095 
3096  giraffe_image_delete(rimage);
3097  rimage = NULL;
3098 
3099  giraffe_paf_delete(qc);
3100  qc = NULL;
3101 
3102  return 1;
3103  }
3104 
3105  status = giraffe_table_attach(ptable, cpl_frame_get_filename(pframe),
3106  1, NULL);
3107 
3108  if (status != 0) {
3109  cpl_msg_error(fctid, "Could not save extracted flat field spectra "
3110  "'%s'!", cpl_frame_get_filename(pframe));
3111 
3112  giraffe_table_delete(ptable);
3113  ptable = NULL;
3114 
3115  giraffe_image_delete(pimage);
3116  pimage = NULL;
3117 
3118  giraffe_image_delete(rimage);
3119  rimage = NULL;
3120 
3121  giraffe_paf_delete(qc);
3122  qc = NULL;
3123 
3124  return 1;
3125  }
3126 
3127  giraffe_image_delete(pimage);
3128  pimage = NULL;
3129 
3130  giraffe_table_delete(ptable);
3131  ptable = NULL;
3132 
3133  giraffe_qclog_close(qc);
3134  qc = NULL;
3135 
3136 
3137  /*
3138  * Cleanup
3139  */
3140 
3141  giraffe_image_delete(rimage);
3142 
3143  return 0;
3144 
3145 }
3146 
3147 
3148 /*
3149  * Build table of contents, i.e. the list of available plugins, for
3150  * this module. This function is exported.
3151  */
3152 
3153 int
3154 cpl_plugin_get_info(cpl_pluginlist* list)
3155 {
3156 
3157  cpl_recipe* recipe = cx_calloc(1, sizeof *recipe);
3158  cpl_plugin* plugin = &recipe->interface;
3159 
3160 
3161  cpl_plugin_init(plugin,
3162  CPL_PLUGIN_API,
3163  GIRAFFE_BINARY_VERSION,
3164  CPL_PLUGIN_TYPE_RECIPE,
3165  "gimasterflat",
3166  "Create the fiber master flat field and the "
3167  "localization mask.",
3168  "For detailed information please refer to the "
3169  "GIRAFFE pipeline user manual.\nIt is available at "
3170  "http://www.eso.org/pipelines.",
3171  "Giraffe Pipeline",
3172  PACKAGE_BUGREPORT,
3174  gimasterflat_create,
3175  gimasterflat_exec,
3176  gimasterflat_destroy);
3177 
3178  cpl_pluginlist_append(list, plugin);
3179 
3180  return 0;
3181 
3182 }
GiBiasConfig * giraffe_bias_config_create(cpl_parameterlist *list)
Creates a setup structure for a bias removal task.
Definition: gibias.c:3438
void giraffe_bias_config_add(cpl_parameterlist *list)
Adds parameters for the bias removal.
Definition: gibias.c:3597
cxint giraffe_bias_remove(GiImage *result, const GiImage *raw, const GiImage *master_bias, const GiImage *bad_pixels, const cpl_matrix *biaslimits, const GiBiasConfig *config)
Removes the bias from an image.
Definition: gibias.c:3106
void giraffe_bias_config_destroy(GiBiasConfig *config)
Destroys a bias removal setup structure.
Definition: gibias.c:3569
cxint giraffe_subtract_dark(GiImage *image, const GiImage *dark, const GiImage *bpixel, GiDarkResults *data, const GiDarkConfig *config)
Subtract the dark current from a bias corrected image.
Definition: gidark.c:478
void giraffe_extract_config_add(cpl_parameterlist *list)
Adds parameters for the spectrum extraction.
Definition: giextract.c:3504
cxint giraffe_extract_spectra(GiExtraction *result, GiImage *image, GiTable *fibers, GiLocalization *sloc, GiImage *bpixel, GiImage *slight, GiExtractConfig *config)
Extracts the spectra from a preprocessed frame.
Definition: giextract.c:2475
GiExtractConfig * giraffe_extract_config_create(cpl_parameterlist *list)
Creates a setup structure for the spectrum extraction.
Definition: giextract.c:3400
void giraffe_extract_config_destroy(GiExtractConfig *config)
Destroys a spectrum extraction setup structure.
Definition: giextract.c:3474
GiTable * giraffe_fibers_select(const cpl_frame *frame, const GiTable *reference, GiFibersConfig *config)
Selects the spectra to process.
Definition: gifibers.c:72
void giraffe_fibers_config_destroy(GiFibersConfig *config)
Destroys a fibers setup structure.
Definition: gifibers.c:363
void giraffe_fibers_config_add(cpl_parameterlist *list)
Adds parameters for the spectrum selection.
Definition: gifibers.c:391
GiFibersConfig * giraffe_fibers_config_create(cpl_parameterlist *list)
Creates a setup structure for the fiber selection.
Definition: gifibers.c:315
GiTable * giraffe_fibers_setup(const cpl_frame *frame, const cpl_frame *reference)
Setup a fiber list.
Definition: gifibers.c:218
cxint giraffe_fiberlist_compare(const GiTable *fibers, const GiTable *reference)
Compare two fiber lists.
Definition: gifiberutils.c:913
cxint giraffe_fiberlist_attach(cpl_frame *frame, GiTable *fibers)
Attach a fiber table to a frame.
Definition: gifiberutils.c:845
cxint giraffe_fiberlist_clear_index(GiTable *fibers)
Remove the reference index column from a fiber list.
cpl_frame * giraffe_frame_create_table(GiTable *table, const cxchar *tag, cpl_frame_level level, cxbool save, cxbool update)
Create a table product frame.
Definition: giframe.c:532
cpl_frame * giraffe_frame_create_image(GiImage *image, const cxchar *tag, cpl_frame_level level, cxbool save, cxbool update)
Create an image product frame.
Definition: giframe.c:393
cpl_frame * giraffe_get_slitgeometry(const cpl_frameset *set)
Get the slit geometry frame from a frame set.
Definition: giframe.c:775
cpl_frame * giraffe_get_frame(const cpl_frameset *set, const cxchar *tag, cpl_frame_group group)
Get a frame from a frame set.
Definition: giframe.c:728
cpl_frame * giraffe_frame_create(const cxchar *tag, cpl_frame_level level, const cpl_propertylist *properties, cxcptr object, cxcptr data, GiFrameCreator creator)
Create a product frame using a provided frame creator.
Definition: giframe.c:237
void giraffe_image_delete(GiImage *self)
Destroys an image.
Definition: giimage.c:181
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
Definition: giimage.c:282
cxint giraffe_image_add_info(GiImage *image, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to an image.
Definition: giimage.c:773
cxint giraffe_image_save(GiImage *self, const cxchar *filename)
Write a Giraffe image to a file.
Definition: giimage.c:570
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
Definition: giimage.c:218
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
Definition: giimage.c:65
cxint giraffe_image_load(GiImage *self, const cxchar *filename, cxint position)
Gets image data and properties from a file.
Definition: giimage.c:536
GiLocalizeConfig * giraffe_localize_config_create(cpl_parameterlist *list)
Creates a setup structure for the spectrum localization.
Definition: gilocalize.c:3188
void giraffe_localize_config_destroy(GiLocalizeConfig *config)
Destroys a spectrum localization setup structure.
Definition: gilocalize.c:3295
void giraffe_localize_config_add(cpl_parameterlist *list)
Adds parameters for the spectrum localization.
Definition: gilocalize.c:3319
cxint giraffe_localize_spectra(GiLocalization *result, GiImage *image, GiTable *fibers, GiLocalization *master, GiImage *badpixels, GiLocalizeConfig *config)
Finds the location of spectra in a Giraffe observation.
Definition: gilocalize.c:2560
void giraffe_psf_config_destroy(GiPsfConfig *self)
Destroys a PSF profile fit setup object.
Definition: gipsf.c:3254
GiPsfConfig * giraffe_psf_config_create(cpl_parameterlist *list)
Creates a setup object for the PSF profile fit.
Definition: gipsf.c:3150
cxint giraffe_compute_fiber_profiles(GiLocalization *result, GiImage *image, GiTable *fibers, GiLocalization *master, GiImage *bpixel, GiPsfConfig *config)
Compute the position and width of the spectra from the fiber profile.
Definition: gipsf.c:2601
void giraffe_psf_config_add(cpl_parameterlist *list)
Adds parameters for the PSF profile computation of the fibers.
Definition: gipsf.c:3283
void giraffe_slight_config_add(cpl_parameterlist *list)
Adds parameters for the scattered light computation.
Definition: gislight.c:1601
GiSLightConfig * giraffe_slight_config_create(cpl_parameterlist *list)
Creates a setup structure for the scattered light computation.
Definition: gislight.c:1379
cxint giraffe_adjust_scattered_light(GiImage *result, const GiImage *image, const GiLocalization *localization, const GiImage *bpixel, GiImage *phff, const GiSLightConfig *config)
Compute a scattered light model for a given image.
Definition: gislight.c:1197
void giraffe_slight_config_destroy(GiSLightConfig *config)
Destroys a scattered light setup structure.
Definition: gislight.c:1569
GiTable * giraffe_slitgeometry_load(const GiTable *fibers, const cxchar *filename, cxint pos, const cxchar *tag)
Load the slit geometry information for a given fiber setup.
cxint giraffe_table_load(GiTable *self, const cxchar *filename, cxint position, const cxchar *id)
Reads a data set from a file into a Giraffe table.
Definition: gitable.c:562
cxint giraffe_table_attach(GiTable *self, const cxchar *filename, cxint position, const cxchar *id)
Attach a Giraffe table to a file.
Definition: gitable.c:749
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
Definition: gitable.c:85
void giraffe_table_delete(GiTable *self)
Destroys a Giraffe table.
Definition: gitable.c:154
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
Definition: gitable.c:433
cxint giraffe_table_add_info(GiTable *table, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to a table.
Definition: gitable.c:836
GiTransmissionConfig * giraffe_transmission_config_create(cpl_parameterlist *list)
Creates a setup structure for the relative transmission computation.
void giraffe_transmission_config_add(cpl_parameterlist *list)
Adds parameters for the transmission correction computation.
void giraffe_transmission_config_destroy(GiTransmissionConfig *config)
Destroys a transmission field setup structure.
cxint giraffe_propertylist_copy(cpl_propertylist *self, const cxchar *name, const cpl_propertylist *other, const cxchar *othername)
Copy a property from one list to another.
Definition: giutils.c:1104
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.
Definition: giutils.c:418

This file is part of the GIRAFFE Pipeline Reference Manual 2.16.10.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Dec 15 2022 21:18:51 by doxygen 1.9.1 written by Dimitri van Heesch, © 1997-2004