VIRCAM Pipeline 2.3.12
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
59static int vircam_reset_combine_create(cpl_plugin *) ;
60static int vircam_reset_combine_exec(cpl_plugin *) ;
61static int vircam_reset_combine_destroy(cpl_plugin *) ;
62static int vircam_reset_combine(cpl_parameterlist *, cpl_frameset *) ;
63static int vircam_reset_combine_save(cpl_frameset *framelist,
64 cpl_parameterlist *parlist);
65static void vircam_reset_combine_dummy_products(void);
66static void vircam_reset_combine_normal(int jext);
67static int vircam_reset_combine_lastbit(int jext, cpl_frameset *framelist,
68 cpl_parameterlist *parlist);
69static void vircam_reset_combine_init(void);
70static void vircam_reset_combine_tidy(int level);
71
72/* Static global variables */
73
74static 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
94static 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
114static int isfirst;
115static cpl_frame *product_frame_mean_reset = NULL;
116static cpl_frame *product_frame_diffimg = NULL;
117static cpl_frame *product_frame_diffimg_stats = NULL;
118static int we_expect;
119static int we_get;
120
121static 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
267int 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
305static 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
393static 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
414static 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
437static 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
630static 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
863static 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
908static 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
1011static 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
1043static 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
1068static 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 $
1093Revision 1.59 2012/01/15 17:40:09 jim
1094Minor modifications to take into accout the changes in cpl API for v6
1095
1096Revision 1.58 2010/03/21 06:48:21 jim
1097Fixed bug where DATANCOM wasn't being updated in all products
1098
1099Revision 1.57 2010/03/09 14:27:40 jim
1100Now updates ESO PRO DATANCOM to reflect the number of images used
1101
1102Revision 1.56 2010/02/05 09:42:22 jim
1103Fixed call to non-existent cpl routine
1104
1105Revision 1.55 2010/01/31 18:54:01 jim
1106Reference reset included in paf
1107
1108Revision 1.54 2009/09/09 09:50:21 jim
1109Modified to try and get headers right
1110
1111Revision 1.53 2008/12/05 13:28:32 jim
1112Fixed save routine so that the correct version of PRO CATG is written to the
1113paf file
1114
1115Revision 1.52 2008/10/01 04:59:13 jim
1116Added call to vircam_frameset_fexists to check input frameset
1117
1118Revision 1.51 2008/09/30 11:33:23 jim
1119Added PRO CATG to pafs
1120
1121Revision 1.50 2007/10/19 09:25:09 jim
1122Fixed problems with missing includes
1123
1124Revision 1.49 2007/10/15 12:53:26 jim
1125Modified for compatibiliity with cpl_4.0
1126
1127Revision 1.48 2007/07/18 15:35:42 jim
1128Added better error handling for missing or corrupt mask extensions
1129
1130Revision 1.47 2007/07/09 13:21:56 jim
1131Modified to use new version of vircam_exten_range
1132
1133Revision 1.46 2007/04/04 10:36:18 jim
1134Modified to use new dfs tags
1135
1136Revision 1.45 2007/03/29 12:19:39 jim
1137Little changes to improve documentation
1138
1139Revision 1.44 2007/03/02 12:37:16 jim
1140Removed WCS stuff from table headers
1141
1142Revision 1.43 2007/03/01 12:41:49 jim
1143Modified slightly after code checking
1144
1145Revision 1.42 2007/02/25 06:27:41 jim
1146plugged a few memory leaks
1147
1148Revision 1.41 2007/02/19 10:03:02 jim
1149Fixed small memory leak
1150
1151Revision 1.40 2007/02/15 11:54:09 jim
1152Modified to make a distinction between initial channel table and one that
1153has the proper linearity information
1154
1155Revision 1.39 2007/02/15 06:59:38 jim
1156Added ability to write QC paf files
1157
1158Revision 1.38 2007/02/06 13:11:12 jim
1159Fixed entry for PRO dictionary in cpl_dfs_set_product_header
1160
1161Revision 1.37 2007/02/05 14:14:05 jim
1162Input master frame is now tagged as REFERENCE. QC removed from stats table
1163headers
1164
1165Revision 1.36 2007/01/09 11:39:02 jim
1166Moved free for ps.good in tidy routine to the correct place
1167
1168Revision 1.35 2007/01/08 19:09:11 jim
1169Fixed memory leak
1170
1171Revision 1.34 2006/12/13 13:19:52 jim
1172Fixed problem with bad sigma estimate
1173
1174Revision 1.33 2006/12/08 11:39:27 jim
1175Fixed bug where we_expect didn't check to see if the difference image was
1176being produced before deciding whether or not a table would be produced.
1177
1178Revision 1.32 2006/11/27 12:15:08 jim
1179changed calls to cpl_propertylist_append to cpl_propertylist_update
1180
1181Revision 1.31 2006/09/29 11:19:31 jim
1182changed aliases on parameter names
1183
1184Revision 1.30 2006/09/09 16:49:40 jim
1185Header comment update
1186
1187Revision 1.29 2006/08/27 20:30:02 jim
1188Major mods to structure of the main processing routine to deal with missing
1189and dummy frames. Deals better with lower level failures too
1190
1191Revision 1.28 2006/06/15 09:58:58 jim
1192Minor changes to docs
1193
1194Revision 1.27 2006/06/09 11:26:25 jim
1195Small changes to keep lint happy
1196
1197Revision 1.26 2006/06/06 13:01:40 jim
1198Fixed so that the QC parameters go into the correct headers
1199
1200Revision 1.25 2006/05/17 14:43:58 jim
1201Fixed problem in save routine which messed up the PRO CATG keywords
1202
1203Revision 1.24 2006/05/16 13:58:47 jim
1204Fixed memory leaks that occur from not closing images at the end of
1205the image extension loop
1206
1207Revision 1.23 2006/05/09 09:27:06 jim
1208removed unecessary call to cpl_propertylist_delete
1209
1210Revision 1.22 2006/05/04 11:53:15 jim
1211Fixed the way the _save routine works to be more consistent with the
1212standard CPL way of doing things
1213
1214Revision 1.21 2006/04/27 09:46:01 jim
1215Modified DFS frame types to conform to new dictionary
1216
1217Revision 1.20 2006/04/25 13:45:57 jim
1218Fixed to adhere to new calling sequence for vircam_dfs routines
1219
1220Revision 1.19 2006/03/23 21:18:46 jim
1221Minor changes mainly to comment headers
1222
1223Revision 1.18 2006/03/22 12:13:52 jim
1224Modified to use new vircam_mask capability
1225
1226Revision 1.17 2006/03/15 10:43:40 jim
1227Fixed a few things
1228
1229Revision 1.16 2006/03/08 14:32:35 jim
1230Lots of little mods
1231
1232Revision 1.15 2006/03/03 14:29:06 jim
1233Now calls routines with vir_fits.
1234
1235Revision 1.13 2006/02/22 10:01:38 jim
1236Modified to use new version of vircam_imcombine
1237
1238Revision 1.12 2006/02/18 11:50:43 jim
1239Modified the way the dfs product keywords are written using the vircam
1240routines, rather than the cpl routine that doesn't understand image
1241extensions
1242
1243Revision 1.11 2006/01/23 10:37:21 jim
1244Now allows either a BPM or a CPM to be used as a mask
1245
1246Revision 1.10 2005/12/14 22:19:12 jim
1247fixed docs
1248
1249Revision 1.9 2005/12/09 09:47:58 jim
1250Many changes to add more documentation
1251
1252Revision 1.8 2005/12/02 10:45:38 jim
1253The tags used in the sof are now written to the description string in the
1254constructor. This is so that if they change in the vircam_dfs.h file, they
1255aren't then hardcopied into each of the recipes...
1256
1257Revision 1.7 2005/12/01 16:25:48 jim
1258Made the routine a bit more forgiving if certain master calibration files
1259were missing. Now does as much as it can with the info it has
1260
1261Revision 1.6 2005/11/25 09:56:14 jim
1262Tidied up some more documentation
1263
1264Revision 1.5 2005/11/23 14:57:40 jim
1265A bit of tidying in response to splint messages
1266
1267Revision 1.4 2005/11/08 12:47:44 jim
1268Made garbage collection a little better
1269
1270Revision 1.3 2005/11/07 13:13:43 jim
1271Added some docs and calls to vircam_getnpts
1272
1273Revision 1.2 2005/11/03 15:16:28 jim
1274Lots of changes mainly to strengthen error reporting
1275
1276Revision 1.1 2005/09/29 08:58:25 jim
1277new 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_list(cpl_frameset *f, cpl_type type, int exten)
Definition: casu_fits.c:318
int casu_fits_set_error(casu_fits *p, int status)
Definition: casu_fits.c:747
char * casu_fits_get_fullname(casu_fits *p)
Definition: casu_fits.c:680
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
casu_fits * casu_fits_load(cpl_frame *frame, cpl_type type, int nexten)
Definition: casu_fits.c:80
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
int casu_mask_load(casu_mask *m, int nexten, int nx, int ny)
Definition: casu_mask.c:214
void casu_mask_clear(casu_mask *m)
Definition: casu_mask.c:357
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
const char * casu_mask_get_filename(casu_mask *m)
Definition: casu_mask.c:447
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
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_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
cpl_image * casu_dummy_image(casu_fits *model)
Create a dummy image of zeros based on a model.
Definition: casu_utils.c:533
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
const char * vircam_get_license(void)
Definition: vircam_utils.c:116
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)
void vircam_exten_range(int inexten, const cpl_frame *fr, int *out1, int *out2)
Definition: vircam_utils.c:165