HAWKI Pipeline Reference Manual  1.8.12
hawki_util_gendist.c
1 /* $Id: hawki_util_gendist.c,v 1.23 2013/03/11 11:03:00 cgarcia Exp $
2  *
3  * This file is part of the HAWKI 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: cgarcia $
23  * $Date: 2013/03/11 11:03:00 $
24  * $Revision: 1.23 $
25  * $Name: hawki-1_8_12 $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include <math.h>
37 #include <cpl.h>
38 
39 #include "irplib_utils.h"
40 
41 #include "hawki_utils.h"
42 #include "hawki_load.h"
43 #include "hawki_pfits.h"
44 #include "hawki_dfs.h"
45 #include "hawki_distortion.h"
46 #include "hawki_save.h"
47 
48 /*-----------------------------------------------------------------------------
49  Functions prototypes
50  -----------------------------------------------------------------------------*/
51 
52 #ifdef __cplusplus
53 extern "C"
54 #endif
55 int cpl_plugin_get_info(cpl_pluginlist * list);
56 
57 static int hawki_util_gendist_create(cpl_plugin *) ;
58 static int hawki_util_gendist_exec(cpl_plugin *) ;
59 static int hawki_util_gendist_destroy(cpl_plugin *) ;
60 static int hawki_util_gendist(cpl_parameterlist *, cpl_frameset *) ;
61 static cpl_table * hawki_util_gendist_convert(const char *) ;
62 static hawki_distortion * hawki_util_gendist_convert_to_images
63 (const cpl_table * dist_tab,
64  int detector_nx,
65  int detector_ny);
66 
67 /*-----------------------------------------------------------------------------
68  Static variables
69  -----------------------------------------------------------------------------*/
70 
71 static char hawki_util_gendist_description[] =
72 "hawki_util_gendist -- HAWK-I distortion calibration file creation.\n"
73 "The 4 files (chip 1 2 3 4) listed in the Set Of Frames (sof-file) \n"
74 "must be tagged:\n"
75 "raw-file_chip1.txt "HAWKI_UTIL_DISTMAP_RAW"\n"
76 "raw-file_chip2.txt "HAWKI_UTIL_DISTMAP_RAW"\n"
77 "raw-file_chip3.txt "HAWKI_UTIL_DISTMAP_RAW"\n"
78 "raw-file_chip4.txt "HAWKI_UTIL_DISTMAP_RAW"\n" ;
79 
80 /*-----------------------------------------------------------------------------
81  Functions code
82  -----------------------------------------------------------------------------*/
83 
84 /*----------------------------------------------------------------------------*/
92 /*----------------------------------------------------------------------------*/
93 int cpl_plugin_get_info(cpl_pluginlist * list)
94 {
95  cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
96  cpl_plugin * plugin = &recipe->interface ;
97 
98  cpl_plugin_init(plugin,
99  CPL_PLUGIN_API,
100  HAWKI_BINARY_VERSION,
101  CPL_PLUGIN_TYPE_RECIPE,
102  "hawki_util_gendist",
103  "Distortion map creation",
104  hawki_util_gendist_description,
105  "Yves Jung",
106  PACKAGE_BUGREPORT,
108  hawki_util_gendist_create,
109  hawki_util_gendist_exec,
110  hawki_util_gendist_destroy) ;
111 
112  cpl_pluginlist_append(list, plugin) ;
113 
114  return 0;
115 }
116 
117 /*----------------------------------------------------------------------------*/
126 /*----------------------------------------------------------------------------*/
127 static int hawki_util_gendist_create(cpl_plugin * plugin)
128 {
129  cpl_recipe * recipe ;
130  cpl_parameter * p ;
131 
132  /* Get the recipe out of the plugin */
133  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
134  recipe = (cpl_recipe *)plugin ;
135  else return -1 ;
136 
137  /* Create the parameters list in the cpl_recipe object */
138  recipe->parameters = cpl_parameterlist_new() ;
139  if (recipe->parameters == NULL)
140  return 1;
141 
142  /* Fill the parameters list */
143  /* --dim_x */
144  p = cpl_parameter_new_value("hawki.hawki_util_gendist.dim_x",
145  CPL_TYPE_INT, "Dimension of distortion image in X",
146  "hawki.hawki_util_gendist", HAWKI_DET_NPIX_X);
147  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dim_x");
148  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
149  cpl_parameterlist_append(recipe->parameters, p);
150 
151  /* --dim_y */
152  p = cpl_parameter_new_value("hawki.hawki_util_gendist.dim_y",
153  CPL_TYPE_INT, "Dimension of distortion image in Y",
154  "hawki.hawki_util_gendist", HAWKI_DET_NPIX_Y);
155  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dim_y");
156  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
157  cpl_parameterlist_append(recipe->parameters, p);
158 
159 
160  /* Return */
161  return 0;
162 }
163 
164 /*----------------------------------------------------------------------------*/
170 /*----------------------------------------------------------------------------*/
171 static int hawki_util_gendist_exec(cpl_plugin * plugin)
172 {
173  cpl_recipe * recipe ;
174 
175  /* Get the recipe out of the plugin */
176  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
177  recipe = (cpl_recipe *)plugin ;
178  else return -1 ;
179 
180  /* Issue a banner */
182 
183  return hawki_util_gendist(recipe->parameters, recipe->frames) ;
184 }
185 
186 /*----------------------------------------------------------------------------*/
192 /*----------------------------------------------------------------------------*/
193 static int hawki_util_gendist_destroy(cpl_plugin * plugin)
194 {
195  cpl_recipe * recipe ;
196 
197  /* Get the recipe out of the plugin */
198  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
199  recipe = (cpl_recipe *)plugin ;
200  else return -1 ;
201 
202  cpl_parameterlist_delete(recipe->parameters) ;
203  return 0 ;
204 }
205 
206 /*----------------------------------------------------------------------------*/
212 /*----------------------------------------------------------------------------*/
213 static int hawki_util_gendist
214 (cpl_parameterlist * parlist,
215  cpl_frameset * framelist)
216 {
217  cpl_frameset * rawframes;
218  const cpl_frame * cur_frame;
219  const char * dist_name;
220  cpl_table ** distortion_table;
221  hawki_distortion ** distortion_im;
222  cpl_propertylist * plist;
223  cpl_propertylist * plist_ext;
224  char sval[64];
225  const char * recipe_name = "hawki_util_gendist";
226  int iext;
227  int ichip;
228  cpl_parameter * par;
229  int dim_x;
230  int dim_y;
231 
232  /* Identify the RAW and CALIB frames in the input frameset */
233  if (hawki_dfs_set_groups(framelist)) {
234  cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
235  return -1 ;
236  }
237 
238  /* Retrieve raw frames */
239  if ((rawframes = hawki_extract_frameset(framelist,
240  HAWKI_UTIL_DISTMAP_RAW)) == NULL) {
241  cpl_msg_error(__func__, "Cannot find raw frames in the input list") ;
242  return -1 ;
243  }
244 
245  /* There should be HAWKI_NB_DETECTORS input frames ordered */
246  if (cpl_frameset_get_size(rawframes) != HAWKI_NB_DETECTORS) {
247  cpl_msg_error(__func__, "%d frames expected", HAWKI_NB_DETECTORS) ;
248  cpl_frameset_delete(rawframes) ;
249  return -1 ;
250  }
251 
252  /* Retrieve parameters */
253  par = cpl_parameterlist_find(parlist, "hawki.hawki_util_gendist.dim_x") ;
254  dim_x = cpl_parameter_get_int(par);
255  par = cpl_parameterlist_find(parlist, "hawki.hawki_util_gendist.dim_y") ;
256  dim_y = cpl_parameter_get_int(par);
257 
258  /* Allocate holder for the tables */
259  distortion_table = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_table*)) ;
260 
261  /* Loop on the chips */
262  for (ichip=0 ; ichip<HAWKI_NB_DETECTORS ; ichip++) {
263 
264  /* Get the file name */
265  cur_frame = cpl_frameset_get_frame_const(rawframes, ichip) ;
266  dist_name = cpl_frame_get_filename(cur_frame) ;
267 
268  /* Create the output table */
269  cpl_msg_info(__func__, "Create the output table for chip %d", ichip+1) ;
270  if ((distortion_table[ichip] = hawki_util_gendist_convert(dist_name)) == NULL) {
271  int j;
272  cpl_msg_error(__func__, "Cannot create the output table") ;
273  cpl_frameset_delete(rawframes) ;
274  for (j=0 ; j<ichip ; j++) cpl_table_delete(distortion_table[j]) ;
275  cpl_free(distortion_table) ;
276  return -1 ;
277  }
278  }
279 
280  /* Write the table */
281  plist = cpl_propertylist_new() ;
282  cpl_propertylist_append_string(plist, "INSTRUME", "HAWKI") ;
283  cpl_propertylist_append_string(plist, CPL_DFS_PRO_TYPE,
284  HAWKI_PROTYPE_DISTORTION) ;
285  cpl_propertylist_append_string(plist, CPL_DFS_PRO_CATG,
286  HAWKI_CALPRO_DISTORTION) ;
287 
288  plist_ext = cpl_propertylist_new() ;
289  cpl_propertylist_prepend_string(plist_ext, "EXTNAME", "CHIP1.INT1") ;
290  if (cpl_dfs_save_table(framelist, NULL, parlist, rawframes, NULL,
291  distortion_table[0], plist_ext, recipe_name,
292  plist, NULL, PACKAGE "/" PACKAGE_VERSION,
293  "hawki_util_gendist.fits") != CPL_ERROR_NONE) {
294  cpl_msg_error(__func__, "Cannot save the first extension table") ;
295  cpl_propertylist_delete(plist_ext) ;
296  cpl_propertylist_delete(plist) ;
297  for (iext=0 ; iext<HAWKI_NB_DETECTORS ; iext++)
298  cpl_table_delete(distortion_table[iext]) ;
299  cpl_free(distortion_table) ;
300  cpl_frameset_delete(rawframes) ;
301  return -1 ;
302  }
303  cpl_propertylist_delete(plist) ;
304  cpl_propertylist_delete(plist_ext) ;
305 
306  /* Save the extensions */
307  for (iext=1 ; iext<HAWKI_NB_DETECTORS; iext++)
308  {
309  ichip = iext;
310  //This is the actual layout of the chips in raw HAWK-I images.
311  if(iext == 2)
312  ichip = 3;
313  if(iext == 3)
314  ichip = 2;
315  plist_ext = cpl_propertylist_new() ;
316  sprintf(sval, "CHIP%d.INT1", ichip+1) ;
317  cpl_propertylist_prepend_string(plist_ext, "EXTNAME", sval) ;
318  cpl_table_save(distortion_table[ichip], NULL, plist_ext,
319  "hawki_util_gendist.fits", CPL_IO_EXTEND);
320  cpl_propertylist_delete(plist_ext) ;
321  }
322 
323  /* Allocate holder for the distortion images */
324  distortion_im = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(hawki_distortion*));
325 
326  /* Loop on the chips */
327  for (ichip=0 ; ichip<HAWKI_NB_DETECTORS ; ichip++)
328  {
329  /* Get the file name */
330  cur_frame = cpl_frameset_get_frame_const(rawframes, ichip) ;
331  dist_name = cpl_frame_get_filename(cur_frame) ;
332 
333  /* Create the output image */
334  cpl_msg_info(__func__, "Create the output images for extension %d", ichip+1) ;
335  if ((distortion_im[ichip] = hawki_util_gendist_convert_to_images
336  (distortion_table[ichip], dim_x, dim_y)) == NULL)
337  {
338  int j;
339  cpl_msg_error(__func__,"Cannot create the output distortion images");
340  cpl_frameset_delete(rawframes);
341  for (j=0 ;j < ichip; j++)
342  hawki_distortion_delete(distortion_im[j]);
343  cpl_free(distortion_im) ;
344  return -1 ;
345  }
346  }
347 
348  /* Write the distortion images */
349  plist = cpl_propertylist_new() ;
350  cpl_propertylist_append_string(plist, "INSTRUME", "HAWKI");
351  //This two keywords are needed by QC. I do not why..
352  cpl_propertylist_append_string(plist, "MJD-OBS", "55128.5000000");
353  cpl_propertylist_append_string(plist, "FOR_QC", "dummy.fits");
354  cpl_propertylist_append_string(plist, "ORIGFILE",
355  "hawki_util_gendist_distx.fits") ;
356  hawki_main_header_save(framelist, parlist, rawframes,
357  "hawki_util_gendist",
358  HAWKI_CALPRO_DISTORTION_X,
359  HAWKI_PROTYPE_DISTORTION_X,
360  plist, "hawki_util_gendist_distx.fits");
361  cpl_propertylist_erase(plist, "ORIGFILE");
362  cpl_propertylist_append_string(plist, "ORIGFILE",
363  "hawki_util_gendist_distx.fits") ;
364  hawki_main_header_save(framelist, parlist, rawframes,
365  "hawki_util_gendist",
366  HAWKI_CALPRO_DISTORTION_Y,
367  HAWKI_PROTYPE_DISTORTION_Y,
368  plist, "hawki_util_gendist_disty.fits");
369  cpl_propertylist_delete(plist) ;
370 
371  /* Save the extensions */
372  //There is kind of a hack here
373  //We use the distortion table as a reference to save the distortion images
374  //to have a proper layout of the detectors in the FITS file.
375  //For that hawki_get_extref_file has been modified.
376  for (iext=0 ; iext<HAWKI_NB_DETECTORS; iext++) {
377  ichip = iext;
378  //This is the actual layout of the chips in raw HAWK-I images.
379  if(iext == 2)
380  ichip = 3;
381  if(iext == 3)
382  ichip = 2;
383  plist_ext = cpl_propertylist_new() ;
384  cpl_propertylist_append_double(plist_ext, "CRVAL1",
385  distortion_im[ichip]->x_crval);
386  cpl_propertylist_append_double(plist_ext, "CRVAL2",
387  distortion_im[ichip]->y_crval);
388  cpl_propertylist_append_double(plist_ext, "CDELT1",
389  distortion_im[ichip]->x_cdelt);
390  cpl_propertylist_append_double(plist_ext, "CDELT2",
391  distortion_im[ichip]->y_cdelt);
392  cpl_propertylist_append_double(plist_ext, "CRPIX1", 1);
393  cpl_propertylist_append_double(plist_ext, "CRPIX2", 1);
394  cpl_propertylist_append_string(plist_ext, "CTYPE1", "");
395  cpl_propertylist_append_string(plist_ext, "CTYPE2", "");
396  cpl_propertylist_append_string(plist_ext, "CUNIT1", "");
397  cpl_propertylist_append_string(plist_ext, "CUNIT2", "");
398  hawki_image_ext_save(framelist, distortion_im[ichip]->dist_x, iext + 1,
399  plist_ext, "hawki_util_gendist_distx.fits");
400  hawki_image_ext_save(framelist, distortion_im[ichip]->dist_y, iext + 1,
401  plist_ext, "hawki_util_gendist_disty.fits");
402  cpl_propertylist_delete(plist_ext);
403  }
404 
405  for (iext=0 ; iext<HAWKI_NB_DETECTORS ; iext++)
406  cpl_table_delete(distortion_table[iext]);
407  cpl_free(distortion_table) ;
408 
409  for (iext=0 ; iext<HAWKI_NB_DETECTORS ; iext++)
410  hawki_distortion_delete(distortion_im[iext]);
411  cpl_free(distortion_im) ;
412  cpl_frameset_delete(rawframes) ;
413 
414 
415  /* Return */
416  if (cpl_error_get_code())
417  {
418  cpl_msg_error(__func__,
419  "HAWK-I pipeline could not recover from previous errors");
420  return -1 ;
421  }
422  else return 0 ;
423 }
424 
425 /*----------------------------------------------------------------------------*/
450 /*----------------------------------------------------------------------------*/
451 static cpl_table * hawki_util_gendist_convert(const char * filename)
452 {
453  cpl_table * out ;
454  int nbentries ;
455  FILE * in ;
456  double dxgc, dygc ;
457  int i, j ;
458  char line[1024];
459 
460  /* Check entries */
461  if (filename == NULL) return NULL ;
462 
463  /* Get the number of lines */
464  nbentries = 0 ;
465  if ((in = fopen(filename, "r")) == NULL) {
466  return NULL ;
467  }
468  while (fgets(line, 1024, in) != NULL) {
469  if (line[0] != '#') nbentries ++ ;
470  }
471  fclose(in) ;
472 
473  /* Create the table */
474  out = cpl_table_new(nbentries);
475  cpl_table_new_column(out, HAWKI_COL_DIST_DXGC, CPL_TYPE_DOUBLE);
476  cpl_table_set_column_unit(out, HAWKI_COL_DIST_DXGC, "pixels");
477  cpl_table_new_column(out, HAWKI_COL_DIST_DYGC, CPL_TYPE_DOUBLE);
478  cpl_table_set_column_unit(out, HAWKI_COL_DIST_DYGC, "pixels");
479  cpl_table_new_column(out, HAWKI_COL_DIST_I, CPL_TYPE_INT);
480  cpl_table_set_column_unit(out, HAWKI_COL_DIST_I, "pixels");
481  cpl_table_new_column(out, HAWKI_COL_DIST_J, CPL_TYPE_INT);
482  cpl_table_set_column_unit(out, HAWKI_COL_DIST_J, "pixels");
483 
484  /* Parse the file */
485  if ((in = fopen(filename, "r")) == NULL) {
486  cpl_table_delete(out) ;
487  return NULL ;
488  }
489  nbentries = 0 ;
490  while (fgets(line, 1024, in) != NULL) {
491  if (line[0] != '#') {
492  if (sscanf(line, "%lg %lg %d %d",
493  &dxgc, &dygc, &i, &j) != 4) {
494  cpl_msg_error(__func__, "Bad line %d", nbentries+1) ;
495  cpl_table_delete(out) ;
496  return NULL ;
497  }
498  cpl_table_set_double(out, HAWKI_COL_DIST_DXGC, nbentries, dxgc);
499  cpl_table_set_double(out, HAWKI_COL_DIST_DYGC, nbentries, dygc);
500  cpl_table_set_int(out, HAWKI_COL_DIST_I, nbentries, i);
501  cpl_table_set_int(out, HAWKI_COL_DIST_J, nbentries, j);
502  nbentries ++ ;
503  }
504  }
505  fclose(in) ;
506 
507  return out ;
508 }
509 
510 /*----------------------------------------------------------------------------*/
528 /*----------------------------------------------------------------------------*/
529 static hawki_distortion * hawki_util_gendist_convert_to_images
530 (const cpl_table * dist_tab,
531  int detector_nx,
532  int detector_ny)
533 {
534  hawki_distortion * out ;
535  int nbentries ;
536  int ngrid;
537  const int * i_ptr;
538  const int * j_ptr;
539  cpl_array * i_vec;
540  cpl_array * j_vec;
541  int irow;
542 
543 
544  /* Check entries */
545  if (dist_tab == NULL) return NULL ;
546 
547  /* Create the table */
548  nbentries = cpl_table_get_nrow(dist_tab);
549  ngrid = sqrt(nbentries);
550  if(ngrid * ngrid != nbentries)
551  {
552  cpl_msg_error(__func__,"Only square grids are supported");
553  return NULL;
554  }
555  out = hawki_distortion_grid_new(detector_nx, detector_ny, ngrid);
556 
557  /* Get the crval, cdelt */
558  i_ptr = cpl_table_get_data_int_const(dist_tab, HAWKI_COL_DIST_I);
559  i_vec = cpl_array_wrap_int((int *)i_ptr, nbentries);
560  out->x_crval = cpl_array_get_min(i_vec);
561  out->x_cdelt = (cpl_array_get_max(i_vec) - cpl_array_get_min(i_vec)) /
562  (ngrid - 1);
563  cpl_array_unwrap(i_vec);
564  j_ptr = cpl_table_get_data_int_const(dist_tab, HAWKI_COL_DIST_J);
565  j_vec = cpl_array_wrap_int((int *)j_ptr, nbentries);
566  out->y_crval = cpl_array_get_min(j_vec);
567  out->y_cdelt = (cpl_array_get_max(j_vec) - cpl_array_get_min(j_vec)) /
568  (ngrid - 1);
569  cpl_array_unwrap(j_vec);
570 
571 
572  /* Fill the image */
573  for(irow = 0; irow < nbentries; ++irow)
574  {
575  double i_ima;
576  double j_ima;
577  double dx;
578  double dy;
579  int null;
580 
581  i_ima = (cpl_table_get_int(dist_tab, HAWKI_COL_DIST_I, irow, &null) -
582  out->x_crval) / out->x_cdelt;
583  if(floor(i_ima) != i_ima)
584  {
585  cpl_msg_error(__func__, " The distortion tables must be defined "
586  "in a regular grid");
588  return NULL;
589  }
590  j_ima = (cpl_table_get_int(dist_tab, HAWKI_COL_DIST_J, irow, &null) -
591  out->y_crval) / out->y_cdelt;
592  if(floor(j_ima) != j_ima)
593  {
594  cpl_msg_error(__func__, " The distortion tables must be defined "
595  "in a regular grid");
597  return NULL;
598  }
599  dx = cpl_table_get_double(dist_tab, HAWKI_COL_DIST_DXGC, irow, &null);
600  dy = cpl_table_get_double(dist_tab, HAWKI_COL_DIST_DYGC, irow, &null);
601 
602  cpl_image_set(out->dist_x, (int)i_ima + 1, (int)j_ima + 1, dx);
603  cpl_image_set(out->dist_y, (int)i_ima + 1, (int)j_ima + 1, dy);
604  }
605 
606  return out ;
607 }