KMOS Pipeline Reference Manual 4.5.10
kmos_std_star.c
1/*
2 * This file is part of the KMOS Pipeline
3 * Copyright (C) 2002,2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 * Includes
26 *----------------------------------------------------------------------------*/
27
28#include <math.h>
29#include <string.h>
30
31#include <cpl.h>
32
33#include "kmclipm_math.h"
34
35#include "kmo_constants.h"
36#include "kmo_cpl_extensions.h"
37#include "kmo_utils.h"
38#include "kmo_functions.h"
39#include "kmo_priv_std_star.h"
40#include "kmo_priv_fit_profile.h"
41#include "kmo_priv_extract_spec.h"
42#include "kmo_priv_functions.h"
43#include "kmo_dfs.h"
44#include "kmo_error.h"
45#include "kmo_debug.h"
46#include "kmo_priv_reconstruct.h"
47
48const int nr_lines_h = 10;
49const double lines_center_h[] = {
50 1.7001, // HeI // triplet
51 1.53429, // Br-18
52 1.54400, // Br-17
53 1.55576, // Br-16
54 1.57018, // Br-15
55 1.58817, // Br-14
56 1.61105, // Br-13
57 1.64084, // Br-12
58 1.68077, // Br-11
59 1.73634 // Br-10
60};
61const double lines_width_h[] = {
62 0.025, // HeI
63 0.003, // Br-18
64 0.015, // Br-17
65 0.015, // Br-16
66 0.015, // Br-15
67 0.025, // Br-14
68 0.015, // Br-13
69 0.025, // Br-12
70 0.025, // Br-11
71 0.05 // Br-10
72};
73const int nr_lines_k = 2;
74const double lines_center_k[] = {
75 2.1120, // HeI // triplet
76 2.16569 // Br-gamma
77};
78const double lines_width_k[] = {
79 0.01, // HeI // triplet
80 0.015 // Br-gamma
81};
82const int nr_lines_hk = 12;
83const double lines_center_hk[] = {
84 1.7001, // HeI // triplet
85 1.53429, // Br-18
86 1.54400, // Br-17
87 1.55576, // Br-16
88 1.57018, // Br-15
89 1.58817, // Br-14
90 1.61105, // Br-13
91 1.64084, // Br-12
92 1.68077, // Br-11
93 1.73634, // Br-10
94 2.1120, // HeI // triplet
95 2.16569 // Br-gamma
96};
97const double lines_width_hk[] = {
98 0.025, // HeI
99 0.003, // Br-18
100 0.015, // Br-17
101 0.015, // Br-16
102 0.015, // Br-15
103 0.025, // Br-14
104 0.015, // Br-13
105 0.025, // Br-12
106 0.025, // Br-11
107 0.05, // Br-10
108 0.015, // HeI // triplet
109 0.015 // Br-gamma
110};
111const int nr_lines_iz = 12;
112const double lines_center_iz[] = {
113 0.84386, // Pa-18
114 0.84679, // Pa-17
115 0.85031, // Pa-16
116 0.85460, // Pa-15
117 0.85990, // Pa-14
118 0.86657, // Pa-13
119 0.87511, // Pa-12
120 0.88635, // Pa-11
121 0.90156, // Pa-10
122 0.92297, // Pa-9
123 0.95467, // Pa-epsilon
124 1.00501 // Pa-delta
125};
126const double lines_width_iz[] = {
127 0.0008, // Pa-18
128 0.003225, // Pa-17
129 0.0039, // Pa-16
130 0.0048, // Pa-15
131 0.006, // Pa-14
132 0.0076, // Pa-13
133 0.001, // Pa-12
134 0.013, // Pa-11
135 0.01, // Pa-10
136 0.013, // Pa-9
137 0.02, // Pa-epsilon
138 0.025 // Pa-delta
139};
140const int nr_lines_yj = 7;
141const double lines_center_yj[] = {
142 1.08331, // HeI
143 1.09160, // HeI
144 1.09389, // Pa-gamma
145 1.19723, // HeI
146 1.28191, // Pa-beta
147 1.27882, // HeI
148 1.29720 // HeI
149};
150const double lines_width_yj[] = {
151 .01, //0.005, // HeI
152 .01, //0.002, // HeI
153 0.02, // Pa-gamma
154 0.003, // HeI
155 0.02, // Pa-beta
156 0.0025, // HeI
157 0.002 // HeI
158};
159
160/*-----------------------------------------------------------------------------
161 * Functions prototypes
162 *----------------------------------------------------------------------------*/
163
164static int kmos_std_star_compute_ifu(
165 cpl_propertylist * sub_header_orig,
166 cpl_frame * obj_frame,
167 cpl_frame * sky_frame,
168 cpl_frame * flat_frame,
169 cpl_frame * xcal_frame,
170 cpl_frame * ycal_frame,
171 cpl_frame * lcal_frame,
172 cpl_frame * illum_frame,
173 cpl_frame * atmos_frame,
174 cpl_frame * solar_frame,
175 int ifu_nr,
176 cpl_propertylist * main_header_tel,
177 gridDefinition gd,
178 int low_bound,
179 int high_bound,
180 const char * fmethod,
181 int flux,
182 int xcal_interpolation,
183 const char * mask_method,
184 const char * cmethod,
185 double cpos_rej,
186 double cneg_rej,
187 int citer,
188 int cmax,
189 int cmin,
190 double cen_x,
191 double cen_y,
192 double radius,
193 const char * filter_id,
194 char star_type,
195 int no_noise,
196 int is_stdstarscipatt,
197 skySkyStruct sky_sky_struct,
198 double star_temp,
199 cpl_vector ** spec_qc,
200 cpl_propertylist ** out_sub_tel_data_header,
201 cpl_propertylist ** out_sub_psf_header,
202 cpl_propertylist ** out_sub_cube_data_header,
203 cpl_imagelist ** out_data_cube,
204 cpl_imagelist ** out_noise_cube,
205 cpl_image ** out_psf_data,
206 cpl_image ** out_mask,
207 cpl_vector ** out_starspec_data,
208 cpl_vector ** out_starspec_noise,
209 cpl_vector ** out_noisespec,
210 cpl_vector ** out_telluric_data,
211 cpl_vector ** out_telluric_noise) ;
212static int kmos_std_star_check_inputs(
213 cpl_frameset * frameset,
214 const char * magnitude_txt,
215 int * is_stdstarscipatt,
216 int * compute_qcs,
217 double * magnitude1,
218 double * magnitude2) ;
219static int kmos_std_star_plot(void) ;
220static int kmos_std_star_adjust_double(
221 cpl_propertylist * header,
222 const char * key1,
223 const char * key2,
224 const char * key3) ;
225static int kmos_std_star_adjust_string(
226 cpl_propertylist * header,
227 const char * key1,
228 const char * key2,
229 const char * key3) ;
230static cpl_frameset * kmos_std_star_extract_same_grat_stds(
231 cpl_frameset * in,
232 int * same_gratings) ;
233
234static int kmos_std_star_create(cpl_plugin *);
235static int kmos_std_star_exec(cpl_plugin *);
236static int kmos_std_star_destroy(cpl_plugin *);
237static int kmos_std_star(cpl_parameterlist *, cpl_frameset *);
238
239/*-----------------------------------------------------------------------------
240 * Static variables
241 *----------------------------------------------------------------------------*/
242
243static char kmos_std_star_description[] =
244"This recipe creates a telluric frame and a PSF frames.\n"
245"Since there cannot be 1 std star per IFU in one exposure, we use several\n"
246"exposures in order to have at least one standard star and one sky\n"
247"in each IFU. The frames are organised following this logic:\n"
248"1. For each IFU the first standard star in the list of frames is\n"
249" taken. All subsequent standard star exposures for this IFU are ignored\n"
250"2. A closest in time sky exposure is uѕed\n"
251"3. IFUs not containing a standard star and a sky will be empty in the result\n"
252"\n"
253"NOISE_SPEC contains the shot noise [sqrt(counts*gain)/gain]\n"
254"If the exposures have been taken with KMOS_spec_cal_stdstarscipatt, an\n"
255"additional noise component is added: All existing sky exposures for an IFU\n"
256"are subtracted pairwise, spectra are extracted and the std deviation is \n"
257"computed\n"
258"\n"
259"-------------------------------------------------------------------------------\n"
260" Input files:\n"
261"\n"
262" DO KMOS \n"
263" category Type Explanation Required #Frames\n"
264" -------- ----- ----------- -------- -------\n"
265" STD RAW Std. star & sky exposures Y >=1 \n"
266" XCAL F2D x calibration frame Y 1 \n"
267" YCAL F2D y calibration frame Y 1 \n"
268" LCAL F2D Wavelength calib. frame Y 1 \n"
269" MASTER_FLAT F2D Master flat frame Y 1 \n"
270" WAVE_BAND F2L Table with start-/end-wl Y 1 \n"
271" ILLUM_CORR F2I Illumination correction N 0,1 \n"
272" SOLAR_SPEC F1S Solar spectrum N 0,1 \n"
273" (only for G stars) \n"
274" ATMOS_MODEL F1S Model atmospheric transmisson N 0,1 \n"
275" (only for OBAF stars in K band) \n"
276" SPEC_TYPE_LOOKUP F2L LUT eff. stellar temperature N 0,1 \n"
277"\n"
278" Output files: \n"
279"\n"
280" DO KMOS \n"
281" category Type Explanation \n"
282" -------- ----- ----------- \n"
283" TELLURIC F1I The normalised telluric spectrum \n"
284" (including errors) \n"
285" STAR_SPEC F1I The extracted star spectrum \n"
286" (including errors) \n"
287" STD_IMAGE F2I The standard star PSF images \n"
288" STD_MASK F2I The mask used to extract the star spec \n"
289" NOISE_SPEC F1I The extracted noise spectrum \n"
290"---------------------------------------------------------------------------\n"
291"\n";
292
293/*-----------------------------------------------------------------------------
294 * Functions code
295 *----------------------------------------------------------------------------*/
296
297/*----------------------------------------------------------------------------*/
301/*----------------------------------------------------------------------------*/
302
305/*----------------------------------------------------------------------------*/
314/*----------------------------------------------------------------------------*/
315int cpl_plugin_get_info(cpl_pluginlist *list)
316{
317 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
318 cpl_plugin *plugin = &recipe->interface;
319
320 cpl_plugin_init(plugin,
321 CPL_PLUGIN_API,
322 KMOS_BINARY_VERSION,
323 CPL_PLUGIN_TYPE_RECIPE,
324 "kmos_std_star",
325 "Create the telluric correction frame.",
326 kmos_std_star_description,
327 "Alex Agudo Berbel, Y. Jung",
328 "https://support.eso.org/",
329 kmos_get_license(),
330 kmos_std_star_create,
331 kmos_std_star_exec,
332 kmos_std_star_destroy);
333 cpl_pluginlist_append(list, plugin);
334
335 return 0;
336}
337
338/*----------------------------------------------------------------------------*/
346/*----------------------------------------------------------------------------*/
347static int kmos_std_star_create(cpl_plugin *plugin)
348{
349 cpl_recipe *recipe;
350 cpl_parameter *p;
351
352 /* Check that the plugin is part of a valid recipe */
353 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
354 recipe = (cpl_recipe *)plugin;
355 else
356 return -1;
357
358 /* Create the parameters list in the cpl_recipe object */
359 recipe->parameters = cpl_parameterlist_new();
360
361 /* --startype */
362 p = cpl_parameter_new_value("kmos.kmos_std_star.startype", CPL_TYPE_STRING,
363 "The spectral type of the star (O, B, A, F, G) e.g. G4V",
364 "kmos.kmos_std_star", "");
365 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startype");
366 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
367 cpl_parameterlist_append(recipe->parameters, p);
368
369 /* --imethod */
370 p = cpl_parameter_new_value("kmos.kmos_std_star.imethod", CPL_TYPE_STRING,
371 "Method to use for interpolation. "
372 "[\"NN\" (nearest neighbour), "
373 "\"lwNN\" (linear weighted nearest neighbor), "
374 "\"swNN\" (square weighted nearest neighbor), "
375 "\"MS\" (Modified Shepard's method), "
376 "\"CS\" (Cubic spline)]",
377 "kmos.kmos_std_star", "CS");
378 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
379 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
380 cpl_parameterlist_append(recipe->parameters, p);
381
382 /* --fmethod */
383 p = cpl_parameter_new_value("kmos.kmos_std_star.fmethod", CPL_TYPE_STRING,
384 "Fitting method (gauss, moffat, profile", "kmos.kmos_std_star",
385 "gauss");
386 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
387 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
388 cpl_parameterlist_append(recipe->parameters, p);
389
390 /* --neighborhoodRange */
391 p = cpl_parameter_new_value("kmos.kmos_std_star.neighborhoodRange",
392 CPL_TYPE_DOUBLE,
393 "Defines the range to search for neighbors in pixels",
394 "kmos.kmos_std_star", 1.001);
395 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
396 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
397 cpl_parameterlist_append(recipe->parameters, p);
398
399 /* --magnitude */
400 p = cpl_parameter_new_value("kmos.kmos_std_star.magnitude", CPL_TYPE_STRING,
401 "Star magnitude (2 values in HK, eg. 12.1,13.2)",
402 "kmos.kmos_std_star", "");
403 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "magnitude");
404 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
405 cpl_parameterlist_append(recipe->parameters, p);
406
407 /* --flux */
408 p = cpl_parameter_new_value("kmos.kmos_std_star.flux", CPL_TYPE_BOOL,
409 "TRUE: Apply flux conservation. FALSE: otherwise",
410 "kmos.kmos_std_star", TRUE);
411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
412 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
413 cpl_parameterlist_append(recipe->parameters, p);
414
415 /* --save_cubes */
416 p = cpl_parameter_new_value("kmos.kmos_std_star.save_cubes", CPL_TYPE_BOOL,
417 "Flag to save reconstructed cubes", "kmos.kmos_std_star", FALSE);
418 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save_cubes");
419 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
420 cpl_parameterlist_append(recipe->parameters, p);
421
422 /* --no_noise */
423 p = cpl_parameter_new_value("kmos.kmos_std_star.no_noise", CPL_TYPE_BOOL,
424 "Skip the noise computation on sky exposures", "kmos.kmos_std_star",
425 FALSE);
426 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_noise");
427 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
428 cpl_parameterlist_append(recipe->parameters, p);
429
430 /* --xcal_interpolation */
431 p = cpl_parameter_new_value("kmos.kmos_std_star.xcal_interpolation",
432 CPL_TYPE_BOOL, "Flag to Interpolate xcal between rotator angles",
433 "kmos.kmos_std_star", TRUE);
434 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation");
435 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
436 cpl_parameterlist_append(recipe->parameters, p);
437
438 /* --suppress_extension */
439 p = cpl_parameter_new_value("kmos.kmos_std_star.suppress_extension",
440 CPL_TYPE_BOOL, "Flag to Suppress filename extension",
441 "kmos.kmos_std_star", FALSE);
442 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension");
443 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
444 cpl_parameterlist_append(recipe->parameters, p);
445
446 /* Add parameters for band-definition */
447 kmos_band_pars_create(recipe->parameters, "kmos.kmos_std_star");
448
449 /* --mask_method */
450 p = cpl_parameter_new_value("kmos.kmos_std_star.mask_method",
451 CPL_TYPE_STRING, "Method used : mask, integrated or optimal",
452 "kmos.kmos_std_star", "optimal");
453 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "mask_method");
454 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
455 cpl_parameterlist_append(recipe->parameters, p);
456
457 /* --centre */
458 p = cpl_parameter_new_value("kmos.kmos_std_star.centre",
459 CPL_TYPE_STRING, "The centre of the circular mask (pixel)",
460 "kmos.kmos_std_star", "7.5,7.5");
461 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "centre");
462 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
463 cpl_parameterlist_append(recipe->parameters, p);
464
465 /* --radius */
466 p = cpl_parameter_new_value("kmos.kmos_std_star.radius",
467 CPL_TYPE_DOUBLE, "The radius of the circular mask (pixel)",
468 "kmos.kmos_std_star", 3.0);
469 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "radius");
470 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
471 cpl_parameterlist_append(recipe->parameters, p);
472
473 /* --extra_outputs */
474 p = cpl_parameter_new_value("kmos.kmos_std_star.extra_outputs",
475 CPL_TYPE_BOOL, "Flag to save extra outputs",
476 "kmos.kmos_std_star", FALSE);
477 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extra_outputs");
478 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
479 cpl_parameterlist_append(recipe->parameters, p);
480
481 /* Add parameters for combining */
482 return kmos_combine_pars_create(recipe->parameters, "kmos.kmos_std_star",
483 DEF_REJ_METHOD, FALSE);
484}
485
486/*----------------------------------------------------------------------------*/
492/*----------------------------------------------------------------------------*/
493static int kmos_std_star_exec(cpl_plugin *plugin)
494{
495 cpl_recipe *recipe;
496
497 /* Get the recipe out of the plugin */
498 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
499 recipe = (cpl_recipe *)plugin;
500 else return -1;
501
502 return kmos_std_star(recipe->parameters, recipe->frames);
503}
504
505/*----------------------------------------------------------------------------*/
511/*----------------------------------------------------------------------------*/
512static int kmos_std_star_destroy(cpl_plugin *plugin)
513{
514 cpl_recipe *recipe;
515
516 /* Get the recipe out of the plugin */
517 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
518 recipe = (cpl_recipe *)plugin;
519 else return -1 ;
520
521 cpl_parameterlist_delete(recipe->parameters);
522 return 0 ;
523}
524
525/*----------------------------------------------------------------------------*/
538/*----------------------------------------------------------------------------*/
539static int kmos_std_star(cpl_parameterlist *parlist, cpl_frameset *frameset)
540{
541 const cpl_parameter * par ;
542 /*********************/
543 /* Parsed Parameters */
544 const char * imethod ;
545 const char * cmethod ;
546 const char * fmethod ;
547 const char * mask_method ;
548 const char * centre_txt ;
549 cpl_vector * centre ;
550 const char * spec_type ;
551 const char * magnitude_txt ;
552 double cpos_rej, cneg_rej, neighborhoodRange;
553 double cen_x = 0., cen_y = 0., radius = 0.;
554 int flux, save_cubes, no_noise, citer, cmin, cmax,
555 xcal_interpolation, suppress_extension,
556 extra_outputs ;
557 /*********************/
558 char * suffix ;
559 char * keyword ;
560 char * extname ;
561 char * fn_suffix ;
562 const char * filter_id ;
563 cpl_array ** unused_ifus_before ;
564 cpl_array ** unused_ifus_after ;
565 const int * punused_ifus ;
566 gridDefinition gd;
567 cpl_propertylist * tmp_header ;
568 cpl_propertylist * main_header_tel ;
569 cpl_propertylist * sub_header_orig ;
570 cpl_propertylist * main_header_psf ;
571 int * bounds ;
572 objSkyStruct * obj_sky_struct ;
573 skySkyStruct * sky_sky_struct ;
574
575 cpl_imagelist ** stored_data_cube ;
576 cpl_imagelist ** stored_noise_cube ;
577 cpl_image ** stored_psf_data ;
578 cpl_image ** stored_mask ;
579 cpl_vector ** stored_telluric_data ;
580 cpl_vector ** stored_telluric_noise ;
581 cpl_vector ** stored_starspec_data ;
582 cpl_vector ** stored_starspec_noise ;
583 cpl_vector ** stored_noisespec ;
584 double * stored_qc_throughput ;
585 cpl_propertylist ** stored_sub_tel_data_headers ;
586 cpl_propertylist ** stored_sub_tel_noise_headers ;
587 cpl_propertylist ** stored_sub_cube_data_headers ;
588 cpl_propertylist ** stored_sub_cube_noise_headers ;
589 cpl_propertylist ** stored_sub_psf_headers ;
590 char filename_telluric[256],
591 filename_starspec[256],
592 filename_psf[256],
593 filename_mask[256],
594 filename_cubes[256],
595 filename_noise[256] ;
596 cpl_frame * obj_frame ;
597 cpl_frame * sky_frame ;
598 cpl_frame * xcal_frame ;
599 cpl_frame * ycal_frame ;
600 cpl_frame * lcal_frame ;
601 cpl_frame * flat_frame ;
602 cpl_frame * illum_frame ;
603 cpl_frame * solar_frame ;
604 cpl_frame * atmos_frame ;
605 cpl_table * band_table ;
606 cpl_frameset * frameset_std ;
607 cpl_vector * spec_qc ;
608 int is_stdstarscipatt, compute_qcs,
609 ifu_nr, nifus, nr_std_stars ;
610 double magnitude1, magnitude2, star_temp, exptime,
611 throughput_mean, throughput_sdv, cdelt1, crpix1,
612 crval1, zeropoint, tmp_data, tmp_noise, counts1,
613 counts2, gain ;
614 double sat_nb;
615 char star_type ;
616 kmclipm_vector * ddd ;
617 int i, j ;
618
619 /* Check initial Entries */
620 if (kmos_check_and_set_groups(frameset) != CPL_ERROR_NONE) {
621 return cpl_error_get_code();
622 }
623
624 /* Initialise */
625 nr_std_stars = 0 ;
626 zeropoint = throughput_mean = throughput_sdv = -1.0 ;
627 magnitude1 = magnitude2 = -1.0 ;
628
629 /* Get parameters */
630 par = cpl_parameterlist_find_const(parlist,
631 "kmos.kmos_std_star.extra_outputs");
632 extra_outputs = cpl_parameter_get_bool(par);
633 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.imethod");
634 imethod = cpl_parameter_get_string(par) ;
635 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.startype");
636 spec_type = cpl_parameter_get_string(par) ;
637 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.fmethod");
638 fmethod = cpl_parameter_get_string(par) ;
639 par = cpl_parameterlist_find_const(parlist,
640 "kmos.kmos_std_star.neighborhoodRange");
641 neighborhoodRange = cpl_parameter_get_double(par) ;
642 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.magnitude");
643 magnitude_txt = cpl_parameter_get_string(par) ;
644 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.flux");
645 flux = cpl_parameter_get_bool(par);
646 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_std_star.save_cubes");
647 save_cubes = cpl_parameter_get_bool(par);
648 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.no_noise");
649 no_noise = cpl_parameter_get_bool(par);
650 par = cpl_parameterlist_find_const(parlist,
651 "kmos.kmos_std_star.xcal_interpolation");
652 xcal_interpolation = cpl_parameter_get_bool(par);
653 par = cpl_parameterlist_find_const(parlist,
654 "kmos.kmos_std_star.suppress_extension");
655 suppress_extension = cpl_parameter_get_bool(par);
656 kmos_band_pars_load(parlist, "kmos.kmos_std_star");
657 par = cpl_parameterlist_find_const(parlist,
658 "kmos.kmos_std_star.mask_method");
659 mask_method = cpl_parameter_get_string(par) ;
660 if (!strcmp(mask_method, "integrated")) {
661 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_std_star.centre");
662 centre_txt = cpl_parameter_get_string(par) ;
663 centre = kmo_identify_ranges(centre_txt);
664 if (cpl_vector_get_size(centre) != 2) {
665 cpl_msg_error(__func__, "centre must have 2 values like a,b") ;
666 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
667 return -1 ;
668 }
669 cen_x = cpl_vector_get(centre, 0);
670 cen_y = cpl_vector_get(centre, 1);
671 cpl_vector_delete(centre);
672 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_std_star.radius");
673 radius = cpl_parameter_get_double(par) ;
674 if (radius < 0.0) {
675 cpl_msg_error(__func__, "radius must be greater than 0.0") ;
676 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
677 return -1 ;
678 }
679 } else if (strcmp(mask_method, "optimal")) {
680 cpl_msg_error(__func__, "Unsupported mask method: %s", mask_method) ;
681 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
682 return -1 ;
683 }
684 kmos_combine_pars_load(parlist, "kmos.kmos_std_star", &cmethod,
685 &cpos_rej, &cneg_rej, &citer, &cmin, &cmax, FALSE);
686
687 /* Check Parameters */
688 if (strcmp(cmethod, "average") && strcmp(cmethod, "median") &&
689 strcmp(cmethod, "sum") && strcmp(cmethod, "min_max") &&
690 strcmp(cmethod, "ksigma")) {
691 cpl_msg_error(__func__,
692 "cmethod must be average median sum min_max or ksigma") ;
693 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
694 return -1 ;
695 }
696 if (strcmp(imethod, "NN") && strcmp(imethod, "lwNN") &&
697 strcmp(imethod, "swNN") && strcmp(imethod, "MS") &&
698 strcmp(imethod, "CS")) {
699 cpl_msg_error(__func__, "imethod must be NN,lwNN,swNN,MS or CS") ;
700 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
701 return -1 ;
702 }
703 if (strcmp(fmethod, "gauss") && strcmp(fmethod, "moffat")) {
704 cpl_msg_error(__func__, "fmethod must be gauss or moffat") ;
705 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
706 return -1 ;
707 }
708 if (neighborhoodRange <= 0.0) {
709 cpl_msg_error(__func__, "neighborhoodRange must be greater than 0.0") ;
710 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
711 return -1 ;
712 }
713
714 /* Check the inputs consistency */
715 if (kmos_std_star_check_inputs(frameset, magnitude_txt, &is_stdstarscipatt,
716 &compute_qcs, &magnitude1, &magnitude2) != 1) {
717 cpl_msg_error(__func__, "Input frameset is not consistent") ;
718 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
719 return -1 ;
720 }
721
722 /* Instrument setup */
723 suffix = kmo_dfs_get_suffix(kmo_dfs_get_frame(frameset, STD), TRUE, FALSE);
724 cpl_msg_info("", "Detected instrument setup: %s", suffix+1);
725
726 /* Check which IFUs are active for all frames */
727 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0);
728 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before);
729 kmo_print_unused_ifus(unused_ifus_before, FALSE);
730 kmo_free_unused_ifus(unused_ifus_before);
731
732 /* Setup grid definition, wavelength start and end are set later */
733 kmclipm_setup_grid(&gd, imethod, neighborhoodRange, KMOS_PIX_RESOLUTION,0.);
734
735 /* Get left and right bounds of IFUs from XCAL */
736 tmp_header = kmo_dfs_load_primary_header(frameset, XCAL);
737 bounds = kmclipm_extract_bounds(tmp_header);
738 cpl_propertylist_delete(tmp_header);
739
740 /* Extract STD frames */
741 frameset_std = kmos_std_star_extract_same_grat_stds(frameset, &i) ;
742
743 /* Get valid STD frames with objects in it and associated sky exposures */
744 obj_sky_struct = kmo_create_objSkyStruct(frameset_std, STD, FALSE);
745 kmo_print_objSkyStruct(obj_sky_struct);
746
747 /* Check if there is at least 1 object */
748 if (obj_sky_struct->size == 0) {
749 cpl_free(suffix);
750 cpl_free(bounds);
751 kmo_free_unused_ifus(unused_ifus_after);
752 cpl_frameset_delete(frameset_std) ;
753 cpl_msg_error(cpl_func, "No Object found");
754 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
755 return -1 ;
756 }
757
758 /* Identify sky-sky-pairs for NOISE_SPEC calculation */
759 sky_sky_struct = kmo_create_skySkyStruct(frameset_std);
760
761 /* Get frame */
762 illum_frame = kmo_dfs_get_frame(frameset, ILLUM_CORR);
763 flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT);
764 xcal_frame = kmo_dfs_get_frame(frameset, XCAL) ;
765 ycal_frame = kmo_dfs_get_frame(frameset, YCAL) ;
766 lcal_frame = kmo_dfs_get_frame(frameset, LCAL) ;
767 atmos_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL);
768 solar_frame = kmo_dfs_get_frame(frameset, SOLAR_SPEC);
769
770 /* Allocate intermediate memory */
771 nifus = KMOS_NR_DETECTORS * KMOS_IFUS_PER_DETECTOR ;
772 stored_telluric_data = (cpl_vector**)cpl_calloc(nifus, sizeof(cpl_vector*));
773 stored_telluric_noise = (cpl_vector**)cpl_calloc(nifus,sizeof(cpl_vector*));
774 stored_starspec_data = (cpl_vector**)cpl_calloc(nifus, sizeof(cpl_vector*));
775 stored_starspec_noise = (cpl_vector**)cpl_calloc(nifus,sizeof(cpl_vector*));
776 stored_psf_data = (cpl_image**)cpl_calloc(nifus, sizeof(cpl_image*));
777 stored_mask = (cpl_image**)cpl_calloc(nifus, sizeof(cpl_image*));
778 stored_data_cube =(cpl_imagelist**)cpl_calloc(nifus,sizeof(cpl_imagelist*));
779 stored_noise_cube=(cpl_imagelist**)cpl_calloc(nifus,sizeof(cpl_imagelist*));
780 stored_qc_throughput = (double*)cpl_calloc(nifus, sizeof(double));
781 stored_sub_psf_headers = (cpl_propertylist**)cpl_calloc(nifus,
782 sizeof(cpl_propertylist*));
783 stored_sub_tel_data_headers = (cpl_propertylist**)cpl_calloc(nifus,
784 sizeof(cpl_propertylist*));
785 stored_sub_tel_noise_headers = (cpl_propertylist**)cpl_calloc(nifus,
786 sizeof(cpl_propertylist*));
787 stored_sub_cube_data_headers = (cpl_propertylist**)cpl_calloc(nifus,
788 sizeof(cpl_propertylist*));
789 stored_sub_cube_noise_headers=(cpl_propertylist**)cpl_calloc(nifus,
790 sizeof(cpl_propertylist*));
791 stored_noisespec = (cpl_vector**)cpl_calloc(nifus, sizeof(cpl_vector*));
792
793 strcpy(filename_telluric, TELLURIC);
794 strcpy(filename_starspec, STAR_SPEC);
795 strcpy(filename_psf, STD_IMAGE);
796 strcpy(filename_mask, STD_MASK);
797 strcpy(filename_cubes, STD_CUBE);
798 strcpy(filename_noise, NOISE_SPEC);
799
800 /*
801 cpl_free(stored_telluric_data);
802 cpl_free(stored_telluric_noise);
803 cpl_free(stored_starspec_data);
804 cpl_free(stored_starspec_noise);
805 cpl_free(stored_psf_data);
806 cpl_free(stored_sub_tel_data_headers);
807 cpl_free(stored_sub_tel_noise_headers);
808 cpl_free(stored_noisespec);
809 cpl_free(stored_sub_cube_data_headers);
810 cpl_free(stored_sub_cube_noise_headers);
811 cpl_free(stored_sub_psf_headers);
812 cpl_free(stored_mask);
813 cpl_free(stored_data_cube);
814 cpl_free(stored_noise_cube);
815 cpl_free(stored_qc_throughput) ;
816 kmo_delete_objSkyStruct(obj_sky_struct);
817 kmo_delete_skySkyStruct(sky_sky_struct);
818 cpl_free(suffix);
819 cpl_free(bounds);
820 kmo_free_unused_ifus(unused_ifus_after);
821 cpl_frameset_delete(frameset_std) ;
822 return 0 ;
823 */
824
825 /* Get the first frame containing object */
826 obj_frame = obj_sky_struct->table[0].objFrame;
827 main_header_tel = kmclipm_propertylist_load(
828 cpl_frame_get_filename(obj_frame), 0);
829 exptime = cpl_propertylist_get_double(main_header_tel, EXPTIME);
830
831 /* Get the star temperature */
832 star_temp = kmos_get_temperature(frameset, spec_type, &star_type) ;
833
834 /* Loop on detectors */
835 for (i = 1; i <= KMOS_NR_DETECTORS ; i++) {
836 print_cal_angle_msg_once = FALSE;
837 print_xcal_angle_msg_once = FALSE;
838 if (i==1) {
839 print_cal_angle_msg_once = TRUE;
840 print_xcal_angle_msg_once = TRUE;
841 }
842
843 /* Get filter for this detector ESO INS FILTi ID */
844 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i,
845 IFU_FILTID_POSTFIX);
846 filter_id = cpl_propertylist_get_string(main_header_tel, keyword);
847 cpl_free(keyword);
848
849 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0);
850 kmclipm_setup_grid_band_lcal(&gd, filter_id, band_table);
851 cpl_table_delete(band_table);
852
853 /* Load extension header */
854 sub_header_orig = kmclipm_propertylist_load(
855 cpl_frame_get_filename(obj_frame), i);
856 if (i == 1) {
857 sat_nb = 0;
858 }
859 /* Loop on IFUs */
860 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
861 ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
862
863 /* Check if IFU valid */
864
865 /* Check if there is a sky frame available for this IFU */
866 kmo_collapse_objSkyStruct(obj_sky_struct, ifu_nr, &obj_frame,
867 &sky_frame);
868 punused_ifus = cpl_array_get_data_int_const(unused_ifus_after[i-1]);
869 /* Search for keyword ESO OCS ARMi NOTUSED */
870 /* If CPL_ERROR_DATA_NOT_FOUND, process standard star */
871 keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr,
872 IFU_VALID_POSTFIX);
873 cpl_propertylist_get_string(main_header_tel, keyword);
874 cpl_free(keyword);
875
876 if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) &&
877 (bounds[2*(ifu_nr-1)] != -1) &&
878 (bounds[2*(ifu_nr-1)+1] != -1) &&
879 (sky_frame != NULL) && (punused_ifus[j] == 0)) {
880 cpl_error_reset();
881 /* IFU is valid */
882
883 /* Process IFU */
884 if (kmos_std_star_compute_ifu(sub_header_orig, obj_frame,
885 sky_frame, flat_frame, xcal_frame, ycal_frame,
886 lcal_frame, illum_frame, atmos_frame, solar_frame,
887 ifu_nr, main_header_tel, gd, bounds[2*(ifu_nr-1)],
888 bounds[2*(ifu_nr-1)+1], fmethod, flux,
889 xcal_interpolation, mask_method, cmethod, cpos_rej,
890 cneg_rej, citer, cmax, cmin, cen_x, cen_y, radius,
891 filter_id, star_type, no_noise, is_stdstarscipatt,
892 sky_sky_struct[ifu_nr-1], star_temp,
893 &spec_qc,
894 &stored_sub_tel_data_headers[ifu_nr-1],
895 &stored_sub_psf_headers[ifu_nr-1],
896 &stored_sub_cube_data_headers[ifu_nr-1],
897 &stored_data_cube[ifu_nr-1],
898 &stored_noise_cube[ifu_nr-1],
899 &stored_psf_data[ifu_nr-1],
900 &stored_mask[ifu_nr-1],
901 &stored_starspec_data[ifu_nr-1],
902 &stored_starspec_noise[ifu_nr-1],
903 &stored_noisespec[ifu_nr-1],
904 &stored_telluric_data[ifu_nr-1],
905 &stored_telluric_noise[ifu_nr-1]) == -1) {
906 stored_telluric_data[ifu_nr-1] = NULL ;
907 stored_telluric_noise[ifu_nr-1] = NULL ;
908 stored_starspec_data[ifu_nr-1] = NULL ;
909 stored_starspec_noise[ifu_nr-1] = NULL ;
910 stored_psf_data[ifu_nr-1] = NULL ;
911 stored_mask[ifu_nr-1] = NULL ;
912 stored_data_cube[ifu_nr-1] = NULL ;
913 stored_noise_cube[ifu_nr-1] = NULL ;
914 stored_noisespec[ifu_nr-1] = NULL ;
915
916 stored_sub_tel_data_headers[ifu_nr-1] =
917 cpl_propertylist_duplicate(sub_header_orig);
918 stored_sub_tel_noise_headers[ifu_nr-1] =
919 cpl_propertylist_duplicate(sub_header_orig);
920 stored_sub_psf_headers[ifu_nr-1] =
921 cpl_propertylist_duplicate(sub_header_orig);
922 stored_sub_cube_data_headers[ifu_nr-1] =
923 cpl_propertylist_duplicate(sub_header_orig);
924 stored_sub_cube_noise_headers[ifu_nr-1] =
925 cpl_propertylist_duplicate(sub_header_orig);
926 } else {
927 /* If magnitude is provided, get zeropoint and throughput */
928 if (compute_qcs) {
929 /* QC THROUGHPUT */
930 gain = cpl_propertylist_get_double(
931 stored_sub_tel_data_headers[ifu_nr-1], GAIN);
932 crpix1=cpl_propertylist_get_double(
933 stored_sub_tel_data_headers[ifu_nr-1], CRPIX1);
934 crval1=cpl_propertylist_get_double(
935 stored_sub_tel_data_headers[ifu_nr-1], CRVAL1);
936 cdelt1=cpl_propertylist_get_double(
937 stored_sub_tel_data_headers[ifu_nr-1], CDELT1);
938 kmo_calc_counts(spec_qc, filter_id, crpix1, crval1,
939 cdelt1, &counts1, &counts2);
940 counts1 /= exptime;
941 counts2 /= exptime;
942 stored_qc_throughput[ifu_nr-1] =
943 kmo_calc_throughput(magnitude1, magnitude2,
944 counts1, counts2, gain, filter_id);
945 if (kmclipm_is_nan_or_inf(
946 stored_qc_throughput[ifu_nr-1]))
947 stored_qc_throughput[ifu_nr-1] = -1;
948 kmclipm_update_property_double(
949 stored_sub_tel_data_headers[ifu_nr-1],
950 QC_THROUGHPUT,
951 stored_qc_throughput[ifu_nr-1],
952 "[] IFU throughput");
953
954 /* QC ZEROPOINT */
955 zeropoint = kmo_calc_zeropoint(magnitude1, magnitude2,
956 counts1, counts2, cdelt1, filter_id);
957 if (kmclipm_is_nan_or_inf(zeropoint)) zeropoint = -1;
958 kmclipm_update_property_double(
959 stored_sub_tel_data_headers[ifu_nr-1],
960 QC_ZEROPOINT, zeropoint, "[mag] IFU zeropoint");
961
962 /* QC SAT_NB*/
963 cpl_image * sat_im = kmclipm_image_load(cpl_frame_get_filename(obj_frame), CPL_TYPE_FLOAT, 0, 1);
964 cpl_mask * sat_mask = cpl_mask_threshold_image_create(sat_im,
965 QC_SAT_LEVEL_VAL, INFINITY);
966 cpl_msg_info(__func__, "calculating SAT_NB new - %lld, %lld", cpl_mask_get_size_x(sat_mask), cpl_mask_get_size_y(sat_mask) );
967 sat_nb = (cpl_mask_count(sat_mask) >= sat_nb)? cpl_mask_count(sat_mask): sat_nb;
968 cpl_msg_info(__func__, "%f", sat_nb);
969
970 cpl_mask_delete(sat_mask);
971 cpl_image_delete(sat_im);
972
973 }
974 /* Update number of standard stars */
975 nr_std_stars++;
976 cpl_vector_delete(spec_qc) ;
977 }
978 } else {
979 cpl_error_reset();
980 /* IFU is invalid */
981 stored_telluric_data[ifu_nr-1] = NULL ;
982 stored_telluric_noise[ifu_nr-1] = NULL ;
983 stored_starspec_data[ifu_nr-1] = NULL ;
984 stored_starspec_noise[ifu_nr-1] = NULL ;
985 stored_psf_data[ifu_nr-1] = NULL ;
986 stored_mask[ifu_nr-1] = NULL ;
987 stored_data_cube[ifu_nr-1] = NULL ;
988 stored_noise_cube[ifu_nr-1] = NULL ;
989 stored_noisespec[ifu_nr-1] = NULL ;
990
991 stored_sub_tel_data_headers[ifu_nr-1] =
992 cpl_propertylist_duplicate(sub_header_orig);
993 stored_sub_tel_noise_headers[ifu_nr-1] =
994 cpl_propertylist_duplicate(sub_header_orig);
995 stored_sub_psf_headers[ifu_nr-1] =
996 cpl_propertylist_duplicate(sub_header_orig);
997 stored_sub_cube_data_headers[ifu_nr-1] =
998 cpl_propertylist_duplicate(sub_header_orig);
999 stored_sub_cube_noise_headers[ifu_nr-1] =
1000 cpl_propertylist_duplicate(sub_header_orig);
1001 }
1002
1003 /* EXTNAME for DATA */
1004 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA);
1005 kmclipm_update_property_string(
1006 stored_sub_tel_data_headers[ifu_nr-1], EXTNAME, extname,
1007 "FITS extension name");
1008 kmclipm_update_property_string(
1009 stored_sub_psf_headers[ifu_nr-1], EXTNAME, extname,
1010 "FITS extension name");
1011 kmclipm_update_property_string(
1012 stored_sub_cube_data_headers[ifu_nr-1], EXTNAME,
1013 extname, "FITS extension name");
1014 cpl_free(extname);
1015
1016 /* EXTNAME for NOISE */
1017 if (stored_sub_tel_noise_headers[ifu_nr-1] == NULL) {
1018 stored_sub_tel_noise_headers[ifu_nr-1] =
1019 cpl_propertylist_duplicate(
1020 stored_sub_tel_data_headers[ifu_nr-1]);
1021 }
1022 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE);
1023 kmclipm_update_property_string(
1024 stored_sub_tel_noise_headers[ifu_nr-1], EXTNAME,
1025 extname, "FITS extension name");
1026 if (stored_sub_cube_noise_headers[ifu_nr-1] == NULL)
1027 stored_sub_cube_noise_headers[ifu_nr-1] =
1028 cpl_propertylist_duplicate(
1029 stored_sub_cube_data_headers[ifu_nr-1]);
1030 kmclipm_update_property_string(
1031 stored_sub_cube_noise_headers[ifu_nr-1], EXTNAME,
1032 extname, "FITS extension name");
1033 cpl_free(extname);
1034 }
1035 cpl_propertylist_delete(sub_header_orig);
1036 }
1037 cpl_free(bounds);
1038
1039 /* Write QC parameter: nr of std stars */
1040 kmclipm_update_property_int(main_header_tel, QC_NR_STD_STARS,
1041 nr_std_stars, "[] Nr. of std stars");
1042 kmclipm_update_property_double(main_header_tel, QC_SAT_LEVEL,
1043 QC_SAT_LEVEL_VAL, "[] Sat. Level ADU");
1044 kmclipm_update_property_double(main_header_tel, QC_SAT_NB,
1045 sat_nb, "Largest number of sat pixels per detector.");
1046
1047 /* Update which IFUs are not used */
1048 kmo_print_unused_ifus(unused_ifus_after, TRUE);
1049 kmo_set_unused_ifus(unused_ifus_after, main_header_tel,"kmos_std_star");
1050 kmo_free_unused_ifus(unused_ifus_after);
1051
1052 main_header_psf = cpl_propertylist_duplicate(main_header_tel);
1053
1054
1055 if (compute_qcs) {
1056 /* QC THROUGHPUT MEAN and QC THROUGHPUT SDV */
1057 kmo_calc_mean_throughput(stored_qc_throughput, nifus, &throughput_mean,
1058 &throughput_sdv);
1059 kmclipm_update_property_double(main_header_tel, QC_THROUGHPUT_MEAN,
1060 throughput_mean, "[] mean throughput for all detectors");
1061 kmclipm_update_property_double(main_header_tel, QC_THROUGHPUT_SDV,
1062 throughput_sdv, "[] stdev throughput for all detectors");
1063 }
1064 cpl_free(stored_qc_throughput);
1065
1066 /* Save output data */
1067 if (!suppress_extension) fn_suffix = cpl_sprintf("%s", suffix);
1068 else fn_suffix = cpl_sprintf("%s", "");
1069 cpl_free(suffix);
1070
1071 /* Save primary extension */
1072 kmo_dfs_save_main_header(frameset, filename_telluric, fn_suffix,
1073 obj_frame, main_header_tel, parlist, cpl_func);
1074 kmo_dfs_save_main_header(frameset, filename_starspec, fn_suffix,
1075 obj_frame, main_header_tel, parlist, cpl_func);
1076 kmo_dfs_save_main_header(frameset, filename_mask, fn_suffix,
1077 obj_frame, main_header_psf, parlist, cpl_func);
1078 kmo_dfs_save_main_header(frameset, filename_psf, fn_suffix,
1079 obj_frame, main_header_psf, parlist, cpl_func) ;
1080 if (!no_noise && is_stdstarscipatt) {
1081 kmo_dfs_save_main_header(frameset, filename_noise, fn_suffix,
1082 obj_frame, main_header_tel, parlist, cpl_func);
1083 }
1084 cpl_propertylist_delete(main_header_tel);
1085
1086 if (save_cubes) {
1087 kmo_dfs_save_main_header(frameset, filename_cubes, fn_suffix,
1088 obj_frame, main_header_psf, parlist, cpl_func);
1089 }
1090 cpl_propertylist_delete(main_header_psf);
1091
1092 /* Save stored frames */
1093 for (i = 1; i <= KMOS_NR_DETECTORS ; i++) {
1094 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
1095 ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
1096
1097 /* Save telluric-vector */
1098 if (stored_telluric_data[ifu_nr-1] != NULL) {
1099 ddd = kmclipm_vector_create(cpl_vector_duplicate(
1100 stored_telluric_data[ifu_nr-1]));
1101 kmo_dfs_save_vector(ddd, filename_telluric, fn_suffix,
1102 stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
1103 kmclipm_vector_delete(ddd) ;
1104 } else {
1105 kmo_dfs_save_vector(NULL, filename_telluric, fn_suffix,
1106 stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
1107 }
1108 if (stored_telluric_noise[ifu_nr-1] != NULL) {
1109 ddd = kmclipm_vector_create(cpl_vector_duplicate(
1110 stored_telluric_noise[ifu_nr-1]));
1111 kmo_dfs_save_vector(ddd, filename_telluric, fn_suffix,
1112 stored_sub_tel_noise_headers[ifu_nr-1], 0./0.);
1113 kmclipm_vector_delete(ddd) ;
1114 } else {
1115 kmo_dfs_save_vector(NULL, filename_telluric, fn_suffix,
1116 stored_sub_tel_noise_headers[ifu_nr-1], 0./0.);
1117 }
1118
1119 /* Save star_spec-vector */
1120 if (stored_starspec_data[ifu_nr-1] != NULL) {
1121 ddd = kmclipm_vector_create(cpl_vector_duplicate(
1122 stored_starspec_data[ifu_nr-1]));
1123 kmo_dfs_save_vector(ddd, filename_starspec, fn_suffix,
1124 stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
1125 kmclipm_vector_delete(ddd);
1126 } else {
1127 kmo_dfs_save_vector(NULL, filename_starspec, fn_suffix,
1128 stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
1129 }
1130 if (stored_starspec_noise[ifu_nr-1] != NULL) {
1131 ddd = kmclipm_vector_create(cpl_vector_duplicate(
1132 stored_starspec_noise[ifu_nr-1]));
1133 kmo_dfs_save_vector(ddd, filename_starspec, fn_suffix,
1134 stored_sub_tel_noise_headers[ifu_nr-1], 0./0.);
1135 kmclipm_vector_delete(ddd);
1136 } else {
1137 kmo_dfs_save_vector(NULL, filename_starspec, fn_suffix,
1138 stored_sub_tel_noise_headers[ifu_nr-1], 0./0.);
1139 }
1140
1141 /* Save psf-image */
1142 kmo_dfs_save_image(stored_psf_data[ifu_nr-1], filename_psf,
1143 fn_suffix, stored_sub_psf_headers[ifu_nr-1], 0./0.);
1144
1145 /* Save mask-image */
1146 kmo_dfs_save_image(stored_mask[ifu_nr-1], filename_mask,
1147 fn_suffix, stored_sub_psf_headers[ifu_nr-1], 0./0.);
1148
1149 /* Save noise_spec-vector */
1150 if (!no_noise && is_stdstarscipatt && stored_noisespec != NULL &&
1151 stored_noisespec[ifu_nr-1] != NULL &&
1152 stored_starspec_data[ifu_nr-1] != NULL) {
1153 /* QC SNR */
1154 kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
1155 filter_id, stored_starspec_data[ifu_nr-1], NULL,
1156 &tmp_data, NULL);
1157 kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
1158 filter_id, stored_noisespec[ifu_nr-1], NULL,
1159 &tmp_noise, NULL);
1160 kmclipm_update_property_double(
1161 stored_sub_tel_data_headers[ifu_nr-1], QC_SNR,
1162 tmp_data/tmp_noise, "[] SNR");
1163 }
1164
1165 if (!no_noise && is_stdstarscipatt) {
1166 if ((stored_noisespec != NULL) &&
1167 stored_noisespec[ifu_nr-1] != NULL) {
1168 ddd = kmclipm_vector_create(cpl_vector_duplicate(
1169 stored_noisespec[ifu_nr-1]));
1170 kmo_dfs_save_vector(ddd, filename_noise, fn_suffix,
1171 stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
1172 kmclipm_vector_delete(ddd);
1173 } else {
1174 kmo_dfs_save_vector(NULL, filename_noise, fn_suffix,
1175 stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
1176 }
1177 }
1178
1179 /* Save reonstructed cubes */
1180 if (save_cubes) {
1181 kmo_dfs_save_cube(stored_data_cube[ifu_nr-1],
1182 filename_cubes, fn_suffix,
1183 stored_sub_cube_data_headers[ifu_nr-1], 0./0.);
1184 kmo_dfs_save_cube(stored_noise_cube[ifu_nr-1],
1185 filename_cubes, fn_suffix,
1186 stored_sub_cube_noise_headers[ifu_nr-1], 0./0.);
1187 }
1188 }
1189 }
1190
1191 /* Save extra outputs if needed */
1192 if (extra_outputs) {
1193 char * tell_name = cpl_sprintf("%s%s", filename_telluric, fn_suffix) ;
1194 kmos_idp_save_extra_outputs(frameset, parlist, cpl_func, tell_name) ;
1195 cpl_free(tell_name);
1196 char * spec_name = cpl_sprintf("%s%s", filename_starspec, fn_suffix) ;
1197 kmos_idp_save_extra_outputs(frameset, parlist, cpl_func, spec_name) ;
1198 cpl_free(spec_name);
1199 }
1200 cpl_free(fn_suffix);
1201
1202 /* DE-Allocate Warning --- Frames (e.g obj_frame) point to */
1203 /* obj_..._struct which point to frameset_ѕtd */
1204 kmo_delete_objSkyStruct(obj_sky_struct);
1205 kmo_delete_skySkyStruct(sky_sky_struct);
1206 cpl_frameset_delete(frameset_std);
1207
1208 for (i = 0; i < nifus ; i++) {
1209 cpl_vector_delete(stored_telluric_data[i]);
1210 cpl_vector_delete(stored_telluric_noise[i]);
1211 cpl_vector_delete(stored_starspec_data[i]);
1212 cpl_vector_delete(stored_starspec_noise[i]);
1213 cpl_image_delete(stored_psf_data[i]);
1214 cpl_propertylist_delete(stored_sub_tel_data_headers[i]);
1215 cpl_propertylist_delete(stored_sub_tel_noise_headers[i]);
1216 cpl_vector_delete(stored_noisespec[i]);
1217 cpl_propertylist_delete(stored_sub_cube_data_headers[i]);
1218 cpl_propertylist_delete(stored_sub_cube_noise_headers[i]);
1219 cpl_propertylist_delete(stored_sub_psf_headers[i]);
1220 cpl_image_delete(stored_mask[i]);
1221 cpl_imagelist_delete(stored_data_cube[i]);
1222 cpl_imagelist_delete(stored_noise_cube[i]);
1223 }
1224 cpl_free(stored_telluric_data);
1225 cpl_free(stored_telluric_noise);
1226 cpl_free(stored_starspec_data);
1227 cpl_free(stored_starspec_noise);
1228 cpl_free(stored_psf_data);
1229 cpl_free(stored_sub_tel_data_headers);
1230 cpl_free(stored_sub_tel_noise_headers);
1231 cpl_free(stored_noisespec);
1232 cpl_free(stored_sub_cube_data_headers);
1233 cpl_free(stored_sub_cube_noise_headers);
1234 cpl_free(stored_sub_psf_headers);
1235 cpl_free(stored_mask);
1236 cpl_free(stored_data_cube);
1237 cpl_free(stored_noise_cube);
1238
1239 return 0;
1240}
1241
1244/*----------------------------------------------------------------------------*/
1249/*----------------------------------------------------------------------------*/
1250static int kmos_std_star_compute_ifu(
1251 cpl_propertylist * sub_header_orig,
1252 cpl_frame * obj_frame,
1253 cpl_frame * sky_frame,
1254 cpl_frame * flat_frame,
1255 cpl_frame * xcal_frame,
1256 cpl_frame * ycal_frame,
1257 cpl_frame * lcal_frame,
1258 cpl_frame * illum_frame,
1259 cpl_frame * atmos_frame,
1260 cpl_frame * solar_frame,
1261 int ifu_nr,
1262 cpl_propertylist * main_header_tel,
1263 gridDefinition gd,
1264 int low_bound,
1265 int high_bound,
1266 const char * fmethod,
1267 int flux,
1268 int xcal_interpolation,
1269 const char * mask_method,
1270 const char * cmethod,
1271 double cpos_rej,
1272 double cneg_rej,
1273 int citer,
1274 int cmax,
1275 int cmin,
1276 double cen_x,
1277 double cen_y,
1278 double radius,
1279 const char * filter_id,
1280 char star_type,
1281 int no_noise,
1282 int is_stdstarscipatt,
1283 skySkyStruct sky_sky_struct,
1284 double star_temp,
1285 cpl_vector ** spec_qc,
1286 cpl_propertylist ** out_sub_tel_data_header,
1287 cpl_propertylist ** out_sub_psf_header,
1288 cpl_propertylist ** out_sub_cube_data_header,
1289 cpl_imagelist ** out_data_cube,
1290 cpl_imagelist ** out_noise_cube,
1291 cpl_image ** out_psf_data,
1292 cpl_image ** out_mask,
1293 cpl_vector ** out_starspec_data,
1294 cpl_vector ** out_starspec_noise,
1295 cpl_vector ** out_noisespec,
1296 cpl_vector ** out_telluric_data,
1297 cpl_vector ** out_telluric_noise)
1298{
1299 char * keyword ;
1300 cpl_propertylist * tmp_head ;
1301 cpl_image * illum_corr ;
1302 cpl_propertylist * pl_psf ;
1303 cpl_propertylist * plist ;
1304 double std_trace, factor_fwhm, spat_res, x_lo, y_lo, x_hi,
1305 y_hi, loc_cen_x, loc_cen_y, r ;
1306 cpl_size auto_cen_x, auto_cen_y, nx, ny ;
1307 cpl_vector * tmp_vec ;
1308 cpl_vector * tmp_spec_data ;
1309 cpl_vector * tmp_spec_noise ;
1310 cpl_vector * shot_noise ;
1311 cpl_vector * solar_spec ;
1312 double * ppp ;
1313 double gain, mean_data, mean_data2, flux_scale_factor,
1314 angle ;
1315 double ** pvec_array ;
1316 double * ptmp_vec ;
1317 double * pstored_noisespec ;
1318 cpl_vector ** vec_array ;
1319 const double * ptmp_spec_data ;
1320 double * ptmp_spec_noise ;
1321 float * pmask ;
1322 cpl_imagelist * tmp_cube ;
1323 cpl_vector * lambda_x ;
1324 cpl_vector * atmos_model ;
1325 int i, j, k, nr_sky_pairs, npix, x, y ;
1326
1327 /* Check inputs */
1328
1329 /* Initialise */
1330 std_trace = -1.0 ;
1331
1332 /* Messages */
1333 if (sky_frame != NO_CORRESPONDING_SKYFRAME) {
1334 cpl_msg_info(cpl_func, "Processing standard star in IFU %d", ifu_nr);
1335 cpl_msg_info(cpl_func, " (obj: %s, sky: %s)",
1336 cpl_frame_get_filename(obj_frame),
1337 cpl_frame_get_filename(sky_frame));
1338 } else {
1339 sky_frame = NULL;
1340 cpl_msg_warning(cpl_func,
1341 "Processing standard star in IFU %d", ifu_nr);
1342 cpl_msg_warning(cpl_func,
1343 " (obj: %s, no corresponding sky frame)",
1344 cpl_frame_get_filename(obj_frame));
1345 }
1346
1347 keyword = cpl_sprintf("%s%d", PRO_STD, ifu_nr);
1348 cpl_propertylist_update_int(main_header_tel, keyword, 1);
1349 cpl_free(keyword);
1350
1351 /* Compute WCS and make copies of sub_header */
1352 tmp_head=cpl_propertylist_duplicate(sub_header_orig);
1353 kmo_calc_wcs_gd(main_header_tel, tmp_head, ifu_nr,gd);
1354 *out_sub_tel_data_header = cpl_propertylist_duplicate(tmp_head);
1355 *out_sub_psf_header = cpl_propertylist_duplicate(tmp_head);
1356 *out_sub_cube_data_header = cpl_propertylist_duplicate(tmp_head);
1357 cpl_propertylist_delete(tmp_head);
1358
1359 /* Adjust telluric-headers: copy key3 to key1 - rm key2 key3*/
1360 kmos_std_star_adjust_double(*out_sub_tel_data_header, CRVAL1,CRVAL2,CRVAL3);
1361 kmos_std_star_adjust_double(*out_sub_tel_data_header, CRPIX1,CRPIX2,CRPIX3);
1362 kmos_std_star_adjust_double(*out_sub_tel_data_header, CDELT1,CDELT2,CDELT3);
1363 kmos_std_star_adjust_string(*out_sub_tel_data_header, CTYPE1,CTYPE2,CTYPE3);
1364 kmos_std_star_adjust_string(*out_sub_tel_data_header, CUNIT1,CUNIT2,CUNIT3);
1365
1366 /* CDx_x */
1367 cpl_propertylist_erase(*out_sub_tel_data_header, CD1_1);
1368 cpl_propertylist_erase(*out_sub_tel_data_header, CD1_2);
1369 cpl_propertylist_erase(*out_sub_tel_data_header, CD1_3);
1370 cpl_propertylist_erase(*out_sub_tel_data_header, CD2_1);
1371 cpl_propertylist_erase(*out_sub_tel_data_header, CD2_2);
1372 cpl_propertylist_erase(*out_sub_tel_data_header, CD2_3);
1373 cpl_propertylist_erase(*out_sub_tel_data_header, CD3_1);
1374 cpl_propertylist_erase(*out_sub_tel_data_header, CD3_2);
1375 cpl_propertylist_erase(*out_sub_tel_data_header, CD3_3);
1376
1377 /* Adjust psf-headers: delete CRPIX3 etc. */
1378 cpl_propertylist_erase(*out_sub_psf_header, CRPIX3);
1379 cpl_propertylist_erase(*out_sub_psf_header, CRPIX3);
1380 cpl_propertylist_erase(*out_sub_psf_header, CDELT3);
1381 cpl_propertylist_erase(*out_sub_psf_header, CRVAL3);
1382 cpl_propertylist_erase(*out_sub_psf_header, CTYPE3);
1383 cpl_propertylist_erase(*out_sub_psf_header, CUNIT3);
1384 cpl_propertylist_erase(*out_sub_psf_header, CD1_3);
1385 cpl_propertylist_erase(*out_sub_psf_header, CD2_3);
1386 cpl_propertylist_erase(*out_sub_psf_header, CD3_1);
1387 cpl_propertylist_erase(*out_sub_psf_header, CD3_2);
1388 cpl_propertylist_erase(*out_sub_psf_header, CD3_3);
1389
1390 /* Reconstruct */
1391 kmo_reconstruct_sci(ifu_nr, low_bound, high_bound, obj_frame, STD,
1392 sky_frame, STD, flat_frame, NULL, xcal_frame, ycal_frame,
1393 lcal_frame, NULL, NULL, &gd, out_data_cube, out_noise_cube, flux,
1394 FALSE, xcal_interpolation, "");
1395
1396 /* Illumination correction */
1397 /* Illumination noise small versus noise - skipped */
1398 if (illum_frame != NULL) {
1399 plist = kmclipm_propertylist_load(cpl_frame_get_filename(obj_frame), 0);
1400 angle = kmo_dfs_get_property_double(plist, ROTANGLE);
1401 cpl_propertylist_delete(plist);
1402 double dummy1 ;
1403 illum_corr = kmos_illum_load(cpl_frame_get_filename(illum_frame),
1404 CPL_TYPE_FLOAT, ifu_nr, angle, &dummy1) ;
1405 if (illum_corr != NULL) {
1406 cpl_imagelist_divide_image(*out_data_cube, illum_corr);
1407 cpl_image_delete(illum_corr);
1408 }
1409 }
1410
1411 /* QC_STD_TRACE (distance of the PSF to the centre) */
1412 kmo_calculate_std_trace(*out_data_cube, fmethod, &std_trace);
1413 kmclipm_update_property_double(*out_sub_psf_header, QC_STD_TRACE, std_trace,
1414 "[pix] distance PSF - IFU center");
1415
1416 /* Collapse cube and get PSF image */
1417 kmclipm_make_image(*out_data_cube, NULL, out_psf_data, NULL, NULL,
1418 cmethod, cpos_rej, cneg_rej, citer, cmax, cmin);
1419
1420 /* Fit a 2D profile to get a mask and fwhm in x and y */
1421 tmp_vec = kmo_fit_profile_2D(*out_psf_data, NULL, fmethod,out_mask,&pl_psf);
1422
1423 if (!strcmp(mask_method, "integrated")) {
1424 if (cen_x < 1.0 || cen_y < 1.0) {
1425 cpl_image_get_maxpos(*out_psf_data,&auto_cen_x,&auto_cen_y);
1426 loc_cen_x = (double)auto_cen_x - 1.0 ;
1427 loc_cen_y = (double)auto_cen_y - 1.0 ;
1428 } else {
1429 loc_cen_x = cen_x - 1.0 ;
1430 loc_cen_y = cen_y - 1.0 ;
1431 }
1432 kmo_image_fill(*out_mask,0.0);
1433 pmask = cpl_image_get_data_float(*out_mask);
1434 nx = cpl_image_get_size_x(*out_mask);
1435 ny = cpl_image_get_size_y(*out_mask);
1436
1437 /* draw circle */
1438 x_lo = floor(loc_cen_x - radius);
1439 if (x_lo < 0) x_lo = 0;
1440 y_lo = floor(loc_cen_y - radius);
1441 if (y_lo < 0) y_lo = 0;
1442 x_hi = ceil(loc_cen_x + radius);
1443 if (x_hi > nx) x_hi = nx;
1444 y_hi = ceil(loc_cen_y + radius);
1445 if (y_hi > ny) y_hi = ny;
1446 for (x = x_lo; x < x_hi; x++) {
1447 for (y = y_lo; y < y_hi; y++) {
1448 r = sqrt(pow(x - loc_cen_x,2) + pow(y - loc_cen_y,2));
1449 if (r <= radius) pmask[x + y * nx] = 1.0;
1450 }
1451 }
1452 } else {
1453 /* Normalise mask to 1 and clip values below 0.5 */
1454 cpl_image_divide_scalar(*out_mask, cpl_image_get_max(*out_mask));
1455 for (i = 1; i <= cpl_image_get_size_x(*out_mask); i++) {
1456 for (j = 1; j <= cpl_image_get_size_y(*out_mask); j++) {
1457 if (cpl_image_get(*out_mask, i, j, &k) < 0.5)
1458 cpl_image_set(*out_mask, i, j, 0.);
1459 else
1460 cpl_image_set(*out_mask, i, j, 1.);
1461 }
1462 }
1463 }
1464
1465 /* Update subheader with fit parameters */
1466 cpl_propertylist_append(*out_sub_tel_data_header, pl_psf);
1467 cpl_propertylist_delete(pl_psf);
1468
1469 /* QC_SPAT_RES (RMS of fwhm_x and fwhm_y) */
1470 factor_fwhm = 2*sqrt(2*log(2));
1471 spat_res = pow(cpl_vector_get(tmp_vec, 4) * factor_fwhm, 2);
1472 spat_res += pow(cpl_vector_get(tmp_vec, 5)* factor_fwhm, 2);
1473 spat_res /= 2;
1474 kmclipm_update_property_double(*out_sub_psf_header, QC_SPAT_RES,
1475 sqrt(spat_res)*KMOS_PIX_RESOLUTION,
1476 "[arcsec] mean fwhm resolution of PSF");
1477 cpl_vector_delete(tmp_vec);
1478
1479 /* Extract spectrum with mask */
1480 /* Convert Mean to Sum (* mask area) */
1481 tmp_spec_data = tmp_spec_noise = NULL ;
1482 kmo_priv_extract_spec(*out_data_cube, *out_noise_cube, *out_mask,
1483 &tmp_spec_data, &tmp_spec_noise);
1484 cpl_vector_multiply_scalar(tmp_spec_data, cpl_image_get_flux(*out_mask));
1485 if (tmp_spec_noise != NULL) {
1486 cpl_vector_multiply_scalar(tmp_spec_noise,
1487 cpl_image_get_flux(*out_mask));
1488 }
1489
1490 /* Extract spectrum of whole area for QCs */
1491 /* Convert mean to sum (* 196, IFU area) */
1492 tmp_vec = *spec_qc = NULL ;
1493 kmo_priv_extract_spec(*out_data_cube, *out_noise_cube, NULL, spec_qc,
1494 &tmp_vec);
1495 npix = cpl_image_get_size_x(cpl_imagelist_get(*out_data_cube, 0)) *
1496 cpl_image_get_size_y(cpl_imagelist_get(*out_data_cube, 0)) ;
1497 cpl_vector_multiply_scalar(*spec_qc, npix);
1498 if (tmp_vec != NULL) cpl_vector_multiply_scalar(tmp_vec, npix);
1499
1500 /* Shot noise */
1501 gain = cpl_propertylist_get_double(*out_sub_tel_data_header, GAIN);
1502
1503 /* Shot_noise = sqrt(tmp_spec_data*gain)/gain */
1504 /* set negative values and NaN's to zero before sqrt */
1505 shot_noise = cpl_vector_duplicate(tmp_spec_data);
1506 cpl_vector_multiply_scalar(shot_noise, gain);
1507 ppp = cpl_vector_get_data(shot_noise);
1508 for (i = 0; i < cpl_vector_get_size(shot_noise); i++) {
1509 if ((ppp[i] < 0.0) || kmclipm_is_nan_or_inf(ppp[i]))
1510 ppp[i] = 0.0;
1511 }
1512 cpl_vector_sqrt(shot_noise);
1513 cpl_vector_divide_scalar(shot_noise, gain);
1514
1515 /* Scale extracted spectrum to match the one */
1516 /* calculated over the whole area (band specific) */
1517 kmo_calc_band_mean(*out_sub_tel_data_header, filter_id, tmp_spec_data,
1518 tmp_spec_noise, &mean_data, NULL);
1519 kmo_calc_band_mean(*out_sub_tel_data_header, filter_id, *spec_qc, tmp_vec,
1520 &mean_data2, NULL);
1521 cpl_vector_delete(tmp_vec) ;
1522
1523 flux_scale_factor = mean_data2/mean_data;
1524
1525 cpl_vector_multiply_scalar(shot_noise, flux_scale_factor);
1526 cpl_vector_multiply_scalar(tmp_spec_data,flux_scale_factor);
1527 if ((tmp_spec_noise != NULL) && (fabs(mean_data) > 1e-8))
1528 cpl_vector_multiply_scalar(tmp_spec_noise, flux_scale_factor);
1529
1530 /* Store to save to disk later on */
1531 *out_starspec_data = cpl_vector_duplicate(tmp_spec_data);
1532 if (tmp_spec_noise != NULL)
1533 *out_starspec_noise = cpl_vector_duplicate(tmp_spec_noise);
1534 else
1535 *out_starspec_noise = NULL ;
1536
1537 /* Noise spectra */
1538 if (!no_noise && is_stdstarscipatt) {
1539 nr_sky_pairs = sky_sky_struct.nrSkyPairs;
1540 if (nr_sky_pairs > 2) {
1541 cpl_msg_info(__func__, "Get noise spec on sky for IFU %d", ifu_nr);
1542 vec_array = cpl_calloc(nr_sky_pairs,sizeof(cpl_vector*));
1543 pvec_array = cpl_calloc(nr_sky_pairs, sizeof(double*));
1544 /* Reconstruct all sky-Pairs, extract spectra */
1545 for (i = 0; i < nr_sky_pairs; i++) {
1546 // reconstruct (sky1-sky2)/flatfield
1547 kmo_reconstruct_sci(ifu_nr, low_bound, high_bound,
1548 sky_sky_struct.skyPairs[i].skyFrame1, STD,
1549 sky_sky_struct.skyPairs[i].skyFrame2, STD, flat_frame,
1550 NULL, xcal_frame, ycal_frame, lcal_frame, NULL, NULL,
1551 &gd, &tmp_cube, NULL, FALSE, FALSE,
1552 xcal_interpolation, "");
1553
1554 /* Extract spectrum using masked */
1555 /* convert mean to sum (* mask aperture) */
1556 kmo_priv_extract_spec(tmp_cube, NULL, *out_mask,
1557 &(vec_array[i]), NULL);
1558 cpl_vector_multiply_scalar(vec_array[i],
1559 cpl_image_get_flux(*out_mask));
1560
1561 /* Scale extracted spectrum to match the one */
1562 /* calculated over the whole area (band spec) */
1563 cpl_vector_multiply_scalar(vec_array[i], flux_scale_factor);
1564 pvec_array[i] = cpl_vector_get_data(vec_array[i]);
1565 cpl_imagelist_delete(tmp_cube);
1566 }
1567
1568 /* stddev on each wavelength of all extrac spec */
1569 *out_noisespec = cpl_vector_new(gd.l.dim);
1570 pstored_noisespec = cpl_vector_get_data(*out_noisespec);
1571 tmp_vec = cpl_vector_new(nr_sky_pairs);
1572 ptmp_vec = cpl_vector_get_data(tmp_vec);
1573 for (i = 0; i < gd.l.dim; i++) {
1574 for (j = 0; j < nr_sky_pairs; j++)
1575 ptmp_vec[j] = pvec_array[j][i];
1576 pstored_noisespec[i] = cpl_vector_get_stdev(tmp_vec);
1577 }
1578 for (i = 0; i < nr_sky_pairs; i++) cpl_vector_delete(vec_array[i]);
1579 cpl_free(vec_array);
1580 cpl_free(pvec_array);
1581 cpl_vector_delete(tmp_vec);
1582
1583 /* total noise = sqrt (shot_noise^2+sky_noise^2) */
1584 // and set negative values and NaN's to zero
1585 cpl_vector_power(*out_noisespec, 2.);
1586 cpl_vector_power(shot_noise, 2.);
1587 cpl_vector_add(*out_noisespec, shot_noise);
1588 ppp = cpl_vector_get_data(*out_noisespec);
1589 for (i = 0; i < cpl_vector_get_size(*out_noisespec); i++) {
1590 if ((ppp[i] < 0.0) || kmclipm_is_nan_or_inf(ppp[i])) ppp[i]=0.0;
1591 }
1592 cpl_vector_sqrt(*out_noisespec);
1593 cpl_vector_delete(shot_noise);
1594 } else {
1595 cpl_msg_warning(__func__, "Omit noise-spectra (<2 sky pairs)");
1596 *out_noisespec = shot_noise;
1597 }
1598 } else {
1599 *out_noisespec = shot_noise;
1600 }
1601
1602 /* Spectrum correction */
1603 /* Abscissa of output spectrum */
1604 lambda_x = kmo_create_lambda_vec(gd.l.dim, 1, gd.l.start, gd.l.delta);
1605
1606 if (star_type=='O' || star_type=='B' || star_type=='A' || star_type=='F') {
1607 /* OBAF star */
1608
1609 /* Remove lines if ATMOS_MODEL is provided */
1610 if (atmos_frame != NULL) {
1611 /* Interpolate ATMOS_MODEL to same scale as data */
1612 atmos_model = kmo_interpolate_vector_wcs(atmos_frame, lambda_x);
1613
1614 /* Remove band-specific lines */
1615 if (!strcmp(filter_id, "H"))
1616 for (i = 0; i < nr_lines_h; i++)
1617 kmo_remove_line(tmp_spec_data, lambda_x, atmos_model,
1618 lines_center_h[i], lines_width_h[i]);
1619 else if (!strcmp(filter_id, "HK"))
1620 for (i = 0; i < nr_lines_hk; i++)
1621 kmo_remove_line(tmp_spec_data, lambda_x, atmos_model,
1622 lines_center_hk[i], lines_width_hk[i]);
1623 else if (!strcmp(filter_id, "K"))
1624 for (i = 0; i < nr_lines_k; i++)
1625 kmo_remove_line(tmp_spec_data, lambda_x, atmos_model,
1626 lines_center_k[i], lines_width_k[i]);
1627 else if (!strcmp(filter_id, "IZ")) {
1628 /*
1629 if (ifu_nr == 18) {
1630 cpl_vector_save(lambda_x, "ifu18_x.fits",
1631 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE) ;
1632 cpl_vector_save(tmp_spec_data, "ifu18_y.fits",
1633 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE) ;
1634 }
1635 if (ifu_nr == 12) {
1636 cpl_vector_save(lambda_x, "ifu12_x.fits",
1637 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE) ;
1638 cpl_vector_save(tmp_spec_data, "ifu12_y.fits",
1639 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE) ;
1640 }
1641 */
1642 for (i = 0; i < nr_lines_iz; i++)
1643 kmo_remove_line(tmp_spec_data, lambda_x, atmos_model,
1644 lines_center_iz[i], lines_width_iz[i]);
1645 } else if (strcmp(filter_id, "YJ") == 0)
1646 for (i = 0; i < nr_lines_yj; i++)
1647 kmo_remove_line(tmp_spec_data, lambda_x, atmos_model,
1648 lines_center_yj[i], lines_width_yj[i]);
1649
1650 if (0) kmos_std_star_plot() ;
1651 cpl_vector_delete(atmos_model);
1652 } else {
1653 cpl_msg_warning(__func__, "Missing ATMOS_MODEL");
1654 }
1655 } else if (star_type == 'G') {
1656 /* G star */
1657 if (solar_frame != NULL) {
1658 /* Interpolate SOLAR_SPEC to same scale and divide it */
1659 solar_spec = kmo_interpolate_vector_wcs(solar_frame,
1660 lambda_x);
1661 /* Set to zero if solar_spec isn't overlapping */
1662 /* wavelength range of star apectrum completely */
1663 cpl_vector_divide(tmp_spec_data, solar_spec);
1664 cpl_vector_delete(solar_spec);
1665 } else {
1666 cpl_msg_warning(__func__, "Missing SOLAR_SPEC");
1667 }
1668 }
1669
1670 if (star_temp > 0.0) {
1671 /* Divide blackbody from tmp_spec_data */
1672 kmo_divide_blackbody(tmp_spec_data, lambda_x, star_temp);
1673 }
1674 cpl_vector_delete(lambda_x);
1675
1676 /* Normalise telluric and its noise */
1677 /* mean is taken in lambda defined range */
1678 kmo_calc_band_mean(*out_sub_tel_data_header, filter_id, tmp_spec_data,
1679 tmp_spec_noise, &mean_data, NULL);
1680 cpl_vector_divide_scalar(tmp_spec_data, mean_data);
1681
1682 if (tmp_spec_noise != NULL) {
1683 /* Scale noise with the same factor as data */
1684 cpl_vector_divide_scalar(tmp_spec_noise, mean_data);
1685
1686 /* Set noise spectrum to zero when solar_spec is short*/
1687 ptmp_spec_data = cpl_vector_get_data_const(tmp_spec_data);
1688 ptmp_spec_noise = cpl_vector_get_data(tmp_spec_noise);
1689 for (i = 0; i < cpl_vector_get_size(tmp_spec_data);i++)
1690 if (ptmp_spec_data[i]==0.0) ptmp_spec_noise[i]=0.0;
1691 }
1692
1693 /* Store telluric & error spectrum */
1694 *out_telluric_data = tmp_spec_data;
1695 *out_telluric_noise = tmp_spec_noise;
1696 return 0 ;
1697}
1698
1699/*----------------------------------------------------------------------------*/
1709/*----------------------------------------------------------------------------*/
1710static int kmos_std_star_check_inputs(
1711 cpl_frameset * frameset,
1712 const char * magnitude_txt,
1713 int * is_stdstarscipatt,
1714 int * compute_qcs,
1715 double * magnitude1,
1716 double * magnitude2)
1717{
1718 int nb_std, nb_illum, nb_xcal, nb_ycal, nb_lcal,
1719 nb_flat, nb_wave ;
1720 cpl_frame * tmp_frame ;
1721 cpl_frameset * frameset_std ;
1722 cpl_propertylist * tmp_head ;
1723 const char * my_mag_txt ;
1724 int nr_split_mag ;
1725 char ** split_mag ;
1726 char * grat_id ;
1727 int same_gratings ;
1728 const char * tmp_str ;
1729
1730 /* Check Entries */
1731 if (frameset == NULL || is_stdstarscipatt == NULL || compute_qcs == NULL ||
1732 magnitude1 == NULL || magnitude2 == NULL) return -1;
1733
1734 /* Count frames */
1735 nb_std = cpl_frameset_count_tags(frameset, STD) ;
1736 nb_illum = cpl_frameset_count_tags(frameset, ILLUM_CORR) ;
1737 nb_xcal = cpl_frameset_count_tags(frameset, XCAL) ;
1738 nb_ycal = cpl_frameset_count_tags(frameset, YCAL) ;
1739 nb_lcal = cpl_frameset_count_tags(frameset, LCAL) ;
1740 nb_flat = cpl_frameset_count_tags(frameset, MASTER_FLAT) ;
1741 nb_wave = cpl_frameset_count_tags(frameset, WAVE_BAND) ;
1742
1743 /* Check numbers */
1744 if (nb_std < 1) {
1745 cpl_msg_error(__func__, "At least one STD frame is required") ;
1746 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1747 return 0 ;
1748 }
1749 if (nb_std == 1)
1750 cpl_msg_warning(__func__, "2 STD frames needed for sky subtraction") ;
1751
1752 if (nb_illum < 0 || nb_illum > 1) {
1753 cpl_msg_error(__func__, "0 or 1 ILLUM frame expected") ;
1754 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1755 return 0 ;
1756 }
1757 if (nb_xcal != 1 || nb_ycal != 1 || nb_lcal != 1) {
1758 cpl_msg_error(__func__, "1 X/Y/LCAL required") ;
1759 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1760 return 0 ;
1761 }
1762 if (nb_flat != 1) {
1763 cpl_msg_error(__func__, "1 MASTER_FLAT required") ;
1764 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1765 return 0 ;
1766 }
1767 if (nb_wave != 1) {
1768 cpl_msg_error(__func__, "1 WAVE_BAND required") ;
1769 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1770 return 0 ;
1771 }
1772
1773 /* Extract STD frames with same gratings as the first STD frame */
1774 frameset_std=kmos_std_star_extract_same_grat_stds(frameset,&same_gratings) ;
1775
1776 /* Get infos from the first STD frame */
1777 tmp_frame = kmo_dfs_get_frame(frameset_std, STD);
1778 tmp_head=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
1779 grat_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_head,
1780 "ESO INS GRAT1 ID"));
1781 if (!strcmp(cpl_propertylist_get_string(tmp_head, TPL_ID),
1782 "KMOS_spec_cal_stdstarscipatt")) *is_stdstarscipatt = TRUE ;
1783 else *is_stdstarscipatt = FALSE ;
1784 cpl_propertylist_delete(tmp_head);
1785 cpl_frameset_delete(frameset_std) ;
1786
1787 /* Check if QC are computed */
1788 if (same_gratings) {
1789 *compute_qcs = TRUE ;
1790 // now check source of magnitude (user or keyword)
1791 tmp_frame = kmo_dfs_get_frame(frameset, STD);
1792 tmp_head=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
1793
1794 if (!strcmp(magnitude_txt, "")) {
1795 /* No user defined magnitude */
1796 if ((cpl_propertylist_has(tmp_head, STDSTAR_MAG)) &&
1797 (cpl_propertylist_get_type(tmp_head, STDSTAR_MAG) ==
1798 CPL_TYPE_STRING)) {
1799 my_mag_txt = cpl_propertylist_get_string(tmp_head, STDSTAR_MAG);
1800 split_mag = kmo_strsplit(my_mag_txt, ",", &nr_split_mag);
1801
1802 /* Check if band and number of magnitudes matches */
1803 if (nr_split_mag == 2 && !strcmp(grat_id, "HK")) {
1804 *magnitude1 = atof(split_mag[0]);
1805 *magnitude2 = atof(split_mag[1]);
1806 cpl_msg_info("", "Magnitude in H: %g", *magnitude1);
1807 cpl_msg_info("", "Magnitude in K: %g", *magnitude2);
1808 } else if (nr_split_mag >= 1 && (!strcmp(grat_id, "K") ||
1809 !strcmp(grat_id, "H") || !strcmp(grat_id, "IZ") ||
1810 !strcmp(grat_id, "YJ"))) {
1811 *magnitude1 = atof(split_mag[0]);
1812 cpl_msg_info("", "Magnitude in %s: %g",grat_id,*magnitude1);
1813 } else {
1814 // keyword STDSTAR_MAG doesn't match filter
1815 *compute_qcs = FALSE;
1816 cpl_msg_warning(cpl_func, "Wrong Mag, QCs not computed") ;
1817 }
1818 kmo_strfreev(split_mag);
1819 } else {
1820 /* STDSTAR_MAG unavailable or wrong type */
1821 *compute_qcs = FALSE;
1822 cpl_msg_warning(cpl_func, "%s is not set, QCs not computed",
1823 STDSTAR_MAG);
1824 }
1825 } else {
1826 // magnitude is user specified
1827 cpl_msg_info(cpl_func, "Magnitude entered by user, ignore header");
1828
1829 split_mag = kmo_strsplit(magnitude_txt, ",", &nr_split_mag);
1830 switch (nr_split_mag) {
1831 case 1:
1832 *magnitude1 = atof(split_mag[0]);
1833 cpl_msg_info(cpl_func, "Magnitude in %s: %g", grat_id,
1834 *magnitude1);
1835 break;
1836 case 2:
1837 *magnitude1 = atof(split_mag[0]);
1838 *magnitude2 = atof(split_mag[1]);
1839 cpl_msg_info("", "Magnitude in H: %g", *magnitude1);
1840 cpl_msg_info("", "Magnitude in K: %g", *magnitude2);
1841 break;
1842 default:
1843 kmo_strfreev(split_mag);
1844 cpl_propertylist_delete(tmp_head);
1845 cpl_msg_error(__func__, "Wrong Magnitude Specified") ;
1846 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1847 return 0 ;
1848 }
1849 kmo_strfreev(split_mag);
1850 }
1851 cpl_propertylist_delete(tmp_head);
1852 } else {
1853 *compute_qcs = FALSE ;
1854 }
1855
1856 /* Check SOLAR_SPEC grating */
1857 tmp_frame = kmo_dfs_get_frame(frameset, SOLAR_SPEC);
1858 if (tmp_frame != NULL) {
1859 tmp_head=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
1860 tmp_str = cpl_propertylist_get_string(tmp_head, FILT_ID);
1861 if (strcmp(tmp_str, grat_id)) {
1862 cpl_propertylist_delete(tmp_head) ;
1863 cpl_msg_error(__func__, "Wrong SOLAR_SPEC grating") ;
1864 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1865 return 0 ;
1866 }
1867 cpl_propertylist_delete(tmp_head) ;
1868 }
1869
1870 /* Check ATMOS_MODEL grating */
1871 tmp_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL);
1872 if (tmp_frame != NULL) {
1873 tmp_head=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
1874 tmp_str = cpl_propertylist_get_string(tmp_head, FILT_ID);
1875 if (strcmp(tmp_str, grat_id)) {
1876 cpl_propertylist_delete(tmp_head) ;
1877 cpl_msg_error(__func__, "Wrong ATMOS_MODEL grating") ;
1878 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1879 return 0 ;
1880 }
1881 cpl_propertylist_delete(tmp_head) ;
1882 }
1883 cpl_free(grat_id) ;
1884
1885 /* Check if filter_id and grating_id match for all detectors */
1886 kmo_check_frameset_setup(frameset, XCAL, FALSE, FALSE, TRUE);
1887 kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE);
1888 kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE);
1889 kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, TRUE, FALSE, TRUE);
1890 kmo_check_frame_setup(frameset, XCAL, STD, FALSE, FALSE, TRUE);
1891 if (nb_illum == 1)
1892 kmo_check_frame_setup(frameset, XCAL, ILLUM_CORR, TRUE, FALSE, FALSE);
1893 kmo_check_frame_setup_md5_xycal(frameset);
1894 kmo_check_frame_setup_md5(frameset);
1895 return 1 ;
1896}
1897
1898/*----------------------------------------------------------------------------*/
1904/*----------------------------------------------------------------------------*/
1905static int kmos_std_star_plot(void)
1906{
1907
1908 /*
1909 cpl_vector *tmp_spec_data_atmo = NULL;
1910 cpl_vector *tmp_spec_data_new = NULL;
1911 tmp_spec_data_orig=cpl_vector_duplicate(tmp_spec_data);
1912 KMO_TRY_EXIT_IF_NULL(
1913 tmp_spec_data_atmo = cpl_vector_duplicate(tmp_spec_data_orig));
1914 KMO_TRY_EXIT_IF_NULL(
1915 tmp_spec_data_new = cpl_vector_duplicate(tmp_spec_data));
1916 KMO_TRY_EXIT_IF_ERROR(
1917 cpl_vector_divide(tmp_spec_data_atmo, atmos_model));
1918
1919 char *sss = cpl_sprintf("atmo_div_%s.fits", filter_id);
1920 if (i == 1) {
1921 cpl_vector_save(tmp_spec_data_atmo, sss, CPL_BPP_IEEE_DOUBLE, stored_sub_tel_data_headers[ifu_nr-1], CPL_IO_CREATE);
1922 } else {
1923 cpl_vector_save(tmp_spec_data_atmo, sss, CPL_BPP_IEEE_DOUBLE, stored_sub_tel_data_headers[ifu_nr-1], CPL_IO_EXTEND);
1924 }
1925
1926 cpl_vector *med_vec = cpl_vector_duplicate(tmp_spec_data_orig);
1927 double median = cpl_vector_get_median(med_vec);
1928 cpl_vector_delete(med_vec);
1929 int ii = 0;
1930 for (ii = 0; ii < cpl_vector_get_size(tmp_spec_data_orig); ii++) {
1931 if (cpl_vector_get(tmp_spec_data_orig, ii) < median/8)
1932 cpl_vector_set(tmp_spec_data_orig, ii, 0);
1933 if (cpl_vector_get(tmp_spec_data_atmo, ii) < median/8)
1934 cpl_vector_set(tmp_spec_data_atmo, ii, 0);
1935 if (cpl_vector_get(tmp_spec_data_new, ii) < median/8)
1936 cpl_vector_set(tmp_spec_data_new, ii, 0);
1937
1938 if (cpl_vector_get(tmp_spec_data_orig, ii) > 3*median)
1939 cpl_vector_set(tmp_spec_data_orig, ii, 3*median);
1940 if (cpl_vector_get(tmp_spec_data_atmo, ii) > 3*median)
1941 cpl_vector_set(tmp_spec_data_atmo, ii, 3*median);
1942 if (cpl_vector_get(tmp_spec_data_new, ii) > 3*median)
1943 cpl_vector_set(tmp_spec_data_new, ii, 3*median);
1944 }
1945
1946 double *pspec_dup = cpl_vector_get_data(tmp_spec_data_atmo);
1947 for (ii = 0; ii < cpl_vector_get_size(tmp_spec_data_atmo); ii++) {
1948 if (kmclipm_is_nan_or_inf(pspec_dup[ii])) {
1949 pspec_dup[ii] = 0.;
1950 }
1951 }
1952
1953 cpl_bivector *plots[3];
1954 plots[0] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_orig);
1955 plots[1] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_atmo);
1956 plots[2] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_new);
1957 char *options[3] = {"w l t 'original'",
1958 "w l t 'atmo divided'",
1959 "w l t 'lines removed'"};
1960 sss = cpl_sprintf("set title '%s-band line removal (DET #%d)';", filter_id, i);
1961 cpl_plot_bivectors(sss,
1962 (const char**)options, "", (const cpl_bivector**)plots, 3);
1963 cpl_bivector_unwrap_vectors(plots[0]);
1964 cpl_bivector_unwrap_vectors(plots[1]);
1965 cpl_bivector_unwrap_vectors(plots[2]);
1966 cpl_free(sss); sss = NULL;
1967 cpl_vector_delete(tmp_spec_data_orig); tmp_spec_data_orig = NULL;
1968 cpl_vector_delete(tmp_spec_data_atmo); tmp_spec_data_atmo = NULL;
1969 cpl_vector_delete(tmp_spec_data_new); tmp_spec_data_new = NULL;
1970
1971*/
1972 return 0 ;
1973}
1974
1975/*----------------------------------------------------------------------------*/
1981/*----------------------------------------------------------------------------*/
1982static int kmos_std_star_adjust_double(
1983 cpl_propertylist * header,
1984 const char * key1,
1985 const char * key2,
1986 const char * key3)
1987{
1988 if (header==NULL || key1==NULL || key2==NULL || key3==NULL) return -1 ;
1989 cpl_propertylist_update_double(header, key1,
1990 cpl_propertylist_get_double(header, key3));
1991 cpl_propertylist_erase(header, key2) ;
1992 cpl_propertylist_erase(header, key3) ;
1993 return 0 ;
1994}
1995
1996/*----------------------------------------------------------------------------*/
2002/*----------------------------------------------------------------------------*/
2003static int kmos_std_star_adjust_string(
2004 cpl_propertylist * header,
2005 const char * key1,
2006 const char * key2,
2007 const char * key3)
2008{
2009 if (header==NULL || key1==NULL || key2==NULL || key3==NULL) return -1 ;
2010 cpl_propertylist_update_string(header, key1,
2011 cpl_propertylist_get_string(header, key3));
2012 cpl_propertylist_erase(header, key2) ;
2013 cpl_propertylist_erase(header, key3) ;
2014 return 0 ;
2015}
2016
2017/*----------------------------------------------------------------------------*/
2025/*----------------------------------------------------------------------------*/
2026static cpl_frameset * kmos_std_star_extract_same_grat_stds(
2027 cpl_frameset * in,
2028 int * same_gratings)
2029{
2030 cpl_frameset * frameset_std ;
2031 cpl_frame * tmp_frame ;
2032 cpl_propertylist * tmp_header ;
2033 char * grat_id ;
2034
2035 /* Check entries */
2036 if (in == NULL || same_gratings== NULL) return NULL ;
2037
2038 /* Create new frameset */
2039 frameset_std = cpl_frameset_new();
2040
2041 tmp_frame = kmo_dfs_get_frame(in, STD);
2042 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
2043 grat_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_header,
2044 "ESO INS GRAT1 ID"));
2045 cpl_propertylist_delete(tmp_header);
2046 cpl_frameset_insert(frameset_std, cpl_frame_duplicate(tmp_frame));
2047
2048 tmp_frame = kmo_dfs_get_frame(in, NULL);
2049 *same_gratings = TRUE ;
2050 while (tmp_frame != NULL ) {
2051 tmp_header=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),
2052 0);
2053 if (!strcmp(grat_id, cpl_propertylist_get_string(tmp_header,
2054 "ESO INS GRAT1 ID"))) {
2055 cpl_frameset_insert(frameset_std, cpl_frame_duplicate(tmp_frame));
2056 } else {
2057 *same_gratings = FALSE;
2058 }
2059 cpl_propertylist_delete(tmp_header);
2060
2061 tmp_frame = kmo_dfs_get_frame(in, NULL);
2062 }
2063 cpl_free(grat_id) ;
2064 return frameset_std ;
2065}
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.