VIRCAM Pipeline  2.3.10
vircam_reset_combine.c
1 /* $Id: vircam_reset_combine.c,v 1.60 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.60 $
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_mask.h>
40 #include <casu_stats.h>
41 #include <casu_wcsutils.h>
42 #include <casu_mods.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 the bit mask that flags dummy results */
52 
53 #define MEANRESET 1
54 #define DIFFIMG 2
55 #define STATS_TAB 4
56 
57 /* Function prototypes */
58 
59 static int vircam_reset_combine_create(cpl_plugin *) ;
60 static int vircam_reset_combine_exec(cpl_plugin *) ;
61 static int vircam_reset_combine_destroy(cpl_plugin *) ;
62 static int vircam_reset_combine(cpl_parameterlist *, cpl_frameset *) ;
63 static int vircam_reset_combine_save(cpl_frameset *framelist,
64  cpl_parameterlist *parlist);
65 static void vircam_reset_combine_dummy_products(void);
66 static void vircam_reset_combine_normal(int jext);
67 static int vircam_reset_combine_lastbit(int jext, cpl_frameset *framelist,
68  cpl_parameterlist *parlist);
69 static void vircam_reset_combine_init(void);
70 static void vircam_reset_combine_tidy(int level);
71 
72 /* Static global variables */
73 
74 static struct {
75 
76  /* Input */
77 
78  int combtype;
79  int scaletype;
80  int xrej;
81  float thresh;
82  int ncells;
83  int extenum;
84 
85  /* Output */
86 
87  float resetmed;
88  float resetrms;
89  float resetdiff_med;
90  float resetdiff_rms;
91 
92 } vircam_reset_combine_config ;
93 
94 static struct {
95  cpl_size *labels;
96  cpl_frameset *resetlist;
97  casu_fits **resets;
98  int nresets;
99  casu_fits **good;
100  int ngood;
101  cpl_frame *master_reset;
102  casu_mask *master_mask;
103  cpl_frame *chantab;
104  cpl_image *outimage;
105  cpl_propertylist *drs;
106  unsigned char *rejmask;
107  unsigned char *rejplus;
108  casu_fits *mrimage;
109  cpl_image *diffimg;
110  cpl_table *diffimstats;
111  cpl_propertylist *phupaf;
112 } ps;
113 
114 static int isfirst;
115 static cpl_frame *product_frame_mean_reset = NULL;
116 static cpl_frame *product_frame_diffimg = NULL;
117 static cpl_frame *product_frame_diffimg_stats = NULL;
118 static int we_expect;
119 static int we_get;
120 
121 static char vircam_reset_combine_description[] =
122 "vircam_reset_combine -- VIRCAM reset combine recipe.\n\n"
123 "Combine a list of reset frames into a mean reset frame. Optionally compare \n"
124 "the output frame to a master reset frame\n\n"
125 "The program requires the following files in the SOF:\n\n"
126 " Tag Description\n"
127 " -----------------------------------------------------------------------\n"
128 " %-21s A list of raw reset images\n"
129 " %-21s Optional reference reset frame\n"
130 " %-21s Optional master bad pixel map or\n"
131 " %-21s Optional master confidence map\n"
132 " %-21s Optional channel table or\n"
133 " %-21s Optional initial channel table\n"
134 "\n"
135 "If no master reset frame is made available, then no comparison will be done\n"
136 "This means there will be no output difference image. If a master reset is\n"
137 "available, but no channel table is, then a difference image will be formed\n"
138 "but no stats will be written."
139 "\n";
140 
255 /* Function code */
256 
257 /*---------------------------------------------------------------------------*/
265 /*---------------------------------------------------------------------------*/
266 
267 int cpl_plugin_get_info(cpl_pluginlist *list) {
268  cpl_recipe *recipe = cpl_calloc(1,sizeof(*recipe));
269  cpl_plugin *plugin = &recipe->interface;
270  char alldesc[SZ_ALLDESC];
271  (void)snprintf(alldesc,SZ_ALLDESC,vircam_reset_combine_description,
272  VIRCAM_RESET_RAW,VIRCAM_REF_RESET,VIRCAM_CAL_BPM,
273  VIRCAM_CAL_CONF,VIRCAM_CAL_CHANTAB,VIRCAM_CAL_CHANTAB_INIT);
274 
275  cpl_plugin_init(plugin,
276  CPL_PLUGIN_API,
277  VIRCAM_BINARY_VERSION,
278  CPL_PLUGIN_TYPE_RECIPE,
279  "vircam_reset_combine",
280  "VIRCAM reset combination recipe",
281  alldesc,
282  "Jim Lewis",
283  "jrl@ast.cam.ac.uk",
285  vircam_reset_combine_create,
286  vircam_reset_combine_exec,
287  vircam_reset_combine_destroy);
288 
289  cpl_pluginlist_append(list,plugin);
290 
291  return(0);
292 }
293 
294 /*---------------------------------------------------------------------------*/
303 /*---------------------------------------------------------------------------*/
304 
305 static int vircam_reset_combine_create(cpl_plugin *plugin) {
306  cpl_recipe *recipe;
307  cpl_parameter *p;
308 
309  /* Get the recipe out of the plugin */
310 
311  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
312  recipe = (cpl_recipe *)plugin;
313  else
314  return(-1);
315 
316  /* Create the parameters list in the cpl_recipe object */
317 
318  recipe->parameters = cpl_parameterlist_new();
319 
320  /* Fill in the parameters. First the combination type */
321 
322  p = cpl_parameter_new_range("vircam.vircam_reset_combine.combtype",
323  CPL_TYPE_INT,
324  "1 == Median,\n 2 == Mean",
325  "vircam.vircam_reset_combine",
326  1,1,2);
327  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"combtype");
328  cpl_parameterlist_append(recipe->parameters,p);
329 
330  /* The requested scaling */
331 
332  p = cpl_parameter_new_range("vircam.vircam_reset_combine.scaletype",
333  CPL_TYPE_INT,
334  "0 == none,\n 1 == additive offset,\n 2 == multiplicative offset,\n 3 == exposure time scaling + additive offset",
335  "vircam.vircam_reset_combine",
336  1,0,3);
337  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"scaletype");
338  cpl_parameterlist_append(recipe->parameters,p);
339 
340  /* Extra rejection cycle */
341 
342  p = cpl_parameter_new_value("vircam.vircam_reset_combine.xrej",
343  CPL_TYPE_BOOL,
344  "True if using extra rejection cycle",
345  "vircam.vircam_reset_combine",
346  TRUE);
347  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"xrej");
348  cpl_parameterlist_append(recipe->parameters,p);
349 
350  /* Rejection threshold */
351 
352  p = cpl_parameter_new_value("vircam.vircam_reset_combine.thresh",
353  CPL_TYPE_DOUBLE,
354  "Rejection threshold in sigma above background",
355  "vircam.vircam_reset_combine",5.0);
356  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"thresh");
357  cpl_parameterlist_append(recipe->parameters,p);
358 
359  /* How many cells to divide each data channel */
360 
361  p = cpl_parameter_new_enum("vircam.vircam_reset_combine.ncells",
362  CPL_TYPE_INT,
363  "Number of cells for data channel stats",
364  "vircam.vircam_reset_combine",8,7,1,2,4,8,
365  16,32,64);
366  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ncells");
367  cpl_parameterlist_append(recipe->parameters,p);
368 
369  /* Extension number of input frames to use */
370 
371  p = cpl_parameter_new_range("vircam.vircam_reset_combine.extenum",
372  CPL_TYPE_INT,
373  "Extension number to be done, 0 == all",
374  "vircam.vircam_reset_combine",
375  0,0,16);
376  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ext");
377  cpl_parameterlist_append(recipe->parameters,p);
378 
379  /* Get out of here */
380 
381  return(0);
382 }
383 
384 
385 /*---------------------------------------------------------------------------*/
391 /*---------------------------------------------------------------------------*/
392 
393 static int vircam_reset_combine_exec(cpl_plugin *plugin) {
394  cpl_recipe *recipe;
395 
396  /* Get the recipe out of the plugin */
397 
398  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
399  recipe = (cpl_recipe *)plugin;
400  else
401  return(-1);
402 
403  return(vircam_reset_combine(recipe->parameters,recipe->frames));
404 }
405 
406 /*---------------------------------------------------------------------------*/
412 /*---------------------------------------------------------------------------*/
413 
414 static int vircam_reset_combine_destroy(cpl_plugin *plugin) {
415  cpl_recipe *recipe ;
416 
417  /* Get the recipe out of the plugin */
418 
419  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
420  recipe = (cpl_recipe *)plugin;
421  else
422  return(-1);
423 
424  cpl_parameterlist_delete(recipe->parameters);
425  return(0);
426 }
427 
428 /*---------------------------------------------------------------------------*/
435 /*---------------------------------------------------------------------------*/
436 
437 static int vircam_reset_combine(cpl_parameterlist *parlist,
438  cpl_frameset *framelist) {
439  const char *fctid="vircam_reset_combine";
440  int j,jst,jfn,retval,status,i,live,nx,ny;
441  cpl_size nlab;
442  cpl_parameter *p;
443  casu_fits *ff;
444 
445  /* Check validity of input frameset */
446 
447  if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
448  cpl_msg_error(fctid,"Input framelist NULL or has no input data");
449  return(-1);
450  }
451 
452  /* Initialise a few things */
453 
454  vircam_reset_combine_init();
455  we_expect |= MEANRESET;
456 
457  /* Get the parameters */
458 
459  p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.combtype");
460  vircam_reset_combine_config.combtype = cpl_parameter_get_int(p);
461  p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.scaletype");
462  vircam_reset_combine_config.scaletype = cpl_parameter_get_int(p);
463  p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.xrej");
464  vircam_reset_combine_config.xrej = cpl_parameter_get_bool(p);
465  p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.thresh");
466  vircam_reset_combine_config.thresh = (float)cpl_parameter_get_double(p);
467  p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.ncells");
468  vircam_reset_combine_config.ncells = cpl_parameter_get_int(p);
469  p = cpl_parameterlist_find(parlist,"vircam.vircam_reset_combine.extenum");
470  vircam_reset_combine_config.extenum = cpl_parameter_get_int(p);
471 
472  /* Sort out raw from calib frames */
473 
474  if (vircam_dfs_set_groups(framelist) != CASU_OK) {
475  cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
476  return(-1);
477  }
478 
479  /* Get the reset frames */
480 
481  if ((ps.labels = cpl_frameset_labelise(framelist,casu_compare_tags,
482  &nlab)) == NULL) {
483  cpl_msg_error(fctid,"Cannot labelise the input frames");
484  return(-1);
485  }
486  if ((ps.resetlist = casu_frameset_subgroup(framelist,ps.labels,nlab,
487  VIRCAM_RESET_RAW)) == NULL) {
488  cpl_msg_error(fctid,"Cannot find reset frames in input frameset");
489  return(-1);
490  }
491  ps.nresets = cpl_frameset_get_size(ps.resetlist);
492 
493  /* Check to see if there is a master reset frame */
494 
495  if ((ps.master_reset = casu_frameset_subgroup_1(framelist,ps.labels,nlab,
496  VIRCAM_REF_RESET)) == NULL)
497  cpl_msg_info(fctid,"No master reset found -- no difference image will be formed");
498  else
499  we_expect |= DIFFIMG;
500 
501  /* Check to see if there is a master bad pixel map. If there isn't one
502  then look for a confidence map */
503 
504  ps.master_mask = casu_mask_define(framelist,ps.labels,nlab,VIRCAM_CAL_CONF,
505  VIRCAM_CAL_BPM);
506 
507  /* Check to see if there is a channel table */
508 
509  if ((ps.chantab = casu_frameset_subgroup_1(framelist,ps.labels,nlab,
510  VIRCAM_CAL_CHANTAB)) == NULL) {
511  if ((ps.chantab = casu_frameset_subgroup_1(framelist,ps.labels,nlab,
512  VIRCAM_CAL_CHANTAB_INIT)) == NULL)
513  cpl_msg_info(fctid,"No channel table found -- no difference image stats will be done");
514  } else if (we_expect & DIFFIMG)
515  we_expect |= STATS_TAB;
516 
517  /* Now, how many image extensions do we want to do? If the extension
518  number is zero, then we loop for all possible extensions. If it
519  isn't then we just do the extension specified */
520 
521  vircam_exten_range(vircam_reset_combine_config.extenum,
522  (const cpl_frame *)cpl_frameset_get_position(ps.resetlist,0),
523  &jst,&jfn);
524  if (jst == -1 || jfn == -1) {
525  cpl_msg_error(fctid,"Unable to continue");
526  vircam_reset_combine_tidy(2);
527  return(-1);
528  }
529 
530  /* Get some space for the good frames */
531 
532  ps.good = cpl_malloc(ps.nresets*sizeof(casu_fits *));
533 
534  /* Now loop for all the extension... */
535 
536  for (j = jst; j <= jfn; j++) {
537  status = CASU_OK;
538  we_get = 0;
539  isfirst = (j == jst);
540 
541  /* Load up the images. If they won't load the signal a major error */
542 
543  ps.resets = casu_fits_load_list(ps.resetlist,CPL_TYPE_FLOAT,j);
544  if (ps.resets == NULL) {
545  cpl_msg_info(fctid,
546  "Extension %" CPL_SIZE_FORMAT " resets wouldn't load",
547  (cpl_size)j);
548  retval = vircam_reset_combine_lastbit(j,framelist,parlist);
549  if (retval != 0)
550  return(-1);
551  continue;
552  }
553 
554  /* Are any of these reset images good? */
555 
556  ps.ngood = 0;
557  for (i = 0; i < ps.nresets; i++) {
558  ff = ps.resets[i];
560  if (! live) {
561  cpl_msg_info(fctid,"Detector flagged dead %s",
563  casu_fits_set_error(ff,CASU_FATAL);
564  } else {
565  ps.good[ps.ngood] = ff;
566  ps.ngood += 1;
567  }
568  }
569 
570  /* If there are no good images, then signal that wee need to
571  create some dummy products and move on */
572 
573  if (ps.ngood == 0) {
574  cpl_msg_info(fctid,"All images flagged bad for this extension");
575  retval = vircam_reset_combine_lastbit(j,framelist,parlist);
576  if (retval != 0)
577  return(-1);
578  continue;
579  }
580 
581  /* Load the mask */
582 
583  nx = (int)cpl_image_get_size_x(casu_fits_get_image(ps.good[0]));
584  ny = (int)cpl_image_get_size_y(casu_fits_get_image(ps.good[0]));
585  if (casu_mask_load(ps.master_mask,j,nx,ny) == CASU_FATAL) {
586  cpl_msg_info(fctid,
587  "Unable to load mask image %s[%" CPL_SIZE_FORMAT "]",
588  casu_mask_get_filename(ps.master_mask),
589  (cpl_size)j);
590  cpl_msg_info(fctid,"Forcing all pixels to be good from now on");
591  casu_mask_force(ps.master_mask,nx,ny);
592  }
593 
594  /* Call the combine module. If it fails then signal that
595  all products will be dummies */
596 
597  cpl_msg_info(fctid,"Doing combination for extension %" CPL_SIZE_FORMAT,
598  (cpl_size)j);
599  (void)casu_imcombine(ps.good,NULL,ps.ngood,
600  vircam_reset_combine_config.combtype,
601  vircam_reset_combine_config.scaletype,
602  vircam_reset_combine_config.xrej,
603  vircam_reset_combine_config.thresh,"EXPTIME",
604  &(ps.outimage),NULL,&(ps.rejmask),
605  &(ps.rejplus),&(ps.drs),&status);
606  if (status == CASU_OK) {
607  we_get |= MEANRESET;
608  vircam_reset_combine_normal(j);
609  }
610 
611  /* Create any dummies and save products */
612 
613  retval = vircam_reset_combine_lastbit(j,framelist,parlist);
614  if (retval != 0)
615  return(-1);
616  }
617  vircam_reset_combine_tidy(2);
618  return(0);
619 }
620 
621 /*---------------------------------------------------------------------------*/
628 /*---------------------------------------------------------------------------*/
629 
630 static int vircam_reset_combine_save(cpl_frameset *framelist,
631  cpl_parameterlist *parlist) {
632  cpl_propertylist *plist,*elist,*p,*pafprop;
633  const char *fctid = "vircam_reset_combine_save";
634  const char *outfile = "resetcomb.fits";
635  const char *outdiff = "resetdiff.fits";
636  const char *outdimst = "resetdifftab.fits";
637  const char *outfilepaf = "resetcomb";
638  const char *outdiffpaf = "resetdiff";
639  const char *recipeid = "vircam_reset_combine";
640 
641  /* If we need to make a PHU then do that now based on the first frame
642  in the input frame list */
643 
644  if (isfirst) {
645 
646  /* Create a new product frame object and define some tags */
647 
648  product_frame_mean_reset = cpl_frame_new();
649  cpl_frame_set_filename(product_frame_mean_reset,outfile);
650  cpl_frame_set_tag(product_frame_mean_reset,VIRCAM_PRO_RESET);
651  cpl_frame_set_type(product_frame_mean_reset,CPL_FRAME_TYPE_IMAGE);
652  cpl_frame_set_group(product_frame_mean_reset,CPL_FRAME_GROUP_PRODUCT);
653  cpl_frame_set_level(product_frame_mean_reset,CPL_FRAME_LEVEL_FINAL);
654 
655  /* Set up product phu */
656 
657  plist = casu_fits_get_phu(ps.resets[0]);
658  ps.phupaf = vircam_paf_phu_items(plist);
659  if (ps.master_reset != NULL) {
660  cpl_propertylist_update_string(ps.phupaf,"REF_RESET",
661  cpl_frame_get_filename(ps.master_reset));
662  cpl_propertylist_set_comment(ps.phupaf,"REF_RESET",
663  "Reference reset used");
664  }
665  vircam_dfs_set_product_primary_header(plist,product_frame_mean_reset,
666  framelist,parlist,
667  (char *)recipeid,
668  "PRO-1.15",NULL,0);
669 
670  /* 'Save' the PHU image */
671 
672  if (cpl_image_save(NULL,outfile,CPL_TYPE_UCHAR,plist,
673  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
674  cpl_msg_error(fctid,"Cannot save product PHU");
675  cpl_frame_delete(product_frame_mean_reset);
676  return(-1);
677  }
678  cpl_frameset_insert(framelist,product_frame_mean_reset);
679 
680  /* Create a new product frame object for the difference image */
681 
682  if (we_expect & DIFFIMG) {
683  product_frame_diffimg = cpl_frame_new();
684  cpl_frame_set_filename(product_frame_diffimg,outdiff);
685  cpl_frame_set_tag(product_frame_diffimg,
686  VIRCAM_PRO_DIFFIMG_RESET);
687  cpl_frame_set_type(product_frame_diffimg,CPL_FRAME_TYPE_IMAGE);
688  cpl_frame_set_group(product_frame_diffimg,CPL_FRAME_GROUP_PRODUCT);
689  cpl_frame_set_level(product_frame_diffimg,CPL_FRAME_LEVEL_FINAL);
690 
691  /* Set up product phu */
692 
693  plist = casu_fits_get_phu(ps.resets[0]);
694  vircam_dfs_set_product_primary_header(plist,product_frame_diffimg,
695  framelist,parlist,
696  (char *)recipeid,
697  "PRO-1.15",NULL,0);
698  /* 'Save' the PHU image */
699 
700  if (cpl_image_save(NULL,outdiff,CPL_TYPE_UCHAR,plist,
701  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
702  cpl_msg_error(fctid,"Cannot save product PHU");
703  cpl_frame_delete(product_frame_diffimg);
704  return(-1);
705  }
706  cpl_frameset_insert(framelist,product_frame_diffimg);
707  }
708 
709  /* Create a new product frame object for the difference image stats
710  table */
711 
712  if (we_expect & STATS_TAB) {
713  product_frame_diffimg_stats = cpl_frame_new();
714  cpl_frame_set_filename(product_frame_diffimg_stats,outdimst);
715  cpl_frame_set_tag(product_frame_diffimg_stats,
716  VIRCAM_PRO_DIFFIMG_RESET_STATS);
717  cpl_frame_set_type(product_frame_diffimg_stats,
718  CPL_FRAME_TYPE_TABLE);
719  cpl_frame_set_group(product_frame_diffimg_stats,
720  CPL_FRAME_GROUP_PRODUCT);
721  cpl_frame_set_level(product_frame_diffimg_stats,
722  CPL_FRAME_LEVEL_FINAL);
723 
724  /* Set up product phu */
725 
726  plist = casu_fits_get_phu(ps.resets[0]);
728  product_frame_diffimg_stats,
729  framelist,parlist,
730  (char *)recipeid,
731  "PRO-1.15",NULL,0);
732 
733  /* Fiddle with the extension header */
734 
735  elist = casu_fits_get_ehu(ps.resets[0]);
736  p = cpl_propertylist_duplicate(elist);
737  casu_merge_propertylists(p,ps.drs);
738  if (! (we_get & STATS_TAB))
740  casu_removewcs(p, &(int){CASU_OK});
741  vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
742  framelist,parlist,
743  (char *)recipeid,
744  "PRO-1.15",NULL);
745  if (cpl_table_save(ps.diffimstats,plist,p,outdimst,
746  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
747  cpl_msg_error(fctid,"Cannot save product table extension");
748  cpl_propertylist_delete(p);
749  return(-1);
750  }
751  cpl_propertylist_delete(p);
752  cpl_frameset_insert(framelist,product_frame_diffimg_stats);
753  }
754  }
755 
756  /* Get the extension property list */
757 
758  plist = casu_fits_get_ehu(ps.resets[0]);
759  cpl_propertylist_update_int(plist,"ESO PRO DATANCOM",ps.ngood);
760 
761  /* Fiddle with the header now */
762 
763  casu_merge_propertylists(plist,ps.drs);
764  p = cpl_propertylist_duplicate(plist);
765  if (! (we_get & MEANRESET))
767  vircam_dfs_set_product_exten_header(p,product_frame_mean_reset,framelist,
768  parlist,(char *)recipeid,"PRO-1.15",
769  NULL);
770 
771  /* Now save the reset image extension */
772 
773  cpl_propertylist_update_float(p,"ESO QC RESETMED",
774  vircam_reset_combine_config.resetmed);
775  cpl_propertylist_set_comment(p,"ESO QC RESETMED",
776  "Median of mean reset frame");
777  cpl_propertylist_update_float(p,"ESO QC RESETRMS",
778  vircam_reset_combine_config.resetrms);
779  cpl_propertylist_set_comment(p,"ESO QC RESETRMS",
780  "RMS of mean reset frame");
781  if (cpl_image_save(ps.outimage,outfile,CPL_TYPE_FLOAT,p,
782  CPL_IO_EXTEND) != CPL_ERROR_NONE) {
783  cpl_msg_error(fctid,"Cannot save product image extension");
784  cpl_propertylist_delete(p);
785  return(-1);
786  }
787 
788  /* Write out PAF for mean image */
789 
790  pafprop = vircam_paf_req_items(p);
791  casu_merge_propertylists(pafprop,ps.phupaf);
792  vircam_paf_append(pafprop,p,"ESO PRO CATG");
793  vircam_paf_append(pafprop,p,"ESO PRO DATANCOM");
794  if (vircam_paf_print((char *)outfilepaf,"VIRCAM/vircam_reset_combine",
795  "QC file",pafprop) != CASU_OK)
796  cpl_msg_warning(fctid,"Unable to save PAF for mean reset");
797  cpl_propertylist_delete(pafprop);
798  cpl_propertylist_delete(p);
799 
800  /* Now save the reset difference image extension */
801 
802  if (we_expect & DIFFIMG) {
803  p = cpl_propertylist_duplicate(plist);
804  if (! (we_get & DIFFIMG))
806  cpl_propertylist_update_float(p,"ESO QC RESETDIFF_MED",
807  vircam_reset_combine_config.resetdiff_med);
808  cpl_propertylist_set_comment(p,"ESO QC RESETDIFF_MED",
809  "Median value of difference image");
810  cpl_propertylist_update_float(p,"ESO QC RESETDIFF_RMS",
811  vircam_reset_combine_config.resetdiff_rms);
812  cpl_propertylist_set_comment(p,"ESO QC RESETDIFF_RMS",
813  "RMS value of difference image");
814  vircam_dfs_set_product_exten_header(p,product_frame_diffimg,
815  framelist,parlist,(char *)recipeid,
816  "PRO-1.15",NULL);
817  if (cpl_image_save(ps.diffimg,outdiff,CPL_TYPE_FLOAT,p,
818  CPL_IO_EXTEND) != CPL_ERROR_NONE) {
819  cpl_propertylist_delete(p);
820  cpl_msg_error(fctid,"Cannot save product image extension");
821  return(-1);
822  }
823  /* Write out PAF for difference image */
824 
825  pafprop = vircam_paf_req_items(p);
826  casu_merge_propertylists(pafprop,ps.phupaf);
827  vircam_paf_append(pafprop,p,"ESO PRO CATG");
828  if (vircam_paf_print((char *)outdiffpaf,"VIRCAM/vircam_reset_combine",
829  "QC file",pafprop) != CASU_OK)
830  cpl_msg_warning(fctid,"Unable to save PAF for difference image");
831  cpl_propertylist_delete(pafprop);
832  cpl_propertylist_delete(p);
833  }
834 
835  /* Now any further difference image stats tables */
836 
837  if (! isfirst && (we_expect & STATS_TAB)) {
838  p = cpl_propertylist_duplicate(plist);
839  if (! (we_get & STATS_TAB))
841  casu_removewcs(p, &(int){CASU_OK});
842  vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
843  framelist,parlist,(char *)recipeid,
844  "PRO-1.15",NULL);
845  if (cpl_table_save(ps.diffimstats,NULL,p,outdimst,CPL_IO_EXTEND)
846  != CPL_ERROR_NONE) {
847  cpl_msg_error(fctid,"Cannot save product table extension");
848  cpl_propertylist_delete(p);
849  return(-1);
850  }
851  cpl_propertylist_delete(p);
852  }
853 
854  return(0);
855 }
856 
857 /*---------------------------------------------------------------------------*/
861 /*---------------------------------------------------------------------------*/
862 
863 static void vircam_reset_combine_dummy_products(void) {
864 
865  /* See if you even need to be here */
866 
867  if (we_get == we_expect)
868  return;
869 
870  /* First an output combined reset frame */
871 
872  if (! (we_get & MEANRESET)) {
873  ps.outimage = casu_dummy_image(ps.resets[0]);
874 
875  /* Set up the QC parameters */
876 
877  vircam_reset_combine_config.resetmed = 0.0;
878  vircam_reset_combine_config.resetrms = 0.0;
879  }
880 
881  /* Do the difference image */
882 
883  if ((we_expect & DIFFIMG) && ! (we_get & DIFFIMG)) {
884  vircam_reset_combine_config.resetdiff_med = 0.0;
885  vircam_reset_combine_config.resetdiff_rms = 0.0;
886 
887  /* Is a difference image required? If so then let's have it... */
888 
889  ps.diffimg = casu_dummy_image(ps.resets[0]);
890  }
891 
892  /* If a difference image stats table is required, then do that now */
893 
894  if ((we_expect & STATS_TAB) && ! (we_get & STATS_TAB))
895  ps.diffimstats = vircam_create_diffimg_stats(0);
896 
897 
898  return;
899 }
900 
901 /*---------------------------------------------------------------------------*/
906 /*---------------------------------------------------------------------------*/
907 
908 static void vircam_reset_combine_normal(int jext) {
909  int nx,ny,ncells;
910  long npi;
911  unsigned char *bpm;
912  float med,sig,*idata,grms,gdiff;
913  const char *fctid="vircam_reset_combine_normal";
914  cpl_table *ctable;
915  cpl_propertylist *p;
916 
917  /* Load up the bad pixel mask */
918 
919  nx = (int)cpl_image_get_size_x(ps.outimage);
920  ny = (int)cpl_image_get_size_y(ps.outimage);
921  npi = nx*ny;
922  bpm = casu_mask_get_data(ps.master_mask);
923 
924  /* Work out the RMS of the mean reset frame */
925 
926  idata = cpl_image_get_data(ps.outimage);
927  casu_medmad(idata,bpm,npi,&med,&sig);
928  sig *= 1.48;
929  vircam_reset_combine_config.resetmed = med;
930  vircam_reset_combine_config.resetrms = sig;
931 
932  /* Load up the master reset */
933 
934  if (ps.master_reset != NULL) {
935  ps.mrimage = casu_fits_load(ps.master_reset,CPL_TYPE_FLOAT,jext);
936  if (ps.mrimage == NULL)
937  cpl_msg_info(fctid,
938  "Master reset extension %" CPL_SIZE_FORMAT " won't load",
939  (cpl_size)jext);
940  else if (vircam_is_dummy(casu_fits_get_ehu(ps.mrimage))) {
941  cpl_msg_info(fctid,
942  "Master reset extension %" CPL_SIZE_FORMAT " is a dummy!",
943  (cpl_size)jext);
944  freefits(ps.mrimage);
945  }
946  } else
947  ps.mrimage = NULL;
948 
949  /* Load up the channel table */
950 
951  if (ps.chantab != NULL) {
952  ctable = cpl_table_load(cpl_frame_get_filename(ps.chantab),jext,0);
953  if (ctable == NULL) {
954  cpl_error_reset();
955  cpl_msg_info(fctid,
956  "Channel table extension %" CPL_SIZE_FORMAT " won't load",
957  (cpl_size)jext);
958  } else if (vircam_chantab_verify(ctable) != CASU_OK) {
959  cpl_msg_info(fctid,
960  "Channel table extension %" CPL_SIZE_FORMAT " has errors",
961  (cpl_size)jext);
962  freetable(ctable);
963  } else {
964  p = cpl_propertylist_load(cpl_frame_get_filename(ps.chantab),
965  (cpl_size)jext);
966  if (vircam_is_dummy(p)) {
967  cpl_msg_info(fctid,
968  "Channel table extensions %" CPL_SIZE_FORMAT " is a dummy",
969  (cpl_size)jext);
970  freetable(ctable);
971  }
972  freepropertylist(p);
973  }
974  } else
975  ctable = NULL;
976 
977  /* Form the difference image. NB: the difference image routine
978  copes if the input mean image and or the channel tables are
979  null. Thus if either or both are null because of a failure
980  to load then the routine will do as much as it can and return
981  allowing you to fill in the rest with dummy products */
982 
983  vircam_reset_combine_config.resetdiff_med = 0.0;
984  vircam_reset_combine_config.resetdiff_rms = 0.0;
985  ncells = vircam_reset_combine_config.ncells;
987  ps.outimage,bpm,ctable,ncells,1,
988  &gdiff,&grms,&(ps.diffimg),
989  &(ps.diffimstats));
990  casu_mask_clear(ps.master_mask);
991  vircam_reset_combine_config.resetdiff_med = gdiff;
992  vircam_reset_combine_config.resetdiff_rms = grms;
993  freetable(ctable);
994  if (ps.diffimg != NULL)
995  we_get |= DIFFIMG;
996  if (ps.diffimstats != NULL)
997  we_get |= STATS_TAB;
998  return;
999 }
1000 
1001 /*---------------------------------------------------------------------------*/
1009 /*---------------------------------------------------------------------------*/
1010 
1011 static int vircam_reset_combine_lastbit(int jext, cpl_frameset *framelist,
1012  cpl_parameterlist *parlist) {
1013  int retval;
1014  const char *fctid="vircam_reset_combine_lastbit";
1015 
1016  /* Make whatever dummy products you need */
1017 
1018  vircam_reset_combine_dummy_products();
1019 
1020  /* Save everything */
1021 
1022  cpl_msg_info(fctid,
1023  "Saving products for extension %" CPL_SIZE_FORMAT,
1024  (cpl_size)jext);
1025  retval = vircam_reset_combine_save(framelist,parlist);
1026  if (retval != 0) {
1027  vircam_reset_combine_tidy(2);
1028  return(-1);
1029  }
1030 
1031  /* Free some stuff up */
1032 
1033  vircam_reset_combine_tidy(1);
1034  return(0);
1035 }
1036 
1037 /*---------------------------------------------------------------------------*/
1041 /*---------------------------------------------------------------------------*/
1042 
1043 static void vircam_reset_combine_init(void) {
1044  ps.labels = NULL;
1045  ps.resetlist = NULL;
1046  ps.resets = NULL;
1047  ps.nresets = 0;
1048  ps.good = NULL;
1049  ps.master_reset = NULL;
1050  ps.master_mask = NULL;
1051  ps.chantab = NULL;
1052  ps.outimage = NULL;
1053  ps.drs = NULL;
1054  ps.rejmask = NULL;
1055  ps.rejplus = NULL;
1056  ps.mrimage = NULL;
1057  ps.diffimg = NULL;
1058  ps.diffimstats = NULL;
1059  ps.phupaf = NULL;
1060 }
1061 
1062 /*---------------------------------------------------------------------------*/
1066 /*---------------------------------------------------------------------------*/
1067 
1068 static void vircam_reset_combine_tidy(int level) {
1069  freeimage(ps.outimage);
1070  freefitslist(ps.resets,ps.nresets);
1071  freespace(ps.rejmask);
1072  freespace(ps.rejplus);
1073  freepropertylist(ps.drs);
1074  freefits(ps.mrimage);
1075  freeimage(ps.diffimg);
1076  freetable(ps.diffimstats);
1077  if (level == 1)
1078  return;
1079  freespace(ps.labels);
1080  freeframeset(ps.resetlist);
1081  freeframe(ps.master_reset);
1082  freemask(ps.master_mask);
1083  freeframe(ps.chantab);
1084  freespace(ps.good);
1085  freepropertylist(ps.phupaf);
1086 }
1087 
1090 /*
1091 
1092 $Log: not supported by cvs2svn $
1093 Revision 1.59 2012/01/15 17:40:09 jim
1094 Minor modifications to take into accout the changes in cpl API for v6
1095 
1096 Revision 1.58 2010/03/21 06:48:21 jim
1097 Fixed bug where DATANCOM wasn't being updated in all products
1098 
1099 Revision 1.57 2010/03/09 14:27:40 jim
1100 Now updates ESO PRO DATANCOM to reflect the number of images used
1101 
1102 Revision 1.56 2010/02/05 09:42:22 jim
1103 Fixed call to non-existent cpl routine
1104 
1105 Revision 1.55 2010/01/31 18:54:01 jim
1106 Reference reset included in paf
1107 
1108 Revision 1.54 2009/09/09 09:50:21 jim
1109 Modified to try and get headers right
1110 
1111 Revision 1.53 2008/12/05 13:28:32 jim
1112 Fixed save routine so that the correct version of PRO CATG is written to the
1113 paf file
1114 
1115 Revision 1.52 2008/10/01 04:59:13 jim
1116 Added call to vircam_frameset_fexists to check input frameset
1117 
1118 Revision 1.51 2008/09/30 11:33:23 jim
1119 Added PRO CATG to pafs
1120 
1121 Revision 1.50 2007/10/19 09:25:09 jim
1122 Fixed problems with missing includes
1123 
1124 Revision 1.49 2007/10/15 12:53:26 jim
1125 Modified for compatibiliity with cpl_4.0
1126 
1127 Revision 1.48 2007/07/18 15:35:42 jim
1128 Added better error handling for missing or corrupt mask extensions
1129 
1130 Revision 1.47 2007/07/09 13:21:56 jim
1131 Modified to use new version of vircam_exten_range
1132 
1133 Revision 1.46 2007/04/04 10:36:18 jim
1134 Modified to use new dfs tags
1135 
1136 Revision 1.45 2007/03/29 12:19:39 jim
1137 Little changes to improve documentation
1138 
1139 Revision 1.44 2007/03/02 12:37:16 jim
1140 Removed WCS stuff from table headers
1141 
1142 Revision 1.43 2007/03/01 12:41:49 jim
1143 Modified slightly after code checking
1144 
1145 Revision 1.42 2007/02/25 06:27:41 jim
1146 plugged a few memory leaks
1147 
1148 Revision 1.41 2007/02/19 10:03:02 jim
1149 Fixed small memory leak
1150 
1151 Revision 1.40 2007/02/15 11:54:09 jim
1152 Modified to make a distinction between initial channel table and one that
1153 has the proper linearity information
1154 
1155 Revision 1.39 2007/02/15 06:59:38 jim
1156 Added ability to write QC paf files
1157 
1158 Revision 1.38 2007/02/06 13:11:12 jim
1159 Fixed entry for PRO dictionary in cpl_dfs_set_product_header
1160 
1161 Revision 1.37 2007/02/05 14:14:05 jim
1162 Input master frame is now tagged as REFERENCE. QC removed from stats table
1163 headers
1164 
1165 Revision 1.36 2007/01/09 11:39:02 jim
1166 Moved free for ps.good in tidy routine to the correct place
1167 
1168 Revision 1.35 2007/01/08 19:09:11 jim
1169 Fixed memory leak
1170 
1171 Revision 1.34 2006/12/13 13:19:52 jim
1172 Fixed problem with bad sigma estimate
1173 
1174 Revision 1.33 2006/12/08 11:39:27 jim
1175 Fixed bug where we_expect didn't check to see if the difference image was
1176 being produced before deciding whether or not a table would be produced.
1177 
1178 Revision 1.32 2006/11/27 12:15:08 jim
1179 changed calls to cpl_propertylist_append to cpl_propertylist_update
1180 
1181 Revision 1.31 2006/09/29 11:19:31 jim
1182 changed aliases on parameter names
1183 
1184 Revision 1.30 2006/09/09 16:49:40 jim
1185 Header comment update
1186 
1187 Revision 1.29 2006/08/27 20:30:02 jim
1188 Major mods to structure of the main processing routine to deal with missing
1189 and dummy frames. Deals better with lower level failures too
1190 
1191 Revision 1.28 2006/06/15 09:58:58 jim
1192 Minor changes to docs
1193 
1194 Revision 1.27 2006/06/09 11:26:25 jim
1195 Small changes to keep lint happy
1196 
1197 Revision 1.26 2006/06/06 13:01:40 jim
1198 Fixed so that the QC parameters go into the correct headers
1199 
1200 Revision 1.25 2006/05/17 14:43:58 jim
1201 Fixed problem in save routine which messed up the PRO CATG keywords
1202 
1203 Revision 1.24 2006/05/16 13:58:47 jim
1204 Fixed memory leaks that occur from not closing images at the end of
1205 the image extension loop
1206 
1207 Revision 1.23 2006/05/09 09:27:06 jim
1208 removed unecessary call to cpl_propertylist_delete
1209 
1210 Revision 1.22 2006/05/04 11:53:15 jim
1211 Fixed the way the _save routine works to be more consistent with the
1212 standard CPL way of doing things
1213 
1214 Revision 1.21 2006/04/27 09:46:01 jim
1215 Modified DFS frame types to conform to new dictionary
1216 
1217 Revision 1.20 2006/04/25 13:45:57 jim
1218 Fixed to adhere to new calling sequence for vircam_dfs routines
1219 
1220 Revision 1.19 2006/03/23 21:18:46 jim
1221 Minor changes mainly to comment headers
1222 
1223 Revision 1.18 2006/03/22 12:13:52 jim
1224 Modified to use new vircam_mask capability
1225 
1226 Revision 1.17 2006/03/15 10:43:40 jim
1227 Fixed a few things
1228 
1229 Revision 1.16 2006/03/08 14:32:35 jim
1230 Lots of little mods
1231 
1232 Revision 1.15 2006/03/03 14:29:06 jim
1233 Now calls routines with vir_fits.
1234 
1235 Revision 1.13 2006/02/22 10:01:38 jim
1236 Modified to use new version of vircam_imcombine
1237 
1238 Revision 1.12 2006/02/18 11:50:43 jim
1239 Modified the way the dfs product keywords are written using the vircam
1240 routines, rather than the cpl routine that doesn't understand image
1241 extensions
1242 
1243 Revision 1.11 2006/01/23 10:37:21 jim
1244 Now allows either a BPM or a CPM to be used as a mask
1245 
1246 Revision 1.10 2005/12/14 22:19:12 jim
1247 fixed docs
1248 
1249 Revision 1.9 2005/12/09 09:47:58 jim
1250 Many changes to add more documentation
1251 
1252 Revision 1.8 2005/12/02 10:45:38 jim
1253 The tags used in the sof are now written to the description string in the
1254 constructor. This is so that if they change in the vircam_dfs.h file, they
1255 aren't then hardcopied into each of the recipes...
1256 
1257 Revision 1.7 2005/12/01 16:25:48 jim
1258 Made the routine a bit more forgiving if certain master calibration files
1259 were missing. Now does as much as it can with the info it has
1260 
1261 Revision 1.6 2005/11/25 09:56:14 jim
1262 Tidied up some more documentation
1263 
1264 Revision 1.5 2005/11/23 14:57:40 jim
1265 A bit of tidying in response to splint messages
1266 
1267 Revision 1.4 2005/11/08 12:47:44 jim
1268 Made garbage collection a little better
1269 
1270 Revision 1.3 2005/11/07 13:13:43 jim
1271 Added some docs and calls to vircam_getnpts
1272 
1273 Revision 1.2 2005/11/03 15:16:28 jim
1274 Lots of changes mainly to strengthen error reporting
1275 
1276 Revision 1.1 2005/09/29 08:58:25 jim
1277 new routine
1278 
1279 
1280 
1281 */
1282 
1283 
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
char * casu_fits_get_fullname(casu_fits *p)
Definition: casu_fits.c:680
int casu_fits_set_error(casu_fits *p, int status)
Definition: casu_fits.c:747
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_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.
void casu_medmad(float *data, unsigned char *bpm, long np, float *med, float *mad)
Definition: casu_stats.c:347
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_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_detlive(const cpl_propertylist *plist, int *detlive)
Get the value of DET_LIVE.
Definition: vircam_pfits.c:624
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