X-shooter Pipeline Reference Manual 3.8.15
xsh_data_spectrum1D.c
Go to the documentation of this file.
1/* *
2 * This file is part of the ESO X-shooter Pipeline *
3 * Copyright (C) 2006 European Southern Observatory *
4 * *
5 * This library 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, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA *
18 * */
19
20/*
21 * $Author: amodigli $
22 * $Date: 2012-02-13 09:50:57 $
23 * $Revision: 1.17 $
24 * $Name: not supported by cvs2svn $
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
41/*-----------------------------------------------------------------------------
42 Includes
43 ----------------------------------------------------------------------------*/
44
45#include <math.h>
46#include <xsh_data_spectrum1D.h>
47#include <xsh_data_spectrum.h>
48#include <xsh_utils.h>
49#include <xsh_error.h>
50#include <xsh_msg.h>
51#include <xsh_pfits.h>
52#include <xsh_dfs.h>
53#include <cpl.h>
54
55/*----------------------------------------------------------------------------
56 Function implementation
57 ----------------------------------------------------------------------------*/
58
59/*---------------------------------------------------------------------------*/
69/*---------------------------------------------------------------------------*/
70xsh_spectrum1D* xsh_spectrum1D_create( double lambda_min, double lambda_max,
71 double lambda_step)
72{
73 xsh_spectrum1D* result = NULL;
74
75
76 /* check input parameters */
77 XSH_ASSURE_NOT_ILLEGAL( lambda_min >= 0.0 && lambda_min <= lambda_max);
79
80 XSH_CALLOC(result, xsh_spectrum1D,1);
81
82 result->lambda_min = lambda_min;
83 result->lambda_max = lambda_max;
84 result->lambda_step = lambda_step;
85
87 check(xsh_pfits_set_wcs1(result->flux_header, 0.5, lambda_min, lambda_step));
88
90 check( xsh_pfits_set_extname ( result->errs_header, "ERRS"));
92 check( xsh_pfits_set_extname ( result->qual_header, "QUAL"));
93
94
95 result->size = (int)((lambda_max-lambda_min)/lambda_step+0.5);
96
97 check( result->flux = cpl_image_new( result->size, 1, CPL_TYPE_DOUBLE));
98 check( result->errs = cpl_image_new( result->size, 1, CPL_TYPE_DOUBLE));
99 check( result->qual = cpl_image_new( result->size, 1, CPL_TYPE_INT));
100
101 cleanup:
102 if (cpl_error_get_code() != CPL_ERROR_NONE) {
103 xsh_spectrum1D_free(&result);
104 }
105 return result;
106}
107
108
109/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119xsh_spectrum1D* xsh_spectrum1D_load( cpl_frame* s1d_frame,
120 xsh_instrument* instr)
121{
122 xsh_spectrum1D* result = NULL;
123 const char *s1dname = NULL;
124
125 XSH_ASSURE_NOT_NULL( s1d_frame);
126 XSH_ASSURE_NOT_NULL( instr);
127
128 XSH_ASSURE_NOT_ILLEGAL(cpl_frame_get_nextensions(s1d_frame) == 2);
129
130 check( s1dname = cpl_frame_get_filename( s1d_frame));
131
132 XSH_CALLOC(result, xsh_spectrum1D,1);
133
134 check( result->flux_header = cpl_propertylist_load( s1dname,0));
135 check( result->errs_header = cpl_propertylist_load( s1dname,1));
136 check( result->qual_header = cpl_propertylist_load( s1dname,2));
137
138 check( result->lambda_min = xsh_pfits_get_crval1( result->flux_header));
140 check( result->size = xsh_pfits_get_naxis1( result->flux_header));
141 result->lambda_max = result->lambda_min+
142 (result->lambda_step*result->size-1);
143
144 check( result->flux = cpl_image_load( s1dname, CPL_TYPE_DOUBLE, 0, 0));
145 check( result->errs = cpl_image_load( s1dname, CPL_TYPE_DOUBLE, 0, 1));
146 check( result->qual = cpl_image_load( s1dname, CPL_TYPE_INT, 0, 2));
147
148 cleanup:
149 if (cpl_error_get_code() != CPL_ERROR_NONE) {
150 xsh_spectrum1D_free(&result);
151 }
152 return result;
153}
154/*---------------------------------------------------------------------------*/
162/*---------------------------------------------------------------------------*/
164{
165 int res=0;
166
168
169 res = s->size;
170
171 cleanup:
172 return res;
173}
174
175/*---------------------------------------------------------------------------*/
183/*---------------------------------------------------------------------------*/
185{
186 double res=0.0;
187
189
190 res = s->lambda_min;
191
192 cleanup:
193 return res;
194}
195
196/*---------------------------------------------------------------------------*/
204/*---------------------------------------------------------------------------*/
206{
207 double res=0.0;
208
210
211 res = s->lambda_max;
212
213 cleanup:
214 return res;
215}
216
217/*---------------------------------------------------------------------------*/
225/*---------------------------------------------------------------------------*/
227{
228 double res=0.0;
229
231
232 res = s->lambda_step;
233
234 cleanup:
235 return res;
236}
237
238
239/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
249{
250 double *res=NULL;
251
253
254 check( res = cpl_image_get_data_double( s->flux));
255
256 cleanup:
257 return res;
258}
259
260
261/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
271{
272 double *res=NULL;
273
275
276 check( res = cpl_image_get_data_double( s->errs));
277
278 cleanup:
279 return res;
280}
281
282
283/*---------------------------------------------------------------------------*/
291/*---------------------------------------------------------------------------*/
293{
294 int* res = NULL;
295
297
298 check( res = cpl_image_get_data_int( s->qual));
299
300 cleanup:
301 return res;
302}
303
304/*---------------------------------------------------------------------------*/
310/*---------------------------------------------------------------------------*/
312{
313 if (s && *s){
314 xsh_free_propertylist( &((*s)->flux_header));
315 xsh_free_propertylist( &((*s)->errs_header));
316 xsh_free_propertylist( &((*s)->qual_header));
317 xsh_free_image( &((*s)->flux));
318 xsh_free_image( &((*s)->errs));
319 xsh_free_image( &((*s)->qual));
320 XSH_FREE( (*s));
321 }
322}
323
324/*---------------------------------------------------------------------------*/
333/*---------------------------------------------------------------------------*/
334cpl_frame* xsh_spectrum1D_save( xsh_spectrum1D* s, const char* filename)
335{
336 cpl_frame *product_frame = NULL;
337
339 XSH_ASSURE_NOT_NULL(filename);
340
341
342 /* Save the file */
343 check_msg (cpl_image_save ( s->flux, filename, XSH_SPECTRUM1D_DATA_BPP,
344 s->flux_header, CPL_IO_DEFAULT),
345 "Could not save data to %s extension 0", filename);
346 check_msg (cpl_image_save ( s->errs, filename, XSH_SPECTRUM1D_ERRS_BPP,
347 s->errs_header, CPL_IO_EXTEND),
348 "Could not save errs to %s extension 1", filename);
349 check_msg (cpl_image_save ( s->qual, filename, XSH_SPECTRUM1D_QUAL_BPP,
350 s->qual_header, CPL_IO_EXTEND),
351 "Could not save qual to %s extension 2", filename);
352 /* Create product frame */
353
354 check(product_frame=xsh_frame_product(filename,
355 "TAG",
356 CPL_FRAME_TYPE_IMAGE,
357 CPL_FRAME_GROUP_PRODUCT,
358 CPL_FRAME_LEVEL_FINAL));
359
360cleanup:
361 if (cpl_error_get_code () != CPL_ERROR_NONE) {
362 xsh_free_frame(&product_frame);
363 product_frame = NULL;
364 }
365 return product_frame;
366}
367
368static cpl_error_code
370 const double wave_s,
371 const double wave_e,
372 const int index)
373{
374
375 int xstart=0;
376 int xend=0;
377 double flux=0;
378 double err=0;
379 double sn=0;
380 double ws=wave_s;
381 double we=wave_e;
382 char comment[40];
383 char qc_key[20];
384 cpl_image* snr=NULL;
385
386 if (index != 0) {
387 xstart=((ws - s->lambda_min)/s->lambda_step+0.5);
388 xend= ((we - s->lambda_min)/s->lambda_step-0.5);
389 } else {
390 xstart=1;
391 xend=s->size;
392 ws=s->lambda_min;
393 we=s->lambda_max;
394 }
395 xstart=(xstart < s->size) ? xstart: s->size;
396 xend=(xend < s->size) ? xend: s->size;
397 xstart=(xstart < xend) ? xstart: xend-1;
398
399 check(flux=cpl_image_get_mean_window(s->flux,xstart,1,xend,1));
400 if (index != 0) {
401 sprintf(qc_key,"%s%d VAL",XSH_QC_FLUX,index);
402 } else {
403 sprintf(qc_key,"%s VAL",XSH_QC_FLUX);
404 }
405 sprintf(comment,"Flux in %4.0f-%4.0f nm",ws,we);
406
407 if (isnan(flux)) {
408 xsh_msg_warning("Calculated a NaN value for the '%s' keyword."
409 " Will force it to -1.0 instead.", qc_key);
410 flux = -1.0;
411 }
412 check(cpl_propertylist_append_double(s->flux_header,qc_key,flux));
413 check(cpl_propertylist_set_comment(s->flux_header,qc_key,comment));
414
415 check(err=cpl_image_get_mean_window(s->errs,xstart,1,xend,1));
416 if (index != 0) {
417 sprintf(qc_key,"%s%d ERR",XSH_QC_FLUX,index);
418 } else {
419 sprintf(qc_key,"%s ERR",XSH_QC_FLUX);
420 }
421 sprintf(comment,"Error Flux in %4.0f-%4.0f nm",ws,we);
422
423 if (isnan(err)) {
424 xsh_msg_warning("Calculated a NaN value for the '%s' keyword."
425 " Will force it to -1.0 instead.", qc_key);
426 err = -1.0;
427 }
428 cpl_propertylist_append_double(s->flux_header,qc_key,err);
429 cpl_propertylist_set_comment(s->flux_header,qc_key,comment);
430 if (index != 0) {
431 sprintf(qc_key,"%s%d SN",XSH_QC_FLUX,index);
432 } else {
433 sprintf(qc_key,"%s SN",XSH_QC_FLUX);
434 }
435 sprintf(comment,"SNR in %4.0f-%4.0f nm",ws,we);
436 /* because the extraction may give values of 0 for both flux and err
437 * we make sure that flux and err are not both 0. For easy/speed we check
438 * their squared value
439 */
440 double flux2=flux*flux;
441 double err2=err*err;
442
443 if( (flux2 >= 1.e-80) && (err2 >=1.e-80) ) {
444 snr=cpl_image_duplicate(s->flux);
445 cpl_image_divide(snr,s->errs);
446 //xsh_msg("flux=%g err=%g",flux,err);
447 //cpl_image_flag_bp(snr,s->qual,inst);
448 sn=cpl_image_get_mean_window(snr,xstart,1,xend,1);
449 }
450 //cpl_image_flag_bp(snr,s->qual,inst);
451 //sn = (fabs(err) > 1.e-37) ? flux/err : -999;
452
453 if (isnan(sn)) {
454 xsh_msg_warning("Calculated a NaN value for the '%s' keyword."
455 " Will force it to -1.0 instead.", qc_key);
456 sn = -1.0;
457 }
458 cpl_propertylist_append_double(s->flux_header,qc_key,sn);
459 cpl_propertylist_set_comment(s->flux_header,qc_key,comment);
460
461 cleanup:
462
463 xsh_free_image(&snr);
464 return cpl_error_get_code();
465
466}
467
468
469cpl_error_code
471{
472
473 xsh_spectrum* s1d=NULL;
474 const char* s1dname=NULL;
475 const char *tag = NULL;
476 cpl_frame *product = NULL;
477
478 check( s1dname=cpl_frame_get_filename(in_frm));
479 check( s1d=xsh_spectrum_load(in_frm));
480 check( tag = cpl_frame_get_tag(in_frm));
481
483 check( xsh_monitor_spectrum1D_flux_qc(s1d,450,550,0));
484
485 check( xsh_monitor_spectrum1D_flux_qc(s1d,450,470,1));
486 check( xsh_monitor_spectrum1D_flux_qc(s1d,510,530,2));
487
488 }
490 xsh_monitor_spectrum1D_flux_qc(s1d,600,999,0);
491 xsh_monitor_spectrum1D_flux_qc(s1d,672,680,1);
492 xsh_monitor_spectrum1D_flux_qc(s1d,745,756,2);
493 xsh_monitor_spectrum1D_flux_qc(s1d,992,999,3);
494
495 }
497 xsh_monitor_spectrum1D_flux_qc(s1d,1100,2450,0);
498 check(xsh_monitor_spectrum1D_flux_qc(s1d,1514,1548,1));
500 check(xsh_monitor_spectrum1D_flux_qc(s1d,2214,2243,2));
501 }
502 }
503
504 check( product = xsh_spectrum_save(s1d,s1dname, tag));
505
506 cleanup:
507 xsh_spectrum_free(&s1d);
508 xsh_free_frame( &product);
509 return cpl_error_get_code();
510}
511cpl_error_code
512xsh_monitor_spectrum1D_extra_qc(cpl_frame* in_frm,xsh_instrument* instrument,cpl_propertylist* qclist)
513{
514
515 xsh_spectrum* s1d=NULL;
516 const char* s1dname=NULL;
517 const char *tag = NULL;
518 cpl_frame *product = NULL;
519
520 check( s1dname=cpl_frame_get_filename(in_frm));
521 check( s1d=xsh_spectrum_load(in_frm));
522 check( tag = cpl_frame_get_tag(in_frm));
523
524 if(s1d->flux_header != NULL && qclist != NULL){
526 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC START1",450.0));
527 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC END1",470.0));
528 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC START2",510.0));
529 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC END2",530.0));
530 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC START3",0.0));
531 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC END3",0.0));
532 }
534 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC START1",672.0));
535 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC END1",680.0));
536 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC START2",745.0));
537 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC END2",756.0));
538 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC START3",992.0));
539 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC END3",999.0));
540 }
542 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC START1",1514.0));
543 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC END1",1548.0));
544 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC START2",2214.0));
545 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC END2",2243.0));
546 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC START3",0.0));
547 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC END3",0.0));
548 }
549
551
552 if(cpl_propertylist_has(s1d->flux_header,"ESO OBS TARG NAME")){
553 char* val = cpl_strdup(cpl_propertylist_get_string(s1d->flux_header,"ESO OBS TARG NAME"));
554 if(val != NULL){
555 for (int i=0;i<strlen(val);i++){
556 if(val[i] == ' ')
557 val[i] = '-';
558 }
559 }
560 check(cpl_propertylist_update_string(s1d->flux_header,"ESO QC OBS TARG NAME",val));
561 cpl_free(val);
562 }
563 if(cpl_propertylist_has(s1d->flux_header,"ESO QC EFF MED ORD 9") &&
564 cpl_propertylist_has(s1d->flux_header,"ESO QC EFF MED ORD 1")){
565 double den = cpl_propertylist_get_double(s1d->flux_header,"ESO QC EFF MED ORD 1");
566 if(den != 0.0){
567 double ratio = cpl_propertylist_get_double(s1d->flux_header,"ESO QC EFF MED ORD 9") / den;
568 check(cpl_propertylist_update_double(s1d->flux_header,"ESO QC CHROMATIC EFF",ratio));
569 }
570 }
571 if(cpl_propertylist_has(s1d->flux_header,"ESO TPL ID")){
572 char* val = cpl_strdup(cpl_propertylist_get_string(s1d->flux_header,"ESO TPL ID"));
573 char* nstr = cpl_strdup("");
574 char* nstr_orig;
575 if(val != NULL){
576 for (int i=0;i<strlen(val);i++){
577 if(val[i] != '_'){
578 nstr_orig = nstr;
579 nstr = cpl_sprintf("%s%c",nstr,val[i]);
580 cpl_free(nstr_orig);
581 }
582 }
583 }
584 check(cpl_propertylist_update_string(s1d->flux_header,"ESO QC TPL ID",nstr));
585 cpl_free(val);
586 cpl_free(nstr);
587 }
588
589 check(cpl_propertylist_append(s1d->flux_header,qclist));
590 }
591
592 check( product = xsh_spectrum_save(s1d,s1dname, tag));
593
594 cleanup:
595 xsh_spectrum_free(&s1d);
596 xsh_free_frame( &product);
597 return cpl_error_get_code();
598}
599
static xsh_instrument * instrument
static float lambda_step
double xsh_spectrum1D_get_lambda_min(xsh_spectrum1D *s)
Get minimum lambda of spectrum.
double xsh_spectrum1D_get_lambda_max(xsh_spectrum1D *s)
Get maximum lambda of spectrum.
cpl_error_code xsh_monitor_spectrum1D_extra_qc(cpl_frame *in_frm, xsh_instrument *instrument, cpl_propertylist *qclist)
double xsh_spectrum1D_get_lambda_step(xsh_spectrum1D *s)
Get bin in lambda of spectrum.
xsh_spectrum1D * xsh_spectrum1D_create(double lambda_min, double lambda_max, double lambda_step)
Create a 1D spectrum structure.
int xsh_spectrum1D_get_size(xsh_spectrum1D *s)
Get size of spectrum.
cpl_frame * xsh_spectrum1D_save(xsh_spectrum1D *s, const char *filename)
save a 1D spectrum
double * xsh_spectrum1D_get_errs(xsh_spectrum1D *s)
Get errs of spectrum.
static cpl_error_code xsh_monitor_spectrum1D_flux_qc(xsh_spectrum *s, const double wave_s, const double wave_e, const int index)
xsh_spectrum1D * xsh_spectrum1D_load(cpl_frame *s1d_frame, xsh_instrument *instr)
Load a 1D spectrum structure.
void xsh_spectrum1D_free(xsh_spectrum1D **s)
free memory associated to an 1D spectrum
double * xsh_spectrum1D_get_flux(xsh_spectrum1D *s)
Get flux of spectrum.
cpl_error_code xsh_monitor_spectrum1D_flux(cpl_frame *in_frm, xsh_instrument *instrument)
int * xsh_spectrum1D_get_qual(xsh_spectrum1D *s)
Get qual of spectrum.
xsh_spectrum * xsh_spectrum_load(cpl_frame *s1d_frame)
Load a 1D spectrum structure.
cpl_frame * xsh_spectrum_save(xsh_spectrum *s, const char *filename, const char *tag)
save a spectrum
void xsh_spectrum_free(xsh_spectrum **s)
free memory associated to an 1D spectrum
#define XSH_ASSURE_NOT_ILLEGAL(cond)
Definition: xsh_error.h:107
#define check(COMMAND)
Definition: xsh_error.h:71
#define check_msg(COMMAND,...)
Definition: xsh_error.h:62
#define XSH_ASSURE_NOT_NULL(pointer)
Definition: xsh_error.h:99
int xsh_instrument_nir_is_JH(cpl_frame *frame, xsh_instrument *instr)
XSH_ARM xsh_instrument_get_arm(xsh_instrument *i)
Get an arm on instrument structure.
int size
static SimAnneal s
Definition: xsh_model_sa.c:99
#define xsh_msg_warning(...)
Print an warning message.
Definition: xsh_msg.h:88
void xsh_pfits_set_extname(cpl_propertylist *plist, const char *value)
Write the EXTNAME value.
Definition: xsh_pfits.c:979
cpl_error_code xsh_pfits_set_wcs1(cpl_propertylist *header, const double crpix1, const double crval1, const double cdelt1)
Definition: xsh_pfits.c:4307
double xsh_pfits_get_cdelt1(const cpl_propertylist *plist)
find out the cdelt1
Definition: xsh_pfits.c:2196
int xsh_pfits_get_naxis1(const cpl_propertylist *plist)
find out the NAXIS1 value
Definition: xsh_pfits.c:227
double xsh_pfits_get_crval1(const cpl_propertylist *plist)
find out the crval1
Definition: xsh_pfits.c:1907
void xsh_pfits_set_qc_slit_width(cpl_propertylist *source_list, cpl_propertylist *set_list, xsh_instrument *instrument)
void xsh_free_image(cpl_image **i)
Deallocate an image and set the pointer to NULL.
Definition: xsh_utils.c:2116
void xsh_free_frame(cpl_frame **f)
Deallocate a frame and set the pointer to NULL.
Definition: xsh_utils.c:2269
void xsh_free_propertylist(cpl_propertylist **p)
Deallocate a property list and set the pointer to NULL.
Definition: xsh_utils.c:2179
cpl_propertylist * errs_header
cpl_propertylist * flux_header
cpl_propertylist * qual_header
cpl_propertylist * flux_header
@ XSH_ARM_UVB
@ XSH_ARM_NIR
@ XSH_ARM_VIS
#define XSH_SPECTRUM1D_ERRS_BPP
#define XSH_SPECTRUM1D_DATA_BPP
#define XSH_SPECTRUM1D_QUAL_BPP
cpl_frame * xsh_frame_product(const char *fname, const char *tag, cpl_frame_type type, cpl_frame_group group, cpl_frame_level level)
Creates a frame with given characteristics.
Definition: xsh_dfs.c:930
#define XSH_QC_FLUX
Definition: xsh_pfits_qc.h:112
#define XSH_NEW_PROPERTYLIST(POINTER)
Definition: xsh_utils.h:70
#define XSH_FREE(POINTER)
Definition: xsh_utils.h:92
#define XSH_CALLOC(POINTER, TYPE, SIZE)
Definition: xsh_utils.h:56