VISIR Pipeline Reference Manual  4.1.7
visir_img_focfwhm.c
1 /* $Id: visir_img_focfwhm.c,v 1.78 2009-02-27 10:37:28 llundin Exp $
2  *
3  * This file is part of the VISIR Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: llundin $
23  * $Date: 2009-02-27 10:37:28 $
24  * $Revision: 1.78 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 
33 
34 /*-----------------------------------------------------------------------------
35  Includes
36  -----------------------------------------------------------------------------*/
37 
38 #include "visir_recipe.h"
39 
40 /*-----------------------------------------------------------------------------
41  Defines
42  -----------------------------------------------------------------------------*/
43 
44 #define RECIPE_STRING "visir_img_focfwhm"
45 
46 /*-----------------------------------------------------------------------------
47  Private Functions prototypes
48  -----------------------------------------------------------------------------*/
49 static cpl_table * visir_img_focfwhm_detect(const cpl_imagelist *,
50  const irplib_framelist *);
51 static double visir_img_focfwhm_best_focus(const cpl_table *);
52 static cpl_error_code visir_img_focfwhm_save(cpl_frameset *,
53  const cpl_parameterlist *,
54  const cpl_table *);
55 
56 VISIR_RECIPE_DEFINE(visir_img_focfwhm,
57  VISIR_PARAM_NODPOS | VISIR_PARAM_AUTOBPM |
58  VISIR_PARAM_STRIPITE | VISIR_PARAM_STRIPMOR |
59  VISIR_PARAM_STRIPNON |
60  VISIR_PARAM_GLITCH | VISIR_PARAM_PURGE,
61  "Focus recipe",
62  "This recipe finds out what is the best focus of the "
63  "telescope\n"
64  "by analysing the evolution of the FWHM for different "
65  "focii.\n"
66  "The files listed in the Set Of Frames (sof-file) must be "
67  "tagged:\n"
68  "VISIR-focus-file.fits " VISIR_IMG_FOCFWHM_RAW "\n"
69  MAN_VISIR_CALIB_BPM_IMG);
70 
71 /*----------------------------------------------------------------------------*/
75 /*----------------------------------------------------------------------------*/
76 
77 /*-----------------------------------------------------------------------------
78  Functions code
79  -----------------------------------------------------------------------------*/
80 
81 /*----------------------------------------------------------------------------*/
88 /*----------------------------------------------------------------------------*/
89 static int visir_img_focfwhm(cpl_frameset * framelist,
90  const cpl_parameterlist * parlist)
91 {
92  irplib_framelist * allframes = NULL;
93  irplib_framelist * rawframes = NULL;
94  const char * badpix;
95  const char * flat;
96  cpl_imagelist * nodded = NULL;
97  cpl_table * tab = NULL;
98  double focus;
99 
100 
101  /* Identify the RAW and CALIB frames in the input frameset */
102  skip_if (visir_dfs_set_groups(framelist));
103 
104  /* Objects observation */
105  allframes = irplib_framelist_cast(framelist);
106  skip_if(allframes == NULL);
107  rawframes = irplib_framelist_extract(allframes, VISIR_IMG_FOCFWHM_RAW);
108  skip_if (rawframes == NULL);
109 
110  skip_if(irplib_framelist_load_propertylist_all(rawframes, 0,
111  visir_property_regexp,
112  CPL_FALSE));
113 
114  skip_if(visir_dfs_check_framelist_tag(rawframes));
115 
116  /* Bad pixels calibration file */
117  badpix = irplib_frameset_find_file(framelist, VISIR_CALIB_BPM);
118 
119  /* Flatfield calibration file */
120  flat = irplib_frameset_find_file(framelist, VISIR_CALIB_FLAT);
121 
122  /* Combine the frames */
123  cpl_msg_info(cpl_func, "Construct the nodded images");
124  nodded = visir_inputs_combine(RECIPE_STRING, parlist, rawframes, badpix, flat,
125  NULL, CPL_FALSE, 0,0);
126  if (nodded == NULL) {
127  cpl_msg_error(cpl_func, "Cannot combine the input frames");
128  skip_if(1);
129  }
130 
131  /* Get apertures positions - FWHMs - FOCUS in a table */
132  cpl_msg_info(cpl_func, "Get positions/FWHMs/FOCUSs");
133  if ((tab = visir_img_focfwhm_detect(nodded, rawframes)) == NULL) {
134  cpl_msg_error(cpl_func, "Cannot detect apertures");
135  skip_if(1);
136  }
137  /* Compute the best FOCUS */
138  cpl_msg_info(cpl_func, "Compute the best focus");
139  focus = visir_img_focfwhm_best_focus(tab);
140  if (focus < 0) {
141  cpl_msg_error(cpl_func, "Cannot compute the best focus(%g): '%s' in %s",
142  focus, cpl_error_get_message(),
143  cpl_error_get_where());
144  skip_if(1);
145  }
146  /* Save the combined image */
147  cpl_msg_info(cpl_func, "Save the produced combined image");
148  skip_if (visir_img_focfwhm_save(framelist, parlist, tab));
149 
150  end_skip;
151 
152  irplib_framelist_delete(allframes);
153  irplib_framelist_delete(rawframes);
154  cpl_imagelist_delete(nodded);
155  cpl_table_delete(tab);
156 
157  return cpl_error_get_code();
158 }
159 
160 /*----------------------------------------------------------------------------*/
172 /*----------------------------------------------------------------------------*/
173 static cpl_table * visir_img_focfwhm_detect(const cpl_imagelist * nodded,
174  const irplib_framelist * rawframes)
175 {
176  cpl_table * tab = NULL;
177  const int nfiles = cpl_imagelist_get_size(nodded);
178  int i;
179 
180 
181  /* Catch also empty imagelist */
182  skip_if (0);
183  skip_if (rawframes == NULL);
184 
185  /* Allocate and initialise arrays */
186  tab = visir_table_new_xypos(nodded, "FWHM");
187  skip_if (tab == NULL);
188 
189  skip_if (cpl_table_new_column(tab, "FOCUS", CPL_TYPE_DOUBLE));
190 
191  /* Get infos on nodded images */
192  for (i=0; i < nfiles ; i++) {
193  const cpl_propertylist * plist
194  = irplib_framelist_get_propertylist_const(rawframes, 2*i);
195 
196  /* Get the FOCUS from the header */
197  skip_if(cpl_table_set_double(tab, "FOCUS", i,
198  visir_pfits_get_focus(plist)));
199 
200  }
201 
202  end_skip;
203 
204  if (cpl_error_get_code()) {
205  cpl_table_delete(tab);
206  tab = NULL;
207  }
208 
209  return tab;
210 }
211 
212 /*----------------------------------------------------------------------------*/
221 /*----------------------------------------------------------------------------*/
222 static double visir_img_focfwhm_best_focus(const cpl_table * tab)
223 {
224  const int nrow = cpl_table_get_nrow(tab);
225  int ngood = 0;
226  cpl_vector * x_to_fit;
227  cpl_vector * y_to_fit;
228  cpl_polynomial * pol;
229  double fwhm_x, fwhm_y, focus;
230  double b, c;
231  double mse = -1;
232  int i;
233 
234 
235  /* This will catch tab == NULL */
236  cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
237 
238  /* Count the number of valid FWHMs values */
239  for (i=0 ; i < nrow ; i++)
240  if (cpl_table_get_double(tab, "X_FWHM", i, NULL) > 0 &&
241  cpl_table_get_double(tab, "Y_FWHM", i, NULL) > 0)
242  ngood++;
243 
244  assert(!cpl_error_get_code());
245 
246  /* Need at least three data-points to fit a 2nd degree polynomial */
247  cpl_ensure(ngood >= 3, CPL_ERROR_DATA_NOT_FOUND, -2);
248 
249  /* Create the vectors for the fitting */
250  x_to_fit = cpl_vector_new(ngood);
251  y_to_fit = cpl_vector_new(ngood);
252  ngood = 0;
253  for (i=0 ; i < nrow ; i++) {
254  fwhm_x = cpl_table_get_double(tab, "X_FWHM", i, NULL);
255  if (fwhm_x <= 0) continue;
256 
257  fwhm_y = cpl_table_get_double(tab, "Y_FWHM", i, NULL);
258  if (fwhm_y <= 0) continue;
259 
260  focus = cpl_table_get_double(tab, "FOCUS", i, NULL);
261 
262  cpl_vector_set(x_to_fit, ngood, focus);
263  cpl_vector_set(y_to_fit, ngood, (fwhm_x+fwhm_y)*0.5);
264  ngood++;
265  }
266 
267  assert( ngood == cpl_vector_get_size(x_to_fit) );
268 
269  /* Apply the fit */
270  pol = cpl_polynomial_fit_1d_create(x_to_fit, y_to_fit, 2, &mse);
271 
272  cpl_msg_info(cpl_func, "Mean Squared Error(%d): %g", ngood, mse);
273 
274  cpl_vector_delete(x_to_fit);
275  cpl_vector_delete(y_to_fit);
276 
277  cpl_ensure(pol != NULL, cpl_error_get_code(), -3);
278 
279  /* Get the focus for which the FWHM is minimal */
280  /* fwhm(foc) = a + b*foc + c*foc*foc */
281  /* Verify that b>=0 and c<0 */
282  i = 1;
283  b = cpl_polynomial_get_coeff(pol, &i);
284  i = 2;
285  c = cpl_polynomial_get_coeff(pol, &i);
286  cpl_polynomial_delete(pol);
287 
288  cpl_ensure(b >= 0.0, CPL_ERROR_DATA_NOT_FOUND, -4);
289 
290  cpl_ensure(b < -2.0 * c * FLT_MAX, CPL_ERROR_DIVISION_BY_ZERO, -5);
291 
292  cpl_msg_info(cpl_func, "Optimal focus (%g:%g): %g ", b, c , b/(-2.0*c));
293 
294  /* Return the focus where fwhm has its minimum */
295  return b/(-2.0*c);
296 }
297 
298 /*----------------------------------------------------------------------------*/
306 /*----------------------------------------------------------------------------*/
307 static cpl_error_code visir_img_focfwhm_save(cpl_frameset * set,
308  const cpl_parameterlist * parlist,
309  const cpl_table * tab)
310 {
311 
312  skip_if(irplib_dfs_save_table(set, parlist, set, tab, NULL, RECIPE_STRING,
313  VISIR_IMG_FOCFWHM_TAB_PROCATG, NULL, NULL,
314  visir_pipe_id, RECIPE_STRING CPL_DFS_FITS));
315  end_skip;
316 
317  return cpl_error_get_code();
318 }
cpl_error_code visir_dfs_check_framelist_tag(const irplib_framelist *self)
Check the tags in a frameset (group raw only)
Definition: visir_dfs.c:218
cpl_error_code irplib_dfs_save_table(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_table *table, const cpl_propertylist *tablelist, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save a table as a DFS-compliant pipeline product.
Definition: irplib_utils.c:335
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
double visir_pfits_get_focus(const cpl_propertylist *self)
The focus.
Definition: visir_pfits.c:394
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
cpl_imagelist * visir_inputs_combine(const char *recipename, const cpl_parameterlist *parlist, const irplib_framelist *rawframes, const char *badpix, const char *flat, int *nodding_p, cpl_boolean do_spc_fix, double wlen, visir_spc_resol resol)
The VISIR input data re-combination is performed here.
Definition: visir_inputs.c:728
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
int visir_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: visir_dfs.c:72
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
const char * irplib_frameset_find_file(const cpl_frameset *self, const char *tag)
Find the filename with the given tag in a frame set.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.