VIRCAM Pipeline  2.3.10
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 
56 typedef 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 
65 typedef 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 
86 struct {
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 
103 struct {
104  int niter;
105  int ipix;
106  float thresh;
107  int nbsize;
108  float smkern;
109 } psm;
110 
111 struct {
112  float lthr;
113  float hthr;
114  int method;
115  int seeing;
116  int fast;
117  int nfst;
118 } stk;
119 
120 struct {
121  int ipix;
122  float thresh;
123  int icrowd;
124  float rcore;
125  int nbsize;
126 } stk_cat;
127 
128 struct {
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 
177 enum {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 
200 char current_cat[VIRCAM_PATHSZ];
201 char current_catpath[VIRCAM_PATHSZ];
202 char vircam_recipename[VIRCAM_PATHSZ];
203 char vircam_recipepaf[VIRCAM_PATHSZ];
204 cpl_propertylist *dummyqc = NULL;
205 int offsky = 0;
206 
207 /* Main stuff for CPL/esorex */
208 
209 static int vircam_science_process_create(cpl_plugin *plugin);
210 static int vircam_science_process_exec(cpl_plugin *plugin);
211 static int vircam_science_process_destroy(cpl_plugin *plugin);
212 static int vircam_science_process(cpl_parameterlist *parlist,
213  cpl_frameset *framelist);
214 
215 /* Pawprint manipulation routines */
216 
217 static void vircam_sci_paw_init(pawprint *paw, cpl_frameset *frms, int ispj,
218  int *nfrms_tot);
219 static void vircam_sci_paw_delete(pawprint *paws);
220 static void vircam_sci_paws_delete(int npaws, pawprint **paws);
221 static void vircam_sci_paws_create(cpl_frameset *infrms, int *npaws,
222  pawprint **paws);
223 
224 /* Processing routines */
225 
226 static int vircam_sci_sky_stripe_wcs(int npaw, pawprint *paw, const char *tag,
227  cpl_frameset *framelist,
228  cpl_parameterlist *parlist, int destripe);
229 static void vircam_sci_cat(pawprint *paw, int extn);
230 static void vircam_sci_stack(pawprint *paw, int extn);
231 static void vircam_sci_wcsfit(casu_fits **in, casu_fits **conf,
232  casu_tfits **incat, int nf, int level);
233 static void vircam_sci_init(void);
234 static void vircam_sci_tidy(int level);
235 static int vircam_destripe_four(casu_fits **curfits, int stripefilt,
236  int *status);
237 static void stripe_profile(casu_fits *in, int stripefilt, float *profile,
238  unsigned char *pbpm);
239 static void vircam_sci_photcal(pawprint *paw);
240 
241 /* Sky related routines */
242 
243 static void vircam_sci_choose_skyalgo(int *nskys, skystruct **skys);
244 static int vircam_sci_makesky(cpl_frameset *framelist,
245  cpl_parameterlist *parlist, skystruct *sky,
246  const char *tag);
247 static void vircam_sci_assign_sky_all(pawprint paw, int whichone);
248 static skystruct vircam_sci_crsky(int algorithm, cpl_frameset *frms,
249  cpl_frame *template, int snum);
250 static void vircam_sci_skydefine(void);
251 static 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);
255 static 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);
259 static 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);
264 static 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 
272 static cpl_frame *vircam_sci_findtemplate(cpl_frame *in);
273 static int vircam_sci_istile(cpl_frame *frm);
274 static int vircam_sci_ispj(cpl_frameset *frms);
275 static int vircam_sci_cmp_jit(const cpl_frame *frame1,
276  const cpl_frame *frame2);
277 static int vircam_sci_cmp_tstart(const cpl_frame *frame1,
278  const cpl_frame *frame2);
279 static int vircam_sci_cmp_property(const cpl_property *p1,
280  const cpl_property *p2);
281 static cpl_frameset *vircam_sci_merge_framesets(int n, cpl_frameset **in);
282 static cpl_frameset *vircam_sci_update_frameset(cpl_frameset *frms, int *nfrms_tot);
283 static int vircam_sci_testfrms(cpl_frameset *frms, int nextn_expected,
284  int isimg);
285 static int vircam_sci_testfrm_1(cpl_frame *fr, int nextn_expected, int isimg);
286 static void vircam_sci_get_readnoise_gain(int jext, float *readnoise,
287  float *gain);
288 static void vircam_sci_product_name(char *template, int producttype,
289  int nametype, int fnumber, char *outfname);
290 
291 /* Save routines */
292 
293 static 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);
298 static 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);
302 static 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);
306 static 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);
310 static 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 
316 static 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 
534 int 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 
576 static 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 
837 static 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 
858 static 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 
881 static 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 
1614 static 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 
1647 static 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 
1816 static 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 
1851 static 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 
1921 static 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 
2092 static 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 
2147 static 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 "]",
2183  casu_fits_get_filename(in[j]),
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 
2303 static 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 
2438 static 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 
2540 static 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 
2566 static 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 
2604 static 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 
2689 static 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 
2729 static 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 
2815 static 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 
2894 static 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 
2997 static 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 
3090 static 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 
3330 static 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 
3388 static 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 
3413 static 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 
3444 static 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 
3485 static 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 
3539 static 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 
3624 static 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 
3710 static 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 
3803 static 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 
3843 static 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 
3894 static 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 
3951 static 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 
4001 static 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 
4070 static 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 
4136 static 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 
4232 static 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 
4332 static 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 
4432 static 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 
4541 static 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 
4610 static 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 
4676 static 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 $
4732 Revision 1.9 2013/10/15 17:01:45 jim
4733 new entry
4734 
4735 
4736 */
int casu_fits_get_status(casu_fits *p)
Definition: casu_fits.c:711
cpl_image * casu_fits_get_image(casu_fits *p)
Definition: casu_fits.c:436
void casu_fits_set_filename(casu_fits *p, char *fname)
Definition: casu_fits.c:839
casu_fits * casu_fits_load(cpl_frame *frame, cpl_type type, int nexten)
Definition: casu_fits.c:80
casu_fits ** casu_fits_load_list(cpl_frameset *f, cpl_type type, int exten)
Definition: casu_fits.c:318
char * casu_fits_get_filename(casu_fits *p)
Definition: casu_fits.c:646
char * casu_fits_get_fullname(casu_fits *p)
Definition: casu_fits.c:680
void casu_fits_delete(casu_fits *p)
Definition: casu_fits.c:364
casu_fits * casu_fits_duplicate(casu_fits *in)
Definition: casu_fits.c:225
int casu_fits_set_error(casu_fits *p, int status)
Definition: casu_fits.c:747
cpl_propertylist * casu_fits_get_phu(casu_fits *p)
Definition: casu_fits.c:531
int casu_fits_get_nexten(casu_fits *p)
Definition: casu_fits.c:497
cpl_propertylist * casu_fits_get_ehu(casu_fits *p)
Definition: casu_fits.c:576
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:159
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
int casu_tfits_get_status(casu_tfits *p)
Definition: casu_tfits.c:575
cpl_table * casu_tfits_get_table(casu_tfits *p)
Definition: casu_tfits.c:364
cpl_propertylist * casu_tfits_get_phu(casu_tfits *p)
Definition: casu_tfits.c:432
cpl_propertylist * casu_tfits_get_ehu(casu_tfits *p)
Definition: casu_tfits.c:473
casu_tfits * casu_tfits_load(cpl_frame *table, int nexten)
Definition: casu_tfits.c:78
casu_tfits * casu_tfits_wrap(cpl_table *tab, casu_tfits *model, cpl_propertylist *phu, cpl_propertylist *ehu)
Definition: casu_tfits.c:739
cpl_frame * casu_frameset_subgroup_1(cpl_frameset *frameset, cpl_size *labels, cpl_size nlab, const char *tag)
Extract a frame of a given label from a frameset.
Definition: casu_utils.c:206
int casu_compare_tags(const cpl_frame *frame1, const cpl_frame *frame2)
Compare input tags.
Definition: casu_utils.c:96
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_frameset * casu_frameset_subgroup(cpl_frameset *frameset, cpl_size *labels, cpl_size nlab, const char *tag)
Extract a frameset from another frameset.
Definition: casu_utils.c:149
int casu_gaincor_calc(cpl_frame *frame, int *n, float **cors, int *status)
Work out gain corrections.
Definition: casu_utils.c:757
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
int vircam_check_crval(cpl_propertylist *phu, cpl_propertylist *ehu)
void vircam_copywcs(cpl_propertylist *p1, cpl_propertylist *p2)
const char * vircam_get_license(void)
Definition: vircam_utils.c:116