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