VIRCAM Pipeline  1.3.4
vircam_twilight_flat_combine.c
1 /* $Id: vircam_twilight_flat_combine.c,v 1.57 2012-01-16 12:32:18 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
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: jim $
23  * $Date: 2012-01-16 12:32:18 $
24  * $Revision: 1.57 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 /* Includes */
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <stdio.h>
35 #include <cpl.h>
36 #include <math.h>
37 
38 #include "vircam_utils.h"
39 #include "vircam_mask.h"
40 #include "vircam_dfs.h"
41 #include "vircam_mods.h"
42 #include "vircam_stats.h"
43 #include "vircam_fits.h"
44 #include "vircam_pfits.h"
45 #include "vircam_channel.h"
46 #include "vircam_paf.h"
47 #include "vircam_wcsutils.h"
48 
49 /* Define values for bit mask that flags dummy results */
50 
51 #define MEANTWI 1
52 #define CONFMAP 2
53 #define RATIMG 4
54 #define STATS_TAB 8
55 
56 /* Function prototypes */
57 
58 static int vircam_twilight_flat_combine_create(cpl_plugin *) ;
59 static int vircam_twilight_flat_combine_exec(cpl_plugin *) ;
60 static int vircam_twilight_flat_combine_destroy(cpl_plugin *) ;
61 static int vircam_twilight_flat_combine(cpl_parameterlist *, cpl_frameset *) ;
62 static int vircam_twilight_flat_combine_save(cpl_frameset *framelist,
63  cpl_parameterlist *parlist);
64 static void vircam_twilight_flat_combine_dummy_products(void);
65 static void vircam_twilight_flat_combine_normal(int jext);
66 static int vircam_twilight_flat_combine_lastbit(int jext,
67  cpl_frameset *framelist,
68  cpl_parameterlist *parlist);
69 static void vircam_twilight_flat_combine_init(void);
70 static void vircam_twilight_flat_combine_tidy(int level);
71 
72 /* Static global variables */
73 
74 static struct {
75 
76  /* Input */
77 
78  float lthr;
79  float hthr;
80  int combtype;
81  int scaletype;
82  int xrej;
83  float thresh;
84  int ncells;
85  int extenum;
86 
87  /* Output */
88 
89  float flatrms;
90  float flatratio_med;
91  float flatratio_rms;
92  float minv;
93  float maxv;
94  float avev;
95  float photnoise;
96  float snratio;
97 
98 } vircam_twilight_flat_combine_config;
99 
100 
101 static struct {
102  vir_fits **good;
103  int ngood;
104  cpl_size *labels;
105  cpl_frameset *twilightlist;
106  cpl_frame *master_dark;
107  cpl_frame *master_twilight_flat;
108  vir_mask *master_mask;
109  cpl_frame *chantab;
110 
111  cpl_image *outimage;
112  cpl_image *outconf;
113  vir_fits **twilights;
114  int ntwilights;
115  cpl_propertylist *drs;
116  cpl_propertylist *drs2;
117  unsigned char *rejmask;
118  unsigned char *rejplus;
119  vir_fits *mfimage;
120  cpl_image *ratioimg;
121  cpl_table *ratioimstats;
122  vir_tfits *ctable;
123  vir_fits *mdark;
124  cpl_propertylist *phupaf;
125 } ps;
126 
127 static int isfirst;
128 static cpl_frame *product_frame_mean_twi = NULL;
129 static cpl_frame *product_frame_conf = NULL;
130 static cpl_frame *product_frame_ratioimg = NULL;
131 static cpl_frame *product_frame_ratioimg_stats = NULL;
132 static int we_expect;
133 static int we_get;
134 
135 static char vircam_twilight_flat_combine_description[] =
136 "vircam_twilight_flat_combine -- VIRCAM twilight flat combine recipe.\n\n"
137 "Combine a list of twilight flat frames into a mean frame. Optionally\n"
138 "compare the output frame to a master twilight flat frame\n\n"
139 "The program accepts the following files in the SOF:\n\n"
140 " Tag Description\n"
141 " -----------------------------------------------------------------------\n"
142 " %-21s A list of raw twilight flat images\n"
143 " %-21s A master dark frame\n"
144 " %-21s Optional reference twilight flat frame\n"
145 " %-21s Optional channel table or\n"
146 " %-21s Optional initial channel table\n"
147 " %-21s Optional master bad pixel map or\n"
148 " %-21s Optional master confidence map\n"
149 "If no reference twilight flat is made available, then no comparison will be\n"
150 "done. This means there will be no output ratio image. If a master twilight\n"
151 "is available, but no channel table is, then a ratio image will be formed\n"
152 "but no stats will be written."
153 "\n";
154 
297 /* Function code */
298 
299 /*---------------------------------------------------------------------------*/
307 /*---------------------------------------------------------------------------*/
308 
309 int cpl_plugin_get_info(cpl_pluginlist *list) {
310  cpl_recipe *recipe = cpl_calloc(1,sizeof(*recipe));
311  cpl_plugin *plugin = &recipe->interface;
312  char alldesc[SZ_ALLDESC];
313  (void)snprintf(alldesc,SZ_ALLDESC,vircam_twilight_flat_combine_description,
314  VIRCAM_TWI_RAW,VIRCAM_CAL_DARK,VIRCAM_REF_TWILIGHT_FLAT,
315  VIRCAM_CAL_CHANTAB,VIRCAM_CAL_CHANTAB_INIT,VIRCAM_CAL_BPM,
316  VIRCAM_CAL_CONF);
317 
318  cpl_plugin_init(plugin,
319  CPL_PLUGIN_API,
320  VIRCAM_BINARY_VERSION,
321  CPL_PLUGIN_TYPE_RECIPE,
322  "vircam_twilight_flat_combine",
323  "VIRCAM twilight combination recipe",
324  alldesc,
325  "Jim Lewis",
326  "jrl@ast.cam.ac.uk",
328  vircam_twilight_flat_combine_create,
329  vircam_twilight_flat_combine_exec,
330  vircam_twilight_flat_combine_destroy);
331 
332  cpl_pluginlist_append(list,plugin);
333 
334  return(0);
335 }
336 
337 /*---------------------------------------------------------------------------*/
346 /*---------------------------------------------------------------------------*/
347 
348 static int vircam_twilight_flat_combine_create(cpl_plugin *plugin) {
349  cpl_recipe *recipe;
350  cpl_parameter *p;
351 
352  /* Get the recipe out of the plugin */
353 
354  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
355  recipe = (cpl_recipe *)plugin;
356  else
357  return(-1);
358 
359  /* Create the parameters list in the cpl_recipe object */
360 
361  recipe->parameters = cpl_parameterlist_new();
362 
363  /* Lower threshold for rejecting underexposed images */
364 
365  p = cpl_parameter_new_value("vircam.vircam_twilight_flat_combine.lthr",
366  CPL_TYPE_DOUBLE,
367  "Low rejection threshold for underexpsed images",
368  "vircam.vircam_twilight_flat_combine",
369  4000.0);
370  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"lthr");
371  cpl_parameterlist_append(recipe->parameters,p);
372 
373  /* Upper threshold for rejecting overexposed images */
374 
375  p = cpl_parameter_new_value("vircam.vircam_twilight_flat_combine.hthr",
376  CPL_TYPE_DOUBLE,
377  "High rejection threshold for overexposed images",
378  "vircam.vircam_twilight_flat_combine",
379  12000.0);
380  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"hthr");
381  cpl_parameterlist_append(recipe->parameters,p);
382 
383  /* Fill in the parameters. First the combination type */
384 
385  p = cpl_parameter_new_range("vircam.vircam_twilight_flat_combine.combtype",
386  CPL_TYPE_INT,
387  "1 == Median,\n 2 == Mean",
388  "vircam.vircam_twilight_flat_combine",
389  1,1,2);
390  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"combtype");
391  cpl_parameterlist_append(recipe->parameters,p);
392 
393  /* The requested scaling */
394 
395  p = cpl_parameter_new_range("vircam.vircam_twilight_flat_combine.scaletype",
396  CPL_TYPE_INT,
397  "0 == none,\n 1 == additive offset,\n 2 == multiplicative offset,\n 3 == exposure time scaling + additive offset",
398  "vircam.vircam_twilight_flat_combine",
399  2,0,3);
400  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"scaletype");
401  cpl_parameterlist_append(recipe->parameters,p);
402 
403  /* Extra rejection cycle */
404 
405  p = cpl_parameter_new_value("vircam.vircam_twilight_flat_combine.xrej",
406  CPL_TYPE_BOOL,
407  "True if using extra rejection cycle",
408  "vircam.vircam_twilight_flat_combine",
409  TRUE);
410  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"xrej");
411  cpl_parameterlist_append(recipe->parameters,p);
412 
413  /* Rejection threshold */
414 
415  p = cpl_parameter_new_value("vircam.vircam_twilight_flat_combine.thresh",
416  CPL_TYPE_DOUBLE,
417  "Rejection threshold in sigma above background",
418  "vircam.vircam_twilight_flat_combine",5.0);
419  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"thresh");
420  cpl_parameterlist_append(recipe->parameters,p);
421 
422  /* How many cells to divide each data channel */
423 
424  p = cpl_parameter_new_enum("vircam.vircam_twilight_flat_combine.ncells",
425  CPL_TYPE_INT,
426  "Number of cells for data channel stats",
427  "vircam.vircam_twilight_flat_combine",8,7,1,2,4,
428  8,16,32,64);
429  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ncells");
430  cpl_parameterlist_append(recipe->parameters,p);
431 
432  /* Extension number of input frames to use */
433 
434  p = cpl_parameter_new_range("vircam.vircam_twilight_flat_combine.extenum",
435  CPL_TYPE_INT,
436  "Extension number to be done, 0 == all",
437  "vircam.vircam_twilight_flat_combine",
438  1,0,16);
439  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ext");
440  cpl_parameterlist_append(recipe->parameters,p);
441 
442  /* Get out of here */
443 
444  return(0);
445 }
446 
447 
448 /*---------------------------------------------------------------------------*/
454 /*---------------------------------------------------------------------------*/
455 
456 static int vircam_twilight_flat_combine_exec(cpl_plugin *plugin) {
457  cpl_recipe *recipe;
458 
459  /* Get the recipe out of the plugin */
460 
461  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
462  recipe = (cpl_recipe *)plugin;
463  else
464  return(-1);
465 
466  return(vircam_twilight_flat_combine(recipe->parameters,recipe->frames));
467 }
468 
469 /*---------------------------------------------------------------------------*/
475 /*---------------------------------------------------------------------------*/
476 
477 static int vircam_twilight_flat_combine_destroy(cpl_plugin *plugin) {
478  cpl_recipe *recipe ;
479 
480  /* Get the recipe out of the plugin */
481 
482  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
483  recipe = (cpl_recipe *)plugin;
484  else
485  return(-1);
486 
487  cpl_parameterlist_delete(recipe->parameters);
488  return(0);
489 }
490 
491 /*---------------------------------------------------------------------------*/
498 /*---------------------------------------------------------------------------*/
499 
500 static int vircam_twilight_flat_combine(cpl_parameterlist *parlist,
501  cpl_frameset *framelist) {
502  const char *fctid="vircam_twilight_flat_combine";
503  int j,jst,jfn,retval,status,live,nx,ny,ndit,npts;
504  cpl_size nlab;
505  long i;
506  cpl_parameter *p;
507  vir_fits *ff;
508  cpl_propertylist *pp;
509  cpl_image *im1,*im2,*newim,*diffim;
510  double val1,val2,scl;
511  float *data,med,mad;
512  unsigned char *bpm;
513 
514  /* Check validity of input frameset */
515 
516  if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
517  cpl_msg_error(fctid,"Input framelist NULL or has no input data");
518  return(-1);
519  }
520 
521  /* Check the files in the frameset */
522 
523  if (vircam_frameset_fexists(framelist) != VIR_OK) {
524  cpl_msg_error(fctid,"Input frameset is missing files. Check SOF");
525  return(-1);
526  }
527 
528  /* Initialise some things */
529 
530  vircam_twilight_flat_combine_init();
531  we_expect = MEANTWI + CONFMAP;
532 
533  /* Get the parameters */
534 
535  p = cpl_parameterlist_find(parlist,"vircam.vircam_twilight_flat_combine.lthr");
536  vircam_twilight_flat_combine_config.lthr =
537  (float)cpl_parameter_get_double(p);
538  p = cpl_parameterlist_find(parlist,
539  "vircam.vircam_twilight_flat_combine.hthr");
540  vircam_twilight_flat_combine_config.hthr =
541  (float)cpl_parameter_get_double(p);
542  p = cpl_parameterlist_find(parlist,
543  "vircam.vircam_twilight_flat_combine.combtype");
544  vircam_twilight_flat_combine_config.combtype = cpl_parameter_get_int(p);
545  p = cpl_parameterlist_find(parlist,
546  "vircam.vircam_twilight_flat_combine.scaletype");
547  vircam_twilight_flat_combine_config.scaletype = cpl_parameter_get_int(p);
548  p = cpl_parameterlist_find(parlist,
549  "vircam.vircam_twilight_flat_combine.xrej");
550  vircam_twilight_flat_combine_config.xrej = cpl_parameter_get_bool(p);
551  p = cpl_parameterlist_find(parlist,
552  "vircam.vircam_twilight_flat_combine.thresh");
553  vircam_twilight_flat_combine_config.thresh =
554  (float)cpl_parameter_get_double(p);
555  p = cpl_parameterlist_find(parlist,
556  "vircam.vircam_twilight_flat_combine.ncells");
557  vircam_twilight_flat_combine_config.ncells = cpl_parameter_get_int(p);
558  p = cpl_parameterlist_find(parlist,
559  "vircam.vircam_twilight_flat_combine.extenum");
560  vircam_twilight_flat_combine_config.extenum = cpl_parameter_get_int(p);
561 
562  /* Sort out raw from calib frames */
563 
564  if (vircam_dfs_set_groups(framelist) != VIR_OK) {
565  cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
566  vircam_twilight_flat_combine_tidy(2);
567  return(-1);
568  }
569 
570  /* Get the twilight frames */
571 
572  if ((ps.labels = cpl_frameset_labelise(framelist,vircam_compare_tags,
573  &nlab)) == NULL) {
574  cpl_msg_error(fctid,"Cannot labelise the input frames");
575  vircam_twilight_flat_combine_tidy(2);
576  return(-1);
577  }
578  if ((ps.twilightlist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
579  VIRCAM_TWI_RAW)) == NULL) {
580  cpl_msg_error(fctid,"Cannot find twilight frames in input frameset");
581  vircam_twilight_flat_combine_tidy(2);
582  return(-1);
583  }
584  ps.ntwilights = cpl_frameset_get_size(ps.twilightlist);
585 
586  /* Check to see if there is a master dark frame */
587 
588  if ((ps.master_dark = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
589  VIRCAM_CAL_DARK)) == NULL) {
590  cpl_msg_error(fctid,"No master dark found");
591  vircam_twilight_flat_combine_tidy(2);
592  return(-1);
593  }
594 
595  /* Check to see if there is a master twilight flat frame */
596 
597  if ((ps.master_twilight_flat = vircam_frameset_subgroup_1(framelist,
598  ps.labels,nlab,VIRCAM_REF_TWILIGHT_FLAT)) == NULL)
599  cpl_msg_info(fctid,"No master twilight flat found -- no ratio image will be formed");
600  else
601  we_expect |= RATIMG;
602 
603  /* Check to see if there is a master bad pixel map. If there isn't one
604  then look for a confidence map */
605 
606  ps.master_mask = vircam_mask_define(framelist,ps.labels,nlab);
607 
608  /* Check to see if there is a channel table */
609 
610  if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
611  VIRCAM_CAL_CHANTAB)) == NULL) {
612  if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
613  VIRCAM_CAL_CHANTAB_INIT)) == NULL) {
614  cpl_msg_info(fctid,"No channel table found -- no ratio image stats and no linearisation will be done");
615  } else {
616  cpl_msg_info(fctid,"Channel table is labelled INIT -- no linearisation will be done");
617  if (we_expect & RATIMG)
618  we_expect |= STATS_TAB;
619  }
620  } else if (we_expect & RATIMG) {
621  we_expect |= STATS_TAB;
622  }
623 
624  /* Get the number of DITs */
625 
626  pp = cpl_propertylist_load(cpl_frame_get_filename(cpl_frameset_get_frame(ps.twilightlist,0)),0);
627  if (vircam_pfits_get_ndit(pp,&ndit) != VIR_OK) {
628  cpl_msg_error(fctid,"No value for NDIT available");
629  freepropertylist(pp);
630  vircam_twilight_flat_combine_tidy(2);
631  return(-1);
632  }
633  cpl_propertylist_delete(pp);
634 
635  /* Now, how many image extensions do we want to do? If the extension
636  number is zero, then we loop for all possible extensions. If it
637  isn't then we just do the extension specified */
638 
639  vircam_exten_range(vircam_twilight_flat_combine_config.extenum,
640  (const cpl_frame *)cpl_frameset_get_frame(ps.twilightlist,0),
641  &jst,&jfn);
642  if (jst == -1 || jfn == -1) {
643  cpl_msg_error(fctid,"Unable to continue");
644  vircam_twilight_flat_combine_tidy(2);
645  return(-1);
646  }
647 
648  /* Get some space for the good frames */
649 
650  ps.good = cpl_malloc(ps.ntwilights*sizeof(vir_fits *));
651 
652  /* Now loop for all the extension... */
653 
654  for (j = jst; j <= jfn; j++) {
655  status = VIR_OK;
656  we_get = 0;
657  isfirst = (j == jst);
658 
659  /* Load the images and the master dark. */
660 
661  ps.twilights = vircam_fits_load_list(ps.twilightlist,CPL_TYPE_FLOAT,j);
662  if (ps.twilights == NULL) {
663  cpl_msg_info(fctid,
664  "Extension %" CPL_SIZE_FORMAT " twilights wouldn't load",
665  (cpl_size)j);
666  retval = vircam_twilight_flat_combine_lastbit(j,framelist,parlist);
667  if (retval != 0)
668  return(-1);
669  continue;
670  }
671 
672  /* Are any of these twilight flats any good? */
673 
674  ps.ngood = 0;
675  for (i = 0; i < ps.ntwilights; i++) {
676  ff = ps.twilights[i];
678  if (! live) {
679  cpl_msg_info(fctid,"Detector flagged dead %s",
681  vircam_fits_set_error(ff,VIR_FATAL);
682  } else {
683  ps.good[ps.ngood] = ff;
684  ps.ngood += 1;
685  }
686  }
687 
688  /* If there are no good images, then signal that we need to create
689  dummy products and move on */
690 
691  if (ps.ngood == 0) {
692  cpl_msg_info(fctid,"All images flagged bad for this extension");
693  retval = vircam_twilight_flat_combine_lastbit(j,framelist,parlist);
694  if (retval != 0)
695  return(-1);
696  continue;
697  }
698 
699  /* Sort out the images that are either over or under exposed */
700 
701  vircam_overexp(ps.good,&(ps.ngood),ndit,
702  vircam_twilight_flat_combine_config.lthr,
703  vircam_twilight_flat_combine_config.hthr,0,
704  &(vircam_twilight_flat_combine_config.minv),
705  &(vircam_twilight_flat_combine_config.maxv),
706  &(vircam_twilight_flat_combine_config.avev));
707 
708  /* Check to see how many are left. If there aren't any, then
709  signal a major error */
710 
711  if (ps.ngood == 0) {
712  cpl_msg_info(fctid,"All images either under or overexposed");
713  retval = vircam_twilight_flat_combine_lastbit(j,framelist,parlist);
714  if (retval != 0)
715  return(-1);
716  continue;
717  }
718 
719  /* Load up the mask */
720 
721  nx = (int)cpl_image_get_size_x(vircam_fits_get_image(ps.good[0]));
722  ny = (int)cpl_image_get_size_y(vircam_fits_get_image(ps.good[0]));
723  if (vircam_mask_load(ps.master_mask,j,nx,ny) == VIR_FATAL) {
724  cpl_msg_info(fctid,
725  "Unable to load mask image %s[%" CPL_SIZE_FORMAT "]",
726  vircam_mask_get_filename(ps.master_mask),
727  (cpl_size)j);
728  cpl_msg_info(fctid,"Forcing all pixels to be good from now on");
729  vircam_mask_force(ps.master_mask,nx,ny);
730  }
731 
732  /* Take the middle two exposures and create a scaled difference image
733  estimate */
734 
735  if (ps.ngood > 1) {
736  i = ps.ngood/2 - 1;
737  im1 = vircam_fits_get_image(ps.good[i]);
738  im2 = vircam_fits_get_image(ps.good[i+1]);
739  val1 = cpl_image_get_median_window(im1,500,500,1000,1000);
740  val2 = cpl_image_get_median_window(im2,500,500,1000,1000);
741  val1 /= (double)ndit;
742  val2 /= (double)ndit;
743  scl = val1/val2;
744  newim = cpl_image_multiply_scalar_create(im2,scl);
745  diffim = cpl_image_subtract_create(im1,newim);
746  cpl_image_delete(newim);
747  data = cpl_image_get_data_float(diffim);
748  bpm = vircam_mask_get_data(ps.master_mask);
749  npts = nx*ny;
750  vircam_medmad(data,bpm,npts,&med,&mad);
751  mad *= 1.48/CPL_MATH_SQRT2;
752  vircam_twilight_flat_combine_config.photnoise = mad;
753  vircam_twilight_flat_combine_config.snratio =
754  val1*sqrt((double)(ps.ngood))/mad;
755  cpl_image_delete(diffim);
756  } else {
757  vircam_twilight_flat_combine_config.photnoise = 0.0;
758  vircam_twilight_flat_combine_config.snratio = 0.0;
759  }
760 
761  /* Right, we want to dark correct, so we need to load the mean
762  dark and make sure it isn't a dummy */
763 
764  ps.mdark = vircam_fits_load(ps.master_dark,CPL_TYPE_FLOAT,j);
765  if (ps.mdark == NULL) {
766  cpl_msg_info(fctid,
767  "Can't load master dark for extension %" CPL_SIZE_FORMAT,
768  (cpl_size)j);
769  retval = vircam_twilight_flat_combine_lastbit(j,framelist,parlist);
770  if (retval != 0)
771  return(-1);
772  continue;
773  } else if (vircam_is_dummy(vircam_fits_get_ehu(ps.mdark))) {
774  cpl_msg_info(fctid,
775  "Can't master dark extension %" CPL_SIZE_FORMAT " is a dummy",
776  (cpl_size)j);
777  retval = vircam_twilight_flat_combine_lastbit(j,framelist,parlist);
778  if (retval != 0)
779  return(-1);
780  continue;
781  }
782 
783  /* Loop for each image and dark correct */
784 
785  cpl_msg_info(fctid,"Dark correcting extension %" CPL_SIZE_FORMAT,
786  (cpl_size)j);
787  for (i = 0; i < ps.ngood; i++)
788  vircam_darkcor((ps.good)[i],ps.mdark,1.0,&status);
789 
790  /* We need to load the channel table (if it exists) for linearisation
791  and for the ratio image stats table */
792 
793  if (ps.chantab != NULL) {
794  ps.ctable = vircam_tfits_load(ps.chantab,j);
795  if (ps.ctable == NULL) {
796  cpl_msg_info(fctid,
797  "Channel table extension %" CPL_SIZE_FORMAT " won't load",
798  (cpl_size)j);
799  } else if (vircam_chantab_verify(vircam_tfits_get_table(ps.ctable)) != VIR_OK) {
800  cpl_msg_info(fctid,
801  "Channel table extension %" CPL_SIZE_FORMAT " has errors",
802  (cpl_size)j);
803  freetfits(ps.ctable);
804  } else {
805  pp = cpl_propertylist_load(cpl_frame_get_filename(ps.chantab),
806  (cpl_size)j);
807  if (vircam_is_dummy(pp)) {
808  cpl_msg_info(fctid,
809  "Channel table extensions %" CPL_SIZE_FORMAT " is a dummy",
810  (cpl_size)j);
811  freetfits(ps.ctable);
812  }
813  freepropertylist(pp);
814  }
815  } else
816  ps.ctable = NULL;
817 
818  /* Loop for each of the input images and linearise it if there
819  is a channel table */
820 
821  if (ps.ctable != NULL) {
822  cpl_msg_info(fctid,
823  "Linearising extension %" CPL_SIZE_FORMAT,
824  (cpl_size)j);
825  for (i = 0; i < ps.ngood; i++)
826  (void)vircam_lincor((ps.good)[i],ps.ctable,1,ndit,&status);
827  }
828 
829  /* Correct for ndit */
830 
831  for (i = 0; i < ps.ngood; i++)
832  (void)vircam_nditcor((ps.good)[i],ndit,&status);
833 
834  /* Call the combine module */
835 
836  cpl_msg_info(fctid,
837  "Doing combination for extension %" CPL_SIZE_FORMAT,
838  (cpl_size)j);
839  (void)vircam_imcombine(ps.good,ps.ngood,
840  vircam_twilight_flat_combine_config.combtype,
841  vircam_twilight_flat_combine_config.scaletype,
842  vircam_twilight_flat_combine_config.xrej,
843  vircam_twilight_flat_combine_config.thresh,
844  &(ps.outimage),&(ps.rejmask),&(ps.rejplus),
845  &(ps.drs),&status);
846 
847  /* If these correction and combination routines failed at any stage
848  then get out of here */
849 
850  if (status == VIR_OK) {
851  we_get |= MEANTWI;
852  vircam_twilight_flat_combine_normal(j);
853  } else {
854  cpl_msg_info(fctid,"A processing step failed");
855  }
856 
857  /* Create any dummies and save the products */
858 
859  retval = vircam_twilight_flat_combine_lastbit(j,framelist,parlist);
860  if (retval != 0)
861  return(-1);
862 
863  }
864  vircam_twilight_flat_combine_tidy(2);
865  return(0);
866 }
867 
868 
869 /*---------------------------------------------------------------------------*/
876 /*---------------------------------------------------------------------------*/
877 
878 static int vircam_twilight_flat_combine_save(cpl_frameset *framelist,
879  cpl_parameterlist *parlist) {
880  cpl_propertylist *plist,*elist,*p,*pafprop;
881  int status;
882  float val;
883  const char *fctid = "vircam_twilight_flat_combine_save";
884  const char *outfile = "twilightcomb.fits";
885  const char *outdiff = "twilightratio.fits";
886  const char *outdimst = "twilightratiotab.fits";
887  const char *outconf = "twilightconf.fits";
888  const char *outfilepaf = "twilightcomb";
889  const char *outdiffpaf = "twilightratio";
890  const char *recipeid = "vircam_twilight_flat_combine";
891 
892  /* If we need to make a PHU then do that now based on the first frame
893  in the input frame list */
894 
895  if (isfirst) {
896 
897  /* Create a new product frame object and define some tags */
898 
899  product_frame_mean_twi = cpl_frame_new();
900  cpl_frame_set_filename(product_frame_mean_twi,outfile);
901  cpl_frame_set_tag(product_frame_mean_twi,VIRCAM_PRO_TWILIGHT_FLAT);
902  cpl_frame_set_type(product_frame_mean_twi,CPL_FRAME_TYPE_IMAGE);
903  cpl_frame_set_group(product_frame_mean_twi,CPL_FRAME_GROUP_PRODUCT);
904  cpl_frame_set_level(product_frame_mean_twi,CPL_FRAME_LEVEL_FINAL);
905 
906  /* Set up the PHU header */
907 
908  plist = vircam_fits_get_phu(ps.twilights[0]);
909  ps.phupaf = vircam_paf_phu_items(plist);
910  if (ps.master_twilight_flat != NULL) {
911  cpl_propertylist_update_string(ps.phupaf,"REF_TWILIGHT",
912  cpl_frame_get_filename(ps.master_twilight_flat));
913  cpl_propertylist_set_comment(ps.phupaf,"REF_TWILIGHT",
914  "Reference twilight flat used");
915  }
916  vircam_dfs_set_product_primary_header(plist,product_frame_mean_twi,
917  framelist,parlist,
918  (char *)recipeid,
919  "PRO-1.15",NULL,0);
920 
921  /* 'Save' the PHU image */
922 
923  if (cpl_image_save(NULL,outfile,CPL_TYPE_UCHAR,plist,
924  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
925  cpl_msg_error(fctid,"Cannot save product PHU");
926  cpl_frame_delete(product_frame_mean_twi);
927  return(-1);
928  }
929  cpl_frameset_insert(framelist,product_frame_mean_twi);
930 
931  /* Create a new product frame object and define some tags for the
932  output confidence map */
933 
934  product_frame_conf = cpl_frame_new();
935  cpl_frame_set_filename(product_frame_conf,outconf);
936  cpl_frame_set_tag(product_frame_conf,VIRCAM_PRO_CONF);
937  cpl_frame_set_type(product_frame_conf,CPL_FRAME_TYPE_IMAGE);
938  cpl_frame_set_group(product_frame_conf,CPL_FRAME_GROUP_PRODUCT);
939  cpl_frame_set_level(product_frame_conf,CPL_FRAME_LEVEL_FINAL);
940 
941  /* Set up the PHU header */
942 
943  plist = vircam_fits_get_phu(ps.twilights[0]);
944  vircam_dfs_set_product_primary_header(plist,product_frame_conf,
945  framelist,parlist,
946  (char *)recipeid,"PRO-1.15",
947  NULL,0);
948 
949  /* 'Save' the PHU image */
950 
951  if (cpl_image_save(NULL,outconf,CPL_TYPE_UCHAR,plist,
952  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
953  cpl_msg_error(fctid,"Cannot save product PHU");
954  cpl_frame_delete(product_frame_conf);
955  return(-1);
956  }
957  cpl_frameset_insert(framelist,product_frame_conf);
958 
959  /* Create a new product frame object for the difference image */
960 
961  if (we_expect & RATIMG) {
962  product_frame_ratioimg = cpl_frame_new();
963  cpl_frame_set_filename(product_frame_ratioimg,outdiff);
964  cpl_frame_set_tag(product_frame_ratioimg,
965  VIRCAM_PRO_RATIOIMG_TWILIGHT_FLAT);
966  cpl_frame_set_type(product_frame_ratioimg,CPL_FRAME_TYPE_IMAGE);
967  cpl_frame_set_group(product_frame_ratioimg,
968  CPL_FRAME_GROUP_PRODUCT);
969  cpl_frame_set_level(product_frame_ratioimg,CPL_FRAME_LEVEL_FINAL);
970 
971  /* Set up the PHU header */
972 
973  plist = vircam_fits_get_phu(ps.twilights[0]);
974  vircam_dfs_set_product_primary_header(plist,product_frame_ratioimg,
975  framelist,parlist,
976  (char *)recipeid,"PRO-1.15",
977  NULL,0);
978 
979  /* 'Save' the PHU image */
980 
981  if (cpl_image_save(NULL,outdiff,CPL_TYPE_CHAR,plist,
982  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
983  cpl_msg_error(fctid,"Cannot save product PHU");
984  cpl_frame_delete(product_frame_ratioimg);
985  return(-1);
986  }
987  cpl_frameset_insert(framelist,product_frame_ratioimg);
988  }
989 
990  /* Create a new product frame object for the difference image stats
991  table */
992 
993  if (we_expect & STATS_TAB) {
994  product_frame_ratioimg_stats = cpl_frame_new();
995  cpl_frame_set_filename(product_frame_ratioimg_stats,outdimst);
996  cpl_frame_set_tag(product_frame_ratioimg_stats,
997  VIRCAM_PRO_RATIOIMG_TWILIGHT_FLAT_STATS);
998  cpl_frame_set_type(product_frame_ratioimg_stats,
999  CPL_FRAME_TYPE_TABLE);
1000  cpl_frame_set_group(product_frame_ratioimg_stats,
1001  CPL_FRAME_GROUP_PRODUCT);
1002  cpl_frame_set_level(product_frame_ratioimg_stats,
1003  CPL_FRAME_LEVEL_FINAL);
1004 
1005  /* Set up PHU header */
1006 
1007  plist = vircam_fits_get_phu(ps.twilights[0]);
1009  product_frame_ratioimg_stats,
1010  framelist,parlist,
1011  (char *)recipeid,"PRO-1.15",
1012  NULL,0);
1013 
1014  /* Fiddle with the extension header now */
1015 
1016  elist = vircam_fits_get_ehu(ps.twilights[0]);
1017  p = cpl_propertylist_duplicate(elist);
1018  vircam_merge_propertylists(p,ps.drs);
1019  if (! (we_get & STATS_TAB))
1021  vircam_dfs_set_product_exten_header(p,product_frame_ratioimg_stats,
1022  framelist,parlist,
1023  (char *)recipeid,
1024  "PRO-1.15",NULL);
1025  status = VIR_OK;
1026  vircam_removewcs(p,&status);
1027 
1028  /* And finally the difference image stats table */
1029 
1030  if (cpl_table_save(ps.ratioimstats,plist,p,outdimst,
1031  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
1032  cpl_msg_error(fctid,"Cannot save product table extension");
1033  cpl_propertylist_delete(p);
1034  return(-1);
1035  }
1036  cpl_propertylist_delete(p);
1037  cpl_frameset_insert(framelist,product_frame_ratioimg_stats);
1038  }
1039  }
1040 
1041  /* Get the extension property list */
1042 
1043  plist = vircam_fits_get_ehu(ps.twilights[0]);
1044  vircam_merge_propertylists(plist,ps.drs);
1045  cpl_propertylist_update_int(plist,"ESO PRO DATANCOM",ps.ngood);
1046 
1047  /* Fiddle with the header now */
1048 
1049  p = cpl_propertylist_duplicate(plist);
1050  if (! (we_get & MEANTWI))
1052  vircam_dfs_set_product_exten_header(p,product_frame_mean_twi,framelist,
1053  parlist,(char *)recipeid,
1054  "PRO-1.15",NULL);
1055 
1056  /* Now save the mean twilight flat image extension */
1057 
1058  cpl_propertylist_update_float(p,"ESO QC FLATRMS",
1059  vircam_twilight_flat_combine_config.flatrms);
1060  cpl_propertylist_set_comment(p,"ESO QC FLATRMS","RMS of output flat");
1061  cpl_propertylist_update_float(p,"ESO QC FLATMIN",
1062  vircam_twilight_flat_combine_config.minv);
1063  cpl_propertylist_set_comment(p,"ESO QC FLATMIN","Ensemble minimum");
1064  cpl_propertylist_update_float(p,"ESO QC FLATMAX",
1065  vircam_twilight_flat_combine_config.maxv);
1066  cpl_propertylist_set_comment(p,"ESO QC FLATMAX","Ensemble maximum");
1067  cpl_propertylist_update_float(p,"ESO QC FLATAVG",
1068  vircam_twilight_flat_combine_config.avev);
1069  cpl_propertylist_set_comment(p,"ESO QC FLATAVG","Ensemble average");
1070  val = vircam_twilight_flat_combine_config.maxv -
1071  vircam_twilight_flat_combine_config.minv;
1072  cpl_propertylist_update_float(p,"ESO QC FLATRNG",val);
1073  cpl_propertylist_set_comment(p,"ESO QC FLATRNG","Ensemble range");
1074  cpl_propertylist_update_float(p,"ESO QC TWIPHOT",
1075  vircam_twilight_flat_combine_config.photnoise);
1076  cpl_propertylist_set_comment(p,"ESO QC TWIPHOT",
1077  "[adu] Estimated photon noise");
1078  cpl_propertylist_update_float(p,"ESO QC TWISNRATIO",
1079  vircam_twilight_flat_combine_config.snratio);
1080  cpl_propertylist_set_comment(p,"ESO QC TWISNRATIO","Estimated S/N ratio");
1081  if (cpl_image_save(ps.outimage,outfile,CPL_TYPE_FLOAT,p,
1082  CPL_IO_EXTEND) != CPL_ERROR_NONE) {
1083  cpl_msg_error(fctid,"Cannot save product image extension");
1084  cpl_propertylist_delete(p);
1085  return(-1);
1086  }
1087 
1088  /* Write out PAF for mean image */
1089 
1090  pafprop = vircam_paf_req_items(p);
1091  vircam_merge_propertylists(pafprop,ps.phupaf);
1092  vircam_paf_append(pafprop,vircam_fits_get_phu(ps.twilights[0]),
1093  "ESO INS FILT1 NAME");
1094  vircam_paf_append(pafprop,p,"ESO PRO CATG");
1095  vircam_paf_append(pafprop,p,"ESO PRO DATANCOM");
1096  vircam_paf_append(pafprop,p,"ESO DET NDIT");
1097  if (vircam_paf_print((char *)outfilepaf,
1098  "VIRCAM/vircam_twilight_flat_combine",
1099  "QC file",pafprop) != VIR_OK)
1100  cpl_msg_warning(fctid,"Unable to save PAF for mean twilight");
1101  cpl_propertylist_delete(pafprop);
1102  cpl_propertylist_delete(p);
1103 
1104  /* Now save the twilight ratio image extension */
1105 
1106  if (we_expect & RATIMG) {
1107  p = cpl_propertylist_duplicate(plist);
1108  if (! (we_get & RATIMG))
1110  cpl_propertylist_update_float(p,"ESO QC FLATRATIO_MED",
1111  vircam_twilight_flat_combine_config.flatratio_med);
1112  cpl_propertylist_set_comment(p,"ESO QC FLATRATIO_MED",
1113  "Median of ratio map");
1114  cpl_propertylist_update_float(p,"ESO QC FLATRATIO_RMS",
1115  vircam_twilight_flat_combine_config.flatratio_rms);
1116  cpl_propertylist_set_comment(p,"ESO QC FLATRATIO_RMS",
1117  "RMS of ratio map");
1118  vircam_dfs_set_product_exten_header(p,product_frame_ratioimg,
1119  framelist,parlist,(char *)recipeid,
1120  "PRO-1.15",NULL);
1121  if (cpl_image_save(ps.ratioimg,outdiff,CPL_TYPE_FLOAT,p,
1122  CPL_IO_EXTEND) != CPL_ERROR_NONE) {
1123  cpl_propertylist_delete(p);
1124  cpl_msg_error(fctid,"Cannot save product image extension");
1125  return(-1);
1126  }
1127 
1128  /* Write out PAF for difference image */
1129 
1130  pafprop = vircam_paf_req_items(p);
1131  vircam_merge_propertylists(pafprop,ps.phupaf);
1132  vircam_paf_append(pafprop,vircam_fits_get_phu(ps.twilights[0]),
1133  "ESO INS FILT1 NAME");
1134  vircam_paf_append(pafprop,p,"ESO PRO CATG");
1135  if (vircam_paf_print((char *)outdiffpaf,
1136  "VIRCAM/vircam_twilight_flat_combine",
1137  "QC file",pafprop) != VIR_OK)
1138  cpl_msg_warning(fctid,"Unable to save PAF for twilight ratio image");
1139  cpl_propertylist_delete(pafprop);
1140  cpl_propertylist_delete(p);
1141  }
1142 
1143  /* Now any further ratio image stats tables */
1144 
1145  if (! isfirst && (we_expect & STATS_TAB)) {
1146  p = cpl_propertylist_duplicate(plist);
1147  if (! (we_get & STATS_TAB))
1149  vircam_dfs_set_product_exten_header(p,product_frame_ratioimg_stats,
1150  framelist,parlist,(char *)recipeid,
1151  "PRO-1.15",NULL);
1152  status = VIR_OK;
1153  vircam_removewcs(p,&status);
1154  if (cpl_table_save(ps.ratioimstats,NULL,p,outdimst,CPL_IO_EXTEND)
1155  != CPL_ERROR_NONE) {
1156  cpl_msg_error(fctid,"Cannot save product table extension");
1157  cpl_propertylist_delete(p);
1158  return(-1);
1159  }
1160  cpl_propertylist_delete(p);
1161  }
1162 
1163  /* Fiddle with the header now */
1164 
1165  vircam_merge_propertylists(plist,ps.drs2);
1166  p = cpl_propertylist_duplicate(plist);
1167  if (! (we_get & CONFMAP))
1169 
1170  /* Now save the confidence map */
1171 
1172  vircam_dfs_set_product_exten_header(p,product_frame_conf,framelist,
1173  parlist,(char *)recipeid,"PRO-1.15",
1174  NULL);
1175  if (cpl_image_save(ps.outconf,outconf,CPL_TYPE_SHORT,p,
1176  CPL_IO_EXTEND) != CPL_ERROR_NONE) {
1177  cpl_msg_error(fctid,"Cannot save product image extension");
1178  cpl_propertylist_delete(p);
1179  return(-1);
1180  }
1181  cpl_propertylist_delete(p);
1182 
1183  /* Get out of here */
1184 
1185  return(0);
1186 }
1187 
1188 /*---------------------------------------------------------------------------*/
1192 /*---------------------------------------------------------------------------*/
1193 
1194 static void vircam_twilight_flat_combine_dummy_products(void) {
1195 
1196  /* See if you even need to be here */
1197 
1198  if (we_get == we_expect)
1199  return;
1200 
1201  /* First an output combined twilight frame */
1202 
1203  if (! (we_get & MEANTWI)) {
1204  ps.outimage = vircam_dummy_image(ps.twilights[0]);
1205  vircam_twilight_flat_combine_config.flatrms = 0.0;
1206  }
1207 
1208  /* Now the confidence map */
1209 
1210  if (! (we_get & CONFMAP)) {
1211  ps.outconf = vircam_dummy_image(ps.twilights[0]);
1212  vircam_twilight_flat_combine_config.flatrms = 0.0;
1213  }
1214 
1215  /* Do a ratio image */
1216 
1217  if ((we_expect & RATIMG) && ! (we_get & RATIMG)) {
1218  vircam_twilight_flat_combine_config.flatratio_med = 0.0;
1219  vircam_twilight_flat_combine_config.flatratio_rms = 0.0;
1220  ps.ratioimg = vircam_dummy_image(ps.twilights[0]);
1221  }
1222 
1223  /* If a ratio image stats table is required, then do that now */
1224 
1225  if ((we_expect & STATS_TAB) && ! (we_get & STATS_TAB))
1226  ps.ratioimstats = vircam_create_diffimg_stats(0);
1227 
1228  return;
1229 }
1230 
1231 /*---------------------------------------------------------------------------*/
1236 /*---------------------------------------------------------------------------*/
1237 
1238 static void vircam_twilight_flat_combine_normal(int jext) {
1239  int nx,ny,ncells,status;
1240  long i,npi;
1241  unsigned char *bpm;
1242  float *idata,med,sig,gdiff,grms;
1243  const char *fctid="vircam_twilight_flat_combine_normal";
1244 
1245  /* Load up a bad pixel mask */
1246 
1247  nx = (int)cpl_image_get_size_x(ps.outimage);
1248  ny = (int)cpl_image_get_size_y(ps.outimage);
1249  npi = nx*ny;
1250  vircam_mask_load(ps.master_mask,jext,nx,ny);
1251  bpm = vircam_mask_get_data(ps.master_mask);
1252 
1253  /* Create the bad pixel mask */
1254 
1255  status = VIR_OK;
1256  (void)vircam_mkconf(ps.outimage,(char *)"None Available",ps.master_mask,
1257  &(ps.outconf),&(ps.drs2),&status);
1258  if (status == VIR_OK)
1259  we_get |= CONFMAP;
1260  else {
1261  cpl_msg_info(fctid,
1262  "Confidence map creation failed extension %" CPL_SIZE_FORMAT,
1263  (cpl_size)jext);
1264  status = VIR_OK;
1265  }
1266 
1267  /* Work out the RMS of the mean twilight frame */
1268 
1269  idata = cpl_image_get_data(ps.outimage);
1270  vircam_medsig(idata,bpm,npi,&med,&sig);
1271 
1272  /* Fill in the bad bits... */
1273 
1274  for (i = 0; i < npi; i++)
1275  if (bpm[i])
1276  idata[i] = med;
1277 
1278  /* Divide through by the median */
1279 
1280  cpl_propertylist_update_float(ps.drs,"ESO DRS MEDFLAT",med);
1281  cpl_propertylist_set_comment(ps.drs,"ESO DRS MEDFLAT",
1282  "Median value before normalisation");
1283  cpl_image_divide_scalar(ps.outimage,med);
1284  vircam_medmad(idata,bpm,npi,&med,&sig);
1285  sig *= 1.48;
1286  vircam_twilight_flat_combine_config.flatrms = sig;
1287 
1288  /* Load up the master twilight flat */
1289 
1290  if (ps.master_twilight_flat != NULL) {
1291  ps.mfimage = vircam_fits_load(ps.master_twilight_flat,CPL_TYPE_FLOAT,jext);
1292  if (ps.mfimage == NULL) {
1293  cpl_msg_info(fctid,
1294  "Master twilight extension %" CPL_SIZE_FORMAT " won't load",
1295  (cpl_size)jext);
1296  } else if (vircam_is_dummy(vircam_fits_get_ehu(ps.mfimage))) {
1297  cpl_msg_info(fctid,
1298  "Master twilight extension %" CPL_SIZE_FORMAT " is a dummy",
1299  (cpl_size)jext);
1300  freefits(ps.mfimage);
1301  }
1302  } else
1303  ps.mfimage = NULL;
1304 
1305 
1306  /* Create a ratio image. NB: the difference image routine copes if the
1307  input mean image or the channel tables are null. Thus if either or
1308  both are null because of a failure to load, then the routine will do
1309  as much as it can and return, allowing you to fill in the rest with
1310  dummy products */
1311 
1312  vircam_twilight_flat_combine_config.flatratio_med = 0.0;
1313  vircam_twilight_flat_combine_config.flatratio_rms = 0.0;
1314  ncells = vircam_twilight_flat_combine_config.ncells;
1315  vircam_difference_image(vircam_fits_get_image(ps.mfimage),ps.outimage,bpm,
1316  vircam_tfits_get_table(ps.ctable),ncells,2,
1317  &gdiff,&grms,&(ps.ratioimg),
1318  &(ps.ratioimstats));
1319  vircam_mask_clear(ps.master_mask);
1320  vircam_twilight_flat_combine_config.flatratio_med = gdiff;
1321  vircam_twilight_flat_combine_config.flatratio_rms = grms;
1322  if (ps.ratioimg != NULL)
1323  we_get |= RATIMG;
1324  if (ps.ratioimstats != NULL)
1325  we_get |= STATS_TAB;
1326  return;
1327 }
1328 
1329 /*---------------------------------------------------------------------------*/
1337 /*---------------------------------------------------------------------------*/
1338 
1339 
1340 static int vircam_twilight_flat_combine_lastbit(int jext,
1341  cpl_frameset *framelist,
1342  cpl_parameterlist *parlist) {
1343  int retval;
1344  const char *fctid="vircam_twilight_flat_combine_lastbit";
1345 
1346  /* Make whatever dummy products you need */
1347 
1348  vircam_twilight_flat_combine_dummy_products();
1349 
1350  /* Save everything */
1351 
1352  cpl_msg_info(fctid,
1353  "Saving products for extension %" CPL_SIZE_FORMAT,
1354  (cpl_size)jext);
1355  retval = vircam_twilight_flat_combine_save(framelist,parlist);
1356  if (retval != 0) {
1357  vircam_twilight_flat_combine_tidy(2);
1358  return(-1);
1359  }
1360 
1361  /* Free some stuff up */
1362 
1363  vircam_twilight_flat_combine_tidy(1);
1364  return(0);
1365 }
1366 
1367 /*---------------------------------------------------------------------------*/
1371 /*---------------------------------------------------------------------------*/
1372 
1373 static void vircam_twilight_flat_combine_init(void) {
1374  ps.labels = NULL;
1375  ps.twilightlist = NULL;
1376  ps.twilights = NULL;
1377  ps.good = NULL;
1378  ps.master_dark = NULL;
1379  ps.master_twilight_flat = NULL;
1380  ps.master_mask = NULL;
1381  ps.chantab = NULL;
1382  ps.ctable = NULL;
1383  ps.outimage = NULL;
1384  ps.outconf = NULL;
1385  ps.drs = NULL;
1386  ps.drs2 = NULL;
1387  ps.rejmask = NULL;
1388  ps.rejplus = NULL;
1389  ps.mfimage = NULL;
1390  ps.ratioimg = NULL;
1391  ps.ratioimstats = NULL;
1392  ps.phupaf = NULL;
1393 }
1394 
1395 /*---------------------------------------------------------------------------*/
1399 /*---------------------------------------------------------------------------*/
1400 
1401 static void vircam_twilight_flat_combine_tidy(int level) {
1402  freeimage(ps.outimage);
1403  freeimage(ps.outconf);
1404  freefitslist(ps.twilights,ps.ntwilights);
1405  freepropertylist(ps.drs);
1406  freepropertylist(ps.drs2);
1407  freespace(ps.rejmask);
1408  freespace(ps.rejplus);
1409  freefits(ps.mfimage);
1410  freeimage(ps.ratioimg);
1411  freetable(ps.ratioimstats);
1412  freetfits(ps.ctable);
1413  freefits(ps.mdark);
1414  if (level == 1)
1415  return;
1416 
1417  freespace(ps.good);
1418  freespace(ps.labels);
1419  freeframeset(ps.twilightlist);
1420  freeframe(ps.master_dark);
1421  freeframe(ps.master_twilight_flat);
1422  freemask(ps.master_mask);
1423  freeframe(ps.chantab);
1424  freepropertylist(ps.phupaf);
1425 }
1426 
1429 /*
1430 
1431 $Log: not supported by cvs2svn $
1432 Revision 1.56 2012/01/15 17:40:09 jim
1433 Minor modifications to take into accout the changes in cpl API for v6
1434 
1435 Revision 1.55 2011/05/09 09:58:10 jim
1436 Cosmetic changes to stop compiler warnings
1437 
1438 Revision 1.54 2010/12/09 13:21:36 jim
1439 Added code to calculate rough photon noise and s/n ratio
1440 
1441 Revision 1.53 2010/03/21 06:48:21 jim
1442 Fixed bug where DATANCOM wasn't being updated in all products
1443 
1444 Revision 1.52 2010/03/09 14:27:40 jim
1445 Now updates ESO PRO DATANCOM to reflect the number of images used
1446 
1447 Revision 1.51 2010/02/05 09:42:22 jim
1448 Fixed call to non-existent cpl routine
1449 
1450 Revision 1.50 2010/01/31 18:53:22 jim
1451 Reference flat included in paf
1452 
1453 Revision 1.49 2009/12/11 06:52:56 jim
1454 Minor mods to documentation
1455 
1456 Revision 1.48 2009/11/18 21:32:40 jim
1457 Modified to write NDIT to the paf
1458 
1459 Revision 1.47 2009/09/21 11:59:37 jim
1460 Modified to use new version of vircam_overexp and to write ensemble stats
1461 to QC headers
1462 
1463 Revision 1.46 2009/09/09 09:50:21 jim
1464 Modified to try and get headers right
1465 
1466 Revision 1.45 2008/12/05 13:28:32 jim
1467 Fixed save routine so that the correct version of PRO CATG is written to the
1468 paf file
1469 
1470 Revision 1.44 2008/11/26 18:33:59 jim
1471 Now fills bad pixels in the output flat with a median value before normalisation
1472 
1473 Revision 1.43 2008/10/01 04:59:13 jim
1474 Added call to vircam_frameset_fexists to check input frameset
1475 
1476 Revision 1.42 2008/09/30 11:33:23 jim
1477 Added PRO CATG to pafs
1478 
1479 Revision 1.41 2008/09/29 11:21:47 jim
1480 Default is to form medians
1481 
1482 Revision 1.40 2007/11/26 09:59:06 jim
1483 Recipe now takes ndit into account when doing linearity correction
1484 
1485 Revision 1.39 2007/10/19 09:25:09 jim
1486 Fixed problems with missing includes
1487 
1488 Revision 1.38 2007/10/15 12:53:26 jim
1489 Modified for compatibiliity with cpl_4.0
1490 
1491 Revision 1.37 2007/07/18 15:35:42 jim
1492 Added better error handling for missing or corrupt mask extensions
1493 
1494 Revision 1.36 2007/07/09 13:21:56 jim
1495 Modified to use new version of vircam_exten_range
1496 
1497 Revision 1.35 2007/06/13 08:11:27 jim
1498 Modified docs to reflect changes in DFS tags
1499 
1500 Revision 1.34 2007/05/08 10:42:33 jim
1501 Added DRS MEDFLAT keyword
1502 
1503 Revision 1.33 2007/04/30 09:40:17 jim
1504 Added more stuff to paf files
1505 
1506 Revision 1.32 2007/04/04 10:36:18 jim
1507 Modified to use new dfs tags
1508 
1509 Revision 1.31 2007/03/29 12:19:39 jim
1510 Little changes to improve documentation
1511 
1512 Revision 1.30 2007/03/02 12:37:16 jim
1513 Removed WCS stuff from table headers
1514 
1515 Revision 1.29 2007/03/01 12:41:49 jim
1516 Modified slightly after code checking
1517 
1518 Revision 1.28 2007/02/25 06:27:41 jim
1519 plugged a few memory leaks
1520 
1521 Revision 1.27 2007/02/15 11:54:09 jim
1522 Modified to make a distinction between initial channel table and one that
1523 has the proper linearity information
1524 
1525 Revision 1.26 2007/02/15 06:59:38 jim
1526 Added ability to write QC paf files
1527 
1528 Revision 1.25 2007/02/07 10:12:40 jim
1529 Removed calls to vircam_ndit_correct as this is now no longer necessary
1530 
1531 Revision 1.24 2007/02/06 13:11:12 jim
1532 Fixed entry for PRO dictionary in cpl_dfs_set_product_header
1533 
1534 Revision 1.23 2007/02/05 14:14:05 jim
1535 Input master frame is now tagged as REFERENCE. QC removed from stats table
1536 headers
1537 
1538 Revision 1.22 2007/01/08 19:09:11 jim
1539 Fixed memory leak
1540 
1541 Revision 1.21 2006/12/13 13:26:09 jim
1542 Fxied bad sigma estimate
1543 
1544 Revision 1.20 2006/11/27 12:15:08 jim
1545 changed calls to cpl_propertylist_append to cpl_propertylist_update
1546 
1547 Revision 1.19 2006/11/10 09:24:49 jim
1548 Fixed bug in save routine where the wrong propertylist was being saved
1549 
1550 Revision 1.18 2006/09/29 11:19:31 jim
1551 changed aliases on parameter names
1552 
1553 Revision 1.17 2006/09/10 20:47:03 jim
1554 Small documentation fix
1555 
1556 Revision 1.16 2006/09/09 16:49:40 jim
1557 Header comment update
1558 
1559 Revision 1.15 2006/08/27 20:30:02 jim
1560 Major mods to structure of the main processing routine to deal with missing
1561 and dummy frames. Deals better with lower level failures too
1562 
1563 Revision 1.14 2006/07/11 14:55:12 jim
1564 Now checks for zeros in the output flat and replaces them
1565 
1566 Revision 1.13 2006/06/20 19:07:01 jim
1567 Corrects for ndit != 1
1568 
1569 Revision 1.12 2006/06/15 09:58:58 jim
1570 Minor changes to docs
1571 
1572 Revision 1.11 2006/06/09 11:26:25 jim
1573 Small changes to keep lint happy
1574 
1575 Revision 1.10 2006/06/06 13:01:40 jim
1576 Fixed so that the QC parameters go into the correct headers
1577 
1578 Revision 1.9 2006/05/26 19:34:18 jim
1579 Fixed recipe to normalise the flats
1580 
1581 Revision 1.8 2006/05/17 14:43:58 jim
1582 Fixed problem in save routine which messed up the PRO CATG keywords
1583 
1584 Revision 1.7 2006/05/16 13:58:47 jim
1585 Fixed memory leaks that occur from not closing images at the end of
1586 the image extension loop
1587 
1588 Revision 1.6 2006/05/09 08:54:40 jim
1589 Fixed _save routine so that the confidence map is saved as a signed 16 bit
1590 integer
1591 
1592 Revision 1.5 2006/05/08 14:54:03 jim
1593 Fixed little bug where the confidence map file name wasn't being declared to
1594 the header correctly
1595 
1596 Revision 1.4 2006/05/08 13:20:23 jim
1597 Fixed bug where the fitslist for the flats got deleted twice
1598 
1599 Revision 1.3 2006/05/04 11:53:15 jim
1600 Fixed the way the _save routine works to be more consistent with the
1601 standard CPL way of doing things
1602 
1603 Revision 1.2 2006/04/27 14:21:26 jim
1604 Renamed undefined tag
1605 
1606 Revision 1.1 2006/04/27 09:44:47 jim
1607 new file
1608 
1609 */
const char * vircam_get_license(void)
Definition: vircam_utils.c:92
void vircam_mask_force(vir_mask *m, int nx, int ny)
Definition: vircam_mask.c:385
cpl_table * vircam_tfits_get_table(vir_tfits *p)
Definition: vircam_tfits.c:364
int vircam_compare_tags(const cpl_frame *frame1, const cpl_frame *frame2)
Definition: vircam_utils.c:141
int vircam_chantab_verify(cpl_table *intab)
int vircam_is_dummy(cpl_propertylist *p)
void vircam_merge_propertylists(cpl_propertylist *p1, cpl_propertylist *p2)
vir_fits ** vircam_fits_load_list(cpl_frameset *f, cpl_type type, int exten)
Definition: vircam_fits.c:231
void vircam_medsig(float *data, unsigned char *bpm, long np, float *med, float *sig)
Definition: vircam_stats.c:756
cpl_frame * vircam_frameset_subgroup_1(cpl_frameset *frameset, cpl_size *labels, cpl_size nlab, const char *tag)
Definition: vircam_utils.c:247
void vircam_mask_clear(vir_mask *m)
Definition: vircam_mask.c:349
cpl_image * vircam_dummy_image(vir_fits *model)
int vircam_mkconf(cpl_image *flat, char *flatfile, vir_mask *bpm, cpl_image **outconf, cpl_propertylist **drs, int *status)
Create a confidence map.
int vircam_lincor(vir_fits *infile, vir_tfits *lchantab, int kconst, int ndit, int *status)
Apply linearity curves to data.
int vircam_mask_load(vir_mask *m, int nexten, int nx, int ny)
Definition: vircam_mask.c:210
char * vircam_fits_get_fullname(vir_fits *p)
Definition: vircam_fits.c:560
unsigned char * vircam_mask_get_data(vir_mask *m)
Definition: vircam_mask.c:535
cpl_image * vircam_fits_get_image(vir_fits *p)
Definition: vircam_fits.c:349
int vircam_darkcor(vir_fits *infile, vir_fits *darksrc, float darkscl, int *status)
Correct input data for dark current.
cpl_table * vircam_create_diffimg_stats(int nrows)
cpl_frameset * vircam_frameset_subgroup(cpl_frameset *frameset, cpl_size *labels, cpl_size nlab, const char *tag)
Definition: vircam_utils.c:193
void vircam_dfs_set_product_exten_header(cpl_propertylist *plist, cpl_frame *frame, cpl_frameset *frameset, cpl_parameterlist *parlist, char *recipeid, const char *dict, cpl_frame *inherit)
Definition: vircam_dfs.c:273
void vircam_dfs_set_product_primary_header(cpl_propertylist *plist, cpl_frame *frame, cpl_frameset *frameset, cpl_parameterlist *parlist, char *recipeid, const char *dict, cpl_frame *inherit, int synch)
Definition: vircam_dfs.c:203
int vircam_fits_set_error(vir_fits *p, int status)
Definition: vircam_fits.c:627
void vircam_medmad(float *data, unsigned char *bpm, long np, float *med, float *mad)
Definition: vircam_stats.c:625
int vircam_pfits_get_ndit(const cpl_propertylist *plist, int *ndit)
Get the value of NDIT.
Definition: vircam_pfits.c:583
void vircam_dummy_property(cpl_propertylist *p)
cpl_propertylist * vircam_fits_get_phu(vir_fits *p)
Definition: vircam_fits.c:416
vir_fits * vircam_fits_load(cpl_frame *frame, cpl_type type, int nexten)
Definition: vircam_fits.c:80
vir_tfits * vircam_tfits_load(cpl_frame *table, int nexten)
Definition: vircam_tfits.c:78
int vircam_nditcor(vir_fits *infile, int ndit, int *status)
Correct input data for dark current.
cpl_propertylist * vircam_fits_get_ehu(vir_fits *p)
Definition: vircam_fits.c:457
void vircam_overexp(vir_fits **fitslist, int *n, int ndit, float lthr, float hthr, int ditch, float *minv, float *maxv, float *avev)
int vircam_frameset_fexists(cpl_frameset *frameset)
Definition: vircam_utils.c:285
const char * vircam_mask_get_filename(vir_mask *m)
Definition: vircam_mask.c:438
vir_mask * vircam_mask_define(cpl_frameset *framelist, cpl_size *labels, cpl_size nlab)
Definition: vircam_mask.c:86
int vircam_pfits_get_detlive(const cpl_propertylist *plist, int *detlive)
Get the value of DET_LIVE.
Definition: vircam_pfits.c:624
int vircam_imcombine(vir_fits **fset, int nfits, int combtype, int scaletype, int xrej, float thresh, cpl_image **outimage, unsigned char **rejmask, unsigned char **rejplus, cpl_propertylist **drs, int *status)
Stack images into a mean or median image with rejection.
void vircam_exten_range(int inexten, const cpl_frame *fr, int *out1, int *out2)
Definition: vircam_utils.c:353
void vircam_difference_image(cpl_image *master, cpl_image *prog, unsigned char *bpm, cpl_table *chantab, int ncells, int oper, float *global_diff, float *global_rms, cpl_image **diffim, cpl_table **diffimstats)
Definition: vircam_utils.c:950
int vircam_removewcs(cpl_propertylist *p, int *status)
int vircam_dfs_set_groups(cpl_frameset *set)
Definition: vircam_dfs.c:87