GRAVI Pipeline Reference Manual 1.8.0
Loading...
Searching...
No Matches
gravi_idp.c
Go to the documentation of this file.
1/*
2 * This file is part of the GRAVI Pipeline
3 * Copyright (C) 2022 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/*-----------------------------------------------------------------------------
21 Includes
22 -----------------------------------------------------------------------------*/
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <math.h>
29#include "gravi_idp.h"
30#include "gravi_pfits.h"
31#include "gravi_dfs.h"
32#include "gravi_cpl.h"
33#include "gravi_vis.h"
34
35/*-----------------------------------------------------------------------------*/
44/*-----------------------------------------------------------------------------*/
45cpl_propertylist * gravi_idp_compute (gravi_data * vis_data,
46 cpl_propertylist * header,
47 cpl_frameset * frameset)
48{
49 cpl_propertylist * idp_plist = cpl_propertylist_new ();
50 int nbase = 6;
51
53 char qc_name[100];
54
55 /* Scratch tables to merge polarization tables */
56 cpl_table * oi_vis2_SC_allpol = NULL;
57 cpl_table * oi_T3_SC_allpol = NULL;
58 cpl_table * oi_wave_SC_allpol = NULL;
59
60 /* There are products like the p2vmred that do not have all columns */
62 {
63 oi_vis2_SC_allpol = cpl_table_duplicate(gravi_data_get_oi_vis2 (vis_data, GRAVI_SC, 0, npol_sc));
64 oi_T3_SC_allpol = cpl_table_duplicate(gravi_data_get_oi_t3 (vis_data, GRAVI_SC, 0, npol_sc));
65 oi_wave_SC_allpol = cpl_table_duplicate(gravi_data_get_oi_wave (vis_data, GRAVI_SC, 0, npol_sc));
66
67 for (int pol = 1; pol < npol_sc; pol++) {
68 cpl_table_insert(oi_vis2_SC_allpol, gravi_data_get_oi_vis2 (vis_data, GRAVI_SC, pol, npol_sc), cpl_table_get_nrow(oi_vis2_SC_allpol));
69 cpl_table_insert(oi_T3_SC_allpol, gravi_data_get_oi_t3 (vis_data, GRAVI_SC, pol, npol_sc), cpl_table_get_nrow(oi_T3_SC_allpol));
70 cpl_table_insert(oi_wave_SC_allpol, gravi_data_get_oi_wave (vis_data, GRAVI_SC, pol, npol_sc), cpl_table_get_nrow(oi_wave_SC_allpol));
71 }
72
73 /* Compute QC values that aggregate on polarizations */
74 sprintf (qc_name, "VIS2ERR");
75 cpl_propertylist_update_double (idp_plist, qc_name, gravi_table_get_column_flagged_mean(oi_vis2_SC_allpol, "VIS2ERR"));
76 cpl_propertylist_set_comment (idp_plist, qc_name, "Representative squared visibility error [%]");
77
78 sprintf (qc_name, "T3PHIERR");
79 cpl_propertylist_update_double (idp_plist, qc_name, gravi_table_get_column_flagged_mean(oi_T3_SC_allpol, "T3PHIERR"));
80 cpl_propertylist_set_comment (idp_plist, qc_name, "Representative closure phase error [deg]");
81
82 double min_uvcoord, max_uvcoord;
83 gravi_data_get_minmax_uvcoord(oi_vis2_SC_allpol, &min_uvcoord, &max_uvcoord);
84
85 double min_eff_wave = cpl_table_get_column_min(oi_wave_SC_allpol, "EFF_WAVE");
86 double max_eff_wave = cpl_table_get_column_max(oi_wave_SC_allpol, "EFF_WAVE");
87
88 double base_max = max_uvcoord / min_eff_wave;
89 double base_min = min_uvcoord / max_eff_wave;
90 if(isnan(base_max) || isinf(base_max))
91 base_max = 0;
92 if(isnan(base_min) || isinf(base_min))
93 base_min = 0;
94
95 sprintf (qc_name, "BASE_MAX");
96 cpl_propertylist_update_double (idp_plist, qc_name, base_max);
97 cpl_propertylist_set_comment (idp_plist, qc_name, "Maximum baseline / Minimum effective wavelenth");
98
99 sprintf (qc_name, "BASE_MIN");
100 cpl_propertylist_update_double (idp_plist, qc_name, base_min);
101 cpl_propertylist_set_comment (idp_plist, qc_name, "Minimum baseline / Maximum effective wavelenth");
102
103 /* The rows in oi_wave_SC_allpol contain each wavelenght npol_sc times,
104 since it has been aggregated. Therefore dividing by npol_sc times */
105 sprintf (qc_name, "NUM_CHAN");
106 cpl_propertylist_update_int (idp_plist, qc_name, cpl_table_get_nrow(oi_wave_SC_allpol) / npol_sc );
107 cpl_propertylist_set_comment (idp_plist, qc_name, "Number of wavelength channels");
108
109 sprintf (qc_name, "WAVELMAX");
110 cpl_propertylist_update_double (idp_plist, qc_name, max_eff_wave);
111 cpl_propertylist_set_comment (idp_plist, qc_name, "Maximum wavelength");
112
113 sprintf (qc_name, "WAVELMIN");
114 cpl_propertylist_update_double (idp_plist, qc_name, min_eff_wave);
115 cpl_propertylist_set_comment (idp_plist, qc_name, "Minimum wavelength");
116
117 cpl_table_duplicate_column(oi_wave_SC_allpol, "SPEC_RES", oi_wave_SC_allpol, "EFF_WAVE");
118 cpl_table_divide_columns(oi_wave_SC_allpol,"EFF_WAVE", "EFF_BAND");
119
120 sprintf (qc_name, "SPEC_RES");
121 cpl_propertylist_update_double (idp_plist, qc_name, cpl_table_get_column_mean(oi_wave_SC_allpol, "SPEC_RES"));
122 cpl_propertylist_set_comment (idp_plist, qc_name, "Spectral resolution");
123
124 /* This is the mean INT_TIME, which includes duplicated entries due to the several polarizations.
125 Since it is a mean, the final value should be the same */
126 sprintf (qc_name, "EXPTIME");
127 double mean_int_time = gravi_table_get_column_flagged_mean(oi_vis2_SC_allpol, "INT_TIME");
128 cpl_propertylist_update_double (idp_plist, qc_name, mean_int_time);
129 cpl_propertylist_set_comment (idp_plist, qc_name, "Exposure time");
130 /* This is the sum of all INT_TIME divided by the number of baselines. The mean is multiplied
131 by the number of rows and then divided by the number of polarizations since they have been
132 aggregated. Finally divided by the number of baselines as specified in PIPE-9900 */
133 if(!cpl_propertylist_has(header, "TEXPTIME"))
134 {
135 sprintf (qc_name, "TEXPTIME");
136 cpl_propertylist_update_double (idp_plist, qc_name, mean_int_time * cpl_table_get_nrow(oi_vis2_SC_allpol) / npol_sc / nbase);
137 cpl_propertylist_set_comment (idp_plist, qc_name, "Total exposure time");
138 }
139 else
140 {
141 cpl_propertylist_update_double (idp_plist, "TEXPTIME",
142 cpl_propertylist_get_double(header, "TEXPTIME") );
143 cpl_propertylist_set_comment (idp_plist, "TEXPTIME", "Total exposure time");
144 }
145 }
146
147 /* PRODCATG */
148 cpl_propertylist_update_string (idp_plist, "PRODCATG", "SCIENCE.VISIBILITY.UNCALIBRATED");
149 cpl_propertylist_set_comment (idp_plist, "PRODCATG", "Data product category");
150
151 /* MJD-END */
152 double exptime;
153 if ( cpl_propertylist_has(idp_plist, "EXPTIME") )
154 exptime = cpl_propertylist_get_double(idp_plist, "EXPTIME");
155 else
156 exptime = cpl_propertylist_get_double(header, "EXPTIME");
157 cpl_propertylist_update_double (idp_plist, "MJD-END",
158 gravi_pfits_get_mjd(header) + exptime / 86400.);
159 cpl_propertylist_set_comment (idp_plist, "MJD-END", "End of observation");
160
161 /* OBID */
162 cpl_propertylist_update_int (idp_plist, "OBID1",
163 cpl_propertylist_get_int(header, "ESO OBS ID"));
164 cpl_propertylist_set_comment (idp_plist, "OBID1", "Obseration Block ID");
165
166 /* NCOMBINE */
167 if(frameset != NULL)
168 {
169 cpl_frameset * science_frames = gravi_frameset_extract_science_data(frameset);
170 cpl_size nscience = cpl_frameset_get_size(science_frames);
171 cpl_frameset_delete(science_frames);
172 if(!cpl_propertylist_has(header, "NCOMBINE"))
173 {
174 if (nscience != 0)
175 {
176 cpl_propertylist_update_int (idp_plist, "NCOMBINE", nscience);
177 cpl_propertylist_set_comment (idp_plist, "NCOMBINE", "Number of raw science combined");
178 }
179 }
180 else
181 {
182 cpl_propertylist_update_int (idp_plist, "NCOMBINE",
183 cpl_propertylist_get_int(header, "NCOMBINE") );
184 cpl_propertylist_set_comment (idp_plist, "NCOMBINE", "Number of raw science combined");
185 }
186 }
187 /* OBSTECH */
188 // Only create OBSTECH if it does not exist yet.
189 // This is needed for For gravity_viscal which starts from
190 // products and does not have a ESO DPR TECH anymore
191 if(cpl_propertylist_has(header, "ESO DPR TECH"))
192 {
193 cpl_propertylist_update_string (idp_plist, "OBSTECH",
194 cpl_propertylist_get_string(header, "ESO DPR TECH") );
195 cpl_propertylist_set_comment (idp_plist, "OBSTECH", "Observation technique");
196 }
197 else if(cpl_propertylist_has(header, "OBSTECH"))
198 {
199 cpl_propertylist_update_string (idp_plist, "OBSTECH",
200 cpl_propertylist_get_string(header, "OBSTECH") );
201 cpl_propertylist_set_comment (idp_plist, "OBSTECH", "Observation technique");
202 }
203
204 /* SPECSYS */
205 cpl_propertylist_update_string (idp_plist, "SPECSYS", "TOPOCENT");
206 cpl_propertylist_set_comment (idp_plist, "SPECSYS", "Frame of reference for spectral coordinates");
207
208 /* TIMESYS */
209 cpl_propertylist_update_string (idp_plist, "TIMESYS", "UTC");
210 cpl_propertylist_set_comment (idp_plist, "TIMESYS", "Time system");
211
212 /* SPEC_ERR */
213 /* According to https://jira.eso.org/browse/PIPE-9900 this
214 is hard-coded depending on resolution */
215 double spec_err = 0;
216 const char * resolution = gravi_pfits_get_resolution (header);
217 if ( !strcmp (resolution, "HIGH") )
218 spec_err = 0.28;
219 if ( !strcmp (resolution, "MED") )
220 spec_err = 2.2;
221 if ( !strcmp (resolution, "LOW") )
222 spec_err = 50;
223 cpl_propertylist_update_double (idp_plist, "SPEC_ERR", spec_err);
224 cpl_propertylist_set_comment (idp_plist, "SPEC_ERR", "Statistical error in spectral coordinate");
225
226 /* SPEC_SYE */
227 /* Hard-coded to the values in Sanchez-Bermudez et al. 2017 */
228 cpl_propertylist_update_double (idp_plist, "SPEC_SYE", 0.1);
229 cpl_propertylist_set_comment (idp_plist, "SPEC_SYE", "Systematic error in spectral coordinate");
230
231 /* PROV keywords */
232 if(frameset != NULL)
233 {
234 const cpl_frame *frame;
235 size_t i_prov = 1;
236 char prov_keyword[8];
237 cpl_frameset_iterator *it = cpl_frameset_iterator_new(frameset);
238 while ((frame = cpl_frameset_iterator_get(it)) != NULL) {
239 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_RAW)
240 {
241 snprintf(prov_keyword, 7, "PROV%zu",i_prov);
242 cpl_propertylist_update_string(idp_plist, prov_keyword, cpl_frame_get_filename(frame));
243 i_prov++;
244 }
245 cpl_frameset_iterator_advance(it, 1);
246 }
247 cpl_frameset_iterator_delete(it);
248 }
249
250 /* Delete scratch tables */
251 cpl_table_delete(oi_vis2_SC_allpol);
252 cpl_table_delete(oi_T3_SC_allpol);
253 cpl_table_delete(oi_wave_SC_allpol);
254
255 return idp_plist;
256}
257
typedefCPL_BEGIN_DECLS struct _gravi_data_ gravi_data
Definition: gravi_data.h:38
#define gravi_data_get_oi_t3(data, type, pol, npol)
Definition: gravi_data.h:47
#define gravi_data_get_oi_vis2(data, type, pol, npol)
Definition: gravi_data.h:46
#define gravi_data_get_oi_wave(data, type, pol, npol)
Definition: gravi_data.h:44
cpl_propertylist * gravi_idp_compute(gravi_data *vis_data, cpl_propertylist *header, cpl_frameset *frameset)
Create IDP keywords to satisfy standard.
Definition: gravi_idp.c:45
cpl_propertylist * header
Definition: gravi_old.c:2004
cpl_propertylist_update_double(header, "ESO QC MINWAVE SC", cpl_propertylist_get_double(plist, "ESO QC MINWAVE SC"))
#define GRAVI_OI_VIS2_EXT
Definition: gravi_pfits.h:95
#define GRAVI_SC
Definition: gravi_pfits.h:165
double gravi_table_get_column_flagged_mean(cpl_table *table, const char *name)
Function to compute the mean of a column table with arrays.
Definition: gravi_cpl.c:217
int gravi_data_has_extension(gravi_data *raw_calib, const char *ext_name)
Check if data has extension with given EXTNAME.
Definition: gravi_data.c:1808
cpl_frameset * gravi_frameset_extract_science_data(cpl_frameset *frameset)
Definition: gravi_dfs.c:1382
int gravi_pfits_get_pola_num(const cpl_propertylist *plist, int type_data)
Definition: gravi_pfits.c:263
double gravi_pfits_get_mjd(const cpl_propertylist *plist)
Definition: gravi_pfits.c:526
const char * gravi_pfits_get_resolution(const cpl_propertylist *plist)
Definition: gravi_pfits.c:155
cpl_error_code gravi_data_get_minmax_uvcoord(const cpl_table *oi_vis2, double *min_uvcoord, double *max_uvcoord)
Compute the minimum and maximum values of sqrt(ucoord**2 + vcoord**2)
Definition: gravi_vis.c:2510