VIRCAM Pipeline 2.3.15
vircam_science_process.c
1/* $Id: vircam_science_process.c,v 1.10 2013-10-21 14:43:04 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: 2013-10-21 14:43:04 $
24 * $Revision: 1.10 $
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 <string.h>
36#include <unistd.h>
37#include <libgen.h>
38#include <cpl.h>
39#include <math.h>
40
41#include <casu_utils.h>
42#include <casu_mask.h>
43#include <casu_mods.h>
44#include <casu_wcsutils.h>
45#include <casu_stats.h>
46#include <casu_filt.h>
47#include <casu_sky.h>
48
49#include "vircam_utils.h"
50#include "vircam_pfits.h"
51#include "vircam_dfs.h"
52#include "vircam_mods.h"
53#include "vircam_paf.h"
54#include "vircam_sky.h"
55
56typedef struct {
57 cpl_frameset *contrib;
58 cpl_frame *objmask;
59 int skyalgo;
60 cpl_frame *skyframe;
61 cpl_frame *template;
62 char fname[BUFSIZ];
63} skystruct;
64
65typedef struct {
66 cpl_frameset *current;
67 cpl_frameset *orig;
68 int *whichsky;
69 casu_fits *stack[VIRCAM_NEXTN];
70 casu_fits *stackc[VIRCAM_NEXTN];
71 casu_tfits *cat[VIRCAM_NEXTN];
72 casu_tfits *mstds[VIRCAM_NEXTN];
73 cpl_frame *product_frame_im;
74 cpl_frame *product_frame_conf;
75 cpl_frame *product_frame_cat;
76 int tilenum;
77 int jitternum;
78 char projname[16];
79 double mjd_start;
80 double mjd_end;
81 int ispj;
82} pawprint;
83
84/* User supplied command line options */
85
86struct {
87
88 /* Input */
89
90 int destripe;
91 int str_filt;
92 int skyalgo;
93 int preview_only;
94 int minphotom;
95 int prettynames;
96 int cdssearch;
97 char *cacheloc;
98 float magerrcut;
99
100} vircam_sci_config;
101
102
103struct {
104 int niter;
105 int ipix;
106 float thresh;
107 int nbsize;
108 float smkern;
109} psm;
110
111struct {
112 float lthr;
113 float hthr;
114 int method;
115 int seeing;
116 int fast;
117 int nfst;
118} stk;
119
120struct {
121 int ipix;
122 float thresh;
123 int icrowd;
124 float rcore;
125 int nbsize;
126} stk_cat;
127
128struct {
129
130 /* Level 0 stuff */
131
132 cpl_size *labels;
133 cpl_frame *master_dark;
134 cpl_frame *master_twilight_flat;
135 cpl_frame *master_conf;
136 cpl_frame *master_sky;
137 cpl_frame *master_objmask;
138 casu_mask *mask;
139 cpl_frame *chantab;
140 cpl_frame *phottab;
141 cpl_table *tphottab;
142 cpl_frame *readgain_file;
143 cpl_frameset *science_frames;
144 cpl_frameset *offset_skies;
145 cpl_frame **product_frames_simple;
146 cpl_frame **product_frames_simple_off;
147 cpl_propertylist *phupaf;
148 float *gaincors;
149 char *catpath;
150 char *catname;
151 int nscipaws;
152 pawprint *science_paws;
153 int noffpaws;
154 pawprint *offsky_paws;
155 int nskys;
156 skystruct *skys;
157 cpl_frame *schlf_n;
158 cpl_frame *schlf_s;
159
160 /* Level 1 stuff */
161
162 casu_fits *fdark;
163 casu_fits *fflat;
164 casu_fits *fconf;
165 casu_fits *fsky;
166 casu_tfits *fchantab;
167
168 int nscience;
169 casu_fits **sci_fits;
170 int noffsets;
171 casu_fits **offsky_fits;
172
173} ps;
174
175/* List of data products types */
176
177enum {SIMPLE_FILE,
178 SIMPLE_CONF,
179 SIMPLE_CAT,
180 STACK_FILE,
181 STACK_CONF,
182 STACK_CAT,
183 SKY_FILE
184};
185
186#define SKYNONE 0
187#define SKYMASTER -1
188#define PAWSKY_MASK 1
189#define PAWSKY_MASK_PRE 2
190#define TILESKY 3
191#define TILESKY_MINUS 4
192#define AUTO 5
193#define PAWSKY_MINUS 6
194
195#define VMCPROJ "179.B-2003"
196#define VIDEOPROJ "179.A-2006"
197
198#define freepaws(_p,_n) if (_p != NULL) {vircam_sci_paws_delete(_n,&(_p)); _p = NULL; _n = 0;}
199
200char current_cat[VIRCAM_PATHSZ];
201char current_catpath[VIRCAM_PATHSZ];
202char vircam_recipename[VIRCAM_PATHSZ];
203char vircam_recipepaf[VIRCAM_PATHSZ];
204cpl_propertylist *dummyqc = NULL;
205int offsky = 0;
206
207/* Main stuff for CPL/esorex */
208
209static int vircam_science_process_create(cpl_plugin *plugin);
210static int vircam_science_process_exec(cpl_plugin *plugin);
211static int vircam_science_process_destroy(cpl_plugin *plugin);
212static int vircam_science_process(cpl_parameterlist *parlist,
213 cpl_frameset *framelist);
214
215/* Pawprint manipulation routines */
216
217static void vircam_sci_paw_init(pawprint *paw, cpl_frameset *frms, int ispj,
218 int *nfrms_tot);
219static void vircam_sci_paw_delete(pawprint *paws);
220static void vircam_sci_paws_delete(int npaws, pawprint **paws);
221static void vircam_sci_paws_create(cpl_frameset *infrms, int *npaws,
222 pawprint **paws);
223
224/* Processing routines */
225
226static int vircam_sci_sky_stripe_wcs(int npaw, pawprint *paw, const char *tag,
227 cpl_frameset *framelist,
228 cpl_parameterlist *parlist, int destripe);
229static void vircam_sci_cat(pawprint *paw, int extn);
230static void vircam_sci_stack(pawprint *paw, int extn);
231static void vircam_sci_wcsfit(casu_fits **in, casu_fits **conf,
232 casu_tfits **incat, int nf, int level);
233static void vircam_sci_init(void);
234static void vircam_sci_tidy(int level);
235static int vircam_destripe_four(casu_fits **curfits, int stripefilt,
236 int *status);
237static void stripe_profile(casu_fits *in, int stripefilt, float *profile,
238 unsigned char *pbpm);
239static void vircam_sci_photcal(pawprint *paw);
240
241/* Sky related routines */
242
243static void vircam_sci_choose_skyalgo(int *nskys, skystruct **skys);
244static int vircam_sci_makesky(cpl_frameset *framelist,
245 cpl_parameterlist *parlist, skystruct *sky,
246 const char *tag);
247static void vircam_sci_assign_sky_all(pawprint paw, int whichone);
248static skystruct vircam_sci_crsky(int algorithm, cpl_frameset *frms,
249 cpl_frame *template, int snum);
250static void vircam_sci_skydefine(void);
251static int vircam_sci_tilesky(cpl_frameset *framelist,
252 cpl_parameterlist *parlist, cpl_frameset *in,
253 cpl_frame *template,
254 char *fname, cpl_frame **product_frame);
255static int vircam_sci_pawsky_mask(cpl_frameset *framelist,
256 cpl_parameterlist *parlist, int algo,
257 cpl_frameset *contrib, cpl_frame *template,
258 char *fname, cpl_frame **product_frame);
259static int vircam_sci_tilesky_minus(cpl_frameset *framelist,
260 cpl_parameterlist *parlist,
261 cpl_frameset *in, cpl_frame *template,
262 const char *tag, char *fname,
263 cpl_frame **skyframe);
264static int vircam_sci_pawsky_minus(cpl_frameset *framelist,
265 cpl_parameterlist *parlist,
266 cpl_frameset *in, cpl_frame *template,
267 const char *tag, char *skyname,
268 cpl_frame **skyframe);
269
270/* Utility routines */
271
272static cpl_frame *vircam_sci_findtemplate(cpl_frame *in);
273static int vircam_sci_istile(cpl_frame *frm);
274static int vircam_sci_ispj(cpl_frameset *frms);
275static int vircam_sci_cmp_jit(const cpl_frame *frame1,
276 const cpl_frame *frame2);
277static int vircam_sci_cmp_tstart(const cpl_frame *frame1,
278 const cpl_frame *frame2);
279static int vircam_sci_cmp_property(const cpl_property *p1,
280 const cpl_property *p2);
281static cpl_frameset *vircam_sci_merge_framesets(int n, cpl_frameset **in);
282static cpl_frameset *vircam_sci_update_frameset(cpl_frameset *frms, int *nfrms_tot);
283static int vircam_sci_testfrms(cpl_frameset *frms, int nextn_expected,
284 int isimg);
285static int vircam_sci_testfrm_1(cpl_frame *fr, int nextn_expected, int isimg);
286static void vircam_sci_get_readnoise_gain(int jext, float *readnoise,
287 float *gain);
288static void vircam_sci_product_name(char *template, int producttype,
289 int nametype, int fnumber, char *outfname);
290
291/* Save routines */
292
293static int vircam_sci_save_simple(casu_fits *obj, cpl_frameset *framelist,
294 cpl_parameterlist *parlist, int isprod,
295 cpl_frame *template, int isfirst,
296 const char *tag, char *fname,
297 cpl_frame **product_frame);
298static int vircam_sci_save_sky(casu_fits *outsky, cpl_frameset *framelist,
299 cpl_parameterlist *parlist,
300 char *fname, cpl_frame *template, int isfirst,
301 cpl_frame **product_frame);
302static int vircam_sci_save_stack(casu_fits *stack, cpl_frameset *framelist,
303 cpl_parameterlist *parlist,
304 cpl_frame *template, int fnametype,
305 int stack_num, cpl_frame **product_frame);
306static int vircam_sci_save_stack_conf(casu_fits *stack, cpl_frameset *framelist,
307 cpl_parameterlist *parlist,
308 cpl_frame *template, int fnametype,
309 int stack_num, cpl_frame **product_frame);
310static int vircam_sci_save_stack_cat(casu_tfits *stack, cpl_frameset *framelist,
311 cpl_parameterlist *parlist,
312 cpl_frame *template, int fnametype,
313 int stack_num, cpl_frame **product_frame);
314
315
316static char vircam_science_process_description[] =
317"vircam_science_process -- VIRCAM science product recipe.\n\n"
318"Process a complete pawprint for VIRCAM data. Remove instrumental\n"
319"signature, background correct, combine jitters, photometrically\n"
320"and astrometrically calibrate the pawprint image\n\n"
321"The program accepts the following files in the SOF:\n\n"
322" Tag Description\n"
323" -----------------------------------------------------------------------\n"
324" %-22s A list of raw science images or\n"
325" %-22s A list of raw science images (extended)\n"
326" %-22s A list of offset sky exposures (optional)\n"
327" %-22s A master dark frame\n"
328" %-22s A master object mask (optional)\n"
329" %-22s A master twilight flat frame\n"
330" %-22s A master sky frame (optional)\n"
331" %-22s A channel table\n"
332" %-22s A photometric calibration table\n"
333" %-22s A readnoise/gain file\n"
334" %-22s A master confidence map\n"
335" %-22s A master standard star index\n"
336" %-22s Northern Schlegel Map\n"
337" %-22s Southern Schlegel Map\n"
338"All of the above are required unless otherwise specified\n"
339"\n";
340
522/* Function code */
523
524/*---------------------------------------------------------------------------*/
532/*---------------------------------------------------------------------------*/
533
534int cpl_plugin_get_info(cpl_pluginlist *list) {
535 cpl_recipe *recipe = cpl_calloc(1,sizeof(*recipe));
536 cpl_plugin *plugin = &recipe->interface;
537 char alldesc[SZ_ALLDESC];
538 (void)snprintf(alldesc,SZ_ALLDESC,
539 vircam_science_process_description,
540 VIRCAM_SCI_OBJECT_RAW,VIRCAM_SCI_OBJECT_EXT_RAW,
541 VIRCAM_OFFSET_SKY_RAW,VIRCAM_CAL_DARK,VIRCAM_CAL_OBJMASK,
542 VIRCAM_CAL_TWILIGHT_FLAT,VIRCAM_CAL_SKY,VIRCAM_CAL_CHANTAB,
543 VIRCAM_CAL_PHOTTAB,VIRCAM_CAL_READGAINFILE,VIRCAM_CAL_CONF,
544 VIRCAM_CAL_2MASS,VIRCAM_CAL_SCHL_N,VIRCAM_CAL_SCHL_S);
545
546 cpl_plugin_init(plugin,
547 CPL_PLUGIN_API,
548 VIRCAM_BINARY_VERSION,
549 CPL_PLUGIN_TYPE_RECIPE,
550 "vircam_science_process",
551 "VIRCAM science recipe",
552 alldesc,
553 "Jim Lewis",
554 "jrl@ast.cam.ac.uk",
556 vircam_science_process_create,
557 vircam_science_process_exec,
558 vircam_science_process_destroy);
559
560 cpl_pluginlist_append(list,plugin);
561
562 return(0);
563}
564
565/*---------------------------------------------------------------------------*/
574/*---------------------------------------------------------------------------*/
575
576static int vircam_science_process_create(cpl_plugin *plugin) {
577 cpl_recipe *recipe;
578 cpl_parameter *p;
579
580 /* Get the recipe out of the plugin */
581
582 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
583 recipe = (cpl_recipe *)plugin;
584 else
585 return(-1);
586
587 /* Create the parameters list in the cpl_recipe object */
588
589 recipe->parameters = cpl_parameterlist_new();
590
591 /* Fill in flag to destripe the images */
592
593 p = cpl_parameter_new_value("vircam.vircam_science_process.destripe",
594 CPL_TYPE_BOOL,"Destripe images?",
595 "vircam.vircam_science_process",TRUE);
596 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"destripe");
597 cpl_parameterlist_append(recipe->parameters,p);
598
599 /* Fill in flag to correct sky background */
600
601 p = cpl_parameter_new_enum("vircam.vircam_science_process.skyalgo",
602 CPL_TYPE_STRING,"Sky subtraction algorithm",
603 "vircam.vircam_science_process","auto",8,
604 "master","none","pawsky_mask","pawsky_mask_pre",
605 "tilesky","tilesky_minus","auto","pawsky_minus");
606 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"skyalgo");
607 cpl_parameterlist_append(recipe->parameters,p);
608
609 /* Fill in flag to just print out how the data will be processed and
610 then exit */
611
612 p = cpl_parameter_new_value("vircam.vircam_science_process.preview_only",
613 CPL_TYPE_BOOL,"Preview only?",
614 "vircam.vircam_science_process",FALSE);
615 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"preview_only");
616 cpl_parameterlist_append(recipe->parameters,p);
617
618 /* Fill in flag to just print out how the data will be processed and
619 then exit */
620
621 p = cpl_parameter_new_range("vircam.vircam_science_process.minphotom",
622 CPL_TYPE_INT,
623 "Minimum stars for photometry solution",
624 "vircam.vircam_science_process",1,1,100000);
625 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"minphotom");
626 cpl_parameterlist_append(recipe->parameters,p);
627
628 /* Fill in flag to decide whether to use predictable names or nice
629 names based on input file names */
630
631 p = cpl_parameter_new_value("vircam.vircam_science_process.prettynames",
632 CPL_TYPE_BOOL,"Use pretty product names?",
633 "vircam.vircam_science_process",FALSE);
634 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"prettynames");
635 cpl_parameterlist_append(recipe->parameters,p);
636
637 /* Fill in flag to decide whether to use CDS to get 2MASS standards */
638
639 p = cpl_parameter_new_value("vircam.vircam_science_process.cdssearch",
640 CPL_TYPE_BOOL,"Use CDS for 2MASS standards?",
641 "vircam.vircam_science_process",FALSE);
642 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"cdssearch");
643 cpl_parameterlist_append(recipe->parameters,p);
644
645 /* ***Special parameters for object detection on stacks*** */
646
647 /* Fill in the minimum object size */
648
649 p = cpl_parameter_new_range("vircam.vircam_science_process.stk_cat_ipix",
650 CPL_TYPE_INT,
651 "Minimum pixel area for each detected object",
652 "vircam.vircam_science_process",5,1,
653 1024);
654 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_ipix");
655 cpl_parameterlist_append(recipe->parameters,p);
656
657 /* Fill in the detection threshold parameter */
658
659 p = cpl_parameter_new_range("vircam.vircam_science_process.stk_cat_thresh",
660 CPL_TYPE_DOUBLE,
661 "Detection threshold in sigma above sky",
662 "vircam.vircam_science_process",2.0,1.0e-6,
663 1.0e10);
664 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_thresh");
665 cpl_parameterlist_append(recipe->parameters,p);
666
667 /* Fill in flag to use deblending software or not */
668
669 p = cpl_parameter_new_value("vircam.vircam_science_process.stk_cat_icrowd",
670 CPL_TYPE_BOOL,"Use deblending?",
671 "vircam.vircam_science_process",TRUE);
672 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_icrowd");
673 cpl_parameterlist_append(recipe->parameters,p);
674
675 /* Fill in core radius */
676
677 p = cpl_parameter_new_range("vircam.vircam_science_process.stk_cat_rcore",
678 CPL_TYPE_DOUBLE,"Value of Rcore in pixels",
679 "vircam.vircam_science_process",3.0,1.0e-6,
680 1024.0);
681 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_rcore");
682 cpl_parameterlist_append(recipe->parameters,p);
683
684 /* Fill in background smoothing box size */
685
686 p = cpl_parameter_new_range("vircam.vircam_science_process.stk_cat_nbsize",
687 CPL_TYPE_INT,"Background smoothing box size",
688 "vircam.vircam_science_process",64,1,2048);
689 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_nbsize");
690 cpl_parameterlist_append(recipe->parameters,p);
691
692 /* ***Special parameters for stacking*** */
693
694 /* The lower rejection threshold to be used during stacking */
695
696 p = cpl_parameter_new_range("vircam.vircam_science_process.stk_lthr",
697 CPL_TYPE_DOUBLE,"Low rejection threshold",
698 "vircam.vircam_science_process",5.0,1.0e-6,
699 1.0e10);
700 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_lthr");
701 cpl_parameterlist_append(recipe->parameters,p);
702
703 /* The upper rejection threshold to be used during stacking */
704
705 p = cpl_parameter_new_range("vircam.vircam_science_process.stk_hthr",
706 CPL_TYPE_DOUBLE,"Upper rejection threshold",
707 "vircam.vircam_science_process",5.0,1.0e-6,
708 1.0e10);
709 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_hthr");
710 cpl_parameterlist_append(recipe->parameters,p);
711
712 /* Stacking method */
713
714 p = cpl_parameter_new_enum("vircam.vircam_science_process.stk_method",
715 CPL_TYPE_STRING,"Stacking method",
716 "vircam.vircam_science_process","linear",2,
717 "nearest","linear");
718 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_method");
719 cpl_parameterlist_append(recipe->parameters,p);
720
721 /* Flag to use seeing weighting */
722
723 p = cpl_parameter_new_value("vircam.vircam_science_process.stk_seeing",
724 CPL_TYPE_BOOL,"Weight by seeing?",
725 "vircam.vircam_science_process",FALSE);
726 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_seeing");
727 cpl_parameterlist_append(recipe->parameters,p);
728
729 /* Stacking speed method */
730
731 p = cpl_parameter_new_enum("vircam.vircam_science_process.stk_fast",
732 CPL_TYPE_STRING,
733 "Use fast stacking?",
734 "vircam.vircam_science_process",
735 "auto",3,"fast","slow","auto");
736 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_fast");
737 cpl_parameterlist_append(recipe->parameters,p);
738
739 /* Number of frames to stack before we revert to the slow algorithm
740 when in auto mode */
741
742 p = cpl_parameter_new_value("vircam.vircam_science_process.stk_nfst",
743 CPL_TYPE_INT,
744 "Nframes to stack in fast mode",
745 "vircam.vircam_science_process",30);
746 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_nfst");
747 cpl_parameterlist_append(recipe->parameters,p);
748
749 /* ***Special parameters for destripe algorithm*** */
750
751 /* Flag to filter stripe pattern */
752
753 p = cpl_parameter_new_value("vircam.vircam_science_process.str_filt",
754 CPL_TYPE_BOOL,"Filter stripe pattern?",
755 "vircam.vircam_science_process",TRUE);
756 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"str_filt");
757 cpl_parameterlist_append(recipe->parameters,p);
758
759 /* ***Special parameters for pawsky_mask algorithm*** */
760
761 /* The pixel area for detected objects */
762
763 p = cpl_parameter_new_range("vircam.vircam_science_process.psm_ipix",
764 CPL_TYPE_INT,
765 "Minimum pixel area for each detected object",
766 "vircam.vircam_science_process",5,1,100000);
767 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_ipix");
768 cpl_parameterlist_append(recipe->parameters,p);
769
770 /* Number of iterations */
771
772 p = cpl_parameter_new_range("vircam.vircam_science_process.psm_niter",
773 CPL_TYPE_INT,
774 "Number of iterations in pawsky mask",
775 "vircam.vircam_science_process",5,1,100);
776 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_niter");
777 cpl_parameterlist_append(recipe->parameters,p);
778
779 /* Detection threshold */
780
781 p = cpl_parameter_new_range("vircam.vircam_science_process.psm_thresh",
782 CPL_TYPE_DOUBLE,
783 "Detection threshold in sigma above sky",
784 "vircam.vircam_science_process",2.0,1.0e-6,
785 1.0e10);
786 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_thresh");
787 cpl_parameterlist_append(recipe->parameters,p);
788
789 /* Background smoothing box size */
790
791 p = cpl_parameter_new_range("vircam.vircam_science_process.psm_nbsize",
792 CPL_TYPE_INT,"Background smoothing box size",
793 "vircam.vircam_science_process",50,1,2048);
794 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_nbsize");
795 cpl_parameterlist_append(recipe->parameters,p);
796
797 /* Smoothing kernel size */
798
799 p = cpl_parameter_new_range("vircam.vircam_science_process.psm_smkern",
800 CPL_TYPE_DOUBLE,
801 "Smoothing kernel size (pixels)",
802 "vircam.vircam_science_process",2.0,1.0e-6,5.0);
803 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_smkern");
804 cpl_parameterlist_append(recipe->parameters,p);
805
806 /* The standard star cache location */
807
808 p = cpl_parameter_new_value("vircam.vircam_science_process.cacheloc",
809 CPL_TYPE_STRING,
810 "Location of standard star cache?",
811 "vircam.vircam_science_process",".");
812 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"cacheloc");
813 cpl_parameterlist_append(recipe->parameters,p);
814
815 /* Magnitude error cut */
816
817 p = cpl_parameter_new_value("vircam.vircam_science_process.magerrcut",
818 CPL_TYPE_DOUBLE,
819 "Magnitude error cut",
820 "vircam.vircam_science_process",100.0);
821 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"magerrcut");
822 cpl_parameterlist_append(recipe->parameters,p);
823
824 /* Get out of here */
825
826 return(0);
827}
828
829/*---------------------------------------------------------------------------*/
835/*---------------------------------------------------------------------------*/
836
837static int vircam_science_process_exec(cpl_plugin *plugin) {
838 cpl_recipe *recipe;
839
840 /* Get the recipe out of the plugin */
841
842 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
843 recipe = (cpl_recipe *)plugin;
844 else
845 return(-1);
846
847 return(vircam_science_process(recipe->parameters,recipe->frames));
848}
849
850/*---------------------------------------------------------------------------*/
856/*---------------------------------------------------------------------------*/
857
858static int vircam_science_process_destroy(cpl_plugin *plugin) {
859 cpl_recipe *recipe ;
860
861 /* Get the recipe out of the plugin */
862
863 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
864 recipe = (cpl_recipe *)plugin;
865 else
866 return(-1);
867
868 cpl_parameterlist_delete(recipe->parameters);
869 return(0);
870}
871
872/*---------------------------------------------------------------------------*/
879/*---------------------------------------------------------------------------*/
880
881static int vircam_science_process(cpl_parameterlist *parlist,
882 cpl_frameset *framelist) {
883 const char *fctid="vircam_science_process";
884 cpl_parameter *p;
885 int nfail,status,i,ndit,j,live,isfirst,nsci,njsteps,n;
886 cpl_size nlab;
887 float gaincor_fac,readnoise,gain,dit;
888 cpl_frame *catindex,*template,*frm;
889 cpl_propertylist *pp;
890 cpl_table *stdscat,*tab;
891 casu_fits *ff;
892 char filt[16],projid[16],*tname,fname[BUFSIZ];
893
894 /* Check validity of the input frameset */
895
896 if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
897 cpl_msg_error(fctid,"Input framelist NULL or has no input data");
898 return(-1);
899 }
900
901 /* Initialise some things */
902
903 vircam_sci_init();
904 (void)strncpy(vircam_recipename,fctid,VIRCAM_PATHSZ);
905 (void)snprintf(vircam_recipepaf,VIRCAM_PATHSZ,"VIRCAM/%s",fctid);
906
907 /* Get the parameters */
908
909 p = cpl_parameterlist_find(parlist,
910 "vircam.vircam_science_process.destripe");
911 vircam_sci_config.destripe = cpl_parameter_get_bool(p);
912 p = cpl_parameterlist_find(parlist,
913 "vircam.vircam_science_process.str_filt");
914 vircam_sci_config.str_filt = cpl_parameter_get_bool(p);
915 p = cpl_parameterlist_find(parlist,
916 "vircam.vircam_science_process.skyalgo");
917 if (! strcmp(cpl_parameter_get_string(p),"none"))
918 vircam_sci_config.skyalgo = SKYNONE;
919 else if (! strcmp(cpl_parameter_get_string(p),"master"))
920 vircam_sci_config.skyalgo = SKYMASTER;
921 else if (! strcmp(cpl_parameter_get_string(p),"pawsky_mask"))
922 vircam_sci_config.skyalgo = PAWSKY_MASK;
923 else if (! strcmp(cpl_parameter_get_string(p),"pawsky_mask_pre"))
924 vircam_sci_config.skyalgo = PAWSKY_MASK_PRE;
925 else if (! strcmp(cpl_parameter_get_string(p),"tilesky"))
926 vircam_sci_config.skyalgo = TILESKY;
927 else if (! strcmp(cpl_parameter_get_string(p),"tilesky_minus"))
928 vircam_sci_config.skyalgo = TILESKY_MINUS;
929 else if (! strcmp(cpl_parameter_get_string(p),"auto"))
930 vircam_sci_config.skyalgo = AUTO;
931 else if (! strcmp(cpl_parameter_get_string(p),"pawsky_minus"))
932 vircam_sci_config.skyalgo = PAWSKY_MINUS;
933 p = cpl_parameterlist_find(parlist,
934 "vircam.vircam_science_process.preview_only");
935 vircam_sci_config.preview_only = cpl_parameter_get_bool(p);
936 p = cpl_parameterlist_find(parlist,
937 "vircam.vircam_science_process.minphotom");
938 vircam_sci_config.minphotom = cpl_parameter_get_int(p);
939 p = cpl_parameterlist_find(parlist,
940 "vircam.vircam_science_process.prettynames");
941 vircam_sci_config.prettynames = cpl_parameter_get_bool(p);
942 p = cpl_parameterlist_find(parlist,
943 "vircam.vircam_science_process.cdssearch");
944 vircam_sci_config.cdssearch = (cpl_parameter_get_bool(p) ? 1 : 0);
945
946 /* Stacking special parameters */
947
948 p = cpl_parameterlist_find(parlist,
949 "vircam.vircam_science_process.stk_lthr");
950 stk.lthr = cpl_parameter_get_double(p);
951 p = cpl_parameterlist_find(parlist,
952 "vircam.vircam_science_process.stk_hthr");
953 stk.hthr = cpl_parameter_get_double(p);
954 p = cpl_parameterlist_find(parlist,
955 "vircam.vircam_science_process.stk_method");
956 stk.method = (! strcmp(cpl_parameter_get_string(p),"nearest") ? 0 : 1);
957 p = cpl_parameterlist_find(parlist,
958 "vircam.vircam_science_process.stk_seeing");
959 stk.seeing = cpl_parameter_get_bool(p);
960 p = cpl_parameterlist_find(parlist,
961 "vircam.vircam_science_process.stk_fast");
962 if (! strcmp(cpl_parameter_get_string(p),"auto"))
963 stk.fast = -1;
964 else if (! strcmp(cpl_parameter_get_string(p),"slow"))
965 stk.fast = 0;
966 else if (! strcmp(cpl_parameter_get_string(p),"fast"))
967 stk.fast = 1;
968 p = cpl_parameterlist_find(parlist,
969 "vircam.vircam_science_process.stk_nfst");
970 stk.nfst = cpl_parameter_get_int(p);
971
972 /* Object detection on stacks special parameters */
973
974 p = cpl_parameterlist_find(parlist,
975 "vircam.vircam_science_process.stk_cat_ipix");
976 stk_cat.ipix = cpl_parameter_get_int(p);
977 p = cpl_parameterlist_find(parlist,
978 "vircam.vircam_science_process.stk_cat_thresh");
979 stk_cat.thresh = (float)cpl_parameter_get_double(p);
980 p = cpl_parameterlist_find(parlist,
981 "vircam.vircam_science_process.stk_cat_icrowd");
982 stk_cat.icrowd = cpl_parameter_get_bool(p);
983 p = cpl_parameterlist_find(parlist,
984 "vircam.vircam_science_process.stk_cat_rcore");
985 stk_cat.rcore = (float)cpl_parameter_get_double(p);
986 p = cpl_parameterlist_find(parlist,
987 "vircam.vircam_science_process.stk_cat_nbsize");
988 stk_cat.nbsize = cpl_parameter_get_int(p);
989
990 /* Pawsky_mask special parameters */
991
992 p = cpl_parameterlist_find(parlist,
993 "vircam.vircam_science_process.psm_ipix");
994 psm.ipix = cpl_parameter_get_int(p);
995 p = cpl_parameterlist_find(parlist,
996 "vircam.vircam_science_process.psm_niter");
997 psm.niter = cpl_parameter_get_int(p);
998 p = cpl_parameterlist_find(parlist,
999 "vircam.vircam_science_process.psm_thresh");
1000 psm.thresh = cpl_parameter_get_double(p);
1001 p = cpl_parameterlist_find(parlist,
1002 "vircam.vircam_science_process.psm_nbsize");
1003 psm.nbsize = cpl_parameter_get_int(p);
1004 p = cpl_parameterlist_find(parlist,
1005 "vircam.vircam_science_process.psm_smkern");
1006 psm.smkern = cpl_parameter_get_double(p);
1007
1008 /* Cache location */
1009
1010 p = cpl_parameterlist_find(parlist,
1011 "vircam.vircam_science_process.cacheloc");
1012 vircam_sci_config.cacheloc = (char *)cpl_parameter_get_string(p);
1013
1014 /* Magnitude error cut */
1015
1016 p = cpl_parameterlist_find(parlist,
1017 "vircam.vircam_science_process.magerrcut");
1018 vircam_sci_config.magerrcut = (float)cpl_parameter_get_double(p);
1019
1020 /* Sort out raw from calib frames */
1021
1022 if (vircam_dfs_set_groups(framelist) != CASU_OK) {
1023 cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
1024 vircam_sci_tidy(0);
1025 return(-1);
1026 }
1027
1028 /* Label the input frames */
1029
1030 if ((ps.labels = cpl_frameset_labelise(framelist,casu_compare_tags,
1031 &nlab)) == NULL) {
1032 cpl_msg_error(fctid,"Cannot labelise the input frames");
1033 vircam_sci_tidy(0);
1034 return(-1);
1035 }
1036
1037 /* Get the input science frames */
1038
1039 nfail = 0;
1040 if ((ps.science_frames =
1041 casu_frameset_subgroup(framelist,ps.labels,nlab,
1042 VIRCAM_SCI_OBJECT_RAW)) == NULL) {
1043 if ((ps.science_frames =
1044 casu_frameset_subgroup(framelist,ps.labels,nlab,
1045 VIRCAM_SCI_OBJECT_EXT_RAW)) == NULL) {
1046 cpl_msg_error(fctid,"No science images to process!");
1047 vircam_sci_tidy(0);
1048 return(-1);
1049 }
1050 }
1051 /* nfail += vircam_sci_testfrms(ps.science_frames,VIRCAM_NEXTN,1); */
1052
1053 /* Get the offset sky frames */
1054
1055 if ((ps.master_sky = casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1056 VIRCAM_CAL_SKY)) == NULL) {
1057 if ((ps.offset_skies =
1058 casu_frameset_subgroup(framelist,ps.labels,nlab,
1059 VIRCAM_OFFSET_SKY_RAW)) == NULL) {
1060 offsky = 0;
1061 } else {
1062 offsky = 1;
1063 nfail += vircam_sci_testfrms(ps.offset_skies,VIRCAM_NEXTN,1);
1064 }
1065 } else {
1066 offsky = -1;
1067 vircam_sci_config.skyalgo = -1;
1068 nfail += vircam_sci_testfrm_1(ps.master_sky,VIRCAM_NEXTN,1);
1069 }
1070
1071 /* Check to see if there is a master dark frame */
1072
1073 if ((ps.master_dark =
1074 casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1075 VIRCAM_CAL_DARK)) == NULL) {
1076 cpl_msg_error(fctid,"No master dark found");
1077 vircam_sci_tidy(0);
1078 return(-1);
1079 }
1080 nfail += vircam_sci_testfrm_1(ps.master_dark,VIRCAM_NEXTN,1);
1081
1082 /* Check to see if there is a master twilight flat frame */
1083
1084 if ((ps.master_twilight_flat =
1085 casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1086 VIRCAM_CAL_TWILIGHT_FLAT)) == NULL) {
1087 cpl_msg_error(fctid,"No master twilight flat found");
1088 vircam_sci_tidy(0);
1089 return(-1);
1090 }
1091 nfail += vircam_sci_testfrm_1(ps.master_twilight_flat,VIRCAM_NEXTN,1);
1092
1093 /* Get the master object mask. Does it make sense to have one in
1094 the context of the sky correction algorithm? */
1095
1096 ps.master_objmask = casu_frameset_subgroup_1(framelist,ps.labels,
1097 nlab,VIRCAM_CAL_OBJMASK);
1098 if ((ps.master_objmask == NULL) &&
1099 (vircam_sci_config.skyalgo == PAWSKY_MASK_PRE)) {
1100 cpl_msg_error(fctid,
1101 "No object mask found. Unable to use requested sky algorithm");
1102 vircam_sci_tidy(0);
1103 return(-1);
1104 } else if (ps.master_objmask != NULL &&
1105 (vircam_sci_config.skyalgo == PAWSKY_MASK ||
1106 vircam_sci_config.skyalgo == TILESKY)) {
1107 cpl_msg_info(fctid,
1108 "Requested sky subt algorithm requires no object mask");
1109 }
1110 nfail += vircam_sci_testfrm_1(ps.master_objmask,0,1);
1111
1112 /* Get the gain corrections */
1113
1114 status = CASU_OK;
1115 if (casu_gaincor_calc(ps.master_twilight_flat,&i,&(ps.gaincors),
1116 &status) != CASU_OK) {
1117 cpl_msg_error(fctid,"Error calculating gain corrections");
1118 vircam_sci_tidy(0);
1119 return(-1);
1120 }
1121
1122 /* Check to see if there is a readgain file */
1123
1124 if ((ps.readgain_file =
1125 casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1126 VIRCAM_CAL_READGAINFILE)) == NULL) {
1127 cpl_msg_error(fctid,"No master readnoise/gain file found");
1128 vircam_sci_tidy(0);
1129 return(-1);
1130 }
1131 nfail += vircam_sci_testfrm_1(ps.readgain_file,VIRCAM_NEXTN,0);
1132
1133 /* Check to see if there is a master confidence map. */
1134
1135 if ((ps.master_conf =
1136 casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1137 VIRCAM_CAL_CONF)) == NULL) {
1138 cpl_msg_error(fctid,"No master confidence map file found");
1139 vircam_sci_tidy(0);
1140 return(-1);
1141 }
1142 nfail += vircam_sci_testfrm_1(ps.master_conf,VIRCAM_NEXTN,1);
1143 ps.mask = casu_mask_define(framelist,ps.labels,nlab,VIRCAM_CAL_CONF,
1144 VIRCAM_CAL_BPM);
1145
1146 /* Check to see if there is a channel table */
1147
1148 if ((ps.chantab = casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1149 VIRCAM_CAL_CHANTAB)) == NULL) {
1150 cpl_msg_error(fctid,"No channel table found");
1151 vircam_sci_tidy(0);
1152 return(-1);
1153 }
1154 nfail += vircam_sci_testfrm_1(ps.chantab,VIRCAM_NEXTN,0);
1155
1156 /* Check to see if there is a photometric table */
1157
1158 if ((ps.phottab = casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1159 VIRCAM_CAL_PHOTTAB)) == NULL) {
1160 cpl_msg_error(fctid,"No photometric table found");
1161 vircam_sci_tidy(0);
1162 return(-1);
1163 }
1164 n = cpl_frame_get_nextensions(ps.phottab);
1165 nfail += vircam_sci_testfrm_1(ps.phottab,n,0);
1166
1167 /* Is the 2mass index file specified? */
1168
1169 catindex = NULL;
1170 if (vircam_sci_config.cdssearch == 0) {
1171 if ((catindex = casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1172 VIRCAM_CAL_2MASS)) == NULL) {
1173 cpl_msg_error(fctid,"No 2MASS index found -- cannot continue");
1174 vircam_sci_tidy(0);
1175 return(-1);
1176 }
1177 nfail += vircam_sci_testfrm_1(catindex,1,0);
1178 }
1179
1180 /* Is the Northern Schlegel file specified? */
1181
1182 if ((ps.schlf_n = casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1183 VIRCAM_CAL_SCHL_N)) == NULL) {
1184 cpl_msg_error(fctid,"Schlegel North map not found -- cannot continue");
1185 vircam_sci_tidy(0);
1186 return(-1);
1187 }
1188 nfail += vircam_sci_testfrm_1(ps.schlf_n,0,1);
1189
1190
1191 /* Is the Southern Schlegel file specified? */
1192
1193 if ((ps.schlf_s = casu_frameset_subgroup_1(framelist,ps.labels,nlab,
1194 VIRCAM_CAL_SCHL_S)) == NULL) {
1195 cpl_msg_error(fctid,"Schlegel South map not found -- cannot continue");
1196 vircam_sci_tidy(0);
1197 return(-1);
1198 }
1199 nfail += vircam_sci_testfrm_1(ps.schlf_s,0,1);
1200
1201 /* Check the cache location is writable */
1202
1203 if (access(vircam_sci_config.cacheloc,R_OK+W_OK+X_OK) != 0) {
1204 cpl_msg_error(fctid,"Cache location %s inacessible",
1205 vircam_sci_config.cacheloc);
1206 nfail++;
1207 }
1208
1209 /* Ok if any of this failed, then get out of here. This makes it a bit
1210 simpler later on since we now know that all of the specified files
1211 have the correct number of extensions and will load properly */
1212
1213 if (nfail > 0) {
1214 cpl_msg_error(fctid,
1215 "There are %" CPL_SIZE_FORMAT " input file errors -- cannot continue",
1216 (cpl_size)nfail);
1217 vircam_sci_tidy(0);
1218 return(-1);
1219 }
1220
1221 /* Get catalogue parameters */
1222
1223 if (catindex != NULL) {
1224 if (casu_catpars(catindex,&(ps.catpath),&(ps.catname)) == CASU_FATAL) {
1225 vircam_sci_tidy(0);
1226 cpl_frame_delete(catindex);
1227 return(-1);
1228 }
1229 cpl_frame_delete(catindex);
1230
1231 /* Set up the photometric calibration catalogue data */
1232
1233 (void)strcpy(current_catpath,ps.catpath);
1234 (void)strcpy(current_cat,ps.catname);
1235 } else {
1236 ps.catpath = NULL;
1237 ps.catname = NULL;
1238 }
1239
1240 /* Get the number of DITs. This assumes it is the same for all the science
1241 images (and it damn well better be!) */
1242
1243 pp = cpl_propertylist_load(cpl_frame_get_filename(cpl_frameset_get_position(ps.science_frames,0)),0);
1244 if (vircam_pfits_get_ndit(pp,&ndit) != CASU_OK) {
1245 cpl_msg_error(fctid,"No value for NDIT available");
1246 freepropertylist(pp);
1247 vircam_sci_tidy(0);
1248 return(-1);
1249 }
1250 cpl_propertylist_delete(pp);
1251
1252 /* Load the photometric table */
1253
1254 ps.tphottab = cpl_table_load(cpl_frame_get_filename(ps.phottab),1,0);
1255
1256 /* Break these into pawprints now */
1257
1258 vircam_sci_paws_create(ps.science_frames,&(ps.nscipaws),&(ps.science_paws));
1259 vircam_sci_paws_create(ps.offset_skies,&(ps.noffpaws),&(ps.offsky_paws));
1260
1261 /* Check what we have and see if it makes sense. If this isn't a tile
1262 and there are multiple pawprints, then signal an error */
1263
1264 if (ps.science_paws[0].tilenum == -1 && ps.nscipaws > 1) {
1265 cpl_msg_error(fctid,
1266 "List has %" CPL_SIZE_FORMAT " pawprints. Only 1 is allowed for non tiles",
1267 (cpl_size)ps.nscipaws);
1268 vircam_sci_tidy(0);
1269 return(-1);
1270 }
1271
1272 /* Define the skys that will be made */
1273
1274 vircam_sci_skydefine();
1275
1276 /* Print out some stuff if you want a preview */
1277
1278 if (vircam_sci_config.preview_only) {
1279 if (ps.science_paws[0].tilenum == -1)
1280 fprintf(stdout,"This is a paw group with %" CPL_SIZE_FORMAT " files\n",
1281 cpl_frameset_get_size(ps.science_frames));
1282 else
1283 fprintf(stdout,"This is a tile group with %" CPL_SIZE_FORMAT " files\n",
1284 cpl_frameset_get_size(ps.science_frames));
1285 frm = cpl_frameset_get_position(ps.science_frames,0);
1286 pp = cpl_propertylist_load(cpl_frame_get_filename(frm),0);
1287 (void)vircam_pfits_get_filter(pp,filt);
1288 (void)vircam_pfits_get_ndit(pp,&ndit);
1289 (void)vircam_pfits_get_dit(pp,&dit);
1290 (void)vircam_pfits_get_projid(pp,projid);
1291 (void)vircam_pfits_get_njsteps(pp,&njsteps);
1292 cpl_propertylist_delete(pp);
1293
1294 fprintf(stdout,"Filter %8s, DIT: %8.1f, NDIT: %" CPL_SIZE_FORMAT ", Project: %s\n",filt,
1295 dit,(cpl_size)ndit,projid);
1296 fprintf(stdout,"Dark: %s\n",cpl_frame_get_filename(ps.master_dark));
1297 fprintf(stdout,"Flat: %s\n",
1298 cpl_frame_get_filename(ps.master_twilight_flat));
1299 fprintf(stdout,"CPM: %s\n",cpl_frame_get_filename(ps.master_conf));
1300 fprintf(stdout,"Channel table: %s\n",
1301 cpl_frame_get_filename(ps.chantab));
1302 fprintf(stdout,"A %" CPL_SIZE_FORMAT " point dither will be done\n",
1303 (cpl_size)njsteps);
1304 if (ps.science_paws[0].tilenum != -1)
1305 fprintf(stdout,"The tile has %" CPL_SIZE_FORMAT " pawprints\n",
1306 (cpl_size)ps.nscipaws);
1307 for (i = 0; i < ps.nscipaws; i++) {
1308 n = cpl_frameset_get_size(ps.science_paws[i].orig);
1309 for (j = 0; j < n; j++) {
1310 frm = cpl_frameset_get_position(ps.science_paws[i].orig,j);
1311 fprintf(stdout,"%s sky%" CPL_SIZE_FORMAT "\n",
1312 cpl_frame_get_filename(frm),
1313 (cpl_size)(ps.science_paws[i].whichsky[j]+1));
1314 }
1315 }
1316 if (ps.noffpaws != 0) {
1317 fprintf(stdout,"There are %" CPL_SIZE_FORMAT " offset sky frames\n",
1318 cpl_frameset_get_size(ps.offset_skies));
1319 for (i = 0; i < ps.noffpaws; i++) {
1320 n = cpl_frameset_get_size(ps.offsky_paws[i].orig);
1321 for (j = 0; j < n; j++) {
1322 frm = cpl_frameset_get_position(ps.offsky_paws[i].orig,j);
1323 fprintf(stdout,"%s sky%" CPL_SIZE_FORMAT "\n",cpl_frame_get_filename(frm),
1324 (cpl_size)(ps.offsky_paws[i].whichsky[j]+1));
1325 }
1326 }
1327 }
1328 fprintf(stdout,"\nRequested sky algorithm: %" CPL_SIZE_FORMAT "\n",
1329 (cpl_size)vircam_sci_config.skyalgo);
1330 for (i = 0; i < ps.nskys; i++) {
1331 fprintf(stdout,"Sky%" CPL_SIZE_FORMAT ": %" CPL_SIZE_FORMAT " ",
1332 (cpl_size)(i+1),(cpl_size)ps.skys[i].skyalgo);
1333 if (ps.skys[i].objmask != NULL)
1334 fprintf(stdout,"mask: %s\nFormed from:\n",
1335 cpl_frame_get_filename(ps.skys[i].objmask));
1336 else
1337 fprintf(stdout,"\nFormed from:\n");
1338 for (j = 0; j < cpl_frameset_get_size(ps.skys[i].contrib); j++) {
1339 frm = cpl_frameset_get_position(ps.skys[i].contrib,j);
1340 fprintf(stdout," %s\n",cpl_frame_get_filename(frm));
1341 }
1342 }
1343 vircam_sci_tidy(0);
1344 return(0);
1345 }
1346
1347 /* Get some workspace for the product frames */
1348
1349 ps.nscience = cpl_frameset_get_size(ps.science_frames);
1350 nsci = ps.nscience;
1351 ps.product_frames_simple = cpl_malloc(ps.nscience*sizeof(cpl_frame *));
1352 for (i = 0; i < ps.nscience; i++)
1353 ps.product_frames_simple[i] = NULL;
1354 if (ps.offset_skies != NULL) {
1355 ps.noffsets = cpl_frameset_get_size(ps.offset_skies);
1356 ps.product_frames_simple_off =
1357 cpl_malloc(ps.noffsets*sizeof(cpl_frame *));
1358 for (i = 0; i < ps.noffsets; i++)
1359 ps.product_frames_simple_off[i] = NULL;
1360 } else {
1361 ps.noffsets = 0;
1362 }
1363
1364 /* Do the stage1 processing. Loop for all extensions */
1365
1366 cpl_msg_info(fctid,"Beginning stage1 reduction");
1367 cpl_msg_indent_more();
1368 for (j = 1; j <= VIRCAM_NEXTN; j++) {
1369 isfirst = (j == 1);
1370 gaincor_fac = (ps.gaincors)[j-1];
1371 cpl_msg_info(fctid,"Extension [%" CPL_SIZE_FORMAT "]",(cpl_size)j);
1372
1373 /* Load up the calibration frames. We know these won't fail now
1374 so we can skip all the boring testing... */
1375
1376 ps.fdark = casu_fits_load(ps.master_dark,CPL_TYPE_FLOAT,j);
1377 ps.fflat = casu_fits_load(ps.master_twilight_flat,CPL_TYPE_FLOAT,j);
1378 ps.fconf = casu_fits_load(ps.master_conf,CPL_TYPE_INT,j);
1379 casu_mask_load(ps.mask,j,
1380 (int)cpl_image_get_size_x(casu_fits_get_image(ps.fconf)),
1381 (int)cpl_image_get_size_y(casu_fits_get_image(ps.fconf)));
1382 if (offsky == -1)
1383 ps.fsky = casu_fits_load(ps.master_sky,CPL_TYPE_FLOAT,j);
1384 ps.fchantab = casu_tfits_load(ps.chantab,j);
1385
1386 /* Now load up the science frames and offset skies, if needed */
1387
1388 ps.nscience = cpl_frameset_get_size(ps.science_frames);
1389 ps.sci_fits = casu_fits_load_list(ps.science_frames,CPL_TYPE_FLOAT,j);
1390 if (j == 1)
1391 ps.phupaf = vircam_paf_phu_items(casu_fits_get_phu(ps.sci_fits[0]));
1392 if (offsky == 1) {
1393 ps.noffsets = cpl_frameset_get_size(ps.offset_skies);
1394 ps.offsky_fits = casu_fits_load_list(ps.offset_skies,
1395 CPL_TYPE_FLOAT,j);
1396 } else {
1397 ps.noffsets = 0;
1398 ps.offsky_fits = NULL;
1399 }
1400
1401 /* Loop through and mark the frames where the header says the detector
1402 wasn't live. Also check to see if the CRVAL == 0 problem is
1403 present. Check for live detectors in the offset skies too */
1404
1405 for (i = 0; i < ps.nscience; i++) {
1406 ff = ps.sci_fits[i];
1408 if (! live)
1409 casu_fits_set_error(ff,CASU_FATAL);
1411 casu_fits_get_ehu(ff)) != CASU_OK) {
1412 cpl_msg_error(fctid,"Unable to correct CRVAL in %s",
1414 vircam_sci_tidy(0);
1415 return(-1);
1416 }
1417 }
1418 for (i = 0; i < ps.noffsets; i++) {
1419 ff = ps.offsky_fits[i];
1421 if (! live)
1422 casu_fits_set_error(ff,CASU_FATAL);
1423 }
1424
1425 /* Do the corrections now. First for the object frames. Write
1426 out intermediate versions as we go */
1427
1428 vircam_sci_get_readnoise_gain(j,&readnoise,&gain);
1429 for (i = 0; i < ps.nscience; i++) {
1430 ff = ps.sci_fits[i];
1431 cpl_propertylist_update_float(casu_fits_get_ehu(ff),"READNOIS",
1432 readnoise);
1433 cpl_propertylist_set_comment(casu_fits_get_ehu(ff),"READNOIS",
1434 "[e-] Readnoise used in processing");
1435 cpl_propertylist_update_float(casu_fits_get_ehu(ff),"GAIN",gain);
1436 cpl_propertylist_set_comment(casu_fits_get_ehu(ff),"GAIN",
1437 "[e-/adu] Gain used in processing");
1438 if (casu_fits_get_status(ff) == CASU_FATAL) {
1439 cpl_msg_info(fctid,"Detector is flagged dead in %s",
1441 } else {
1442 status = CASU_OK;
1443 (void)casu_darkcor(ff,ps.fdark,1.0,&status);
1444 (void)vircam_lincor(ff,ps.fchantab,1,ndit,&status);
1445 (void)casu_nditcor(ff,ndit,"EXPTIME",&status);
1446 (void)casu_flatcor(ff,ps.fflat,&status);
1447 (void)casu_gaincor(ff,gaincor_fac,&status);
1448 casu_fits_set_error(ff,status);
1449 }
1450 frm = cpl_frameset_get_position(ps.science_frames,i);
1451 tname = (char *)cpl_frame_get_filename(frm);
1452 vircam_sci_product_name(tname,SIMPLE_FILE,
1453 vircam_sci_config.prettynames,i+1,fname);
1454 vircam_sci_save_simple(ff,framelist,parlist,0,
1455 cpl_frameset_get_position(ps.science_frames,i),
1456 isfirst,VIRCAM_PRO_SIMPLE_SCI,fname,
1457 ps.product_frames_simple+i);
1458 }
1459 for (i = 0; i < ps.noffsets; i++) {
1460 ff = ps.offsky_fits[i];
1461 if (casu_fits_get_status(ff) == CASU_FATAL) {
1462 cpl_msg_info(fctid,"Detector is flagged dead in %s",
1464 } else {
1465 status = CASU_OK;
1466 (void)casu_darkcor(ff,ps.fdark,1.0,&status);
1467 (void)vircam_lincor(ff,ps.fchantab,1,ndit,&status);
1468 (void)casu_nditcor(ff,ndit,"EXPTIME",&status);
1469 (void)casu_flatcor(ff,ps.fflat,&status);
1470 (void)casu_gaincor(ff,gaincor_fac,&status);
1471 casu_fits_set_error(ff,status);
1472 }
1473 frm = cpl_frameset_get_position(ps.offset_skies,i);
1474 tname = (char *)cpl_frame_get_filename(frm);
1475 vircam_sci_product_name(tname,SIMPLE_FILE,
1476 vircam_sci_config.prettynames,
1477 ps.nscience+i+1,fname);
1478 vircam_sci_save_simple(ff,framelist,parlist,0,
1479 cpl_frameset_get_position(ps.offset_skies,i),
1480 isfirst,VIRCAM_PRO_SIMPLE_SKY,fname,
1481 ps.product_frames_simple_off+i);
1482 }
1483
1484 /* Intermediate tidy */
1485
1486 vircam_sci_tidy(1);
1487 }
1488 for (i = 0; i < nsci; i++)
1489 freeframe(ps.product_frames_simple[i]);
1490 for (i = 0; i < ps.noffsets; i++)
1491 freeframe(ps.product_frames_simple_off[i]);
1492
1493 cpl_msg_indent_less();
1494
1495 /* Form the sky frames. These are saved and registered as products */
1496
1497 cpl_msg_info(fctid,"Making skies");
1498 for (i = 0; i < ps.nskys; i++) {
1499 if (vircam_sci_makesky(framelist,parlist,&(ps.skys[i]),
1500 VIRCAM_PRO_SIMPLE_SCI) != CASU_OK) {
1501 cpl_msg_error(fctid,"Error making sky %" CPL_SIZE_FORMAT "",
1502 (cpl_size)i);
1503 vircam_sci_tidy(0);
1504 return(-1);
1505 }
1506 }
1507
1508 /* Do sky subtraction, destripe and write them out */
1509
1510 cpl_msg_info(fctid,"Beginning stage2 reduction");
1511 (void)vircam_sci_sky_stripe_wcs(ps.nscipaws,ps.science_paws,
1512 VIRCAM_PRO_SIMPLE_SCI,framelist,parlist,
1513 vircam_sci_config.destripe);
1514 (void)vircam_sci_sky_stripe_wcs(ps.noffpaws,ps.offsky_paws,
1515 VIRCAM_PRO_SIMPLE_SKY,framelist,parlist,
1516 vircam_sci_config.destripe);
1517
1518 /* Loop for all science jitters. Jitter, WCSFIT, photcal and write out */
1519
1520 cpl_msg_info(fctid,"Beginning group processing");
1521 cpl_msg_indent_more();
1522 for (i = 0; i < ps.nscipaws; i++) {
1523 cpl_msg_info(fctid,"Working on paw%" CPL_SIZE_FORMAT "",
1524 (cpl_size)(i+1));
1525 cpl_msg_indent_more();
1526 for (j = 1; j <= VIRCAM_NEXTN; j++) {
1527 cpl_msg_info(fctid,
1528 "Stacking paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1529 (cpl_size)(i+1),(cpl_size)j);
1530 vircam_sci_stack(&(ps.science_paws[i]),j);
1531 cpl_msg_info(fctid,
1532 "Source extraction paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1533 (cpl_size)(i+1),(cpl_size)j);
1534 vircam_sci_cat(&(ps.science_paws[i]),j);
1535 cpl_msg_info(fctid,
1536 "WCS fit paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1537 (cpl_size)(i+1),(cpl_size)j);
1538 vircam_sci_wcsfit(&(ps.science_paws[i].stack[j-1]),
1539 &(ps.science_paws[i].stackc[j-1]),
1540 &(ps.science_paws[i].cat[j-1]),1,2);
1541 vircam_copywcs(casu_fits_get_ehu(ps.science_paws[i].stack[j-1]),
1542 casu_fits_get_ehu(ps.science_paws[i].stackc[j-1]));
1543 (void)casu_getstds(casu_fits_get_ehu(ps.science_paws[i].stack[j-1]),
1544 1,current_catpath,current_cat,
1545 vircam_sci_config.cdssearch,
1546 vircam_sci_config.cacheloc,&stdscat,
1547 &status);
1548 (void)casu_matchstds(casu_tfits_get_table(ps.science_paws[i].cat[j-1]),
1549 stdscat,300.0,
1550 &tab,&status);
1551 ps.science_paws[i].mstds[j-1] = casu_tfits_wrap(tab,
1552 ps.science_paws[i].cat[j-1],NULL,NULL);
1553 freetable(stdscat);
1554 }
1555 cpl_msg_indent_less();
1556 cpl_msg_info(fctid,
1557 "Doing photometric calibriation on paw%" CPL_SIZE_FORMAT "",
1558 (cpl_size)(i+1));
1559 vircam_sci_photcal(&(ps.science_paws[i]));
1560 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[i].orig,0));
1561 cpl_msg_info(fctid,"Saving paw%" CPL_SIZE_FORMAT "",(cpl_size)(i+1));
1562 cpl_msg_indent_more();
1563 for (j = 1; j <= VIRCAM_NEXTN; j++) {
1564 cpl_msg_info(fctid,
1565 "Saving image paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1566 (cpl_size)(i+1),(cpl_size)j);
1567 vircam_sci_save_stack(ps.science_paws[i].stack[j-1],framelist,
1568 parlist,template,
1569 vircam_sci_config.prettynames,i+1,
1570 &(ps.science_paws[i].product_frame_im));
1571 cpl_msg_info(fctid,"Saving confidence map paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1572 (cpl_size)(i+1),(cpl_size)j);
1573 vircam_sci_save_stack_conf(ps.science_paws[i].stackc[j-1],framelist,
1574 parlist,template,
1575 vircam_sci_config.prettynames,i+1,
1576 &(ps.science_paws[i].product_frame_conf));
1577 cpl_msg_info(fctid,
1578 "Saving catalogue paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1579 (cpl_size)(i+1),(cpl_size)j);
1580 vircam_sci_save_stack_cat(ps.science_paws[i].cat[j-1],
1581 framelist,parlist,template,
1582 vircam_sci_config.prettynames,i+1,
1583 &(ps.science_paws[i].product_frame_cat));
1584 }
1585 freeframe(template);
1586 cpl_msg_indent_less();
1587 vircam_sci_paw_delete(ps.science_paws+i);
1588 }
1589 cpl_msg_indent_less();
1590
1591 /* Final cleanup */
1592
1593 vircam_sci_tidy(0);
1594 return(0);
1595}
1596
1597/*---------------------------------------------------------------------------*/
1612/*---------------------------------------------------------------------------*/
1613
1614static void vircam_sci_photcal(pawprint *paw) {
1615 char filt[16];
1616 int status;
1617
1618 /* Get the filter name for the pawprint */
1619
1620 vircam_pfits_get_filter(casu_fits_get_phu(paw->stack[0]),filt);
1621
1622 /* Call the routine */
1623
1624 status = CASU_OK;
1625 casu_photcal_extinct(paw->stack,paw->mstds,paw->cat,VIRCAM_NEXTN,
1626 filt,ps.tphottab,vircam_sci_config.minphotom,
1627 ps.schlf_n,ps.schlf_s,"EXPTIME","ESO TEL AIRM START",
1628 vircam_sci_config.magerrcut,&status);
1629}
1630
1631/*---------------------------------------------------------------------------*/
1645/*---------------------------------------------------------------------------*/
1646
1647static void vircam_sci_skydefine(void) {
1648 int i,j;
1649 cpl_frameset *newfrmset,**in;
1650 cpl_frame *template;
1651
1652 /* Switch for the sky algorithm choices. Start with SKYNONE where
1653 we don't have to do anything as the sky frame index in the pawprints
1654 references nothing */
1655
1656 switch (vircam_sci_config.skyalgo) {
1657 case SKYNONE:
1658 break;
1659
1660 /* AUTO means we use the data to determine what is the best way
1661 to estimate the sky. The routine also assigns the sky to be subtracted
1662 to each object image */
1663
1664 case AUTO:
1665 vircam_sci_choose_skyalgo(&(ps.nskys),&(ps.skys));
1666 break;
1667
1668 /* A master sky exists. Therefore all we have to do here is to
1669 create a sky structure and then assign it to all the input objects */
1670
1671 case SKYMASTER:
1672 ps.nskys = 1;
1673 ps.skys = cpl_malloc(sizeof(skystruct));
1674 ps.skys[0].skyframe = cpl_frame_duplicate(ps.master_sky);
1675 ps.skys[0].skyalgo = SKYMASTER;
1676 ps.skys[0].contrib = NULL;
1677 ps.skys[0].objmask = NULL;
1678 ps.skys[0].template = NULL;
1679 for (i = 0; i < ps.nscipaws; i++)
1680 vircam_sci_assign_sky_all(ps.science_paws[i],0);
1681 break;
1682
1683 /* PAWSKY_MASK is requested. NB: there may be more than one sky because
1684 the user may have requested this algorithm for a tile. We need a
1685 section for the case where offset skies have been provided or not */
1686
1687 case PAWSKY_MASK:
1688 if (ps.noffpaws == 0) {
1689 ps.nskys = ps.nscipaws;
1690 ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1691 for (i = 0; i < ps.nscipaws; i++) {
1692 newfrmset = cpl_frameset_duplicate(ps.science_paws[i].current);
1693 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[i].orig,0));
1694 ps.skys[i] = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,
1695 i+1);
1696 vircam_sci_assign_sky_all(ps.science_paws[i],i);
1697 }
1698 } else {
1699 ps.nskys = ps.noffpaws;
1700 ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1701 for (i = 0; i < ps.noffpaws; i++) {
1702 newfrmset = cpl_frameset_duplicate(ps.offsky_paws[i].current);
1703 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.offsky_paws[i].orig,0));
1704 ps.skys[i] = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,
1705 i+1);
1706 vircam_sci_assign_sky_all(ps.offsky_paws[i],i);
1707 }
1708 for (i = 0; i < ps.nscipaws; i++) {
1709 if (i > ps.nskys-1)
1710 j = ps.nskys - 1;
1711 else
1712 j = i;
1713 vircam_sci_assign_sky_all(ps.science_paws[i],j);
1714 }
1715 }
1716 break;
1717
1718 /* PAWSKY_MASK_PRE is requested. NB: there may be more than one sky because
1719 the user may have requested this algorithm for a tile. Offset skies
1720 are ignored because the mask won't cover this. */
1721
1722 case PAWSKY_MASK_PRE:
1723 ps.nskys = ps.nscipaws;
1724 ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1725 for (i = 0; i < ps.nscipaws; i++) {
1726 newfrmset = cpl_frameset_duplicate(ps.science_paws[i].current);
1727 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[i].orig,0));
1728 ps.skys[i] = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,i+1);
1729 vircam_sci_assign_sky_all(ps.science_paws[i],i);
1730 }
1731 break;
1732
1733 /* TILESKY is requested. This results in one sky */
1734
1735 case TILESKY:
1736 ps.nskys = 1;
1737 ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1738 if (ps.noffpaws == 0) {
1739 in = cpl_malloc(ps.nscipaws*sizeof(cpl_frameset *));
1740 for (i = 0; i < ps.nscipaws; i++)
1741 in[i] = ps.science_paws[i].current;
1742 newfrmset = vircam_sci_merge_framesets(ps.nscipaws,in);
1743 freespace(in);
1744 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[0].orig,0));
1745 ps.skys[0] = vircam_sci_crsky(TILESKY,newfrmset,template,1);
1746 for (i = 0; i < ps.nscipaws; i++)
1747 vircam_sci_assign_sky_all(ps.science_paws[i],0);
1748 } else {
1749 in = cpl_malloc(ps.noffpaws*sizeof(cpl_frameset *));
1750 for (i = 0; i < ps.noffpaws; i++)
1751 in[i] = ps.offsky_paws[i].current;
1752 newfrmset = vircam_sci_merge_framesets(ps.noffpaws,in);
1753 freespace(in);
1754 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.offsky_paws[0].orig,0));
1755 ps.skys[0] = vircam_sci_crsky(TILESKY,newfrmset,template,1);
1756 for (i = 0; i < ps.noffpaws; i++)
1757 vircam_sci_assign_sky_all(ps.offsky_paws[i],0);
1758 for (i = 0; i < ps.nscipaws; i++)
1759 vircam_sci_assign_sky_all(ps.science_paws[i],0);
1760 }
1761 break;
1762
1763 /* TILESKY_MINUS is requested. This has to be done separately, so
1764 the information in the sky structure isn't quite what is going
1765 to happen. Offset skies are ignored */
1766
1767 case TILESKY_MINUS:
1768 ps.nskys = 1;
1769 ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1770 in = cpl_malloc(ps.nscipaws*sizeof(cpl_frameset *));
1771 for (i = 0; i < ps.nscipaws; i++)
1772 in[i] = ps.science_paws[i].current;
1773 newfrmset = vircam_sci_merge_framesets(ps.nscipaws,in);
1774 freespace(in);
1775 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[0].orig,0));
1776 ps.skys[0] = vircam_sci_crsky(TILESKY_MINUS,newfrmset,template,1);
1777 for (i = 0; i < ps.nscipaws; i++)
1778 vircam_sci_assign_sky_all(ps.science_paws[i],0);
1779 break;
1780
1781 /* PAWSKY_MINUS is requested. This has to be done separately, so
1782 the information in the sky structure isn't quite what is going
1783 to happen. Offset skies are ignored */
1784
1785 case PAWSKY_MINUS:
1786 ps.nskys = 1;
1787 ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1788 newfrmset = cpl_frameset_duplicate(ps.science_paws[0].current);
1789 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[0].orig,0));
1790 ps.skys[0] = vircam_sci_crsky(PAWSKY_MINUS,newfrmset,template,1);
1791 vircam_sci_assign_sky_all(ps.science_paws[0],0);
1792 break;
1793 }
1794}
1795
1796/*---------------------------------------------------------------------------*/
1814/*---------------------------------------------------------------------------*/
1815
1816static void vircam_sci_cat(pawprint *paw, int extn) {
1817 int status;
1818 casu_tfits *tab;
1819 float gain;
1820
1821 /* Do the catalogue for the current extension */
1822
1823 status = CASU_OK;
1824 (void)vircam_pfits_get_gain(casu_fits_get_ehu(paw->stack[extn-1]),&gain);
1825 (void)casu_imcore(paw->stack[extn-1],paw->stackc[extn-1],stk_cat.ipix,
1826 stk_cat.thresh,stk_cat.icrowd,stk_cat.rcore,
1827 stk_cat.nbsize,6,2.0,&tab,gain,&status);
1828 paw->cat[extn-1] = tab;
1829}
1830
1831/*---------------------------------------------------------------------------*/
1849/*---------------------------------------------------------------------------*/
1850
1851static void vircam_sci_stack(pawprint *paw, int extn) {
1852 casu_fits **inf,*inconf,*out,*outc,*outv;
1853 int ninf,status,i,fastslow;
1854 double sum,mjd;
1855
1856 /* Do the stack for the current extension */
1857
1858 inf = casu_fits_load_list(paw->current,CPL_TYPE_FLOAT,extn);
1859 inconf = casu_fits_load(ps.master_conf,CPL_TYPE_INT,extn);
1860 ninf = (int)cpl_frameset_get_size(paw->current);
1861 status = CASU_OK;
1862 if (stk.fast == -1)
1863 fastslow = (ninf <= stk.nfst);
1864 else
1865 fastslow = stk.fast;
1866 casu_imstack(inf,&inconf,NULL,NULL,ninf,1,stk.lthr,stk.hthr,stk.method,
1867 stk.seeing,fastslow,1,"EXPTIME",&out,&outc,&outv,&status);
1868
1869 /* Get the mjd of each input image. Average it and write that to the
1870 output stack header */
1871
1872 sum = 0.0;
1873 for (i = 0; i < ninf; i++) {
1875 sum += mjd;
1876 }
1877 sum /= (double)ninf;
1878 cpl_propertylist_update_double(casu_fits_get_ehu(out),"MJD_MEAN",sum);
1879 cpl_propertylist_set_comment(casu_fits_get_ehu(out),"MJD_MEAN",
1880 "Mean MJD of the input images");
1881 freefitslist(inf,ninf);
1882 freefits(inconf);
1883 paw->stack[extn-1] = out;
1884 paw->stackc[extn-1] = outc;
1885}
1886
1887/*---------------------------------------------------------------------------*/
1919/*---------------------------------------------------------------------------*/
1920
1921static int vircam_sci_sky_stripe_wcs(int npaw, pawprint *paw, const char *tag,
1922 cpl_frameset *framelist,
1923 cpl_parameterlist *parlist, int destripe) {
1924 int i,j,jj,k,nf,n,isfirst,ii,status,whichsky,skyminus;
1925 long nx,ny,npts;
1926 cpl_frame *curframe,*template,*product_frame = NULL;
1927 cpl_frameset *objframes;
1928 cpl_image *img,*simg;
1929 float med,sig,*sdata;
1930 casu_fits **sky_extns,*curfits[4],*tmpfits,*fconf;
1931 unsigned char *bpm[VIRCAM_NEXTN];
1932 cpl_mask *cplmasks[VIRCAM_NEXTN];
1933 const char *fctid = "vircam_sci_sky_stripe_wcs";
1934 char tmpname[BUFSIZ];
1935
1936 /* NULL input */
1937
1938 if (npaw == 0 || paw == NULL)
1939 return(CASU_OK);
1940
1941 /* Set up the masking from the confidence maps */
1942
1943 for (i = 1; i <= VIRCAM_NEXTN; i++) {
1944 casu_mask_load(ps.mask,i,0,0);
1945 nx = casu_mask_get_size_x(ps.mask);
1946 ny = casu_mask_get_size_y(ps.mask);
1947 bpm[i-1] = cpl_calloc(nx*ny,sizeof(unsigned char));
1948 memmove(bpm[i-1],casu_mask_get_data(ps.mask),
1949 nx*ny*sizeof(unsigned char));
1950 cplmasks[i-1] = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,
1951 (cpl_binary *)bpm[i-1]);
1952 }
1953
1954 /* Loop for all the pawprints... */
1955
1956 cpl_msg_indent_more();
1957 sky_extns = cpl_calloc(VIRCAM_NEXTN,sizeof(casu_fits *));
1958 for (j = 0; j < VIRCAM_NEXTN; j++)
1959 sky_extns[j] = NULL;
1960 for (j = 0; j < npaw; j++) {
1961
1962 /* Do the sky subtraction for each frame in the pawprint. */
1963
1964 objframes = paw[j].current;
1965 nf = cpl_frameset_get_size(objframes);
1966 whichsky = -1;
1967 skyminus = (ps.skys[paw[j].whichsky[0]].skyalgo == TILESKY_MINUS ||
1968 ps.skys[paw[j].whichsky[0]].skyalgo == PAWSKY_MINUS);
1969 for (jj = 0; jj < nf; jj++) {
1970 curframe = cpl_frameset_get_position(objframes,jj);
1971 cpl_msg_info(fctid,"Beginning work on %s",
1972 cpl_frame_get_filename(curframe));
1973 template = cpl_frameset_get_position(paw[j].orig,jj);
1974 n = 0;
1975 (void)snprintf(tmpname,BUFSIZ,"tmp_%s",
1976 cpl_frame_get_filename(curframe));
1977
1978 /* First load up the sky extensions and normalise the data arrays
1979 to a zero median (so long as the sky correction hasn't
1980 already been done). */
1981
1982 if (! skyminus &&
1983 (whichsky == -1 || paw[j].whichsky[jj] != whichsky)) {
1984 whichsky = paw[j].whichsky[jj];
1985 for (i = 1; i <= VIRCAM_NEXTN; i++) {
1986 freefits(sky_extns[i-1]);
1987 sky_extns[i-1] = casu_fits_load(ps.skys[whichsky].skyframe,
1988 CPL_TYPE_FLOAT,i);
1989 img = casu_fits_get_image(sky_extns[i-1]);
1990 sdata = cpl_image_get_data_float(img);
1991 nx = (long)cpl_image_get_size_x(img);
1992 ny = (long)cpl_image_get_size_y(img);
1993 npts = nx*ny;
1994 casu_qmedsig(sdata,bpm[i-1],npts,5.0,3,-1000.0,65535.0,
1995 &med,&sig);
1996 for (k = 0; k < npts; k++)
1997 sdata[k] -= med;
1998 }
1999 }
2000
2001 /* Loop for all the extensions. First do the sky subtraction
2002 (if we need to do it) */
2003
2004 isfirst = 1;
2005 for (i = 1; i <= VIRCAM_NEXTN; i++) {
2006 curfits[n] = casu_fits_load(curframe,CPL_TYPE_FLOAT,i);
2007 img = casu_fits_get_image(curfits[n]);
2008 if (sky_extns[i-1] != NULL) {
2009 simg = casu_fits_get_image(sky_extns[i-1]);
2010 cpl_image_subtract(img,(const cpl_image *)simg);
2011 cpl_propertylist_update_string(casu_fits_get_ehu(curfits[n]),
2012 "ESO DRS SKYCOR",
2013 casu_fits_get_fullname(sky_extns[i-1]));
2014 }
2015
2016 /* Reject the bad pixels from the image */
2017
2018 cpl_image_reject_from_mask(img,cplmasks[i-1]);
2019
2020 /* When we've done four, destripe them and then write them
2021 out in a temporary file */
2022
2023 n++;
2024 if (n == 4) {
2025 n = 0;
2026 status = CASU_OK;
2027 if (destripe)
2028 vircam_destripe_four(curfits,vircam_sci_config.str_filt,
2029 &status);
2030 for (ii = 0; ii < 4; ii++) {
2031 tmpfits = casu_fits_duplicate(curfits[ii]);
2032 casu_fits_set_filename(tmpfits,tmpname);
2033 fconf = casu_fits_load(ps.master_conf,CPL_TYPE_INT,
2034 i-3+ii);
2035 vircam_sci_wcsfit(&tmpfits,&fconf,NULL,1,1);
2036 vircam_sci_save_simple(tmpfits,framelist,parlist,
2037 1,template,isfirst,tag,
2038 tmpname,&product_frame);
2039 isfirst = 0;
2040 freefits(curfits[ii]);
2041 freefits(tmpfits);
2042 freefits(fconf);
2043 }
2044 }
2045 }
2046
2047 /* When we've finished writing out the new file. Delete the
2048 old one and replace it with the new one */
2049
2050 remove(cpl_frame_get_filename(curframe));
2051 cpl_frame_set_filename(product_frame,
2052 cpl_frame_get_filename(curframe));
2053 rename(tmpname,cpl_frame_get_filename(curframe));
2054 }
2055
2056 /* Clear up some memory */
2057
2058 for (i = 0; i < VIRCAM_NEXTN; i++)
2059 freefits(sky_extns[i]);
2060 }
2061 for (i = 0; i < VIRCAM_NEXTN; i++) {
2062 cpl_mask_unwrap(cplmasks[i]);
2063 freespace(bpm[i]);
2064 }
2065 freespace(sky_extns);
2066 cpl_msg_indent_less();
2067 return(CASU_OK);
2068}
2069
2070/*---------------------------------------------------------------------------*/
2090/*---------------------------------------------------------------------------*/
2091
2092static cpl_frame *vircam_sci_findtemplate(cpl_frame *in) {
2093 int i,j,imatch,jmatch,n;
2094 cpl_frame *frm;
2095
2096 imatch = -1;
2097 jmatch = -1;
2098 for (i = 0; i < ps.nscipaws; i++) {
2099 n = cpl_frameset_get_size(ps.science_paws[i].current);
2100 for (j = 0; j < n; j++) {
2101 frm = cpl_frameset_get_position(ps.science_paws[i].current,j);
2102 if (! strcmp(cpl_frame_get_filename(in),
2103 cpl_frame_get_filename(frm))) {
2104 imatch = i;
2105 jmatch = j;
2106 break;
2107 }
2108 }
2109 if (imatch != -1)
2110 break;
2111 }
2112 if (imatch == -1)
2113 return(NULL);
2114 else
2115 return(cpl_frameset_get_position(ps.science_paws[imatch].orig,jmatch));
2116}
2117
2118/*---------------------------------------------------------------------------*/
2145/*---------------------------------------------------------------------------*/
2146
2147static void vircam_sci_wcsfit(casu_fits **in, casu_fits **conf,
2148 casu_tfits **incat, int nf, int level) {
2149 int status,nstd,ncat,slevel,n,i,j;
2150 float *x,*y,*ra,*dec,gain;
2151 double r,d;
2152 casu_tfits *tcat;
2153 cpl_table *stdscat,*newstds,*cat,*tmp,*tmp2,*matchstds;
2154 cpl_propertylist *p;
2155 cpl_wcs *wcs;
2156 const char *fctid = "vircam_sci_wcsfit";
2157
2158 /* Loop for all the images */
2159
2160 for (j = 0; j < nf; j++) {
2161
2162 /* If this is a level one wcsfit, then we generate a temporary
2163 catalogue */
2164
2165 status = CASU_OK;
2166 (void)vircam_pfits_get_gain(casu_fits_get_ehu(in[j]),&gain);
2167 if (level == 1)
2168 (void)casu_imcore(in[j],conf[j],10,1.5,0,3.0,64,3,2.0,&tcat,
2169 gain,&status);
2170 else
2171 tcat = incat[j];
2172
2173 /* Get some standard stars */
2174
2175 (void)casu_getstds(casu_fits_get_ehu(in[j]),1,
2176 current_catpath,current_cat,
2177 vircam_sci_config.cdssearch,
2178 vircam_sci_config.cacheloc,&stdscat,&status);
2179 if (status != CASU_OK) {
2180 freetable(stdscat);
2181 cpl_msg_error(fctid,
2182 "Failed to find any standards for %s[%" CPL_SIZE_FORMAT "]",
2184 (cpl_size)casu_fits_get_nexten(in[j]));
2185 if (level == 1)
2186 freetfits(tcat);
2187 return;
2188 }
2189
2190 /* Restrict to stars with good photometry */
2191
2192 /* (void)cpl_table_or_selected_float(stdscat,"j_msig",CPL_LESS_THAN,0.2); */
2193 /* (void)cpl_table_and_selected_float(stdscat,"k_msig",CPL_LESS_THAN,0.2); */
2194 newstds = cpl_table_extract_selected(stdscat);
2195 nstd = (int)cpl_table_get_nrow(newstds);
2196
2197 /* If there are too many objects in the catalogue then first restrict
2198 ourselves by ellipticity. Cut so that there are similar numbers of
2199 objects in the standards and the object catalogues by retaining the
2200 brighter objects */
2201
2202 cat = casu_tfits_get_table(tcat);
2203 ncat = (int)cpl_table_get_nrow(cat);
2204 if (ncat > 500 && ncat > 2.0*nstd) {
2205 tmp = cpl_table_duplicate(cat);
2206 (void)cpl_table_or_selected_float(tmp,"Ellipticity",CPL_LESS_THAN,0.5);
2207 tmp2 = cpl_table_extract_selected(tmp);
2208 ncat = (int)cpl_table_get_nrow(tmp2);
2209 freetable(tmp);
2210 p = cpl_propertylist_new();
2211 cpl_propertylist_append_bool(p,"Isophotal_flux",TRUE);
2212 cpl_table_sort(tmp2,(const cpl_propertylist *)p);
2213 cpl_propertylist_delete(p);
2214 slevel = min(ncat,max(1,min(5000,max(500,2*nstd))));
2215 tmp = cpl_table_extract(tmp2,1,(cpl_size)slevel);
2216 freetable(tmp2);
2217 ncat = (int)cpl_table_get_nrow(tmp);
2218 cat = tmp;
2219 } else {
2220 tmp = NULL;
2221 }
2222
2223 /* Now match this against the catalogue */
2224
2225 (void)casu_matchstds(cat,newstds,300.0,&matchstds,&status);
2226 freetable(stdscat);
2227 freetable(newstds);
2228 freetable(tmp);
2229 if (status != CASU_OK) {
2230 freetable(matchstds);
2231 cpl_msg_error(fctid,"Failed to match standards to catalogue");
2232 if (level == 1)
2233 freetfits(tcat);
2234 return;
2235 }
2236
2237 /* Fit the plate solution */
2238
2239 (void)casu_platesol(casu_fits_get_ehu(in[j]),
2240 casu_tfits_get_ehu(tcat),matchstds,6,1,&status);
2241 freetable(matchstds);
2242 if (status != CASU_OK) {
2243 cpl_msg_error(fctid,"Failed to fit WCS");
2244 if (level == 1)
2245 freetfits(tcat);
2246 return;
2247 }
2248
2249 /* Update the RA and DEC of the objects in the object catalogue */
2250
2251 if (level == 2) {
2252 cat = casu_tfits_get_table(tcat);
2253 n = (int)cpl_table_get_nrow(cat);
2254 wcs = cpl_wcs_new_from_propertylist(casu_fits_get_ehu(in[j]));
2255 if (wcs == NULL) {
2256 cpl_msg_error(fctid,"Failed to fill RA and Dec in catalogue");
2257 return;
2258 }
2259 x = cpl_table_get_data_float(cat,"X_coordinate");
2260 y = cpl_table_get_data_float(cat,"Y_coordinate");
2261 ra = cpl_table_get_data_float(cat,"RA");
2262 dec = cpl_table_get_data_float(cat,"DEC");
2263 for (i = 0; i < n; i++) {
2264 casu_xytoradec(wcs,x[i],y[i],&r,&d);
2265 ra[i] = (float)r;
2266 dec[i] = (float)d;
2267 }
2268 cpl_wcs_delete(wcs);
2269 } else {
2270 freetfits(tcat);
2271 }
2272 }
2273}
2274
2275/*---------------------------------------------------------------------------*/
2301/*---------------------------------------------------------------------------*/
2302
2303static int vircam_destripe_four(casu_fits **curfits, int stripefilt,
2304 int *status) {
2305 int i,nx,ny,n,k,m,ipstart,ipfin,ip;
2306 float *profiles[4],*meanprof,buf[4],*data,val,mad,rms;
2307 unsigned char *bpms[4],*bp;
2308 cpl_propertylist *plist;
2309
2310 /* Inherited status */
2311
2312 if (*status != CASU_OK)
2313 return(*status);
2314
2315 /* Get the data size of a representative image and get some memory for the
2316 mean profile and its bad pixel mask */
2317
2318 nx = cpl_image_get_size_x(casu_fits_get_image(curfits[0]));
2319 ny = cpl_image_get_size_y(casu_fits_get_image(curfits[0]));
2320 meanprof = cpl_malloc(ny*sizeof(float));
2321 bp = cpl_calloc(ny,sizeof(unsigned char));
2322
2323 /* Loop for the four images and work out the stripe profile for each
2324 one. Trap for missing images */
2325
2326 n = 0;
2327 for (i = 0; i < 4; i++) {
2328 if (casu_fits_get_status(curfits[i]) == CASU_FATAL)
2329 continue;
2330 profiles[n] = cpl_malloc(ny*sizeof(float));
2331 bpms[n] = cpl_calloc(ny,sizeof(unsigned char));
2332 stripe_profile(curfits[i],stripefilt,profiles[n],bpms[n]);
2333 n++;
2334 }
2335
2336 /* Now median the profiles. If there weren't any contributions
2337 this is presumably because all the detectors were missing
2338 so, don't bother doing the destripe. While doing the medianing,
2339 subtract the average profile from the row in each of the contributing
2340 images */
2341
2342 if (n > 0) {
2343 for (k = 0; k < ny; k++) {
2344 m = 0;
2345 for (i = 0; i < n; i++) {
2346 if (bpms[i][k])
2347 continue;
2348 buf[m++] = profiles[i][k];
2349 }
2350 if (m != 0) {
2351 meanprof[k] = casu_med(buf,NULL,(long)m);
2352 bp[k] = 0;
2353 } else {
2354 meanprof[k] = 0.0;
2355 bp[k] = 1;
2356 }
2357 ipstart = k*nx;
2358 ipfin = ipstart + nx;
2359 for (i = 0; i < 4; i++) {
2360 if (casu_fits_get_status(curfits[i]) == CASU_FATAL)
2361 continue;
2362 data = cpl_image_get_data(casu_fits_get_image(curfits[i]));
2363 for (ip = ipstart; ip < ipfin; ip++)
2364 data[ip] -= meanprof[k];
2365 }
2366 }
2367 casu_medmad(meanprof,bp,ny,&val,&mad);
2368 rms = 1.48*mad;
2369
2370 /* Tidy up some memory */
2371
2372 for (i = 0; i < n; i++) {
2373 freespace(profiles[i]);
2374 freespace(bpms[i]);
2375 }
2376
2377 } else {
2378 rms = 0.0;
2379 }
2380
2381 /* Put some stuff in the header */
2382
2383 for (i = 0; i < 4; i++) {
2384 if (casu_fits_get_status(curfits[i]) == CASU_FATAL) {
2385 k = FALSE;
2386 val = 0.0;
2387 } else {
2388 k = TRUE;
2389 val = rms;
2390 }
2391 plist = casu_fits_get_ehu(curfits[i]);
2392 cpl_propertylist_update_bool(plist,"ESO DRS STRIPECOR",k);
2393 cpl_propertylist_set_comment(plist,"ESO DRS STRIPECOR",
2394 "Stripe correction done");
2395 cpl_propertylist_update_float(plist,"ESO DRS STRIPERMS",val);
2396 cpl_propertylist_set_comment(plist,"ESO DRS STRIPERMS",
2397 "RMS of removed stripe profile");
2398 }
2399
2400 /* Tidy up a little more */
2401
2402 freespace(meanprof);
2403 freespace(bp);
2404
2405 /* Get out of here */
2406
2407 GOOD_STATUS
2408}
2409
2410/*---------------------------------------------------------------------------*/
2436/*---------------------------------------------------------------------------*/
2437
2438static void stripe_profile(casu_fits *in, int stripefilt, float *profile,
2439 unsigned char *pbpm) {
2440 float *data,*copy,*d,lcut,hcut,skymed,skynoise,rmsold,rms,val;
2441 unsigned char *bpm,*ob,*b;
2442 cpl_image *img;
2443 long nx,ny,npts;
2444 int i,j;
2445
2446 /* Get the input data array and its bad pixel mask */
2447
2448 img = casu_fits_get_image(in);
2449 nx = cpl_image_get_size_x(img);
2450 ny = cpl_image_get_size_y(img);
2451 data = cpl_image_get_data(img);
2452 bpm = (unsigned char *)cpl_mask_get_data(cpl_image_get_bpm(img));
2453
2454 /* First get an estimate of the background median and sigma */
2455
2456 npts = nx*ny;
2457 casu_qmedsig(data,bpm,npts,3.0,3,-65535.0,65535.0,&skymed,&skynoise);
2458
2459 /* Get some workspace for the profile calculation */
2460
2461 ob = cpl_calloc(ny,sizeof(unsigned char));
2462 copy = cpl_malloc(ny*sizeof(float));
2463
2464 /* Loop for each row */
2465
2466 d = data;
2467 b = bpm;
2468 for (i = 0; i < ny; i++) {
2469
2470 /* Get the median of that row, ignoring any bad pixels. Iterate
2471 to clip out any objects or funny pixels */
2472
2473 lcut = -1.0e-10;
2474 hcut = 1.0e10;
2475 rmsold = 1.0e10;
2476 for (j = 0; j < 3; j++) {
2477 casu_medmadcut(d,b,nx,lcut,hcut,&val,&rms);
2478 if (val == CX_MAXFLOAT) {
2479 break;
2480 } else if (rms == rmsold) {
2481 break;
2482 } else {
2483 lcut = val - 3.0*skynoise;
2484 hcut = val + 3.0*skynoise;
2485 rmsold = rms;
2486 }
2487 }
2488 pbpm[i] = (val == CX_MAXFLOAT);
2489 profile[i] = (pbpm[i] ? 0.0 : val);
2490 copy[i] = profile[i];
2491 d += nx;
2492 b += nx;
2493 }
2494
2495 /* Take out large scale variation if need be */
2496
2497 casu_medmad(profile,pbpm,ny,&val,&rms);
2498 rms *= 1.48;
2499 if (stripefilt && rms > 15.0) {
2500 casu_dostat(copy,pbpm,ob,ny,25,MEDIANCALC);
2501 casu_dostat(copy,pbpm,ob,ny,5,MEANCALC);
2502 for (i = 0; i < ny; i++) {
2503 if (! pbpm[i])
2504 profile[i] -= copy[i];
2505 else
2506 profile[i] = 0.0;
2507 }
2508 } else {
2509 for (i = 0; i < ny; i++)
2510 profile[i] -= val;
2511 }
2512
2513 /* Tidy up and get out of here */
2514
2515 freespace(ob);
2516 freespace(copy);
2517}
2518
2519
2520/*---------------------------------------------------------------------------*/
2538/*---------------------------------------------------------------------------*/
2539
2540static void vircam_sci_paws_delete(int npaws, pawprint **paws) {
2541 int i;
2542
2543 for (i = 0; i < npaws; i++)
2544 vircam_sci_paw_delete(*paws+i);
2545 freespace(*paws);
2546}
2547
2548/*---------------------------------------------------------------------------*/
2564/*---------------------------------------------------------------------------*/
2565
2566static void vircam_sci_paw_delete(pawprint *paw) {
2567 int i;
2568
2569 if (paw->current == NULL)
2570 return;
2571 freespace(paw->whichsky);
2572 freeframeset(paw->orig);
2573 freeframeset(paw->current);
2574 for (i = 0; i < VIRCAM_NEXTN; i++) {
2575 freefits(paw->stack[i]);
2576 freefits(paw->stackc[i]);
2577 freetfits(paw->cat[i]);
2578 freetfits(paw->mstds[i]);
2579 }
2580}
2581
2582/*---------------------------------------------------------------------------*/
2602/*---------------------------------------------------------------------------*/
2603
2604static void vircam_sci_paws_create(cpl_frameset *infrms, int *npaws,
2605 pawprint **paws) {
2606 cpl_size nlab,*labels,*labels2,nlab2;
2607 cpl_frameset *copy,*testme,*tf;
2608 int i,j,nalloc,pj,nfrms_tot;
2609
2610 /* NULL input...*/
2611
2612 *paws = NULL;
2613 *npaws = 0;
2614 if (infrms == NULL)
2615 return;
2616
2617 /* Create the grouping */
2618
2619 copy = cpl_frameset_duplicate(infrms);
2620 labels = cpl_frameset_labelise(copy,vircam_sci_cmp_tstart,&nlab);
2621
2622 /* Get memory for the pawprint groups. We will trim this down or
2623 expand it as necessary */
2624
2625 *npaws = 0;
2626 nalloc = 8;
2627 *paws = cpl_malloc(nalloc*sizeof(pawprint));
2628
2629 /* Now extract the groups */
2630
2631 nfrms_tot = 0;
2632 for (i = 0; i < nlab; i++) {
2633
2634 /* First see if this is a tile. If it is, then break the tile up
2635 into its constituent pawprints */
2636
2637 testme = cpl_frameset_extract(copy,labels,(cpl_size)i);
2638 if (vircam_sci_istile(cpl_frameset_get_position(testme,0))) {
2639 pj = vircam_sci_ispj(testme);
2640 labels2 = cpl_frameset_labelise(testme,vircam_sci_cmp_jit,&nlab2);
2641 for (j = 0; j < nlab2; j++) {
2642 if (*npaws+1 > nalloc) {
2643 nalloc += 8;
2644 *paws = cpl_realloc(*paws,nalloc*sizeof(pawprint));
2645 }
2646 tf = cpl_frameset_extract(testme,labels2,(cpl_size)j);
2647 vircam_sci_paw_init(*paws+*npaws,tf,pj,&nfrms_tot);
2648 freeframeset(tf);
2649 *npaws += 1;
2650 }
2651 freespace(labels2);
2652 } else {
2653 vircam_sci_paw_init(*paws+*npaws,testme,0,&nfrms_tot);
2654 *npaws += 1;
2655 }
2656 freeframeset(testme);
2657 }
2658
2659 /* Trim down allocation */
2660
2661 *paws = cpl_realloc(*paws,*npaws*sizeof(pawprint));
2662
2663 /* Tidy and exit */
2664
2665 cpl_frameset_delete(copy);
2666 freespace(labels);
2667}
2668
2669/*---------------------------------------------------------------------------*/
2687/*---------------------------------------------------------------------------*/
2688
2689static int vircam_sci_istile(cpl_frame *frm) {
2690 cpl_propertylist *plist;
2691 int hasoffs,noffsets;
2692
2693 /* If the frame has a keyword OFFSTNUM and NOFFSETS != 1 then this
2694 is part of a tile */
2695
2696 plist = cpl_propertylist_load(cpl_frame_get_filename(frm),0);
2697 hasoffs = cpl_propertylist_has(plist,"OFFSTNUM");
2698 if (hasoffs)
2699 noffsets = cpl_propertylist_get_int(plist,"NOFFSETS");
2700 else
2701 noffsets = -1;
2702 cpl_propertylist_delete(plist);
2703 return(hasoffs && noffsets != 1);
2704}
2705
2706/*---------------------------------------------------------------------------*/
2727/*---------------------------------------------------------------------------*/
2728
2729static void vircam_sci_paw_init(pawprint *paw, cpl_frameset *frms, int ispj,
2730 int *nfrms_tot) {
2731 cpl_propertylist *plist;
2732 cpl_frame *fr;
2733 float exptime;
2734 int i,n;
2735
2736 /* Initialise everything. Start with all the frames and framesets */
2737
2738 paw->orig = cpl_frameset_duplicate(frms);
2739 paw->current = vircam_sci_update_frameset(paw->orig,nfrms_tot);
2740 n = cpl_frameset_get_size(frms);
2741 paw->whichsky = cpl_malloc(n*sizeof(int));
2742 for (i = 0; i < n; i++)
2743 paw->whichsky[i] = -1;
2744 paw->ispj = ispj;
2745 for (i = 0; i < VIRCAM_NEXTN; i++) {
2746 paw->stack[i] = NULL;
2747 paw->stackc[i] = NULL;
2748 paw->cat[i] = NULL;
2749 paw->mstds[i] = NULL;
2750 }
2751 paw->product_frame_im = NULL;
2752 paw->product_frame_conf = NULL;
2753 paw->product_frame_cat = NULL;
2754
2755 /* Now get some useful information about the pawprint from the headers.
2756 Start with the jitter and tile numbers */
2757
2758 fr = cpl_frameset_get_position(frms,0);
2759 plist = cpl_propertylist_load(cpl_frame_get_filename(fr),0);
2760 (void)vircam_pfits_get_jitternum(plist,&(paw->jitternum));
2761 if (vircam_sci_istile(fr)) {
2762 if (vircam_pfits_get_offsetnum(plist,&(paw->tilenum)) != CASU_OK)
2763 paw->tilenum = -1;
2764 } else {
2765 paw->tilenum = -1;
2766 }
2767
2768 /* Now the project ID */
2769
2770 (void)vircam_pfits_get_projid(plist,paw->projname);
2771
2772 /* The MJD of the start of the jitter and of the end */
2773
2774 (void)vircam_pfits_get_mjd(plist,&(paw->mjd_start));
2775 cpl_propertylist_delete(plist);
2776 n = (int)cpl_frameset_get_size(frms);
2777 fr = cpl_frameset_get_position(frms,n-1);
2778 plist = cpl_propertylist_load(cpl_frame_get_filename(fr),0);
2779 (void)vircam_pfits_get_mjd(plist,&(paw->mjd_end));
2780 (void)vircam_pfits_get_exptime(plist,&exptime);
2781 paw->mjd_end += exptime/(24.0*3600.0);
2782
2783 /* Tidy and exit */
2784
2785 cpl_propertylist_delete(plist);
2786}
2787
2788/*---------------------------------------------------------------------------*/
2813/*---------------------------------------------------------------------------*/
2814
2815static int vircam_sci_makesky(cpl_frameset *framelist,
2816 cpl_parameterlist *parlist, skystruct *sky,
2817 const char *tag) {
2818 int retval;
2819
2820 /* Switch for the various options to sky creation. Options SKYNONE,
2821 SKYMASTER and TILESKY_MINUS we don't do anything at this point. */
2822
2823 retval = CASU_OK;
2824 switch (sky->skyalgo) {
2825 case SKYNONE:
2826 break;
2827 case SKYMASTER:
2828 break;
2829 case PAWSKY_MINUS:
2830 retval = vircam_sci_pawsky_minus(framelist,parlist,sky->contrib,
2831 sky->template,tag,sky->fname,
2832 &(sky->skyframe));
2833 break;
2834 case TILESKY_MINUS:
2835 retval = vircam_sci_tilesky_minus(framelist,parlist,sky->contrib,
2836 sky->template,tag,sky->fname,
2837 &(sky->skyframe));
2838 break;
2839 case PAWSKY_MASK:
2840 retval = vircam_sci_pawsky_mask(framelist,parlist,sky->skyalgo,
2841 sky->contrib,sky->template,
2842 sky->fname,&(sky->skyframe));
2843 break;
2844 case PAWSKY_MASK_PRE:
2845 retval = vircam_sci_pawsky_mask(framelist,parlist,sky->skyalgo,
2846 sky->contrib,sky->template,
2847 sky->fname,&(sky->skyframe));
2848 break;
2849 case TILESKY:
2850 retval = vircam_sci_tilesky(framelist,parlist,sky->contrib,
2851 sky->template,sky->fname,&(sky->skyframe));
2852 break;
2853 }
2854 return(retval);
2855}
2856
2857/*---------------------------------------------------------------------------*/
2892/*---------------------------------------------------------------------------*/
2893
2894static int vircam_sci_tilesky_minus(cpl_frameset *framelist,
2895 cpl_parameterlist *parlist,
2896 cpl_frameset *in, cpl_frame *template,
2897 const char *tag, char *skyname,
2898 cpl_frame **skyframe) {
2899 int n,i,status,isfirst,j;
2900 casu_fits *objmaskfits,**infits,*inconf,*tmpfits,*skyout;
2901 cpl_frame **product_frames,*curframe;
2902 char tmpname[BUFSIZ], *skyname2 = NULL;
2903 const char *fctid = "vircam_sci_tilesky_minus";
2904
2905 n = cpl_frameset_get_size(in);
2906 objmaskfits = casu_fits_load(ps.master_objmask,CPL_TYPE_INT,0);
2907 product_frames = cpl_malloc(n*sizeof(cpl_frame *));
2908 cpl_msg_info(fctid,"Creating sky %s",skyname);
2909 cpl_msg_indent_more();
2910 for (i = 1; i <= VIRCAM_NEXTN; i++) {
2911 cpl_msg_info(fctid,"Beginning on extn %" CPL_SIZE_FORMAT "",
2912 (cpl_size)i);
2913 infits = casu_fits_load_list(in,CPL_TYPE_FLOAT,i);
2914 inconf = casu_fits_load(ps.master_conf,CPL_TYPE_INT,i);
2915 status = CASU_OK;
2916 if (vircam_tilesky_minus(infits,inconf,objmaskfits,n,&skyout,
2917 &status) != CASU_OK) {
2918 freefitslist(infits,n);
2919 freefits(inconf);
2920 freespace(product_frames);
2921 return(CASU_FATAL);
2922 }
2923 isfirst = (i == 1);
2924 vircam_sci_save_sky(skyout,framelist,parlist,skyname,template,
2925 isfirst,skyframe);
2926 //(void)snprintf(skyname2,BUFSIZ,"%s[%d]",skyname,i);
2927 skyname2 = cpl_sprintf("%s[%d]",skyname, i);
2928 for (j = 0; j < n; j++) {
2929 tmpfits = casu_fits_duplicate(infits[j]);
2930 (void)snprintf(tmpname,BUFSIZ,"tmp_%s",
2931 casu_fits_get_filename(infits[j]));
2932 casu_fits_set_filename(tmpfits,tmpname);
2933 curframe = cpl_frameset_get_position(in,j);
2934 template = vircam_sci_findtemplate(curframe);
2935 cpl_propertylist_update_string(casu_fits_get_ehu(tmpfits),
2936 "ESO DRS SKYCOR",skyname2);
2937 vircam_sci_save_simple(tmpfits,framelist,parlist,0,template,
2938 isfirst,tag,tmpname,(product_frames+j));
2939 freefits(tmpfits);
2940 }
2941 cpl_free(skyname2);
2942 freefitslist(infits,n);
2943 freefits(inconf);
2944 freefits(skyout);
2945 }
2946 cpl_msg_indent_less();
2947 for (i = 0; i < n; i++) {
2948 curframe = cpl_frameset_get_position(in,i);
2949 template = product_frames[i];
2950 remove(cpl_frame_get_filename(curframe));
2951 rename(cpl_frame_get_filename(template),
2952 cpl_frame_get_filename(curframe));
2953 freeframe(product_frames[i]);
2954 }
2955 freespace(product_frames);
2956 freefits(objmaskfits);
2957 return(CASU_OK);
2958}
2959
2960/*---------------------------------------------------------------------------*/
2995/*---------------------------------------------------------------------------*/
2996
2997static int vircam_sci_pawsky_minus(cpl_frameset *framelist,
2998 cpl_parameterlist *parlist,
2999 cpl_frameset *in, cpl_frame *template,
3000 const char *tag, char *skyname,
3001 cpl_frame **skyframe) {
3002 int n,i,status,isfirst,j,k;
3003 casu_fits *objmaskfits,**infits,*inconf,*tmpfits,*skyout,*skyvar;
3004 cpl_frame **product_frames,*curframe;
3005 char tmpname[BUFSIZ], *skyname2 = NULL;
3006 const char *fctid = "vircam_sci_pawsky_minus";
3007
3008 n = cpl_frameset_get_size(in);
3009 if (ps.master_objmask != NULL)
3010 objmaskfits = casu_fits_load(ps.master_objmask,CPL_TYPE_INT,0);
3011 else
3012 objmaskfits = NULL;
3013 product_frames = cpl_malloc(n*sizeof(cpl_frame *));
3014 cpl_msg_info(fctid,"Creating sky %s",skyname);
3015 cpl_msg_indent_more();
3016 for (i = 1; i <= VIRCAM_NEXTN; i++) {
3017 cpl_msg_info(fctid,"Beginning on extn %" CPL_SIZE_FORMAT "",
3018 (cpl_size)i);
3019 infits = casu_fits_load_list(in,CPL_TYPE_FLOAT,i);
3020 inconf = casu_fits_load(ps.master_conf,CPL_TYPE_INT,i);
3021 status = CASU_OK;
3022 if (ps.master_objmask != NULL) {
3023 for (k = 0; k < n; k++)
3024 vircam_sci_wcsfit(infits+k,&inconf,NULL,1,1);
3025 }
3026 if (casu_pawsky_minus(infits,NULL,inconf,objmaskfits,n,&skyout,
3027 &skyvar,&status) != CASU_OK) {
3028 freefitslist(infits,n);
3029 freefits(inconf);
3030 freespace(product_frames);
3031 return(CASU_FATAL);
3032 }
3033 isfirst = (i == 1);
3034 vircam_sci_save_sky(skyout,framelist,parlist,skyname,template,
3035 isfirst,skyframe);
3036 //(void)snprintf(skyname2,BUFSIZ,"%s[%d]",skyname,i);
3037 skyname2 = cpl_sprintf("%s[%d]",skyname, i);
3038 for (j = 0; j < n; j++) {
3039 tmpfits = casu_fits_duplicate(infits[j]);
3040 (void)snprintf(tmpname,BUFSIZ,"tmp_%s",
3041 casu_fits_get_filename(infits[j]));
3042 casu_fits_set_filename(tmpfits,tmpname);
3043 curframe = cpl_frameset_get_position(in,j);
3044 template = vircam_sci_findtemplate(curframe);
3045 cpl_propertylist_update_string(casu_fits_get_ehu(tmpfits),
3046 "ESO DRS SKYCOR",skyname2);
3047 vircam_sci_save_simple(tmpfits,framelist,parlist,0,template,
3048 isfirst,tag,tmpname,(product_frames+j));
3049 freefits(tmpfits);
3050 }
3051 cpl_free(skyname2);
3052 freefitslist(infits,n);
3053 freefits(inconf);
3054 freefits(skyout);
3055 }
3056 cpl_msg_indent_less();
3057 for (i = 0; i < n; i++) {
3058 curframe = cpl_frameset_get_position(in,i);
3059 template = product_frames[i];
3060 remove(cpl_frame_get_filename(curframe));
3061 rename(cpl_frame_get_filename(template),
3062 cpl_frame_get_filename(curframe));
3063 freeframe(product_frames[i]);
3064 }
3065 freespace(product_frames);
3066 freefits(objmaskfits);
3067 return(CASU_OK);
3068}
3069
3070/*---------------------------------------------------------------------------*/
3088/*---------------------------------------------------------------------------*/
3089
3090static void vircam_sci_choose_skyalgo(int *nskys, skystruct **skys) {
3091 float halfhour;
3092 skystruct newsky;
3093 int nalloc,i,n,n2,jst,jfn,j,j_1,j_2;
3094 float dt;
3095 cpl_frameset **in,*newfrmset;
3096 cpl_frame *frm,*template;
3097
3098 /* Initialise a few things */
3099
3100 halfhour = 1.0/48.0;
3101
3102 /* In most cases we're only going to create one sky here, but there
3103 is the possibility of more */
3104
3105 *nskys = 0;
3106 nalloc = 1;
3107 *skys = cpl_malloc(nalloc*sizeof(skystruct));
3108
3109 /* Ok start with the easy situation. If there are offset skies, then
3110 choose just straightforward pawsky_mask or tilesky depending upon
3111 how the offset skies were observed */
3112
3113 if (ps.noffpaws > 0) {
3114 if (vircam_sci_istile(cpl_frameset_get_position(ps.offsky_paws[0].orig,0))) {
3115
3116 /* Merge all the current framesets into one */
3117
3118 in = cpl_malloc(ps.noffpaws*sizeof(cpl_frameset *));
3119 for (i = 0; i < ps.noffpaws; i++)
3120 in[i] = ps.offsky_paws[i].current;
3121 newfrmset = vircam_sci_merge_framesets(ps.noffpaws,in);
3122 freespace(in);
3123
3124 /* Create a sky structure */
3125
3126 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.offsky_paws[0].orig,0));
3127 newsky = vircam_sci_crsky(TILESKY,newfrmset,template,1);
3128 *nskys = 1;
3129 (*skys)[*nskys-1] = newsky;
3130
3131 /* Assign this one sky to all of the offset and science pawprint
3132 images */
3133
3134 for (i = 0; i < ps.noffpaws; i++)
3135 vircam_sci_assign_sky_all(ps.offsky_paws[i],*nskys-1);
3136 for (i = 0; i < ps.nscipaws; i++)
3137 vircam_sci_assign_sky_all(ps.science_paws[i],*nskys-1);
3138 } else {
3139 newfrmset = cpl_frameset_duplicate(ps.offsky_paws[0].current);
3140 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.offsky_paws[0].orig,0));
3141 newsky = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,*nskys+1);
3142 *nskys += 1;
3143 (*skys)[*nskys-1] = newsky;
3144 vircam_sci_assign_sky_all(ps.offsky_paws[0],*nskys-1);
3145 vircam_sci_assign_sky_all(ps.science_paws[0],*nskys-1);
3146 }
3147
3148 /* OK there aren't any offset skies. There are lots more choices now.
3149 So first we look to see if this is just a pawprint. */
3150
3151 } else {
3152
3153 /* If it's a pawprint, then look to see if it took less than half
3154 an hour to observe. If it did then split it into two, so long
3155 as there are enough images in each half to form a sky
3156 (nominally 8) */
3157
3158 if (ps.science_paws[0].tilenum == -1) {
3159 dt = ps.science_paws[0].mjd_end - ps.science_paws[0].mjd_start;
3160 n = cpl_frameset_get_size(ps.science_paws[0].current);
3161
3162 /* Situation where we have a pawprint lasting less than half an
3163 hour, or we have one that isn't big enough to split */
3164
3165 if (dt < halfhour || n < 16) {
3166 newfrmset = cpl_frameset_duplicate(ps.science_paws[0].current);
3167 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[0].orig,0));
3168 newsky = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,
3169 *nskys+1);
3170 *nskys = 1;
3171 (*skys)[*nskys-1] = newsky;
3172 vircam_sci_assign_sky_all(ps.science_paws[0],*nskys-1);
3173
3174 /* Pawprint took longer than half an hour and there are enough
3175 exposures so that we can split into two */
3176
3177 } else {
3178 n2 = n/2;
3179 for (i = 0; i < 2; i++) {
3180 if (i == 0) {
3181 jst = 0;
3182 jfn = n2;
3183 } else {
3184 jst = n2;
3185 jfn = n;
3186 }
3187 newfrmset = cpl_frameset_new();
3188 for (j = jst; j < jfn; j++) {
3189 frm = cpl_frameset_get_position(ps.science_paws[0].current,j);
3190 cpl_frameset_insert(newfrmset,cpl_frame_duplicate(frm));
3191 }
3192 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[0].orig,jst));
3193 newsky = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,
3194 *nskys+1);
3195 *nskys += 1;
3196 if (*nskys > nalloc) {
3197 nalloc += 1;
3198 *skys = cpl_realloc(*skys,nalloc*sizeof(skystruct));
3199 }
3200 (*skys)[*nskys-1] = newsky;
3201 for (j = jst; j < jfn; j++)
3202 ps.science_paws[0].whichsky[j] = *nskys-1;
3203 }
3204 }
3205
3206 /* Ok this is a tile. There are a couple of options now. If it's a VIDEO tile,
3207 then default to TILESKY_MINUS, but with a split */
3208
3209 } else {
3210 n = ps.nscipaws;
3211 dt = ps.science_paws[n-1].mjd_end - ps.science_paws[0].mjd_start;
3212 if (! strncmp(ps.science_paws[0].projname,VIDEOPROJ,10)) {
3213 n2 = ps.nscipaws/2;
3214 for (j = 0; j < 2; j++) {
3215 if (j == 0) {
3216 j_1 = 0;
3217 j_2 = n2;
3218 } else {
3219 j_1 = n2;
3220 j_2 = ps.nscipaws;
3221 }
3222 in = cpl_malloc((j_2-j_1)*sizeof(cpl_frameset *));
3223 for (i = j_1; i < j_2; i++)
3224 in[i-j_1] = ps.science_paws[i].current;
3225 newfrmset = vircam_sci_merge_framesets((j_2-j_1),in);
3226 freespace(in);
3227 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[j_1].orig,0));
3228 newsky = vircam_sci_crsky(TILESKY_MINUS,newfrmset,template,
3229 *nskys+1);
3230 *nskys += 1;
3231 if (*nskys > nalloc) {
3232 nalloc += 1;
3233 *skys = cpl_realloc(*skys,nalloc*sizeof(skystruct));
3234 }
3235 (*skys)[*nskys-1] = newsky;
3236 for (i = j_1; i < j_2; i++)
3237 vircam_sci_assign_sky_all(ps.science_paws[i],*nskys-1);
3238 }
3239
3240 /* Look at the time difference. If the timing is less than half an
3241 hour or if this is a VMC tile, then just do a straight-forward
3242 tilesky. */
3243
3244 } else if (dt < halfhour ||
3245 ! strncmp(ps.science_paws[0].projname,VMCPROJ,10)) {
3246 in = cpl_malloc(ps.nscipaws*sizeof(cpl_frameset *));
3247 for (i = 0; i < ps.nscipaws; i++)
3248 in[i] = ps.science_paws[i].current;
3249 newfrmset = vircam_sci_merge_framesets(ps.nscipaws,in);
3250 freespace(in);
3251
3252 /* Create a sky structure */
3253
3254 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[0].orig,0));
3255 newsky = vircam_sci_crsky(TILESKY,newfrmset,template,1);
3256 *nskys = 1;
3257 (*skys)[*nskys-1] = newsky;
3258
3259 /* Assign this one sky to all of the science pawprint images */
3260
3261 for (i = 0; i < ps.nscipaws; i++)
3262 vircam_sci_assign_sky_all(ps.science_paws[i],*nskys-1);
3263
3264 /* OK, we have a tile that's not VMC and not VIDEO that lasts for
3265 more than half an hour. If it's the normal PJ ordering, then just
3266 do a split TILESKY */
3267
3268 } else {
3269 if (ps.science_paws[0].ispj) {
3270 n2 = ps.nscipaws/2;
3271 for (j = 0; j < 2; j++) {
3272 if (j == 0) {
3273 j_1 = 0;
3274 j_2 = n2;
3275 } else {
3276 j_1 = n2;
3277 j_2 = ps.nscipaws;
3278 }
3279 in = cpl_malloc((j_2-j_1)*sizeof(cpl_frameset *));
3280 for (i = j_1; i < j_2; i++)
3281 in[i-j_1] = ps.science_paws[i].current;
3282 newfrmset = vircam_sci_merge_framesets((j_2-j_1),in);
3283 freespace(in);
3284 template = cpl_frame_duplicate(cpl_frameset_get_position(ps.science_paws[j_1].orig,0));
3285 newsky = vircam_sci_crsky(TILESKY,newfrmset,template,
3286 *nskys+1);
3287 *nskys += 1;
3288 if (*nskys > nalloc) {
3289 nalloc += 1;
3290 *skys = cpl_realloc(*skys,nalloc*sizeof(skystruct));
3291 }
3292 (*skys)[*nskys-1] = newsky;
3293 for (i = j_1; i < j_2; i++)
3294 vircam_sci_assign_sky_all(ps.science_paws[i],
3295 *nskys-1);
3296 }
3297 } else {
3298 /******************* bit for jp */
3299 }
3300 } /* end of different type of tiles */
3301 } /* end of tiles */
3302
3303 } /* end of offset sky if */
3304}
3305
3306/*---------------------------------------------------------------------------*/
3328/*---------------------------------------------------------------------------*/
3329
3330static int vircam_sci_ispj(cpl_frameset *frms) {
3331 int n,offnum,i,offnum1,offnum2;
3332 cpl_propertylist *plist,*tmp;
3333 char dateobs[32];
3334 cpl_frame *frm;
3335
3336 /* Create a propertylist to be a hash array */
3337
3338 plist = cpl_propertylist_new();
3339
3340 /* Loop through the frameset. Name each property by the dateobs of
3341 the frame. Then give the value of the property the offset number */
3342
3343 n = cpl_frameset_get_size(frms);
3344 for (i = 0; i < n; i++) {
3345 frm = cpl_frameset_get_position(frms,i);
3346 tmp = cpl_propertylist_load(cpl_frame_get_filename(frm),0);
3347 strcpy(dateobs,cpl_propertylist_get_string(tmp,"DATE-OBS"));
3348 offnum = cpl_propertylist_get_int(tmp,"OFFSET_I");
3349 cpl_propertylist_append_int(plist,dateobs,offnum);
3350 cpl_propertylist_delete(tmp);
3351 }
3352
3353 /* Sort the propertylist by the property name (dateobs). This should
3354 give a chronological ordering */
3355
3356 cpl_propertylist_sort(plist,vircam_sci_cmp_property);
3357
3358 /* Look at the first two now and see if they have the same value
3359 of the offset number. If they do, then this is in PJ order */
3360
3361 offnum1 = cpl_property_get_int(cpl_propertylist_get(plist,0));
3362 offnum2 = cpl_property_get_int(cpl_propertylist_get(plist,1));
3363 cpl_propertylist_delete(plist);
3364 return(offnum1 == offnum2);
3365}
3366
3367/*---------------------------------------------------------------------------*/
3386/*---------------------------------------------------------------------------*/
3387
3388static int vircam_sci_cmp_property(const cpl_property *p1,
3389 const cpl_property *p2) {
3390 return(strcmp(cpl_property_get_name(p1),cpl_property_get_name(p2)));
3391}
3392
3393/*---------------------------------------------------------------------------*/
3411/*---------------------------------------------------------------------------*/
3412
3413static void vircam_sci_assign_sky_all(pawprint paw, int whichone) {
3414 int i,n;
3415
3416 n = cpl_frameset_get_size(paw.current);
3417 for (i = 0; i < n; i++)
3418 paw.whichsky[i] = whichone;
3419}
3420
3421/*---------------------------------------------------------------------------*/
3442/*---------------------------------------------------------------------------*/
3443
3444static skystruct vircam_sci_crsky(int algorithm, cpl_frameset *frms,
3445 cpl_frame *template, int snum) {
3446 skystruct s;
3447
3448 s.contrib = frms;
3449 if (ps.master_objmask != NULL)
3450 s.objmask = cpl_frame_duplicate(ps.master_objmask);
3451 else
3452 s.objmask = NULL;
3453 s.skyalgo = algorithm;
3454 s.skyframe = NULL;
3455 s.template = template;
3456 vircam_sci_product_name((char *)cpl_frame_get_filename(cpl_frameset_get_position(frms,0)),
3457 SKY_FILE,vircam_sci_config.prettynames,snum,
3458 s.fname);
3459 return(s);
3460}
3461
3462/*---------------------------------------------------------------------------*/
3483/*---------------------------------------------------------------------------*/
3484
3485static cpl_frameset *vircam_sci_merge_framesets(int n, cpl_frameset **in) {
3486 int i,j,nf;
3487 cpl_frame *frm;
3488 cpl_frameset *new;
3489
3490 /* Get a new frameset */
3491
3492 new = cpl_frameset_new();
3493
3494 /* Loop for each input frameset. Insert each frame into the new one */
3495
3496 for (i = 0; i < n; i++) {
3497 nf = cpl_frameset_get_size(in[i]);
3498 for (j = 0; j < nf; j++) {
3499 frm = cpl_frame_duplicate(cpl_frameset_get_position(in[i],j));
3500 cpl_frameset_insert(new,frm);
3501 }
3502 }
3503 return(new);
3504}
3505
3506/*---------------------------------------------------------------------------*/
3537/*---------------------------------------------------------------------------*/
3538
3539static int vircam_sci_tilesky(cpl_frameset *framelist,
3540 cpl_parameterlist *parlist, cpl_frameset *in,
3541 cpl_frame *template, char *fname,
3542 cpl_frame **product_frame) {
3543 int j,nfiles,isfirst,status;
3544 const char *fctid="vircam_sci_tilesky";
3545 casu_fits **infits,*skyout;
3546
3547 /* Initialise product frame */
3548
3549 *product_frame = NULL;
3550
3551 /* Loop for each extension */
3552
3553 nfiles = cpl_frameset_get_size(in);
3554 cpl_msg_info(fctid,"Creating sky %s",fname);
3555 cpl_msg_indent_more();
3556 for (j = 1; j <= VIRCAM_NEXTN; j++) {
3557 cpl_msg_info(fctid,"Extension [%" CPL_SIZE_FORMAT "]",(cpl_size)j);
3558 isfirst = (j == 1);
3559
3560 /* Load up input images for this extension and associated bad
3561 pixel mask... */
3562
3563 infits = casu_fits_load_list(in,CPL_TYPE_FLOAT,j);
3564 casu_mask_load(ps.mask,j,
3565 (int)cpl_image_get_size_x(casu_fits_get_image(infits[0])),
3566 (int)cpl_image_get_size_y(casu_fits_get_image(infits[0])));
3567 /* Form the sky for this extension */
3568
3569 status = CASU_OK;
3570 skyout = NULL;
3571 (void)vircam_tilesky(infits,nfiles,ps.mask,&skyout,&status);
3572
3573 /* Save the sky frame */
3574
3575 if (vircam_sci_save_sky(skyout,framelist,parlist,fname,template,
3576 isfirst,product_frame) != CASU_OK) {
3577 freefitslist(infits,nfiles);
3578 freefits(skyout);
3579 return(CASU_FATAL);
3580 }
3581
3582 /* Tidy up and move on to the next one */
3583
3584 freefitslist(infits,nfiles);
3585 freefits(skyout);
3586 }
3587 cpl_msg_indent_less();
3588 return(CASU_OK);
3589}
3590
3591/*---------------------------------------------------------------------------*/
3622/*---------------------------------------------------------------------------*/
3623
3624static int vircam_sci_pawsky_mask(cpl_frameset *framelist,
3625 cpl_parameterlist *parlist, int algo,
3626 cpl_frameset *contrib, cpl_frame *template,
3627 char *fname, cpl_frame **product_frame) {
3628 int j,nfiles,status,isfirst;
3629 const char *fctid="vircam_sci_pawsky_mask";
3630 casu_fits **infits,*conf,*skyout,*opmfits,*skyvar;
3631
3632 /* Output product frame */
3633
3634 *product_frame = NULL;
3635
3636 /* Loop for each extension */
3637
3638 nfiles = cpl_frameset_get_size(contrib);
3639 cpl_msg_info(fctid,"Creating sky %s",fname);
3640 cpl_msg_indent_more();
3641 for (j = 1; j <= VIRCAM_NEXTN; j++) {
3642 cpl_msg_info(fctid,"Extension [%" CPL_SIZE_FORMAT "]",(cpl_size)j);
3643 isfirst = (j == 1);
3644
3645 /* Load up input images for this extension + confidence map
3646 and associated bad pixel mask... */
3647
3648 infits = casu_fits_load_list(contrib,CPL_TYPE_FLOAT,j);
3649 conf = casu_fits_load(ps.master_conf,CPL_TYPE_INT,j);
3650 casu_mask_load(ps.mask,j,
3651 (int)cpl_image_get_size_x(casu_fits_get_image(conf)),
3652 (int)cpl_image_get_size_y(casu_fits_get_image(conf)));
3653
3654 /* Form the sky for this extension */
3655
3656 status = CASU_OK;
3657 skyout = NULL;
3658 if (algo == PAWSKY_MASK) {
3659 (void)casu_pawsky_mask(infits,NULL,nfiles,conf,ps.mask,&skyout,
3660 &skyvar,psm.niter,psm.ipix,psm.thresh,
3661 psm.nbsize,psm.smkern,&status);
3662 } else {
3663 opmfits = casu_fits_load(ps.master_objmask,CPL_TYPE_INT,1);
3664 (void)casu_pawsky_mask_pre(infits,NULL,nfiles,ps.mask,opmfits,
3665 psm.nbsize,&skyout,&skyvar,&status);
3666 casu_fits_delete(opmfits);
3667 }
3668
3669 /* Save the sky frame */
3670
3671 if (vircam_sci_save_sky(skyout,framelist,parlist,fname,template,
3672 isfirst,product_frame) != CASU_OK) {
3673 freefitslist(infits,nfiles);
3674 freefits(conf);
3675 freefits(skyout);
3676 return(CASU_FATAL);
3677 }
3678
3679 /* Tidy up and move on to the next one */
3680
3681 freefitslist(infits,nfiles);
3682 freefits(conf);
3683 freefits(skyout);
3684 }
3685 cpl_msg_indent_less();
3686 return(CASU_OK);
3687}
3688
3689/*---------------------------------------------------------------------------*/
3708/*---------------------------------------------------------------------------*/
3709
3710static int vircam_sci_save_sky(casu_fits *outsky, cpl_frameset *framelist,
3711 cpl_parameterlist *parlist,
3712 char *fname, cpl_frame *template, int isfirst,
3713 cpl_frame **product_frame) {
3714 cpl_propertylist *p;
3715 int isdummy;
3716 cpl_image *fim;
3717 const char *fctid = "vircam_sci_save_sky";
3718
3719 /* Work out which frame to base the output on. If this particular
3720 sequence failed for whatever reason, there will be a dummy sky frame. */
3721
3722 fim = casu_fits_get_image(outsky);
3723 isdummy = (casu_fits_get_status(outsky) != CASU_OK);
3724
3725 /* If we need to make a PHU then do that now based on the first frame
3726 in the input frame list */
3727
3728 if (isfirst) {
3729
3730 /* Create a new product frame object and define some tags */
3731
3732 *product_frame = cpl_frame_new();
3733 cpl_frame_set_filename(*product_frame,fname);
3734 cpl_frame_set_tag(*product_frame,VIRCAM_PRO_OFFSET_SKY);
3735 cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_IMAGE);
3736 cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
3737 cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
3738
3739 /* Set up the PHU header. */
3740
3741 p = casu_fits_get_phu(outsky);
3742 vircam_dfs_set_product_primary_header(p,*product_frame,framelist,
3743 parlist,vircam_recipename,
3744 "PRO-1.15",template,0);
3745
3746 /* 'Save' the PHU image */
3747
3748 if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,p,
3749 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
3750 cpl_msg_error(fctid,"Cannot save product PHU");
3751 cpl_frame_delete(*product_frame);
3752 return(-1);
3753 }
3754 cpl_frameset_insert(framelist,*product_frame);
3755 }
3756
3757 /* Get the extension property list */
3758
3759 p = cpl_propertylist_duplicate(casu_fits_get_ehu(outsky));
3760 if (isdummy)
3762
3763 /* Fiddle with the header now */
3764
3765 vircam_dfs_set_product_exten_header(p,*product_frame,framelist,parlist,
3766 vircam_recipename,"PRO-1.15",template);
3767 if (cpl_image_save(fim,fname,CPL_TYPE_FLOAT,p,CPL_IO_EXTEND) !=
3768 CPL_ERROR_NONE) {
3769 cpl_msg_error(fctid,"Cannot save product image extension");
3770 return(-1);
3771 }
3772
3773 /* Quick tidy */
3774
3775 cpl_propertylist_delete(p);
3776
3777 /* Get out of here */
3778
3779 return(0);
3780}
3781
3782/*---------------------------------------------------------------------------*/
3801/*---------------------------------------------------------------------------*/
3802
3803static int vircam_sci_cmp_jit(const cpl_frame *frame1,
3804 const cpl_frame *frame2) {
3805 int j_1,j_2;
3806 cpl_propertylist *pp;
3807
3808 /* Test entries */
3809
3810 if (frame1 == NULL || frame2 == NULL)
3811 return(-1);
3812 pp = cpl_propertylist_load(cpl_frame_get_filename(frame1),0);
3813 (void)vircam_pfits_get_jitternum(pp,&j_1);
3814 cpl_propertylist_delete(pp);
3815 pp = cpl_propertylist_load(cpl_frame_get_filename(frame2),0);
3816 (void)vircam_pfits_get_jitternum(pp,&j_2);
3817 cpl_propertylist_delete(pp);
3818
3819 return(j_1 == j_2);
3820}
3821
3822/*---------------------------------------------------------------------------*/
3841/*---------------------------------------------------------------------------*/
3842
3843static int vircam_sci_cmp_tstart(const cpl_frame *frame1,
3844 const cpl_frame *frame2) {
3845 char ts1[80],ts2[80];
3846 cpl_propertylist *pp;
3847
3848 /* Test entries */
3849
3850 if (frame1 == NULL || frame2 == NULL)
3851 return(-1);
3852
3853 /* Load the propertylist for each frame and extract the template start
3854 time */
3855
3856 pp = cpl_propertylist_load(cpl_frame_get_filename(frame1),0);
3857 (void)vircam_pfits_get_tplstart(pp,ts1);
3858 cpl_propertylist_delete(pp);
3859 pp = cpl_propertylist_load(cpl_frame_get_filename(frame2),0);
3860 (void)vircam_pfits_get_tplstart(pp,ts2);
3861 cpl_propertylist_delete(pp);
3862
3863 /* Compare the start times */
3864
3865 if (strcmp(ts1,ts2))
3866 return(0);
3867 else
3868 return(1);
3869}
3870
3871/*---------------------------------------------------------------------------*/
3892/*---------------------------------------------------------------------------*/
3893
3894static cpl_frameset *vircam_sci_update_frameset(cpl_frameset *frms, int *nfrms_tot) {
3895 cpl_frameset *copy;
3896 cpl_size i,n;
3897 cpl_frame *fr;
3898 char *fname,bname[BUFSIZ];
3899
3900 /* NULL input... */
3901
3902 if (frms == NULL)
3903 return(NULL);
3904
3905 /* First make a copy of the input frameset */
3906
3907 copy = cpl_frameset_duplicate(frms);
3908
3909 /* Now go through and change the file names */
3910
3911 n = cpl_frameset_get_size(frms);
3912 for (i = 0; i < n; i++) {
3913 fr = cpl_frameset_get_position(copy,i);
3914 fname = cpl_strdup(cpl_frame_get_filename(fr));
3915 (*nfrms_tot)++;
3916 vircam_sci_product_name(fname,SIMPLE_FILE,vircam_sci_config.prettynames,
3917 *nfrms_tot,bname);
3918 cpl_frame_set_filename(fr,basename(bname));
3919 cpl_free(fname);
3920 }
3921
3922 /* Get out of here */
3923
3924 return(copy);
3925}
3926
3927/*---------------------------------------------------------------------------*/
3949/*---------------------------------------------------------------------------*/
3950
3951static int vircam_sci_testfrms(cpl_frameset *frms, int nextn_expected,
3952 int isimg) {
3953 int i,nf,nerr;
3954 cpl_frame *fr;
3955
3956 /* Return immediately if given nonsense */
3957
3958 if (frms == NULL)
3959 return(0);
3960
3961 /* Loop for each frame in the frameset */
3962
3963 nf = cpl_frameset_get_size(frms);
3964 nerr = 0;
3965 for (i = 0; i < nf; i++) {
3966 fr = cpl_frameset_get_position(frms,i);
3967 nerr += vircam_sci_testfrm_1(fr,nextn_expected,isimg);
3968 }
3969
3970 /* Return value */
3971
3972 return(nerr);
3973}
3974
3975/*---------------------------------------------------------------------------*/
3999/*---------------------------------------------------------------------------*/
4000
4001static int vircam_sci_testfrm_1(cpl_frame *fr, int nextn_expected, int isimg) {
4002 int nextn,nerr,j;
4003 casu_fits *test;
4004 casu_tfits *testt;
4005 const char *fctid="vircam_sci_testfrm";
4006
4007 /* Return immediately if given nonsense */
4008
4009 if (fr == NULL)
4010 return(0);
4011
4012 /* Test to see how many extensions there are and compare to see
4013 if it matches the number expected */
4014
4015 nextn = cpl_frame_get_nextensions(fr);
4016 if (nextn != nextn_expected) {
4017 cpl_msg_error(fctid,"Frame %s has %" CPL_SIZE_FORMAT " extensions, expected %" CPL_SIZE_FORMAT "\n",
4018 cpl_frame_get_filename(fr),(cpl_size)nextn,
4019 (cpl_size)nextn_expected);
4020 return(1);
4021 }
4022
4023 /* Test to see if you can load each of the extensions */
4024
4025 nerr = 0;
4026 for (j = 1; j <= nextn; j++) {
4027 if (isimg) {
4028 test = casu_fits_load(fr,CPL_TYPE_FLOAT,j);
4029 if (test == NULL) {
4030 cpl_msg_error(fctid,
4031 "Frame image %s[%" CPL_SIZE_FORMAT "] won't load\n",
4032 cpl_frame_get_filename(fr),(cpl_size)j);
4033 nerr++;
4034 continue;
4035 }
4036 freefits(test);
4037 } else {
4038 testt = casu_tfits_load(fr,j);
4039 if (testt == NULL) {
4040 cpl_msg_error(fctid,
4041 "Frame table %s[%" CPL_SIZE_FORMAT "] won't load\n",
4042 cpl_frame_get_filename(fr),(cpl_size)j);
4043 nerr++;
4044 continue;
4045 }
4046 freetfits(testt);
4047 }
4048 }
4049 return(nerr);
4050}
4051
4052/*---------------------------------------------------------------------------*/
4068/*---------------------------------------------------------------------------*/
4069
4070static void vircam_sci_get_readnoise_gain(int jext, float *readnoise,
4071 float *gain) {
4072 cpl_propertylist *p_rg;
4073 const char *fctid = "vircam_sci_get_readnoise_gain";
4074
4075 /* Load the propertylist */
4076
4077 p_rg = cpl_propertylist_load(cpl_frame_get_filename(ps.readgain_file),
4078 (cpl_size)jext);
4079
4080 /* Check the readnoise property type and read it */
4081
4082 switch (cpl_propertylist_get_type(p_rg,"ESO QC READNOISE")) {
4083 case CPL_TYPE_FLOAT:
4084 *readnoise = cpl_propertylist_get_float(p_rg,"ESO QC READNOISE");
4085 break;
4086 case CPL_TYPE_DOUBLE:
4087 *readnoise = (float)cpl_propertylist_get_double(p_rg,
4088 "ESO QC READNOISE");
4089 break;
4090 default:
4091 cpl_error_reset();
4092 *readnoise = 25.0;
4093 cpl_msg_error(fctid,"Unable to get READNOISE estimate, guessing %g\n",
4094 *readnoise);
4095 }
4096
4097 /* Now the gain */
4098
4099 switch (cpl_propertylist_get_type(p_rg,"ESO QC CONAD")) {
4100 case CPL_TYPE_FLOAT:
4101 *gain = cpl_propertylist_get_float(p_rg,"ESO QC CONAD");
4102 break;
4103 case CPL_TYPE_DOUBLE:
4104 *gain = (float)cpl_propertylist_get_double(p_rg,"ESO QC CONAD");
4105 break;
4106 default:
4107 cpl_error_reset();
4108 *gain = 1.0;
4109 cpl_msg_error(fctid,"Unable to get GAIN estimate, guessing %g\n",
4110 *gain);
4111 }
4112 cpl_propertylist_delete(p_rg);
4113}
4114
4115/*---------------------------------------------------------------------------*/
4134/*---------------------------------------------------------------------------*/
4135
4136static int vircam_sci_save_simple(casu_fits *obj, cpl_frameset *framelist,
4137 cpl_parameterlist *parlist, int isprod,
4138 cpl_frame *template, int isfirst,
4139 const char *tag, char *fname,
4140 cpl_frame **product_frame) {
4141 cpl_propertylist *plist;
4142 int isdummy;
4143 const char *fctid = "vircam_sci_save_simple";
4144
4145 cpl_ensure(product_frame != NULL, CPL_ERROR_NULL_INPUT, -1);
4146
4147 /* Get some information about this guy */
4148
4149 isdummy = (casu_fits_get_status(obj) != CASU_OK);
4150
4151 /* If we need to make a PHU then do that now based on the first frame
4152 in the input frame list. Get rid of the file if it already exists */
4153
4154 if (isfirst) {
4155 if (access(fname,F_OK))
4156 remove(fname);
4157
4158 /* Create a new product frame object and define some tags */
4159
4160 *product_frame = cpl_frame_new();
4161 cpl_frame_set_filename(*product_frame,fname);
4162
4163 /* Tag the product */
4164
4165 cpl_frame_set_tag(*product_frame,tag);
4166 cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_IMAGE);
4167 cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
4168 cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
4169
4170 /* Set up the PHU header */
4171
4172 plist = casu_fits_get_phu(obj);
4173 vircam_dfs_set_product_primary_header(plist,*product_frame,framelist,
4174 parlist,vircam_recipename,
4175 "PRO-1.15",template,1);
4176
4177 /* 'Save' the PHU image */
4178
4179 if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,plist,CPL_IO_DEFAULT) !=
4180 CPL_ERROR_NONE) {
4181 cpl_msg_error(fctid,"Cannot save product PHU");
4182 cpl_frame_delete(*product_frame);
4183 return(-1);
4184 }
4185 if (isprod)
4186 cpl_frameset_insert(framelist,*product_frame);
4187 }
4188
4189 /* Get the extension property list */
4190
4191 plist = casu_fits_get_ehu(obj);
4192 if (isdummy)
4193 casu_dummy_property(plist);
4194
4195 /* Fiddle with the header now */
4196
4197 vircam_dfs_set_product_exten_header(plist,*product_frame,framelist,parlist,
4198 vircam_recipename,"PRO-1.15",template);
4199 if (cpl_image_save(casu_fits_get_image(obj),fname,CPL_TYPE_FLOAT,plist,
4200 CPL_IO_EXTEND) != CPL_ERROR_NONE) {
4201 cpl_msg_error(fctid,"Cannot save product image extension -- %s",
4202 cpl_error_get_message());
4203 return(-1);
4204 }
4205
4206 /* Get out of here */
4207
4208 return(0);
4209}
4210
4211/*---------------------------------------------------------------------------*/
4230/*---------------------------------------------------------------------------*/
4231
4232static int vircam_sci_save_stack(casu_fits *stack, cpl_frameset *framelist,
4233 cpl_parameterlist *parlist,
4234 cpl_frame *template, int fnametype,
4235 int stack_num, cpl_frame **product_frame) {
4236 cpl_propertylist *plist;
4237 int isfirst,isdummy;
4238 char fname[BUFSIZ],*base,*tname;
4239 const char *fctid = "vircam_sci_save_stack";
4240
4241 /* Get some information about this guy */
4242
4243 isdummy = (casu_fits_get_status(stack) != CASU_OK);
4244 isfirst = (*product_frame == NULL);
4245 tname = cpl_strdup(cpl_frame_get_filename(template));
4246 base = basename(tname);
4247 vircam_sci_product_name(base,STACK_FILE,fnametype,stack_num,fname);
4248 freespace(tname);
4249
4250 /* If we need to make a PHU then do that now based on the first frame
4251 in the input frame list. Get rid of the file if it already exists */
4252
4253 if (isfirst) {
4254 if (access(fname,F_OK))
4255 remove(fname);
4256
4257 /* Create a new product frame object and define some tags */
4258
4259 *product_frame = cpl_frame_new();
4260 cpl_frame_set_filename(*product_frame,fname);
4261
4262 /* Tag the product */
4263
4264 cpl_frame_set_tag(*product_frame,VIRCAM_PRO_JITTERED_SCI);
4265 cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_IMAGE);
4266 cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
4267 cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
4268
4269 /* Set up the PHU header */
4270
4271 plist = casu_fits_get_phu(stack);
4272 vircam_dfs_set_product_primary_header(plist,*product_frame,
4273 framelist,parlist,
4274 vircam_recipename,
4275 "PRO-1.15",template,1);
4276
4277 /* 'Save' the PHU image */
4278
4279 if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,plist,
4280 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
4281 cpl_msg_error(fctid,"Cannot save product PHU");
4282 cpl_frame_delete(*product_frame);
4283 return(-1);
4284 }
4285 cpl_frameset_insert(framelist,*product_frame);
4286 }
4287
4288 /* Get the extension property list */
4289
4290 plist = casu_fits_get_ehu(stack);
4291 if (isdummy)
4292 casu_dummy_property(plist);
4293
4294 /* Fiddle with the header now */
4295
4296 vircam_dfs_set_product_exten_header(plist,*product_frame,framelist,
4297 parlist,vircam_recipename,
4298 "PRO-1.15",template);
4299 if (cpl_image_save(casu_fits_get_image(stack),fname,CPL_TYPE_FLOAT,
4300 plist,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
4301 cpl_msg_error(fctid,"Cannot save product image extension -- %s",
4302 cpl_error_get_message());
4303 return(-1);
4304 }
4305
4306 /* Get out of here */
4307
4308 return(0);
4309}
4310
4311/*---------------------------------------------------------------------------*/
4330/*---------------------------------------------------------------------------*/
4331
4332static int vircam_sci_save_stack_conf(casu_fits *stack, cpl_frameset *framelist,
4333 cpl_parameterlist *parlist,
4334 cpl_frame *template, int fnametype,
4335 int stack_num,
4336 cpl_frame **product_frame) {
4337 cpl_propertylist *plist;
4338 int isfirst,isdummy;
4339 char fname[BUFSIZ],*tname,*base;
4340 const char *fctid = "vircam_sci_save_stack_conf";
4341
4342 /* Get some information about this guy */
4343
4344 isdummy = (casu_fits_get_status(stack) != CASU_OK);
4345 isfirst = (*product_frame == NULL);
4346 tname = cpl_strdup(cpl_frame_get_filename(template));
4347 base = basename(tname);
4348 vircam_sci_product_name(base,STACK_CONF,fnametype,stack_num,fname);
4349 freespace(tname);
4350
4351 /* If we need to make a PHU then do that now based on the first frame
4352 in the input frame list. Get rid of the file if it already exists */
4353
4354 if (isfirst) {
4355 if (access(fname,F_OK))
4356 remove(fname);
4357
4358 /* Create a new product frame object and define some tags */
4359
4360 *product_frame = cpl_frame_new();
4361 cpl_frame_set_filename(*product_frame,fname);
4362
4363 /* Tag the product */
4364
4365 cpl_frame_set_tag(*product_frame,VIRCAM_PRO_CONF_SCI);
4366 cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_IMAGE);
4367 cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
4368 cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
4369
4370 /* Set up the PHU header */
4371
4372 plist = casu_fits_get_phu(stack);
4373 vircam_dfs_set_product_primary_header(plist,*product_frame,framelist,
4374 parlist,vircam_recipename,
4375 "PRO-1.15",template,1);
4376
4377 /* 'Save' the PHU image */
4378
4379 if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,plist,
4380 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
4381 cpl_msg_error(fctid,"Cannot save product PHU");
4382 cpl_frame_delete(*product_frame);
4383 return(-1);
4384 }
4385 cpl_frameset_insert(framelist,*product_frame);
4386 }
4387
4388 /* Get the extension property list */
4389
4390 plist = casu_fits_get_ehu(stack);
4391 if (isdummy)
4392 casu_dummy_property(plist);
4393
4394 /* Fiddle with the header now */
4395
4396 vircam_dfs_set_product_exten_header(plist,*product_frame,framelist,
4397 parlist,vircam_recipename,
4398 "PRO-1.15",template);
4399 if (cpl_image_save(casu_fits_get_image(stack),fname,CPL_TYPE_INT,
4400 plist,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
4401 cpl_msg_error(fctid,"Cannot save product image extension -- %s",
4402 cpl_error_get_message());
4403 return(-1);
4404 }
4405
4406 /* Get out of here */
4407
4408 return(0);
4409}
4410
4411/*---------------------------------------------------------------------------*/
4430/*---------------------------------------------------------------------------*/
4431
4432static int vircam_sci_save_stack_cat(casu_tfits *stack, cpl_frameset *framelist,
4433 cpl_parameterlist *parlist,
4434 cpl_frame *template, int fnametype,
4435 int stack_num, cpl_frame **product_frame) {
4436 cpl_propertylist *plist;
4437 int isfirst,isdummy;
4438 char fname[BUFSIZ],*tname,*base;
4439 const char *fctid = "vircam_sci_save_stack_cat";
4440
4441 /* Get some information about this guy */
4442
4443 isdummy = (casu_tfits_get_status(stack) != CASU_OK);
4444 isfirst = (*product_frame == NULL);
4445 tname = cpl_strdup(cpl_frame_get_filename(template));
4446 base = basename(tname);
4447 vircam_sci_product_name(base,STACK_CAT,fnametype,stack_num,fname);
4448 freespace(tname);
4449
4450 /* If we need to make a PHU then do that now based on the first frame
4451 in the input frame list. Get rid of the file if it already exists */
4452
4453 if (isfirst) {
4454 if (access(fname,F_OK))
4455 remove(fname);
4456
4457 /* Create a new product frame object and define some tags */
4458
4459 *product_frame = cpl_frame_new();
4460 cpl_frame_set_filename(*product_frame,fname);
4461
4462 /* Tag the product */
4463
4464 cpl_frame_set_tag(*product_frame,VIRCAM_PRO_OBJCAT_SCI);
4465 cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_TABLE);
4466 cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
4467 cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
4468
4469 /* Set up the PHU header */
4470
4471 plist = casu_tfits_get_phu(stack);
4472 vircam_dfs_set_product_primary_header(plist,*product_frame,framelist,
4473 parlist,vircam_recipename,
4474 "PRO-1.15",NULL,0);
4475
4476 /* 'Save' the PHU image */
4477
4478 if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,plist,
4479 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
4480 cpl_msg_error(fctid,"Cannot save product PHU");
4481 cpl_frame_delete(*product_frame);
4482 return(-1);
4483 }
4484 cpl_frameset_insert(framelist,*product_frame);
4485 }
4486
4487 /* Get the extension property list */
4488
4489 plist = casu_tfits_get_ehu(stack);
4490 if (isdummy)
4491 casu_dummy_property(plist);
4492
4493 /* Fiddle with the header now */
4494
4495 vircam_dfs_set_product_exten_header(plist,*product_frame,framelist,
4496 parlist,vircam_recipename,
4497 "PRO-1.15",NULL);
4498 if (cpl_table_save(casu_tfits_get_table(stack),NULL,
4499 plist,fname,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
4500 cpl_msg_error(fctid,"Cannot save product table extension -- %s",
4501 cpl_error_get_message());
4502 return(-1);
4503 }
4504
4505 /* Get out of here */
4506
4507 return(0);
4508}
4509
4510/*---------------------------------------------------------------------------*/
4539/*---------------------------------------------------------------------------*/
4540
4541static void vircam_sci_product_name(char *template, int producttype,
4542 int nametype, int fnumber, char *outfname) {
4543 const char *esonames[] = {"exp_","exp_conf_","exp_cat_","stack_",
4544 "stack_conf_","stack_cat_","sky_"};
4545 const char *suffix[] = {"_ex","_ex_conf","_ex_cat","_st","_st_conf",
4546 "_st_cat","sky_"};
4547 char *fname,*bname,*dot;
4548
4549 /* If the name type is the ESO predictable sort, then it's easy. Just
4550 use the esonames defined above and append the correct number */
4551
4552 switch (nametype) {
4553 case 0:
4554 (void)sprintf(outfname,"%s%d.fits",esonames[producttype],fnumber);
4555 break;
4556
4557 /* If this is a temporary file, then just append tmp_ to the template
4558 name and return that */
4559
4560 case 2:
4561 fname = cpl_strdup(template);
4562 bname = basename(fname);
4563 (void)sprintf(outfname,"tmp_%s",bname);
4564 freespace(fname);
4565 break;
4566
4567 /* Ok, we want a pretty name... */
4568
4569 case 1:
4570 fname = cpl_strdup(template);
4571 bname = basename(fname);
4572 if (producttype != SKY_FILE) {
4573 (void)sprintf(outfname,"%s",bname);
4574 dot = strrchr(outfname,'.');
4575 (void)sprintf(dot,"%s.fits",suffix[producttype]);
4576 } else {
4577 sprintf(outfname,"%s%s",suffix[producttype],bname);
4578 }
4579 freespace(fname);
4580 break;
4581
4582 /* something else ?? */
4583
4584 default:
4585 (void)strcpy(outfname,"");
4586 break;
4587 }
4588 return;
4589}
4590
4593/*---------------------------------------------------------------------------*/
4608/*---------------------------------------------------------------------------*/
4609
4610static void vircam_sci_init(void) {
4611
4612 /* Level 0 stuff */
4613
4614 ps.labels = NULL;
4615 ps.master_dark = NULL;
4616 ps.master_twilight_flat = NULL;
4617 ps.master_conf = NULL;
4618 ps.master_sky = NULL;
4619 ps.master_objmask = NULL;
4620 ps.mask = NULL;
4621 ps.chantab = NULL;
4622 ps.phottab = NULL;
4623 ps.tphottab = NULL;
4624 ps.readgain_file = NULL;
4625 ps.science_frames = NULL;
4626 ps.offset_skies = NULL;
4627 ps.product_frames_simple = NULL;
4628 ps.product_frames_simple_off = NULL;
4629 ps.phupaf = NULL;
4630 ps.gaincors = NULL;
4631 ps.catpath = NULL;
4632 ps.catname = NULL;
4633 ps.nscipaws = 0;
4634 ps.science_paws = NULL;
4635 ps.noffpaws = 0;
4636 ps.offsky_paws = NULL;
4637 ps.nskys = 0;
4638 ps.skys = NULL;
4639
4640 /* Level 1 stuff */
4641
4642 ps.fdark = NULL;
4643 ps.fflat = NULL;
4644 ps.fconf = NULL;
4645 ps.fsky = NULL;
4646 ps.fchantab = NULL;
4647 ps.nscience = 0;
4648 ps.sci_fits = NULL;
4649 ps.noffsets = 0;
4650 ps.offsky_fits = NULL;
4651}
4652
4653/*---------------------------------------------------------------------------*/
4674/*---------------------------------------------------------------------------*/
4675
4676static void vircam_sci_tidy(int level) {
4677 int i;
4678
4679 /* Level 1 stuff */
4680
4681 freefits(ps.fdark);
4682 freefits(ps.fflat);
4683 freefits(ps.fconf);
4684 freefits(ps.fsky);
4685 freetfits(ps.fchantab);
4686 freefitslist(ps.sci_fits,ps.nscience);
4687 freefitslist(ps.offsky_fits,ps.noffsets);
4688 ps.nscience = 0;
4689
4690 if (level == 1)
4691 return;
4692
4693 /* Level 0 stuff */
4694
4695 freespace(ps.labels);
4696 freeframe(ps.master_dark);
4697 freeframe(ps.master_twilight_flat);
4698 freeframe(ps.master_conf);
4699 freeframe(ps.master_sky);
4700 freeframe(ps.master_objmask);
4701 freemask(ps.mask);
4702 freeframe(ps.chantab);
4703 freeframe(ps.phottab);
4704 freeframe(ps.readgain_file);
4705 freetable(ps.tphottab);
4706 freeframeset(ps.science_frames);
4707 freeframeset(ps.offset_skies);
4708 freepropertylist(ps.phupaf);
4709 freespace(ps.product_frames_simple); /* NB: We only have to delete */
4710 /* the arrays and not the frames */
4711 /* as these get passed back */
4712 freespace(ps.product_frames_simple_off); /* to esorex */
4713 freespace(ps.gaincors);
4714 freespace(ps.catpath);
4715 freespace(ps.catname);
4716 for (i = 0; i < ps.nskys; i++) {
4717 freeframeset(ps.skys[i].contrib);
4718 freeframe(ps.skys[i].objmask);
4719 freeframe(ps.skys[i].template);
4720 }
4721 freespace(ps.skys);
4722 freepaws(ps.science_paws,ps.nscipaws);
4723 freepaws(ps.offsky_paws,ps.noffpaws);
4724 freeframe(ps.schlf_n);
4725 freeframe(ps.schlf_s);
4726}
4727
4728
4729/*
4730
4731$Log: not supported by cvs2svn $
4732Revision 1.9 2013/10/15 17:01:45 jim
4733new entry
4734
4735
4736*/
int casu_fits_get_status(casu_fits *p)
Definition: casu_fits.c:711
void casu_fits_set_filename(casu_fits *p, char *fname)
Definition: casu_fits.c:839
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
void casu_fits_delete(casu_fits *p)
Definition: casu_fits.c:364
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
casu_fits * casu_fits_duplicate(casu_fits *in)
Definition: casu_fits.c:225
cpl_propertylist * casu_fits_get_phu(casu_fits *p)
Definition: casu_fits.c:531
char * casu_fits_get_filename(casu_fits *p)
Definition: casu_fits.c:646
cpl_propertylist * casu_fits_get_ehu(casu_fits *p)
Definition: casu_fits.c:576
int casu_fits_get_nexten(casu_fits *p)
Definition: casu_fits.c:497
casu_fits * casu_fits_load(cpl_frame *frame, cpl_type type, int nexten)
Definition: casu_fits.c:80
unsigned char * casu_mask_get_data(casu_mask *m)
Definition: casu_mask.c:544
int casu_mask_get_size_y(casu_mask *m)
Definition: casu_mask.c:498
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
int casu_mask_get_size_x(casu_mask *m)
Definition: casu_mask.c:475
int casu_imcore(casu_fits *infile, casu_fits *conf, int ipix, float threshold, int icrowd, float rcore, int nbsize, int cattype, float filtfwhm, casu_tfits **outtab, float gainloc, int *status)
Generate object catalogues from input images.
Definition: casu_imcore.c:149
int casu_flatcor(casu_fits *infile, casu_fits *flatsrc, int *status)
Correct input data for flat field response.
Definition: casu_flatcor.c:79
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
int casu_imstack(casu_fits **inf, casu_fits **inconf, casu_fits **invar, casu_tfits **cats, int nimages, int nconfs, float lthr, float hthr, int method, int seeing, int fast, int unmap, const char *expkey, casu_fits **out, casu_fits **outc, casu_fits **outv, int *status)
Stack images into a mean image using WCS info.
Definition: casu_imstack.c:187
int casu_pawsky_mask_pre(casu_fits **inlist, casu_fits **invar, int nfiles, casu_mask *mask, casu_fits *objmask, int nbsize, casu_fits **skyout, casu_fits **skyvar, int *status)
Work out a sky estimate from an input jitter series and a pre-existing object mask.
Definition: casu_sky.c:412
int casu_matchstds(cpl_table *objtab, cpl_table *stdstab, float srad, cpl_table **outtab, int *status)
Match object and standard star tables by their xy coordinates.
Definition: casu_match.c:300
int casu_gaincor(casu_fits *infile, float gainscl, int *status)
Gain correct input data frame.
Definition: casu_gaincor.c:77
int casu_photcal_extinct(casu_fits **images, casu_tfits **mstds, casu_tfits **cats, int nimages, char *filt, cpl_table *phottab, int minstars, cpl_frame *schlf_n, cpl_frame *schlf_s, const char *expkey, const char *amkey, float magerrcut, int *status)
Do photometric calibration.
int casu_platesol(cpl_propertylist *plist, cpl_propertylist *tlist, cpl_table *matchedstds, int nconst, int shiftan, int *status)
Work out a WCS for an image.
int casu_pawsky_mask(casu_fits **inlist, casu_fits **invar, int nfiles, casu_fits *conf, casu_mask *mask, casu_fits **skyout, casu_fits **skyvar, int niter, int ipix, float thresh, int nbsize, float smkern, int *status)
Work out a masked sky estimate from an input jitter series.
Definition: casu_sky.c:110
int casu_pawsky_minus(casu_fits **infiles, casu_fits **invar, casu_fits *conf, casu_fits *objmaskfits, int nfiles, casu_fits **skyout, casu_fits **skyvar, int *status)
Background correct images using pawsky_minus algorithm.
int casu_getstds(cpl_propertylist *plist, int cache, char *path, char *catname, int cdssearch, char *cacheloc, cpl_table **stds, int *status)
Get a table of standard stars that appear on an image from a catalogue.
Definition: casu_getstds.c:167
void casu_medmad(float *data, unsigned char *bpm, long np, float *med, float *mad)
Definition: casu_stats.c:347
float casu_med(float *data, unsigned char *bpm, long npts)
Definition: casu_stats.c:89
void casu_qmedsig(float *data, unsigned char *bpm, long npts, float thresh, int niter, float lowv, float highv, float *median, float *sigma)
Definition: casu_stats.c:258
void casu_medmadcut(float *data, unsigned char *bpm, long np, float lcut, float hcut, float *med, float *mad)
Definition: casu_stats.c:406
cpl_propertylist * casu_tfits_get_ehu(casu_tfits *p)
Definition: casu_tfits.c:473
casu_tfits * casu_tfits_wrap(cpl_table *tab, casu_tfits *model, cpl_propertylist *phu, cpl_propertylist *ehu)
Definition: casu_tfits.c:739
int casu_tfits_get_status(casu_tfits *p)
Definition: casu_tfits.c:575
casu_tfits * casu_tfits_load(cpl_frame *table, int nexten)
Definition: casu_tfits.c:78
cpl_propertylist * casu_tfits_get_phu(casu_tfits *p)
Definition: casu_tfits.c:432
cpl_table * casu_tfits_get_table(casu_tfits *p)
Definition: casu_tfits.c:364
int casu_compare_tags(const cpl_frame *frame1, const cpl_frame *frame2)
Compare input tags.
Definition: casu_utils.c:96
int casu_catpars(cpl_frame *indx, char **catpath, char **catname)
Find the name of the standard catalogue and its location.
Definition: casu_utils.c:899
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
int casu_gaincor_calc(cpl_frame *frame, int *n, float **cors, int *status)
Work out gain corrections.
Definition: casu_utils.c:757
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
void casu_xytoradec(cpl_wcs *wcs, double x, double y, double *ra, double *dec)
Definition: casu_wcsutils.c:93
int vircam_tilesky(casu_fits **inlist, int nfiles, casu_mask *mask, casu_fits **skyout, int *status)
Work sky estimate from an input tile series.
Definition: vircam_sky.c:94
int vircam_lincor(casu_fits *infile, casu_tfits *lchantab, int kconst, int ndit, int *status)
Apply linearity curves to data.
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
int vircam_pfits_get_gain(const cpl_propertylist *plist, float *gain)
Get the value of the detector gain.
Definition: vircam_pfits.c:713
int vircam_pfits_get_jitternum(const cpl_propertylist *plist, int *jitternum)
Get the value of the first run number in the current jitter sequence.
Definition: vircam_pfits.c:503
int vircam_pfits_get_mjd(const cpl_propertylist *plist, double *mjd)
Get the value of the modified Julian date.
Definition: vircam_pfits.c:729
int vircam_pfits_get_projid(const cpl_propertylist *plist, char *projid)
Get the project id.
Definition: vircam_pfits.c:674
int vircam_pfits_get_dit(const cpl_propertylist *plist, float *dit)
Get the value of DIT.
Definition: vircam_pfits.c:608
int vircam_pfits_get_detlive(const cpl_propertylist *plist, int *detlive)
Get the value of DET_LIVE.
Definition: vircam_pfits.c:624
int vircam_pfits_get_njsteps(const cpl_propertylist *plist, int *njsteps)
Get the value of the number of observations in a jitter sequence.
Definition: vircam_pfits.c:476
int vircam_pfits_get_tplstart(cpl_propertylist *plist, char *tplstart)
Get the value of template start time.
Definition: vircam_pfits.c:777
int vircam_pfits_get_exptime(const cpl_propertylist *plist, float *exptime)
Get the value of exposure time.
Definition: vircam_pfits.c:245
int vircam_pfits_get_filter(const cpl_propertylist *plist, char *filt)
Get the name of the current filter.
Definition: vircam_pfits.c:649
int vircam_pfits_get_offsetnum(const cpl_propertylist *plist, int *offsetnum)
Get the value of the first run number in the current tile sequence.
Definition: vircam_pfits.c:557
const char * vircam_get_license(void)
Definition: vircam_utils.c:116
int vircam_check_crval(cpl_propertylist *phu, cpl_propertylist *ehu)
void vircam_copywcs(cpl_propertylist *p1, cpl_propertylist *p2)