ERIS Pipeline Reference Manual 1.9.2
sc_readspec.c
Go to the documentation of this file.
1/*
2 * This file is part of the SKYCORR software package.
3 * Copyright (C) 2009-2013 European Southern Observatory
4 *
5 * This programme 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 programme 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 programme. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
37/*****************************************************************************
38 * INCLUDES *
39 ****************************************************************************/
40
41#include <sc_readspec.h>
42
43
44/*****************************************************************************
45 * CODE *
46 ****************************************************************************/
47
48//cpl_error_code sc_readspec(cpl_table *spec, cpl_parameterlist *parlist)
49//{
50// /*!
51// * \callgraph
52// *
53// * Reads a science or sky spectrum (type taken from the general parameter
54// * list) in ASCII, FITS table, or FITS image format and puts the read data
55// * in a CPL table consisting of the columns "lambda", "flux", and
56// * "weight". Only 1D data are supported. The required observing parameters
57// * are read from the FITS header (only sky spectrum) or the parameter
58// * list.
59// *
60// * \b INPUT:
61// * \param spec empty CPL table
62// * \param parlist general CPL parameter list
63// *
64// * \b OUTPUT:
65// * \param spec CPL table with wavelengths, fluxes, and weights
66// * \param parlist general CPL parameter list with FITS header values
67// *
68// * \b ERRORS:
69// * - Invalid object value(s)
70// * - Error in subroutine
71// * - No data
72// * - see subroutines
73// */
74
75// cpl_error_code status = CPL_ERROR_NONE;
76// cpl_parameter *p;
77// sctarr tabdat;
78// char spectype[4], basedir[SC_MAXLEN], outdir[SC_MAXLEN];
79// char outname[SC_MAXLEN], outfilename[3*SC_MAXLEN];
80// char errtxt[SC_MAXLEN];
81// double meanlam = 0.;
82
83// /* Create output table columns */
84// cpl_table_set_size(spec, 0);
85// cpl_table_new_column(spec, "lambda", CPL_TYPE_DOUBLE);
86// cpl_table_new_column(spec, "flux", CPL_TYPE_DOUBLE);
87// cpl_table_new_column(spec, "dflux", CPL_TYPE_DOUBLE);
88// cpl_table_new_column(spec, "mask", CPL_TYPE_INT);
89// cpl_table_new_column(spec, "weight", CPL_TYPE_DOUBLE);
90
91// /* Get type of spectrum (science or sky) */
92// p = cpl_parameterlist_find(parlist, "spectype");
93// strncpy(spectype, cpl_parameter_get_string(p), 4);
94
95// /* Get name components of converted file */
96// p = cpl_parameterlist_find(parlist, "inst_dir");
97// strncpy(basedir, cpl_parameter_get_string(p), SC_MAXLEN);
98// p = cpl_parameterlist_find(parlist, "output_dir");
99// sc_basic_abspath(outdir, cpl_parameter_get_string(p), basedir);
100// p = cpl_parameterlist_find(parlist, "output_name");
101// strncpy(outname, cpl_parameter_get_string(p), SC_MAXLEN);
102
103// /* Compose name of converted file ('sci' or 'sky' label) */
104// if (strncmp(spectype, "SCI", 3) == 0) {
105// sprintf(outfilename, "%s%s_sci.fits", outdir, outname);
106// } else if (strncmp(spectype, "SKY", 3) == 0) {
107// sprintf(outfilename, "%s%s_sky.fits", outdir, outname);
108// } else {
109// sprintf(errtxt, "%s: cpl_parameterlist *parlist (spectype neither "
110// "'SCI' nor 'SKY')", SC_ERROR_IOV_TXT);
111// return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOV, "%s", errtxt);
112// }
113
114// /* Read file and convert it to CPL table and CPL property list */
115// if ((status = sc_conv_readfile(&tabdat, parlist)) != CPL_ERROR_NONE) {
116// if (strncmp(spectype, "SCI", 3) == 0) {
117// sprintf(errtxt, "%s: error while processing input science "
118// "spectrum", SC_ERROR_EIS_TXT);
119// cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_EIS, "%s", errtxt);
120// } else if (strncmp(spectype, "SKY", 3) == 0) {
121// sprintf(errtxt, "%s: error while processing input sky spectrum",
122// SC_ERROR_EIS_TXT);
123// cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_EIS, "%s", errtxt);
124// }
125// return status;
126// }
127
128// /* Write CPL table and CPL property list to FITS table */
129// sc_conv_writetable(&tabdat, parlist);
130
131// /* Free allocated memory */
132// sc_conv_tarr_delete(&tabdat);
133
134// /* Get spectroscopic data */
135// if (cpl_error_get_code() == CPL_ERROR_NONE) {
136// sc_readspec_fits(spec, parlist, outfilename);
137// }
138
139// /* Get observing parameters (for reference sky spectrum only) */
140// if (cpl_error_get_code() == CPL_ERROR_NONE &&
141// strncmp(spectype, "SKY", 3) == 0) {
142// sc_readspec_header(parlist, outfilename);
143// }
144
145// /* Exit in case of errors */
146// if ((status = cpl_error_get_code()) != CPL_ERROR_NONE) {
147// if (strncmp(spectype, "SCI", 3) == 0) {
148// sprintf(errtxt, "%s: error while processing input science "
149// "spectrum", SC_ERROR_EIS_TXT);
150// cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_EIS, "%s", errtxt);
151// } else if (strncmp(spectype, "SKY", 3) == 0) {
152// sprintf(errtxt, "%s: error while processing input sky spectrum",
153// SC_ERROR_EIS_TXT);
154// cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_EIS, "%s", errtxt);
155// }
156// return status;
157// }
158
159// /* Set weights for spectra without error column */
161
162// if (cpl_table_get_nrow(spec) == 0) {
163// sprintf(errtxt, "%s: cpl_table *spec", SC_ERROR_NDA_TXT);
164// return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_NDA, "%s", errtxt);
165// }
166
167// /* All weights = 0? */
168// if (cpl_table_get_column_max(spec, "weight") == 0) {
169// sprintf(errtxt, "%s: cpl_table *spec (all weights = 0)",
170// SC_ERROR_IOV_TXT);
171// return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOV, "%s", errtxt);
172// }
173
174// /* Set mean wavelength */
175// meanlam = 0.5 * (cpl_table_get(spec, "lambda", 0, NULL) +
176// cpl_table_get(spec, "lambda", cpl_table_get_nrow(spec)-1,
177// NULL));
178// p = cpl_parameterlist_find(parlist, "meanlam");
179// cpl_parameter_set_double(p, meanlam);
180
181
182// return CPL_ERROR_NONE;
183//}
184
185
186//cpl_error_code sc_readspec_fits(cpl_table *spec,
187// const cpl_parameterlist *parlist,
188// const char *filename)
189//{
190// /*!
191// * Reads a FITS file with tabulated spectroscopic data (wavelength, flux,
192// * flux error, mask) in the 1st extension (no other extensions are
193// * allowed) and puts the read data in a CPL table consisting of the
194// * columns "lambda", "flux", and "weight". The names of the required FITS
195// * table columns are provided by the general CPL parameter list. The
196// * presence of flux error is optional. For skipping such a column, the
197// * name has to be 'NONE'. The original input file could also lack a mask
198// * column (also indicated by 'NONE'). However, ::sc_conv_readfile makes
199// * sure that a suitable mask column indicated by the given column name or
200// * ::SC_DEFMASKCOL (in the case of 'NONE') + '_I' is present. A weight of
201// * zero is taken if a wavelength is excluded by the mask. If there is no
202// * error column, the parameter list default error times mean flux is
203// * assumed for all data points.
204// *
205// * \b INPUT:
206// * \param spec empty CPL table
207// * \param parlist general CPL parameter list
208// * \param filename path and name of FITS file
209// *
210// * \b OUTPUT:
211// * \param spec CPL table with wavelengths, fluxes, and weights
212// *
213// * \b ERRORS:
214// * - File opening failed
215// * - Unexpected file structure
216// */
217
218// const cpl_parameter *p;
219// cpl_table *intab;
220// cpl_array *colnames;
221// cpl_boolean exerr = CPL_TRUE, exmask = CPL_TRUE;
222// char errtxt[SC_MAXLEN], col_lam[SC_LENLINE+1];
223// char col_flux[SC_LENLINE+1], col_dflux[SC_LENLINE+1];
224// char col_mask[SC_LENLINE+1], col_imask[SC_LENLINE+3];
225// char colname[SC_LENLINE+1];
226// int coln[4] = {0, 0, 0, 0};
227// int next = 0, ncolmin = 5, ncol = 0, check = 0, j = 0, nrow = 0, i = 0;
228// int mask = 0;
229// double wlgtomicron = 0., lam = 0., flux = 0., dflux = 0.;
230
231// /* Write info message */
232// cpl_msg_debug(cpl_func, "Read %s", filename);
233
234// /* Check file existence and number of FITS extensions */
235// next = cpl_fits_count_extensions(filename);
236// if (next < 0) {
237// sprintf(errtxt, "%s: %s", SC_ERROR_FOF_TXT, filename);
238// return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_FOF, "%s", errtxt);
239// } else if (next != 1) {
240// sprintf(errtxt, "%s: %s (# of FITS extensions != 1)",
241// SC_ERROR_UFS_TXT, filename);
242// return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s", errtxt);
243// }
244
245// /* Get column labels from parameter list */
246// p = cpl_parameterlist_find_const(parlist, "col_lam");
247// strncpy(col_lam, cpl_parameter_get_string(p), SC_LENLINE+1);
248// if (strcmp(col_lam, "NONE") == 0) {
249// sprintf(col_lam, "%s", SC_DEFLAMCOL);
250// }
251// p = cpl_parameterlist_find_const(parlist, "col_flux");
252// strncpy(col_flux, cpl_parameter_get_string(p), SC_LENLINE+1);
253// if (strcmp(col_flux, "NONE") == 0) {
254// sprintf(col_flux, "%s", SC_DEFFLUXCOL);
255// }
256// p = cpl_parameterlist_find_const(parlist, "col_dflux");
257// strncpy(col_dflux, cpl_parameter_get_string(p), SC_LENLINE+1);
258// if (strcmp(col_dflux, "NONE") == 0) {
259// cpl_table_erase_column(spec, "dflux");
260// exerr = CPL_FALSE;
261// ncolmin--;
262// }
263// p = cpl_parameterlist_find_const(parlist, "col_mask");
264// strncpy(col_mask, cpl_parameter_get_string(p), SC_LENLINE+1);
265// if (strcmp(col_mask, "NONE") == 0) {
266// cpl_table_erase_column(spec, "mask");
267// exmask = CPL_FALSE;
268// sprintf(col_imask, "%s_I", SC_DEFMASKCOL);
269// ncolmin--;
270// } else {
271// sprintf(col_imask, "%s_I", col_mask);
272// }
273
274// /* Get wavelength unit conversion factor */
275// p = cpl_parameterlist_find_const(parlist, "wlgtomicron");
276// wlgtomicron = cpl_parameter_get_double(p);
277
278// /* Read FITS table */
279// intab = cpl_table_load(filename, 1, 0);
280
281// /* Get column labels */
282// colnames = cpl_table_get_column_names(intab);
283// ncol = cpl_array_get_size(colnames);
284
285// /* Check existence of columns */
286
287// for (check = 0, j = 0; j < ncol; j++) {
288// strncpy(colname, cpl_array_get_string(colnames, j),
289// SC_LENLINE+1);
290// if (strcmp(colname, col_lam) == 0) {
291// coln[0] = j;
292// check++;
293// } else if (strcmp(colname, col_flux) == 0) {
294// coln[1] = j;
295// check++;
296// } else if (strcmp(colname, col_dflux) == 0) {
297// coln[2] = j;
298// check++;
299// } else if (strcmp(colname, col_mask) == 0) {
300// check++;
301// } else if (strcmp(colname, col_imask) == 0) {
302// coln[3] = j;
303// check++;
304// }
305// }
306
307// if (check < ncolmin) {
308// cpl_table_set_size(spec, 0);
309// cpl_array_delete(colnames);
310// cpl_table_delete(intab);
311// sprintf(errtxt, "%s: %s (missing FITS table column(s))",
312// SC_ERROR_UFS_TXT, filename);
313// return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
314// errtxt);
315// }
316
317// /* Resize output table */
318// nrow = cpl_table_get_nrow(intab);
319// cpl_table_set_size(spec, nrow);
320
321// /* Transfer wavelength and flux/transmission and compute weights */
322
323// for (i = 0; i < nrow; i++) {
324
325// lam = cpl_table_get(intab,
326// cpl_array_get_string(colnames, coln[0]), i, NULL)
327// * wlgtomicron;
328// cpl_table_set(spec, "lambda", i, lam);
329
330// flux = cpl_table_get(intab,
331// cpl_array_get_string(colnames, coln[1]), i,
332// NULL);
333// cpl_table_set(spec, "flux", i, flux);
334
335// if (exerr == CPL_TRUE) {
336// dflux = cpl_table_get(intab,
337// cpl_array_get_string(colnames, coln[2]), i,
338// NULL);
339// cpl_table_set(spec, "dflux", i, dflux);
340// } else {
341// dflux = 1.;
342// }
343
344// mask = cpl_table_get(intab, cpl_array_get_string(colnames, coln[3]),
345// i, NULL);
346// if (exmask == CPL_TRUE) {
347// cpl_table_set(spec, "mask", i, mask);
348// }
349
350// if (dflux <= 0. || mask == 0) {
351// cpl_table_set(spec, "weight", i, 0.);
352// } else {
353// cpl_table_set(spec, "weight", i, 1. / dflux);
354// }
355
356// }
357
358// /* Delete temporary CPL objects */
359// cpl_array_delete(colnames);
360// cpl_table_delete(intab);
361
362// return CPL_ERROR_NONE;
363//}
364
365
366//cpl_error_code sc_readspec_header(cpl_parameterlist *parlist,
367// const char *filename)
368//{
369// /*!
370// * Reads keywords from a FITS file header and puts the read values in the
371// * general CPL parameter list. The presence of keywords for date (MJD or
372// * date in years), time (UTC in s), and telescope altitude angle (in deg)
373// * is required. The keyword names are included in the general parameter
374// * list. The default names are MJD_OBS, TM-START, and ESO TEL ALT. If an
375// * expected keyword cannot be found in the FITS header, an error message
376// * will be written to the CPL error structure. The values of the required
377// * parameters are also part of the general parameter list. If a value is
378// * set manually, this value is taken instead of the corresponding FITS
379// * keyword content.
380// *
381// * \b INPUT:
382// * \param parlist general CPL parameter list
383// * \param filename path and name of FITS file
384// *
385// * \b OUTPUT:
386// * \param parlist general CPL parameter list with FITS header values
387// *
388// * \b ERRORS:
389// * - File opening failed
390// * - Unexpected file structure
391// */
392
393// cpl_parameter *p;
394// cpl_propertylist *header = NULL;
395// cpl_property *prop;
396// cpl_type type;
397// char key[SC_NKEY][SC_LENLINE+1] = {"", "", ""}, errtxt[SC_MAXLEN];
398// int next = 0, ext = 0, i = 0, nerr = 0;
399// double val = 0.;
400
401// /* Parameter names related to FITS keywords */
402// char keypar[SC_NKEY][SC_LENLINE+1] =
403// {"date_key", "time_key", "telalt_key"};
404// char valpar[SC_NKEY][SC_LENLINE+1] =
405// {"date_val", "time_val", "telalt_val"};
406
407// /* Find FITS extension with required keywords and write the header of this
408// extension into CPL property list */
409// next = cpl_fits_count_extensions(filename);
410// for (ext = 0; ext <= next; ext++) {
411// header = cpl_propertylist_load(filename, ext);
412// if (header == NULL) {
413// sprintf(errtxt, "%s: %s", SC_ERROR_FOF_TXT, filename);
414// return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_FOF, "%s",
415// errtxt);
416// }
417// /* Check first keyword */
418// p = cpl_parameterlist_find(parlist, keypar[0]);
419// strncpy(key[0], cpl_parameter_get_string(p), SC_LENLINE+1);
420// prop = cpl_propertylist_get_property(header, key[0]);
421// if (prop != NULL) {
422// break;
423// } else {
424// if (ext < next) {
425// cpl_propertylist_delete(header);
426// }
427// }
428// }
429
430// /* Write info message */
431// cpl_msg_debug(cpl_func, "Take keywords from FITS extension %d", ext);
432
433// /* Update general parameter list with keywords from CPL property list */
434
435// for (i = 0; i < SC_NKEY; i++) {
436
437// /* Get value from parameter list */
438// p = cpl_parameterlist_find(parlist, valpar[i]);
439// val = cpl_parameter_get_double(p);
440
441// /* Get name of required FITS keyword */
442// p = cpl_parameterlist_find(parlist, keypar[i]);
443// strncpy(key[i], cpl_parameter_get_string(p), SC_LENLINE+1);
444
445// /* Write info message */
446// cpl_msg_debug(cpl_func, "Read keyword %s", key[i]);
447
448// /* Get FITS keyword */
449// prop = cpl_propertylist_get_property(header, key[i]);
450
451// if (prop == NULL && val == -1.) {
452
453// /* Set error message in the case of missing keyword */
454// nerr++;
455// sprintf(errtxt, "%s: %s (keyword %s not found)",
456// SC_ERROR_UFS_TXT, filename, key[i]);
457// cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s", errtxt);
458
459// } else {
460
461// /* Take FITS keyword only if parameter value was not given
462// manually */
463// if (val == -1.) {
464// /* Check for type */
465// type = cpl_property_get_type(prop);
466// if (type == CPL_TYPE_DOUBLE) {
467// val = cpl_property_get_double(prop);
468// } else if (type == CPL_TYPE_FLOAT) {
469// val = (double) cpl_property_get_float(prop);
470// } else if (type == CPL_TYPE_INT) {
471// val = (double) cpl_property_get_int(prop);
472// } else {
473// nerr++;
474// sprintf(errtxt, "%s: %s (non-numerical keyword %s)",
475// SC_ERROR_UFS_TXT, filename, key[i]);
476// cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
477// errtxt);
478// continue;
479// }
480// }
481
482// /* MJD -> date in years (if required; save MJD before) */
483// if (i == 0 && val > 3000.) {
484// p = cpl_parameterlist_find(parlist, "mjd");
485// cpl_parameter_set_double(p, val);
486// val = sc_basic_mjd2fracyear(val);
487// }
488
489// /* Write new value into parameter list */
490// p = cpl_parameterlist_find(parlist, valpar[i]);
491// cpl_parameter_set_double(p, val);
492
493// }
494
495// }
496
497// /* Free allocated memory */
498// cpl_propertylist_delete(header);
499
500// /* Return SC_ERROR_UFS in the case of keyword mismatch */
501// if (nerr > 0) {
502// return (cpl_error_code)SC_ERROR_UFS;
503// }
504
505// return CPL_ERROR_NONE;
506//}
507
508
509//cpl_error_code sc_readspec_setweight(cpl_table *spec,
510// const cpl_parameterlist *parlist)
511//{
512// /*!
513// * Sets the weights for spectra that do not contain an error column.
514// * The default relative error provided by the general CPL parameter list
515// * is multiplied by the mean flux of all wavelengths that are used by the
516// * fit. The resulting absolute error is taken for all wavelengths with
517// * non-zero weight.
518// *
519// * \b INPUT:
520// * \param spec CPL table with observed spectrum
521// * \param parlist general CPL parameter list
522// *
523// * \b OUTPUT:
524// * \param spec spectrum with optimised weights
525// *
526// * \b ERRORS:
527// * - Invalid object value(s)
528// */
529
530// cpl_error_code err = CPL_ERROR_NONE;
531// const cpl_parameter *p;
532// char col_dflux[SC_LENLINE+1], errtxt[SC_MAXLEN];
533// int nrow = 0, i = 0, nw = 0;
534// double deferr = 0., weight = 0., fsum = 0., weight0 = 0.;
535
536// /* Return if error data exist */
537// p = cpl_parameterlist_find_const(parlist, "col_dflux");
538// strncpy(col_dflux, cpl_parameter_get_string(p), SC_LENLINE+1);
539// if (strcmp(col_dflux, "NONE") != 0) {
540// return CPL_ERROR_NONE;
541// }
542
543// /* Get default relative error */
544// p = cpl_parameterlist_find_const(parlist, "default_error");
545// deferr = cpl_parameter_get_double(p);
546
547// /* Count data points with non-zero weight and sum up their fluxes */
548// nrow = cpl_table_get_nrow(spec);
549// for (i = 0; i < nrow; i++) {
550// weight = cpl_table_get(spec, "weight", i, NULL);
551// if (weight > 0) {
552// nw++;
553// fsum += cpl_table_get(spec, "flux", i, NULL);
554// }
555// }
556
557// /* Set errors to default error * mean if error column is missing */
558// if (fsum > 0) {
559// weight0 = (double) nw / (fsum * deferr);
560// for (i = 0; i < nrow; i++) {
561// weight = cpl_table_get(spec, "weight", i, NULL);
562// if (weight > 0) {
563// cpl_table_set(spec, "weight", i, weight0);
564// }
565// }
566// }
567
568// /* Check for errors */
569
570// if (fsum == 0) {
571// sprintf(errtxt, "%s: cpl_table *spec (all fluxes = 0)",
572// SC_ERROR_IOV_TXT);
573// err = cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOV, "%s", errtxt);
574// }
575
576// if (nw == 0) {
577// sprintf(errtxt, "%s: cpl_table *spec (all weights = 0)",
578// SC_ERROR_IOV_TXT);
579// err = cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOV, "%s", errtxt);
580// }
581
582// return err;
583//}
584