SINFONI Pipeline Reference Manual  2.6.0
sinfo_new_lamp_flats.c
1 /*
2  * This file is part of the ESO SINFONI Pipeline
3  * Copyright (C) 2004,2005 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, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18  */
19 /*----------------------------------------------------------------------------
20 
21  File name : sinfo_new_lamp_flats.c
22  Author : A. Modigliani
23  Created on : Sep 29, 2003
24  Description :
25 
26  * this step handles stacks of lamp flat fields,
27  * o it takes a clean mean,
28  * o subtracts the off- from the on-frames,
29  * o corrects for static bad pixels and normalizes for a master flat field.
30  * o It distinguishes the spectrally dithered frames and
31  * o treats them the same way.
32  * o It can also generate a static bad pixel mask if wished.
33 
34 
35  ---------------------------------------------------------------------------*/
36 
37 #ifdef HAVE_CONFIG_H
38 # include <config.h>
39 #endif
40 
41 /*----------------------------------------------------------------------------
42  Includes
43  ---------------------------------------------------------------------------*/
44 #include "sinfo_new_lamp_flats.h"
45 #include "sinfo_flat_ini_by_cpl.h"
46 #include "sinfo_pro_save.h"
47 #include "sinfo_pro_types.h"
48 #include "sinfo_functions.h"
49 #include "sinfo_new_cube_ops.h"
50 #include "sinfo_error.h"
51 #include "sinfo_utils_wrappers.h"
52 #include "sinfo_image_ops.h"
53 #include "sinfo_utilities.h"
54 #include "sinfo_globals.h"
55 /*----------------------------------------------------------------------------
56  Defines
57  ---------------------------------------------------------------------------*/
58 
59 static int
60 new_qc_get_cnt(cpl_frameset* on_set, cpl_frameset* of_set, flat_config* cfg);
61 static int
62 new_lamp_flats_det_ncounts(cpl_frameset* raw, flat_config* config);
63 
64 static struct {
65 
66  double avg_on;
67  double std_on;
68  double avg_of;
69  double std_of;
70  double avg_di;
71  double std_di;
72  double nsat_on;
73  double noise_on;
74  double noise_of;
75  double flux_on;
76  double nsat;
77 
78 } qc_lampflat;
79 
80 /*----------------------------------------------------------------------------
81  Function Definitions
82  ---------------------------------------------------------------------------*/
90 /*----------------------------------------------------------------------------
91  @name sinfo_new_lamp_flats()
92  @param plugin_id recipe id
93  @param config input parameterlist
94  @param sof input set of frames
95  @return integer (0 if it worked, -1 if it doesn't)
96  @doc
97 
98  * this step handles stacks of lamp flat fields,
99  * o it takes a clean mean,
100  * o subtracts the off- from the on-frames,
101  * o corrects for static bad pixels and normalizes for a master flat field.
102  * o It distinguishes the spectrally dithered frames and
103  * o treats them the same way.
104  * o It can also generate a static bad pixel mask if wished.
105 
106 
107  ---------------------------------------------------------------------------*/
108 
109 
110 
111 
112 int
113 sinfo_new_lamp_flats (const char* plugin_id,
114  cpl_parameterlist* config,
115  cpl_frameset* sof,
116  cpl_frameset* ref_set)
117 {
118  flat_config * cfg =NULL;
119  cpl_imagelist* list_object=NULL;
120  cpl_imagelist* list_dither_object=NULL ;
121  cpl_imagelist* list_sky=NULL ;
122  cpl_imagelist* list_dither_sky=NULL;
123  cpl_image ** im=NULL ;
124  cpl_image * norm_dith =NULL;
125  cpl_image * im_obj =NULL;
126  cpl_image * int_im =NULL;
127  cpl_image * int_im_dith =NULL;
128  cpl_image * im_sky =NULL;
129  cpl_image * im_dither =NULL;
130  cpl_image * im_obj_sub =NULL;
131  cpl_image * im_dither_sub =NULL;
132  cpl_image * im_dither_sky =NULL;
133  cpl_image ** imMed=NULL ;
134  cpl_image * colImage =NULL;
135  cpl_image * mask_im =NULL;
136  cpl_image * norm =NULL;
137  cpl_image * compImage =NULL;
138  cpl_image * maskImage =NULL;
139  cpl_image * threshIm =NULL;
140 
141  char name[MAX_NAME_SIZE];
142 
143  int typ;
144  Stats * stats =NULL;
145  int i = 0;
146  int* n=NULL;
147  int nob =0;
148  int nsky = 0;
149  int nobjdith = 0;
150  int nskydith = 0;
151  int n_badpixels =0;
152  int pos =0;
153 
154  float** slit_edges=NULL;
155  float local_clean_mean =0.;
156  float clean_stdev =0.;
157  float mean_factor =0.;
158  float val_x=0;
159  float val_y=0;
160 
161  char outNameDither[MAX_NAME_SIZE];
162  char name_list[MAX_NAME_SIZE];
163  char tbl_slitpos_name[MAX_NAME_SIZE];
164 
165  cpl_table* tbl_slitpos=NULL;
166  int* status=NULL;
167 
168  int n_im_med=0;
169  cpl_frameset* raw=NULL;
170 
171  cpl_table* qclog_tbl=NULL;
172  int naxis1=0;
173  int naxis2=0;
174  double fpn_stdev1=0;
175  double fpn_stdev2=0;
176 
177  int no=0;
178  float lo_cut=0;
179  float hi_cut=0;
180 
181  /*
182  -----------------------------------------------------------------
183  1) parse the file names and parameters to the tilt_config data
184  structure cfg
185  -----------------------------------------------------------------
186  */
187 
188  cknull_nomsg(raw=cpl_frameset_new());
189 
190  cknull(cfg = sinfo_parse_cpl_input_flat(config,sof,&raw),
191  "could not parse cpl input!");
192 
193  if (cfg->interpolInd == 1) {
194  if(sinfo_is_fits_file(cfg->mask) != 1) {
195  sinfo_msg_error("Input file %s is not FITS",cfg->mask);
196  goto cleanup;
197  }
198  if (sinfo_is_fits_file(cfg->slitposList) != 1) {
199  sinfo_msg_error("Input file %s is not FITS",cfg->slitposList);
200  goto cleanup;
201  }
202  }
203 
204  /*
205  #---------------------------------------------------------
206  # Take a clean mean of several images
207  # input is 1 or more similar images
208  #---------------------------------------------------------
209  */
210  sinfo_msg("Takes clean mean of several images");
211  /* #allocate memory for lists of object, sky and dithered frames--*/
212  cknull(list_object = cpl_imagelist_new (),"could not allocate memory");
213 
214  if (cfg->contains_dither == 1) {
215  cknull(list_dither_object=cpl_imagelist_new(),"could not allocate memory");
216  }
217 
218  if (cfg->contains_sky == 1) {
219  cknull(list_sky=cpl_imagelist_new(),"could not allocate memory");
220  }
221 
222  if (cfg->contains_dither == 1 && cfg->nditheroff > 0) {
223  cknull(list_dither_sky=cpl_imagelist_new(),"could not allocate memory");
224  }
225 
226  if (cfg->contains_dither == 0 && cfg->nditheroff > 0){
227  sinfo_msg_error("please use non-dithered off-frames, remove the 2!");
228  goto cleanup;
229  }
230 
231 
232  /* problem with im as image holder: cleanup then does not work */
233  im = (cpl_image**) cpl_calloc (cfg -> nframes, sizeof(cpl_image*));
234 
235  for (i=0; i< cfg->nframes; i++) {
236  strcpy(name,cfg->framelist[i]);
237  if(sinfo_is_fits_file(name) != 1) {
238  sinfo_msg_error("PP Input file %s %d is not FITS",name,i);
239  goto cleanup;
240  }
241  im[i]=cpl_image_load(name,CPL_TYPE_FLOAT,0,0);
242 
243  }
244 
245  for (i=0; i< cfg->nframes; i++) {
246  typ = cfg->frametype[i];
247  pos = cfg->frameposition[i];
248  cknull(im[i],"could not load image %d",i);
249  if (pos == 2) {
250  if (typ == 1) {
251  cpl_imagelist_set( list_object, cpl_image_duplicate(im[i]), nob );
252  nob = nob + 1;
253  } else {
254  cpl_imagelist_set( list_sky, cpl_image_duplicate(im[i]), nsky );
255  nsky = nsky + 1 ;
256  }
257  } else {
258  if (typ == 1) {
259  cpl_imagelist_set(list_dither_object,
260  cpl_image_duplicate(im[i]), nobjdith );
261  nobjdith = nobjdith + 1;
262  } else {
263  cpl_imagelist_set( list_dither_sky,
264  cpl_image_duplicate(im[i]), nskydith );
265  nskydith = nskydith + 1 ;
266  }
267  }
268  }
269 
270 
271  if (nob != cfg->nobj || cfg->noff != nsky ||
272  nobjdith != cfg->nditherobj || nskydith != cfg->nditheroff) {
273  sinfo_msg_error("something is wrong with the number of "
274  "the different types of frames");
275  goto cleanup;
276  }
277 
278  /* # create and fill cubes with the different image lists- */
279  sinfo_msg("Creates and fills cubes with the different image lists");
280  cknull(list_object,"could not create data cube!");
281 
282  if (cfg->contains_dither == 1) {
283  cknull(list_dither_object,"could not create data cube!");
284  }
285  if (cfg->contains_sky == 1 && nsky > 0) {
286  cknull(list_sky,"could not create data cube!");
287  }
288 
289  if (cfg->contains_dither == 1 && nskydith > 0) {
290  cknull(list_dither_sky,"could not create data cube!");
291  }
292 
293 
294  /*-take the average of the different cubes -*/
295  sinfo_msg("Takes the average of the different cubes");
296  if (cfg->loReject*cfg->nobj < 1. && cfg->hiReject *cfg->nobj < 1.) {
297  cknull(im_obj = sinfo_new_average_cube_to_image(list_object ),
298  "sinfo_averageCubeToImage failed" );
299  } else {
300 
301  no=cpl_imagelist_get_size(list_object);
302  lo_cut=(floor)(cfg->loReject*no+0.5);
303  hi_cut=(floor)(cfg->hiReject*no+0.5);
304  cknull(im_obj=cpl_imagelist_collapse_minmax_create(list_object,
305  lo_cut,
306  hi_cut),
307  "sinfo_average_with_rejection failed" );
308  }
309  sinfo_free_imagelist(&list_object);
310 
311  if (cfg->contains_sky == 1) {
312  if (cfg->loReject * nsky < 1. && cfg->hiReject * nsky < 1.) {
313  cknull(im_sky = sinfo_new_average_cube_to_image(list_sky ),
314  "sinfo_new_average_cube_to_image failed" );
315  } else {
316 
317  no=cpl_imagelist_get_size(list_sky);
318  lo_cut=(floor)(cfg->loReject*no+0.5);
319  hi_cut=(floor)(cfg->hiReject*no+0.5);
320  cknull(im_sky=cpl_imagelist_collapse_minmax_create(list_sky,lo_cut,hi_cut),
321  "sinfo_average_with_rejection failed" );
322  }
323  sinfo_free_imagelist(&list_sky);
324  }
325 
326  if (cfg->contains_dither == 1) {
327  if (cfg->loReject*nobjdith < 1. && cfg->hiReject * nobjdith < 1.) {
328  cknull(im_dither = sinfo_new_average_cube_to_image(list_dither_object ),
329  "sinfo_new_average_cube_to_image failed" );
330  } else {
331 
332 
333  no=cpl_imagelist_get_size(list_dither_object);
334  lo_cut=(floor)(cfg->loReject*no+0.5);
335  hi_cut=(floor)(cfg->hiReject*no+0.5);
336  cknull(im_dither=cpl_imagelist_collapse_minmax_create(list_dither_object,
337  lo_cut,hi_cut),
338  "sinfo_average_with_rejection failed" );
339  }
340  sinfo_free_imagelist(&list_dither_object);
341  }
342 
343  if (cfg->contains_dither == 1 && nskydith > 0 ) {
344  if (cfg->loReject*nskydith < 1. && cfg->hiReject*nskydith < 1.) {
345  cknull(im_dither_sky = sinfo_new_average_cube_to_image(list_dither_sky ),
346  "sinfo_new_average_cube_to_image failed" );
347  } else {
348  no=cpl_imagelist_get_size(list_dither_sky);
349  lo_cut=(floor)(cfg->loReject*no+0.5);
350  hi_cut=(floor)(cfg->hiReject*no+0.5);
351  cknull(im_dither_sky=cpl_imagelist_collapse_minmax_create(list_dither_sky,
352  lo_cut,hi_cut),
353  "new_average_with_rejection failed" );
354  }
355  sinfo_free_imagelist(&list_dither_sky);
356  }
357 
358  /*
359  #---------------------------------------------------------
360  # Subtract the resulting off-frame (sky) from the on-frame
361  #-------------------------------------------------------
362  #finally, subtract off from on frames and store the result in the
363  # object cube----------------
364  */
365 
366  sinfo_msg("Subtracts the resulting off-frame (sky) from the on-frame");
367  if (cfg->contains_sky == 1) {
368  cknull(im_obj_sub = cpl_image_subtract_create(im_obj, im_sky),
369  "could not sinfo_sub_image");
370  sinfo_free_image(&im_obj);
371  if (((cfg->contains_dither == 1) && (nskydith > 0)) ||
372  (cfg->contains_dither == 0)) {
373  sinfo_free_image(&im_sky);
374  }
375  im_obj = im_obj_sub;
376  }
377 
378  if (cfg->contains_dither == 1 && nskydith > 0) {
379  cknull(im_dither_sub=cpl_image_subtract_create(im_dither, im_dither_sky),
380  "could not sinfo_sub_image");
381  sinfo_free_image(&im_dither);
382  sinfo_free_image(&im_dither_sky);
383  im_dither = im_dither_sub;
384  } else if (cfg->contains_dither == 1 &&
385  nskydith == 0 &&
386  cfg->contains_sky == 1) {
387  cknull(im_dither_sub = cpl_image_subtract_create(im_dither, im_sky),
388  "could not sinfo_sub_image");
389  sinfo_free_image(&im_dither);
390  sinfo_free_image(&im_sky);
391  im_dither = im_dither_sub;
392  }
393  /*
394  #---------------------------------------------------------
395  # Generating a static bad pixel mask:
396  # remove the intensity tilt from every column
397  # and compute the standard deviation on a rectangular zone
398  #---------------------------------------------------------
399  */
400 
401  sinfo_msg("Generating a static bad pixel mask");
402  n_im_med = cfg->iterations+1;
403 
404  imMed=(cpl_image**) cpl_calloc(n_im_med, sizeof(cpl_image*));
405 
406  if (cfg->badInd == 1) {
407  sinfo_msg("removes the intensity tilt from every column and");
408  sinfo_msg("computes the standard deviation on a rectangular zone");
409 
410  /* this call originates 36 bytes leaks */
411  cknull(colImage = sinfo_new_col_tilt( im_obj, cfg->sigmaFactor ),
412  "sinfo_colTilt failed" );
413 
414  cknull(stats = sinfo_new_image_stats_on_rectangle(colImage,
415  cfg->badLoReject,
416  cfg->badHiReject,
417  cfg->llx,
418  cfg->lly,
419  cfg->urx,
420  cfg->ury),
421  "sinfo_get_image_stats_on_vig failed\n");
422 
423  local_clean_mean = stats->cleanmean;
424  clean_stdev = stats->cleanstdev;
425 
426 
427  /* indicate pixels with great deviations from the clean mean as bad */
428  if (cfg->threshInd == 1) {
429  cknull(threshIm = sinfo_new_thresh_image(colImage,
430  local_clean_mean-mean_factor*clean_stdev,
431  local_clean_mean+mean_factor*clean_stdev),
432  " sinfo_threshImage failed\n" );
433  }
434  if (cfg->threshInd == 0) {
435  threshIm = colImage;
436  }
437 
438  /*
439  filter iteratively the images by a sinfo_median filter of the nearest
440  neighbors under the condition of a deviation greater than a factor
441  times the standard deviation
442  */
443 
444  cknull(imMed[0]= sinfo_new_median_image(threshIm,-cfg->factor*clean_stdev),
445  " sinfo_medianImage failed" );
446 
447 
448  /* AMO check again if here the loop start and ending point are proper */
449 
450  for (i=1; i< cfg->iterations+1; i++) {
451  cknull(imMed[i]=sinfo_new_median_image(imMed[i-1],
452  -cfg->factor*clean_stdev),
453  "sinfo_medianImage failed" );
454  }
455 
456  /* compare the filtered image with the input image */
457  cknull(compImage=sinfo_new_compare_images(threshIm,
458  imMed[cfg->iterations],
459  im_obj),
460  "sinfo_compareImages failed" );
461 
462  /*---generate the bad pixel mask */
463  n = (int*)cpl_calloc(1,sizeof(int));
464  cknull(maskImage = sinfo_new_promote_image_to_mask( compImage, n ),
465  "error in sinfo_promoteImageToMask" );
466 
467 
468  n_badpixels = n[0];
469  sinfo_msg("No of bad pixels: %d", n_badpixels);
470 
471  cknull_nomsg(qclog_tbl = sinfo_qclog_init());
472  ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC BP-MAP NBADPIX",n_badpixels,
473  "No of bad pixels","%d"));
474 
475  ck0(sinfo_pro_save_ima(maskImage,ref_set,sof,cfg->maskname,
476  PRO_BP_MAP,qclog_tbl,plugin_id,config),
477  "cannot save ima %s", cfg->maskname);
478 
479 
480  /* free memory */
481  sinfo_free_table(&qclog_tbl);
482 
483  sinfo_new_del_Stats(stats);
484  sinfo_free_int(&n);
485  sinfo_free_image(&threshIm); /* */
486  if (cfg->threshInd == 1) {
487  sinfo_free_image(&colImage);
488  }
489  sinfo_free_image(&compImage);
490  sinfo_free_image(&maskImage);
491 
492  for (i=0; i< cfg->iterations+1; i++) {
493  sinfo_free_image(&imMed[i]);
494  }
495 
496  }
497 
498  cpl_free(imMed);
499  imMed=NULL;
500 
501  /*
502  #---------------------------------------------------------
503  # Master flat field: static bad pixel correction and normalizing
504  #---------------------------------------------------------
505  */
506 
507  sinfo_msg("Creates a Master flat field");
508  if (cfg->interpolInd == 1) {
509  cknull(mask_im = cpl_image_load(cfg->mask,CPL_TYPE_FLOAT,0,0),
510  "could not load static bad pixel mask" );
511 
512  /* open the ASCII list of the slitlet positions */
513 
514  /* slit_edges = sinfo_new_2Dfloat_array(32, 2) ; */
515  slit_edges = (float **) cpl_calloc( 32, sizeof (float*) ) ;
516  for ( i = 0 ; i < 32 ; i++ )
517  {
518  slit_edges[i] = (float *) cpl_calloc( 2, sizeof (float)) ;
519  }
520  /*READ TFITS TABLE*/
521  if(sinfo_is_fits_file(cfg->slitposList) !=1 ) {
522  sinfo_msg_error("Input file %s is not FITS", cfg->slitposList);
523  goto cleanup;
524  }
525  strcpy(tbl_slitpos_name,cfg->slitposList);
526  check(tbl_slitpos = cpl_table_load(tbl_slitpos_name,1,0),
527  "error loading tbl %s",tbl_slitpos_name);
528 
529  for (i =0 ; i< 32; i++){
530  val_x=cpl_table_get_double(tbl_slitpos,"pos1",i,status);
531  val_y=cpl_table_get_double(tbl_slitpos,"pos2",i,status);
532  slit_edges[i][0]=val_x;
533  slit_edges[i][1]=val_y;
534  }
535  sinfo_free_table(&tbl_slitpos);
536 
537  cknull(int_im = sinfo_interpol_source_image (im_obj, mask_im,
538  cfg->maxRad, slit_edges),
539  "could not carry out sinfo_interpolSourceImage" );
540 
541  sinfo_free_image(&im_obj);
542  cknull(norm = sinfo_new_normalize_to_central_pixel(int_im),
543  "could not normalize flatfield" );
544  sinfo_free_image(&int_im);
545  im_obj = norm;
546 
547  if (cfg->contains_dither == 1) {
548  cknull(int_im_dith = sinfo_interpol_source_image(im_dither,
549  mask_im,
550  cfg->maxRad,
551  slit_edges),
552  "could not carry out sinfo_interpolSourceImage" );
553 
554  cpl_image_delete(im_dither);
555  cknull(norm_dith = sinfo_new_normalize_to_central_pixel(int_im_dith),
556  "could not normalize flatfield" );
557  sinfo_free_image(&int_im_dith);
558  im_dither = norm_dith;
559  }
560  /* sinfo_new_destroy_2Dfloatarray(slit_edges, 32); */
561  for ( i = 0 ; i < 32 ; i++ )
562  {
563  cpl_free( slit_edges[i] );
564  }
565  cpl_free( slit_edges ) ;
566  sinfo_free_image(&mask_im);
567 
568  }
569 
570  if (cfg->interpolInd != 1) {
571  cknull(norm = sinfo_new_normalize_to_central_pixel(im_obj),
572  "could not normalize flatfield" );
573  sinfo_free_image(&im_obj);
574  im_obj = norm;
575 
576  if (cfg->contains_dither == 1) {
577  cknull(norm_dith = sinfo_new_normalize_to_central_pixel(im_dither),
578  "could not normalize flatfield" );
579  sinfo_free_image(&im_dither);
580  im_dither = norm_dith;
581  }
582  }
583 
584  naxis1=cpl_image_get_size_x(im_obj);
585  naxis2=cpl_image_get_size_y(im_obj);
586 
587 
588  if(cfg->qc_fpn_xmin1 < 1) {
589  sinfo_msg_error("qc_ron_xmin < 1");
590  goto cleanup;
591  }
592 
593  if(cfg->qc_fpn_xmax1 > naxis1) {
594  sinfo_msg_error("qc_ron_xmax < %d",naxis1);
595  goto cleanup;
596  }
597 
598  if(cfg->qc_fpn_ymin1 < 1) {
599  sinfo_msg_error("qc_ron_ymin < 1");
600  goto cleanup;
601  }
602 
603  if(cfg->qc_fpn_ymax1 > naxis2) {
604  sinfo_msg_error("qc_ron_ymax < %d",naxis2);
605  goto cleanup;
606  }
607  fpn_stdev1 = cpl_image_get_stdev_window(im_obj,
608  cfg->qc_fpn_xmin1,
609  cfg->qc_fpn_ymin1,
610  cfg->qc_fpn_xmax1,
611  cfg->qc_fpn_ymax1);
612 
613 
614  if(cfg->qc_fpn_xmin2 < 1) {
615  sinfo_msg_error("qc_ron_xmin < %d",1);
616  goto cleanup;
617  }
618 
619 
620  if(cfg->qc_fpn_xmax2 > naxis1) {
621  sinfo_msg_error("qc_ron_xmax < %d",naxis1);
622  goto cleanup;
623  }
624 
625  if(cfg->qc_fpn_ymin2 < 1) {
626  sinfo_msg_error("qc_ron_ymin < 1");
627  goto cleanup;
628  }
629 
630  if(cfg->qc_fpn_ymax2 > naxis2) {
631  sinfo_msg_error("qc_ron_ymax < %d",naxis2);
632  goto cleanup;
633  }
634  fpn_stdev2 = cpl_image_get_stdev_window(im_obj,
635  cfg->qc_fpn_xmin2,
636  cfg->qc_fpn_ymin2,
637  cfg->qc_fpn_xmax2,
638  cfg->qc_fpn_ymax2);
639 
640 
641 
642  ck0(new_lamp_flats_det_ncounts(raw,cfg),"error computing number of counts");
643  cknull_nomsg(qclog_tbl = sinfo_qclog_init());
644  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC SPECFLAT NCNTSAVG",
645  qc_lampflat.avg_di,"Average counts","%g"));
646  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC SPECFLAT NCNTSSTD",
647  qc_lampflat.std_di,"Stdev counts","%g"));
648  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC SPECFLAT OFFFLUX",
649  qc_lampflat.avg_of,
650  "Average flux off frames","%g"));
651 
652  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,
653  "QC LFLAT FPN1",
654  fpn_stdev1,
655  "Fixed Pattern Noise of combined frames",
656  "%f"));
657 
658  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,
659  "QC LFLAT FPN2",
660  fpn_stdev2,
661  "Fixed Pattern Noise of combined frames",
662  "%f"));
663 
664  ck0(sinfo_pro_save_ima(im_obj,ref_set,sof,cfg->outName,
665  PRO_MASTER_FLAT_LAMP,qclog_tbl,plugin_id,config),
666  "cannot save ima %s", cfg->outName);
667 
668  sinfo_free_table(&qclog_tbl);
669  sinfo_free_image(&im_obj);
670 
671 
672  if (cfg->contains_dither == 1) {
673 
674  if (strstr(cfg->outName, ".fits" ) != NULL ) {
675 
676  snprintf(name_list, MAX_NAME_SIZE-1,"%s%s",
677  sinfo_new_get_rootname(cfg->outName),
678  "_dither");
679  strcpy(outNameDither,name_list);
680  strcat(outNameDither,strstr(cfg->outName,".fits"));
681 
682  } else {
683  strcpy(outNameDither,cfg->outName);
684  strcat(outNameDither,"_dither");
685  }
686 
687 
688  naxis1=cpl_image_get_size_x(im_dither);
689  naxis2=cpl_image_get_size_y(im_dither);
690 
691 
692  if(cfg->qc_fpn_xmin1 < 1) {
693  sinfo_msg_error("qc_ron_xmin1 < 1");
694  goto cleanup;
695  }
696 
697  if(cfg->qc_fpn_xmax1 > naxis1) {
698  sinfo_msg_error("qc_ron_xmax1 < %d",naxis1);
699  goto cleanup;
700  }
701 
702  if(cfg->qc_fpn_ymin1 < 1) {
703  sinfo_msg_error("qc_ron_ymin1 < 1");
704  goto cleanup;
705  }
706 
707  if(cfg->qc_fpn_ymax1 > naxis2) {
708  sinfo_msg_error("qc_ron_ymax1 < %d",naxis2);
709  goto cleanup;
710  }
711 
712 
713  fpn_stdev1 = cpl_image_get_stdev_window(im_dither,
714  cfg->qc_fpn_xmin1,
715  cfg->qc_fpn_ymin1,
716  cfg->qc_fpn_xmax1,
717  cfg->qc_fpn_ymax1);
718 
719  if(cfg->qc_fpn_xmin2 < 1) {
720  sinfo_msg_error("qc_ron_xmin2 < 1");
721  goto cleanup;
722  }
723 
724  if(cfg->qc_fpn_xmax2 > naxis1) {
725  sinfo_msg_error("qc_ron_xmax2 < %d",naxis1);
726  goto cleanup;
727  }
728 
729  if(cfg->qc_fpn_ymin2 < 1) {
730  sinfo_msg_error("qc_ron_ymin2 < 1");
731  goto cleanup;
732  }
733 
734  if(cfg->qc_fpn_ymax2 > naxis2) {
735  sinfo_msg_error("qc_ron_ymax2 < %d",naxis2);
736  goto cleanup;
737  }
738 
739  fpn_stdev2 = cpl_image_get_stdev_window(im_dither,
740  cfg->qc_fpn_xmin2,
741  cfg->qc_fpn_ymin2,
742  cfg->qc_fpn_xmax2,
743  cfg->qc_fpn_ymax2);
744 
745 
746  ck0(new_lamp_flats_det_ncounts(raw,cfg),"error computing ncounts");
747  cknull_nomsg(qclog_tbl = sinfo_qclog_init());
748  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC SPECFLAT NCNTSAVG",
749  qc_lampflat.avg_di,"Average counts","%g"));
750 
751  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC SPECFLAT NCNTSSTD",
752  qc_lampflat.std_di,"Stdev counts","%g"));
753 
754  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC SPECFLAT OFFFLUX",
755  qc_lampflat.avg_of,"Average flux off frames","%g"));
756 
757  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC LFLAT FPN1",fpn_stdev1,
758  "Fixed Pattern Noise of combined frames","%f"));
759 
760  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC LFLAT FPN2",fpn_stdev2,
761  "Fixed Pattern Noise of combined frames","%f"));
762 
763 
764  ck0(sinfo_pro_save_ima(im_dither,ref_set,sof,outNameDither,
765  PRO_MASTER_FLAT_LAMP,qclog_tbl,plugin_id,config),
766  "cannot save ima %s", outNameDither);
767 
768  sinfo_free_table(&qclog_tbl);
769  sinfo_free_image(&im_dither);
770 
771  }
772 
773 
774  /* could be done earlier? */
775  sinfo_free_image_array(&im,cfg->nframes);
776  sinfo_free_frameset(&raw);
777  sinfo_flat_free(&cfg);
778  return 0;
779 
780  cleanup:
781 
782 
783  /* free memory */
784  if(slit_edges != NULL) {
785  for ( i = 0 ; i < 32 ; i++ )
786  {
787  if(slit_edges[i] != NULL) {
788  cpl_free( slit_edges[i] );
789  }
790  slit_edges[i]=NULL;
791  }
792  cpl_free( slit_edges ) ;
793  }
794  sinfo_free_image(&mask_im);
795  sinfo_free_table(&qclog_tbl);
796  if(stats) {
797  sinfo_new_del_Stats(stats);
798  }
799  sinfo_free_int(&n);
800  sinfo_free_image(&threshIm);
801  sinfo_free_image(&maskImage);
802  if(imMed != NULL) sinfo_free_image_array(&imMed,cfg->iterations);
803  if(stats!= NULL) {
804  sinfo_new_del_Stats(stats);
805  stats=NULL;
806  }
807  sinfo_free_image(&compImage);
808  sinfo_free_image(&colImage);
809  sinfo_free_imagelist(&list_dither_object);
810  sinfo_free_imagelist(&list_dither_sky);
811  if(list_sky != NULL) {
812  sinfo_free_imagelist(&list_sky);
813  }
814  sinfo_free_imagelist(&list_object);
815  sinfo_free_image(&im_dither);
816  sinfo_free_image(&im_dither_sky);
817  sinfo_free_image(&im_obj);
818  sinfo_free_image(&im_sky);
819  if(im != NULL) sinfo_free_image_array(&im,cfg->nframes);
820  sinfo_free_frameset(&raw);
821  if(cfg != NULL) {
822  sinfo_flat_free(&cfg);
823  }
824  return -1;
825 
826 }
827 
828 static int
829 new_lamp_flats_det_ncounts(cpl_frameset* raw, flat_config* cfg)
830 {
831  int i=0;
832  int j=0;
833 
834  int nraw=0;
835  int non=0;
836  int noff=0;
837 
838  double mjd_on=0;
839  double mjd_of=0;
840  double mjd_of_frm=0;
841 
842  char filename[MAX_NAME_SIZE];
843 
844  cpl_frame* frm_dup=NULL;
845  cpl_frame* on_frm=NULL;
846  cpl_frame* of_frm=NULL;
847  cpl_frame* tmp_of_frm=NULL;
848 
849 
850  cpl_frameset* on_set=NULL;
851  cpl_frameset* of_set=NULL;
852  cpl_frameset* wrk_set=NULL;
853 
854  on_set=cpl_frameset_new();
855  of_set=cpl_frameset_new();
856 
857  nraw = cpl_frameset_get_size(raw);
858 
859  for (i=0; i< nraw; i++) {
860  cpl_frame* frm = cpl_frameset_get_frame(raw,i);
861  frm_dup = cpl_frame_duplicate(frm);
862  if(sinfo_frame_is_on(frm) == 1) {
863  cpl_frameset_insert(on_set,frm_dup);
864  non++;
865  } else {
866  cpl_frameset_insert(of_set,frm_dup);
867  noff++;
868  }
869  }
870 
871 
872  if (non == noff) {
873  new_qc_get_cnt(on_set,of_set,cfg);
874 
875  } else if (non == 0) {
876  sinfo_msg("non == 0");
877  sinfo_msg_warning("QC SPECFLAT NCNTAVG/NCTNTSTD/OFFFLUX=0 ");
878 
879  } else if ( noff == 0 ) {
880  sinfo_msg("noff == 0");
881  sinfo_msg_warning("QC SPECFLAT NCNTAVG/NCTNTSTD/OFFFLUX=0 ");
882 
883  } else {
884 
885  sinfo_msg_warning("non != noff, => QC SPECFLAT NCNTAVG/NCTNTSTD/OFFFLUX=0 ");
886 
887  for (i=0;i<non;i++) {
888  wrk_set=cpl_frameset_new();
889  on_frm=cpl_frameset_get_frame(on_set,i);
890  mjd_on=sinfo_get_mjd_obs(on_frm);
891  of_frm=cpl_frameset_get_frame(of_set,0);
892  mjd_of=sinfo_get_mjd_obs(of_frm);
893  strcpy(filename,cpl_frame_get_filename(of_frm));
894  for (j=1;j<noff;j++) {
895  tmp_of_frm = cpl_frameset_get_frame(of_set,j);
896  mjd_of_frm = sinfo_get_mjd_obs(tmp_of_frm);
897 
898  if(1000.*(mjd_of_frm-mjd_on)*(mjd_of_frm-mjd_on) <
899  1000.*(mjd_of- mjd_on)*(mjd_of- mjd_on) ) {
900  mjd_of=mjd_of_frm;
901  of_frm=cpl_frame_duplicate(tmp_of_frm);
902  }
903  }
904  //strcpy(filename,cpl_frame_get_filename(of_frm));
905  frm_dup=cpl_frame_duplicate(of_frm);
906  cpl_frameset_insert(wrk_set,frm_dup);
907  strcpy(filename,cpl_frame_get_filename(of_frm));
908  }
909  /* Commented out as algorithm non robust if non != noff */
910  new_qc_get_cnt(on_set,wrk_set,cfg);
911 
912  }
913 
914  cpl_frameset_delete(wrk_set);
915  cpl_frameset_delete(on_set);
916  cpl_frameset_delete(of_set);
917  return 0;
918 
919 
920 }
921 
922 static int
923 new_qc_get_cnt(cpl_frameset* on_set, cpl_frameset* of_set, flat_config* cfg)
924 {
925 
926  int i=0;
927  int non=0;
928  int nof=0;
929  int nfr=0;
930 
931  char name[MAX_NAME_SIZE];
932  cpl_vector* vec_on=NULL;
933  cpl_vector* vec_of=NULL;
934  cpl_vector* vec_di=NULL;
935  cpl_vector* vec_nsat=NULL;
936 
937 
938  non = cpl_frameset_get_size(on_set);
939  nof = cpl_frameset_get_size(of_set);
940  nfr = (non <= nof) ? non : nof;
941  vec_on = cpl_vector_new(nfr);
942  vec_of = cpl_vector_new(nfr);
943  vec_di = cpl_vector_new(nfr);
944  vec_nsat = cpl_vector_new(nfr);
945 
946 
947  for (i=0; i< nfr; i++) {
948  cpl_frame* on_frm = cpl_frameset_get_frame(on_set,i);
949  strcpy(name,cpl_frame_get_filename(on_frm));
950  cpl_image* on_ima = cpl_image_load(name,CPL_TYPE_FLOAT,0,0);
951  double med= cpl_image_get_median(on_ima);
952  cpl_vector_set(vec_on,i,med);
953 
954  cpl_image* tmp_ima = cpl_image_duplicate(on_ima);
955  cpl_image_threshold(tmp_ima,SINFO_DBL_MIN,
956  cfg->qc_thresh_max,0,1);
957  int nsat=cpl_image_get_flux(tmp_ima);
958  cpl_vector_set(vec_nsat,i,nsat);
959 
960  /* Are you sure to have same frames off as on ? */
961  cpl_frame* of_frm = cpl_frameset_get_frame(of_set,i);
962  strcpy(name,cpl_frame_get_filename(of_frm));
963  cpl_image* of_ima = cpl_image_load(name,CPL_TYPE_FLOAT,0,0);
964  med= cpl_image_get_median(of_ima);
965  cpl_vector_set(vec_of,i,med);
966  cpl_image* dif_ima = cpl_image_subtract_create(on_ima,of_ima);
967  med= cpl_image_get_median(dif_ima);
968  cpl_vector_set(vec_di,i,med);
969 
970  cpl_image_delete(on_ima);
971  cpl_image_delete(of_ima);
972  cpl_image_delete(dif_ima);
973  cpl_image_delete(tmp_ima);
974  }
975  qc_lampflat.avg_on=cpl_vector_get_mean(vec_on);
976  qc_lampflat.avg_of=cpl_vector_get_mean(vec_of);
977  qc_lampflat.avg_di=cpl_vector_get_mean(vec_di);
978  if(nfr > 1 ) {
979  qc_lampflat.std_on=cpl_vector_get_stdev(vec_on);
980  qc_lampflat.std_of=cpl_vector_get_stdev(vec_of);
981  qc_lampflat.std_di=cpl_vector_get_stdev(vec_di);
982  }
983  qc_lampflat.nsat=cpl_vector_get_mean(vec_nsat);
984  cpl_vector_delete(vec_on);
985  cpl_vector_delete(vec_of);
986  cpl_vector_delete(vec_di);
987  cpl_vector_delete(vec_nsat);
988  /*
989  sinfo_msg( "sinfo_qc_get_cnt","avg_on=%g std_on=%g ",
990  qc_lampflat.avg_on,qc_lampflat.std_on);
991  sinfo_msg( "sinfo_qc_get_cnt","avg_of=%g std_of=%g ",
992  qc_lampflat.avg_of,qc_lampflat.std_of);
993  sinfo_msg( "sinfo_qc_get_cnt","avg_di=%g std_di=%g ",
994  qc_lampflat.avg_di,qc_lampflat.std_di);
995  sinfo_msg( "sinfo_qc_get_cnt","nsat=%g ",qc_lampflat.nsat);
996  */
997  return 0;
998 }
999 
#define sinfo_msg_error(...)
Print an error message.
Definition: sinfo_msg.h:69
#define sinfo_msg_warning(...)
Print an warning message.
Definition: sinfo_msg.h:93