VIRCAM Pipeline  1.3.3
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) 2013 Cambridge Astronomy Survey Unit
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 "vircam_utils.h"
42 #include "vircam_mask.h"
43 #include "vircam_pfits.h"
44 #include "vircam_dfs.h"
45 #include "vircam_mods.h"
46 #include "vircam_fits.h"
47 #include "vircam_tfits.h"
48 #include "vircam_paf.h"
49 #include "vircam_sky.h"
50 #include "vircam_filt.h"
51 #include "vircam_stats.h"
52 #include "vircam_wcsutils.h"
53 
54 #define VIRCAM_PATHSZ 128
55 #define VIRCAM_NEXTN 16
56 
57 typedef struct {
58  cpl_frameset *contrib;
59  cpl_frame *objmask;
60  int skyalgo;
61  cpl_frame *skyframe;
62  cpl_frame *template;
63  char fname[BUFSIZ];
64 } skystruct;
65 
66 typedef struct {
67  cpl_frameset *current;
68  cpl_frameset *orig;
69  int *whichsky;
70  vir_fits *stack[VIRCAM_NEXTN];
71  vir_fits *stackc[VIRCAM_NEXTN];
72  vir_tfits *cat[VIRCAM_NEXTN];
73  cpl_table *mstds[VIRCAM_NEXTN];
74  cpl_frame *product_frame_im;
75  cpl_frame *product_frame_conf;
76  cpl_frame *product_frame_cat;
77  int tilenum;
78  int jitternum;
79  char projname[16];
80  double mjd_start;
81  double mjd_end;
82  int ispj;
83 } pawprint;
84 
85 /* User supplied command line options */
86 
87 struct {
88 
89  /* Input */
90 
91  int savecat;
92  int destripe;
93  int str_filt;
94  int skyalgo;
95  int preview_only;
96  int minphotom;
97  int prettynames;
98 
99 } vircam_sci_config;
100 
101 
102 struct {
103  int niter;
104  int ipix;
105  float thresh;
106  int nbsize;
107  float smkern;
108 } psm;
109 
110 struct {
111  float lthr;
112  float hthr;
113  int method;
114  int seeing;
115 } stk;
116 
117 struct {
118  int ipix;
119  float thresh;
120  int icrowd;
121  float rcore;
122  int nbsize;
123 } stk_cat;
124 
125 struct {
126 
127  /* Level 0 stuff */
128 
129  cpl_size *labels;
130  cpl_frame *master_dark;
131  cpl_frame *master_twilight_flat;
132  cpl_frame *master_conf;
133  cpl_frame *master_sky;
134  cpl_frame *master_objmask;
135  vir_mask *mask;
136  cpl_frame *chantab;
137  cpl_frame *phottab;
138  cpl_table *tphottab;
139  cpl_frame *readgain_file;
140  cpl_frameset *science_frames;
141  cpl_frameset *offset_skies;
142  cpl_frame **product_frames_simple;
143  cpl_frame **product_frames_simple_off;
144  cpl_propertylist *phupaf;
145  float *gaincors;
146  char *catpath;
147  char *catname;
148  int nscipaws;
149  pawprint *science_paws;
150  int noffpaws;
151  pawprint *offsky_paws;
152  int nskys;
153  skystruct *skys;
154  cpl_frame *schlf_n;
155  cpl_frame *schlf_s;
156 
157  /* Level 1 stuff */
158 
159  vir_fits *fdark;
160  vir_fits *fflat;
161  vir_fits *fconf;
162  vir_fits *fsky;
163  vir_tfits *fchantab;
164 
165  int nscience;
166  vir_fits **sci_fits;
167  int noffsets;
168  vir_fits **offsky_fits;
169 
170 } ps;
171 
172 /* List of data products types */
173 
174 enum {SIMPLE_FILE,
175  SIMPLE_CONF,
176  SIMPLE_CAT,
177  STACK_FILE,
178  STACK_CONF,
179  STACK_CAT,
180  SKY_FILE
181 };
182 
183 #define SKYNONE 0
184 #define SKYMASTER -1
185 #define PAWSKY_MASK 1
186 #define PAWSKY_MASK_PRE 2
187 #define TILESKY 3
188 #define TILESKY_MINUS 4
189 #define AUTO 5
190 #define PAWSKY_MINUS 6
191 
192 #define VMCPROJ "179.B-2003"
193 #define VIDEOPROJ "179.A-2006"
194 
195 #define freepaws(_p,_n) if (_p != NULL) {vircam_sci_paws_delete(_n,&(_p)); _p = NULL; _n = 0;}
196 
197 char current_cat[VIRCAM_PATHSZ];
198 char current_catpath[VIRCAM_PATHSZ];
199 char vircam_recipename[VIRCAM_PATHSZ];
200 char vircam_recipepaf[VIRCAM_PATHSZ];
201 cpl_propertylist *dummyqc = NULL;
202 int offsky = 0;
203 
204 /* Main stuff for CPL/esorex */
205 
206 static int vircam_science_process_create(cpl_plugin *plugin);
207 static int vircam_science_process_exec(cpl_plugin *plugin);
208 static int vircam_science_process_destroy(cpl_plugin *plugin);
209 static int vircam_science_process(cpl_parameterlist *parlist,
210  cpl_frameset *framelist);
211 
212 /* Pawprint manipulation routines */
213 
214 static void vircam_sci_paw_init(pawprint *paw, cpl_frameset *frms, int ispj);
215 static void vircam_sci_paw_delete(pawprint *paws);
216 static void vircam_sci_paws_delete(int npaws, pawprint **paws);
217 static void vircam_sci_paws_create(cpl_frameset *infrms, int *npaws,
218  pawprint **paws);
219 
220 /* Processing routines */
221 
222 static int vircam_sci_sky_stripe_wcs(int npaw, pawprint *paw, const char *tag,
223  cpl_frameset *framelist,
224  cpl_parameterlist *parlist);
225 static void vircam_sci_cat(pawprint *paw, int extn);
226 static void vircam_sci_stack(pawprint *paw, int extn);
227 static void vircam_sci_wcsfit(vir_fits **in, vir_fits **conf,
228  vir_tfits **incat, int nf, int level);
229 extern void vircam_sci_init(void);
230 extern void vircam_sci_tidy(int level);
231 static int vircam_destripe_four(vir_fits **curfits, int stripefilt,
232  int *status);
233 static void stripe_profile(vir_fits *in, int stripefilt, float *profile,
234  unsigned char *pbpm);
235 static void vircam_sci_photcal(pawprint *paw);
236 
237 /* Sky related routines */
238 
239 static void vircam_sci_choose_skyalgo(int *nskys, skystruct **skys);
240 static int vircam_sci_makesky(cpl_frameset *framelist,
241  cpl_parameterlist *parlist, skystruct *sky,
242  const char *tag);
243 static void vircam_sci_assign_sky_all(pawprint paw, int whichone);
244 static skystruct vircam_sci_crsky(int algorithm, cpl_frameset *frms,
245  cpl_frame *template, int snum);
246 static void vircam_sci_skydefine(void);
247 static int vircam_sci_tilesky(cpl_frameset *framelist,
248  cpl_parameterlist *parlist, cpl_frameset *in,
249  cpl_frame *template,
250  char *fname, cpl_frame **product_frame);
251 static int vircam_sci_pawsky_mask(cpl_frameset *framelist,
252  cpl_parameterlist *parlist, int algo,
253  cpl_frameset *contrib, cpl_frame *template,
254  char *fname, cpl_frame **product_frame);
255 static int vircam_sci_tilesky_minus(cpl_frameset *framelist,
256  cpl_parameterlist *parlist,
257  cpl_frameset *in, cpl_frame *template,
258  const char *tag, char *fname,
259  cpl_frame **skyframe);
260 static int vircam_sci_pawsky_minus(cpl_frameset *framelist,
261  cpl_parameterlist *parlist,
262  cpl_frameset *in, cpl_frame *template,
263  const char *tag, char *skyname,
264  cpl_frame **skyframe);
265 
266 /* Utility routines */
267 
268 static cpl_frame *vircam_sci_findtemplate(cpl_frame *in);
269 static int vircam_sci_istile(cpl_frame *frm);
270 static int vircam_pfits_get_tplstart(cpl_propertylist *plist, char *tplstart);
271 static int vircam_sci_ispj(cpl_frameset *frms);
272 static int vircam_sci_cmp_jit(const cpl_frame *frame1,
273  const cpl_frame *frame2);
274 static int vircam_sci_cmp_tstart(const cpl_frame *frame1,
275  const cpl_frame *frame2);
276 static int vircam_sci_cmp_property(const cpl_property *p1,
277  const cpl_property *p2);
278 static cpl_frameset *vircam_sci_merge_framesets(int n, cpl_frameset **in);
279 static cpl_frameset *vircam_sci_update_frameset(cpl_frameset *frms);
280 static int vircam_sci_testfrms(cpl_frameset *frms, int nextn_expected,
281  int isimg);
282 static int vircam_sci_testfrm_1(cpl_frame *fr, int nextn_expected, int isimg);
283 extern void vircam_sci_get_readnoise_gain(int jext, float *readnoise,
284  float *gain);
285 static void vircam_sci_product_name(char *template, int producttype,
286  int nametype, int fnumber, char *outfname);
287 
288 /* Save routines */
289 
290 extern int vircam_sci_save_simple(vir_fits *obj, cpl_frameset *framelist,
291  cpl_parameterlist *parlist, int isprod,
292  cpl_frame *template, int isfirst,
293  const char *tag, char *fname,
294  cpl_frame **product_frame);
295 extern int vircam_sci_save_sky(vir_fits *outsky, cpl_frameset *framelist,
296  cpl_parameterlist *parlist,
297  char *fname, cpl_frame *template, int isfirst,
298  cpl_frame **product_frame);
299 extern int vircam_sci_save_stack(vir_fits *stack, cpl_frameset *framelist,
300  cpl_parameterlist *parlist,
301  cpl_frame *template, int fnametype,
302  int stack_num, cpl_frame **product_frame);
303 extern int vircam_sci_save_stack_conf(vir_fits *stack, cpl_frameset *framelist,
304  cpl_parameterlist *parlist,
305  cpl_frame *template, int fnametype,
306  int stack_num, cpl_frame **product_frame);
307 extern int vircam_sci_save_stack_cat(vir_tfits *stack, cpl_frameset *framelist,
308  cpl_parameterlist *parlist,
309  cpl_frame *template, int fnametype,
310  int stack_num, cpl_frame **product_frame);
311 
312 
313 static char vircam_science_process_description[] =
314 "vircam_science_process -- VIRCAM science product recipe.\n\n"
315 "Process a complete pawprint for VIRCAM data. Remove instrumental\n"
316 "signature, background correct, combine jitters, photometrically\n"
317 "and astrometrically calibrate the pawprint image\n\n"
318 "The program accepts the following files in the SOF:\n\n"
319 " Tag Description\n"
320 " -----------------------------------------------------------------------\n"
321 " %-22s A list of raw science images or\n"
322 " %-22s A list of raw science images (extended)\n"
323 " %-22s A list of offset sky exposures (optional)\n"
324 " %-22s A master dark frame\n"
325 " %-22s A master twilight flat frame\n"
326 " %-22s A master sky frame (optional)\n"
327 " %-22s A channel table\n"
328 " %-22s A photometric calibration table\n"
329 " %-22s A readnoise/gain file\n"
330 " %-22s A master confidence map\n"
331 " %-22s A master standard star index\n"
332 " %-22s Northern Schlegel Map\n"
333 " %-22s Southern Schlegel Map\n"
334 "All of the above are required unless otherwise specified\n"
335 "\n";
336 
337 /*---------------------------------------------------------------------------*/
345 /*---------------------------------------------------------------------------*/
346 
347 int cpl_plugin_get_info(cpl_pluginlist *list) {
348  cpl_recipe *recipe = cpl_calloc(1,sizeof(*recipe));
349  cpl_plugin *plugin = &recipe->interface;
350  char alldesc[SZ_ALLDESC];
351  (void)snprintf(alldesc,SZ_ALLDESC,
352  vircam_science_process_description,
353  VIRCAM_SCI_OBJECT_RAW,VIRCAM_SCI_OBJECT_EXT_RAW,
354  VIRCAM_OFFSET_SKY_RAW,VIRCAM_CAL_DARK,
355  VIRCAM_CAL_TWILIGHT_FLAT,VIRCAM_CAL_SKY,VIRCAM_CAL_CHANTAB,
356  VIRCAM_CAL_PHOTTAB,VIRCAM_CAL_READGAINFILE,VIRCAM_CAL_CONF,
357  VIRCAM_CAL_2MASS,VIRCAM_CAL_SCHL_N,VIRCAM_CAL_SCHL_S);
358 
359  cpl_plugin_init(plugin,
360  CPL_PLUGIN_API,
361  VIRCAM_BINARY_VERSION,
362  CPL_PLUGIN_TYPE_RECIPE,
363  "vircam_science_process",
364  "VIRCAM science recipe",
365  alldesc,
366  "Jim Lewis",
367  "jrl@ast.cam.ac.uk",
369  vircam_science_process_create,
370  vircam_science_process_exec,
371  vircam_science_process_destroy);
372 
373  cpl_pluginlist_append(list,plugin);
374 
375  return(0);
376 }
377 
378 /*---------------------------------------------------------------------------*/
387 /*---------------------------------------------------------------------------*/
388 
389 static int vircam_science_process_create(cpl_plugin *plugin) {
390  cpl_recipe *recipe;
391  cpl_parameter *p;
392 
393  /* Get the recipe out of the plugin */
394 
395  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
396  recipe = (cpl_recipe *)plugin;
397  else
398  return(-1);
399 
400  /* Create the parameters list in the cpl_recipe object */
401 
402  recipe->parameters = cpl_parameterlist_new();
403 
404  /* Fill in flag to use save the output catalogue */
405 
406  p = cpl_parameter_new_value("vircam.vircam_science_process.savecat",
407  CPL_TYPE_BOOL,"Save catalogue?",
408  "vircam.vircam_science_process",1);
409  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"savecat");
410  cpl_parameterlist_append(recipe->parameters,p);
411 
412  /* Fill in flag to destripe the images */
413 
414  p = cpl_parameter_new_value("vircam.vircam_science_process.destripe",
415  CPL_TYPE_BOOL,"Destripe images?",
416  "vircam.vircam_science_process",1);
417  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"destripe");
418  cpl_parameterlist_append(recipe->parameters,p);
419 
420  /* Fill in flag to correct sky background */
421 
422  p = cpl_parameter_new_enum("vircam.vircam_science_process.skyalgo",
423  CPL_TYPE_INT,"Sky subtraction algorithm",
424  "vircam.vircam_science_process",1,8,-1,0,1,2,3,4,5,6);
425  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"skyalgo");
426  cpl_parameterlist_append(recipe->parameters,p);
427 
428  /* Fill in flag to just print out how the data will be processed and
429  then exit */
430 
431  p = cpl_parameter_new_value("vircam.vircam_science_process.preview_only",
432  CPL_TYPE_BOOL,"Preview only?",
433  "vircam.vircam_science_process",0);
434  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"preview_only");
435  cpl_parameterlist_append(recipe->parameters,p);
436 
437  /* Fill in flag to just print out how the data will be processed and
438  then exit */
439 
440  p = cpl_parameter_new_value("vircam.vircam_science_process.minphotom",
441  CPL_TYPE_INT,
442  "Minimum stars for photometry solution",
443  "vircam.vircam_science_process",0);
444  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"minphotom");
445  cpl_parameterlist_append(recipe->parameters,p);
446 
447  /* Fill in flag to decide whether use predictable names or nice
448  names based on input file names */
449 
450  p = cpl_parameter_new_value("vircam.vircam_science_process.prettynames",
451  CPL_TYPE_BOOL,"Use pretty product names?",
452  "vircam.vircam_science_process",0);
453  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"prettynames");
454  cpl_parameterlist_append(recipe->parameters,p);
455 
456  /* ***Special parameters for object detection on stacks*** */
457 
458  /* Fill in the minimum object size */
459 
460  p = cpl_parameter_new_value("vircam.vircam_science_process.stk_cat_ipix",
461  CPL_TYPE_INT,
462  "Minimum pixel area for each detected object",
463  "vircam.vircam_science_process",5);
464  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_ipix");
465  cpl_parameterlist_append(recipe->parameters,p);
466 
467  /* Fill in the detection threshold parameter */
468 
469  p = cpl_parameter_new_value("vircam.vircam_science_process.stk_cat_thresh",
470  CPL_TYPE_DOUBLE,
471  "Detection threshold in sigma above sky",
472  "vircam.vircam_science_process",2.0);
473  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_thresh");
474  cpl_parameterlist_append(recipe->parameters,p);
475 
476  /* Fill in flag to use deblending software or not */
477 
478  p = cpl_parameter_new_value("vircam.vircam_science_process.stk_cat_icrowd",
479  CPL_TYPE_BOOL,"Use deblending?",
480  "vircam.vircam_science_process",1);
481  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_icrowd");
482  cpl_parameterlist_append(recipe->parameters,p);
483 
484  /* Fill in core radius */
485 
486  p = cpl_parameter_new_value("vircam.vircam_science_process.stk_cat_rcore",
487  CPL_TYPE_DOUBLE,"Value of Rcore in pixels",
488  "vircam.vircam_science_process",3.0);
489  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_rcore");
490  cpl_parameterlist_append(recipe->parameters,p);
491 
492  /* Fill in background smoothing box size */
493 
494  p = cpl_parameter_new_value("vircam.vircam_science_process.stk_cat_nbsize",
495  CPL_TYPE_INT,"Background smoothing box size",
496  "vircam.vircam_science_process",64);
497  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_cat_nbsize");
498  cpl_parameterlist_append(recipe->parameters,p);
499 
500  /* ***Special parameters for stacking*** */
501 
502  /* The lower rejection threshold to be used during stacking */
503 
504  p = cpl_parameter_new_value("vircam.vircam_science_process.stk_lthr",
505  CPL_TYPE_DOUBLE,"Low rejection threshold",
506  "vircam.vircam_science_process",3.0);
507  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_lthr");
508  cpl_parameterlist_append(recipe->parameters,p);
509 
510  /* The upper rejection threshold to be used during stacking */
511 
512  p = cpl_parameter_new_value("vircam.vircam_science_process.stk_hthr",
513  CPL_TYPE_DOUBLE,"Upper rejection threshold",
514  "vircam.vircam_science_process",3.0);
515  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_hthr");
516  cpl_parameterlist_append(recipe->parameters,p);
517 
518  /* Stacking method */
519 
520  p = cpl_parameter_new_enum("vircam.vircam_science_process.stk_method",
521  CPL_TYPE_INT,"Stacking method",
522  "vircam.vircam_science_process",1,2,0,1);
523  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_method");
524  cpl_parameterlist_append(recipe->parameters,p);
525 
526  /* Flag to use seeing weighting */
527 
528  p = cpl_parameter_new_value("vircam.vircam_science_process.stk_seeing",
529  CPL_TYPE_BOOL,"Weight by seeing?",
530  "vircam.vircam_science_process",0);
531  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"stk_seeing");
532  cpl_parameterlist_append(recipe->parameters,p);
533 
534  /* ***Special parameters for destripe algorithm*** */
535 
536  /* Flag to filter stripe pattern */
537 
538  p = cpl_parameter_new_value("vircam.vircam_science_process.str_filt",
539  CPL_TYPE_BOOL,"Filter stripe pattern?",
540  "vircam.vircam_science_process",1);
541  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"str_filt");
542  cpl_parameterlist_append(recipe->parameters,p);
543 
544  /* ***Special parameters for pawsky_mask algorithm*** */
545 
546  /* The pixel area for detected objects */
547 
548  p = cpl_parameter_new_value("vircam.vircam_science_process.psm_ipix",
549  CPL_TYPE_INT,
550  "Minimum pixel area for each detected object",
551  "vircam.vircam_science_process",5);
552  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_ipix");
553  cpl_parameterlist_append(recipe->parameters,p);
554 
555  /* Number of iterations */
556 
557  p = cpl_parameter_new_value("vircam.vircam_science_process.psm_niter",
558  CPL_TYPE_INT,
559  "Number of iterations in pawsky mask",
560  "vircam.vircam_science_process",5);
561  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_niter");
562  cpl_parameterlist_append(recipe->parameters,p);
563 
564  /* Detection threshold */
565 
566  p = cpl_parameter_new_value("vircam.vircam_science_process.psm_thresh",
567  CPL_TYPE_DOUBLE,
568  "Detection threshold in sigma above sky",
569  "vircam.vircam_science_process",2.0);
570  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_thresh");
571  cpl_parameterlist_append(recipe->parameters,p);
572 
573  /* Background smoothing box size */
574 
575  p = cpl_parameter_new_value("vircam.vircam_science_process.psm_nbsize",
576  CPL_TYPE_INT,"Background smoothing box size",
577  "vircam.vircam_science_process",50);
578  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_nbsize");
579  cpl_parameterlist_append(recipe->parameters,p);
580 
581  /* Smoothing kernel size */
582 
583  p = cpl_parameter_new_value("vircam.vircam_science_process.psm_smkern",
584  CPL_TYPE_DOUBLE,
585  "Smoothing kernel size (pixels)",
586  "vircam.vircam_science_process",2.0);
587  cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"psm_smkern");
588  cpl_parameterlist_append(recipe->parameters,p);
589 
590  /* Get out of here */
591 
592  return(0);
593 }
594 
595 /*---------------------------------------------------------------------------*/
601 /*---------------------------------------------------------------------------*/
602 
603 static int vircam_science_process_exec(cpl_plugin *plugin) {
604  cpl_recipe *recipe;
605 
606  /* Get the recipe out of the plugin */
607 
608  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
609  recipe = (cpl_recipe *)plugin;
610  else
611  return(-1);
612 
613  return(vircam_science_process(recipe->parameters,recipe->frames));
614 }
615 
616 /*---------------------------------------------------------------------------*/
622 /*---------------------------------------------------------------------------*/
623 
624 static int vircam_science_process_destroy(cpl_plugin *plugin) {
625  cpl_recipe *recipe ;
626 
627  /* Get the recipe out of the plugin */
628 
629  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
630  recipe = (cpl_recipe *)plugin;
631  else
632  return(-1);
633 
634  cpl_parameterlist_delete(recipe->parameters);
635  return(0);
636 }
637 
638 static int vircam_science_process(cpl_parameterlist *parlist,
639  cpl_frameset *framelist) {
640  const char *fctid="vircam_science_process";
641  cpl_parameter *p;
642  int nfail,status,i,ndit,j,live,isfirst,nsci,njsteps,n;
643  cpl_size nlab;
644  float gaincor_fac,readnoise,gain,dit;
645  cpl_frame *catindex,*template,*frm;
646  cpl_propertylist *pp;
647  cpl_table *stdscat;
648  vir_fits *ff;
649  char filt[16],projid[16],*tname,fname[BUFSIZ];
650 
651  /* Check validity of the input frameset */
652 
653  if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
654  cpl_msg_error(fctid,"Input framelist NULL or has no input data");
655  return(-1);
656  }
657 
658  /* Initialise some things */
659 
660  vircam_sci_init();
661  (void)strncpy(vircam_recipename,fctid,VIRCAM_PATHSZ);
662  (void)snprintf(vircam_recipepaf,VIRCAM_PATHSZ,"VIRCAM/%s",fctid);
663 
664  /* Get the parameters */
665 
666  p = cpl_parameterlist_find(parlist,
667  "vircam.vircam_science_process.savecat");
668  vircam_sci_config.savecat = cpl_parameter_get_bool(p);
669  p = cpl_parameterlist_find(parlist,
670  "vircam.vircam_science_process.destripe");
671  vircam_sci_config.destripe = cpl_parameter_get_bool(p);
672  p = cpl_parameterlist_find(parlist,
673  "vircam.vircam_science_process.str_filt");
674  vircam_sci_config.str_filt = cpl_parameter_get_bool(p);
675  p = cpl_parameterlist_find(parlist,
676  "vircam.vircam_science_process.skyalgo");
677  vircam_sci_config.skyalgo = cpl_parameter_get_int(p);
678  p = cpl_parameterlist_find(parlist,
679  "vircam.vircam_science_process.preview_only");
680  vircam_sci_config.preview_only = cpl_parameter_get_bool(p);
681  p = cpl_parameterlist_find(parlist,
682  "vircam.vircam_science_process.minphotom");
683  vircam_sci_config.minphotom = cpl_parameter_get_int(p);
684  p = cpl_parameterlist_find(parlist,
685  "vircam.vircam_science_process.prettynames");
686  vircam_sci_config.prettynames = cpl_parameter_get_bool(p);
687 
688  /* Stacking special parameters */
689 
690  p = cpl_parameterlist_find(parlist,
691  "vircam.vircam_science_process.stk_lthr");
692  stk.lthr = cpl_parameter_get_double(p);
693  p = cpl_parameterlist_find(parlist,
694  "vircam.vircam_science_process.stk_hthr");
695  stk.hthr = cpl_parameter_get_double(p);
696  p = cpl_parameterlist_find(parlist,
697  "vircam.vircam_science_process.stk_method");
698  stk.method = cpl_parameter_get_int(p);
699  p = cpl_parameterlist_find(parlist,
700  "vircam.vircam_science_process.stk_seeing");
701  stk.seeing = cpl_parameter_get_bool(p);
702 
703  /* Object detection on stacks special parameters */
704 
705  p = cpl_parameterlist_find(parlist,
706  "vircam.vircam_science_process.stk_cat_ipix");
707  stk_cat.ipix = cpl_parameter_get_int(p);
708  p = cpl_parameterlist_find(parlist,
709  "vircam.vircam_science_process.stk_cat_thresh");
710  stk_cat.thresh = (float)cpl_parameter_get_double(p);
711  p = cpl_parameterlist_find(parlist,
712  "vircam.vircam_science_process.stk_cat_icrowd");
713  stk_cat.icrowd = cpl_parameter_get_bool(p);
714  p = cpl_parameterlist_find(parlist,
715  "vircam.vircam_science_process.stk_cat_rcore");
716  stk_cat.rcore = (float)cpl_parameter_get_double(p);
717  p = cpl_parameterlist_find(parlist,
718  "vircam.vircam_science_process.stk_cat_nbsize");
719  stk_cat.nbsize = cpl_parameter_get_int(p);
720 
721  /* Pawsky_mask special parameters */
722 
723  p = cpl_parameterlist_find(parlist,
724  "vircam.vircam_science_process.psm_ipix");
725  psm.ipix = cpl_parameter_get_int(p);
726  p = cpl_parameterlist_find(parlist,
727  "vircam.vircam_science_process.psm_niter");
728  psm.niter = cpl_parameter_get_int(p);
729  p = cpl_parameterlist_find(parlist,
730  "vircam.vircam_science_process.psm_thresh");
731  psm.thresh = cpl_parameter_get_double(p);
732  p = cpl_parameterlist_find(parlist,
733  "vircam.vircam_science_process.psm_nbsize");
734  psm.nbsize = cpl_parameter_get_int(p);
735  p = cpl_parameterlist_find(parlist,
736  "vircam.vircam_science_process.psm_smkern");
737  psm.smkern = cpl_parameter_get_double(p);
738 
739  /* Sort out raw from calib frames */
740 
741  if (vircam_dfs_set_groups(framelist) != VIR_OK) {
742  cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
743  vircam_sci_tidy(0);
744  return(-1);
745  }
746 
747  /* Label the input frames */
748 
749  if ((ps.labels = cpl_frameset_labelise(framelist,vircam_compare_tags,
750  &nlab)) == NULL) {
751  cpl_msg_error(fctid,"Cannot labelise the input frames");
752  vircam_sci_tidy(0);
753  return(-1);
754  }
755 
756  /* Get the input science frames */
757 
758  nfail = 0;
759  if ((ps.science_frames =
760  vircam_frameset_subgroup(framelist,ps.labels,nlab,
761  VIRCAM_SCI_OBJECT_RAW)) == NULL) {
762  if ((ps.science_frames =
763  vircam_frameset_subgroup(framelist,ps.labels,nlab,
764  VIRCAM_SCI_OBJECT_EXT_RAW)) == NULL) {
765  cpl_msg_error(fctid,"No science images to process!");
766  vircam_sci_tidy(0);
767  return(-1);
768  }
769  }
770  /* nfail += vircam_sci_testfrms(ps.science_frames,VIRCAM_NEXTN,1); */
771 
772  /* Get the offset sky frames */
773 
774  if ((ps.master_sky = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
775  VIRCAM_CAL_SKY)) == NULL) {
776  if ((ps.offset_skies =
777  vircam_frameset_subgroup(framelist,ps.labels,nlab,
778  VIRCAM_OFFSET_SKY_RAW)) == NULL) {
779  offsky = 0;
780  } else {
781  offsky = 1;
782  nfail += vircam_sci_testfrms(ps.offset_skies,VIRCAM_NEXTN,1);
783  }
784  } else {
785  offsky = -1;
786  vircam_sci_config.skyalgo = -1;
787  nfail += vircam_sci_testfrm_1(ps.master_sky,VIRCAM_NEXTN,1);
788  }
789 
790  /* Check to see if there is a master dark frame */
791 
792  if ((ps.master_dark =
793  vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
794  VIRCAM_CAL_DARK)) == NULL) {
795  cpl_msg_error(fctid,"No master dark found");
796  vircam_sci_tidy(0);
797  return(-1);
798  }
799  nfail += vircam_sci_testfrm_1(ps.master_dark,VIRCAM_NEXTN,1);
800 
801  /* Check to see if there is a master twilight flat frame */
802 
803  if ((ps.master_twilight_flat =
804  vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
805  VIRCAM_CAL_TWILIGHT_FLAT)) == NULL) {
806  cpl_msg_error(fctid,"No master twilight flat found");
807  vircam_sci_tidy(0);
808  return(-1);
809  }
810  nfail += vircam_sci_testfrm_1(ps.master_twilight_flat,VIRCAM_NEXTN,1);
811 
812  /* Get the master object mask. Does it make sense to have one in
813  the context of the sky correction algorithm? */
814 
815  ps.master_objmask = vircam_frameset_subgroup_1(framelist,ps.labels,
816  nlab,VIRCAM_CAL_OBJMASK);
817  if ((ps.master_objmask == NULL) &&
818  (vircam_sci_config.skyalgo == PAWSKY_MASK_PRE)) {
819  cpl_msg_error(fctid,
820  "No object mask found. Unable to use requested sky algorithm");
821  vircam_sci_tidy(0);
822  return(-1);
823  } else if (ps.master_objmask != NULL &&
824  (vircam_sci_config.skyalgo == PAWSKY_MASK ||
825  vircam_sci_config.skyalgo == TILESKY)) {
826  cpl_msg_info(fctid,
827  "Requested sky subt algorithm requires no object mask");
828  }
829  nfail += vircam_sci_testfrm_1(ps.master_objmask,0,1);
830 
831  /* Get the gain corrections */
832 
833  status = VIR_OK;
834  if (vircam_gaincor_calc(ps.master_twilight_flat,&i,&(ps.gaincors),
835  &status) != VIR_OK) {
836  cpl_msg_error(fctid,"Error calculating gain corrections");
837  vircam_sci_tidy(0);
838  return(-1);
839  }
840 
841  /* Check to see if there is a readgain file */
842 
843  if ((ps.readgain_file =
844  vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
845  VIRCAM_CAL_READGAINFILE)) == NULL) {
846  cpl_msg_error(fctid,"No master readnoise/gain file found");
847  vircam_sci_tidy(0);
848  return(-1);
849  }
850  nfail += vircam_sci_testfrm_1(ps.readgain_file,VIRCAM_NEXTN,0);
851 
852  /* Check to see if there is a master confidence map. */
853 
854  if ((ps.master_conf =
855  vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
856  VIRCAM_CAL_CONF)) == NULL) {
857  cpl_msg_error(fctid,"No master confidence map file found");
858  vircam_sci_tidy(0);
859  return(-1);
860  }
861  nfail += vircam_sci_testfrm_1(ps.master_conf,VIRCAM_NEXTN,1);
862  ps.mask = vircam_mask_define(framelist,ps.labels,nlab);
863 
864  /* Check to see if there is a channel table */
865 
866  if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
867  VIRCAM_CAL_CHANTAB)) == NULL) {
868  cpl_msg_error(fctid,"No channel table found");
869  vircam_sci_tidy(0);
870  return(-1);
871  }
872  nfail += vircam_sci_testfrm_1(ps.chantab,VIRCAM_NEXTN,0);
873 
874  /* Check to see if there is a photometric table */
875 
876  if ((ps.phottab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
877  VIRCAM_CAL_PHOTTAB)) == NULL) {
878  cpl_msg_error(fctid,"No photometric table found");
879  vircam_sci_tidy(0);
880  return(-1);
881  }
882  nfail += vircam_sci_testfrm_1(ps.phottab,1,0);
883 
884  /* Is the 2mass index file specified? */
885 
886  if ((catindex = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
887  VIRCAM_CAL_2MASS)) == NULL) {
888  cpl_msg_error(fctid,"No 2MASS index found -- cannot continue");
889  vircam_sci_tidy(0);
890  return(-1);
891  }
892  nfail += vircam_sci_testfrm_1(catindex,1,0);
893 
894  /* Is the Northern Schlegel file specified? */
895 
896  if ((ps.schlf_n = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
897  VIRCAM_CAL_SCHL_N)) == NULL) {
898  cpl_msg_error(fctid,"Schlegel North map not found -- cannot continue");
899  vircam_sci_tidy(0);
900  return(-1);
901  }
902  nfail += vircam_sci_testfrm_1(ps.schlf_n,0,1);
903 
904 
905  /* Is the Southern Schlegel file specified? */
906 
907  if ((ps.schlf_s = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
908  VIRCAM_CAL_SCHL_S)) == NULL) {
909  cpl_msg_error(fctid,"Schlegel South map not found -- cannot continue");
910  vircam_sci_tidy(0);
911  return(-1);
912  }
913  nfail += vircam_sci_testfrm_1(ps.schlf_s,0,1);
914 
915  /* Ok if any of this failed, then get out of here. This makes it a bit
916  simpler later on since we now know that all of the specified files
917  have the correct number of extensions and will load properly */
918 
919  if (nfail > 0) {
920  cpl_msg_error(fctid,
921  "There are %" CPL_SIZE_FORMAT " input file errors -- cannot continue",
922  (cpl_size)nfail);
923  vircam_sci_tidy(0);
924  return(-1);
925  }
926 
927  /* Get catalogue parameters */
928 
929  if (vircam_catpars(catindex,&(ps.catpath),&(ps.catname)) == VIR_FATAL) {
930  vircam_sci_tidy(0);
931  cpl_frame_delete(catindex);
932  return(-1);
933  }
934  cpl_frame_delete(catindex);
935 
936  /* Set up the photometric calibration catalogue data */
937 
938  (void)strcpy(current_catpath,ps.catpath);
939  (void)strcpy(current_cat,ps.catname);
940 
941  /* Get the number of DITs. This assumes it is the same for all the science
942  images (and it damn well better be!) */
943 
944  pp = cpl_propertylist_load(cpl_frame_get_filename(cpl_frameset_get_frame(ps.science_frames,0)),0);
945  if (vircam_pfits_get_ndit(pp,&ndit) != VIR_OK) {
946  cpl_msg_error(fctid,"No value for NDIT available");
947  freepropertylist(pp);
948  vircam_sci_tidy(0);
949  return(-1);
950  }
951  cpl_propertylist_delete(pp);
952 
953  /* Load the photometric table */
954 
955  ps.tphottab = cpl_table_load(cpl_frame_get_filename(ps.phottab),1,0);
956 
957  /* Break these into pawprints now */
958 
959  vircam_sci_paws_create(ps.science_frames,&(ps.nscipaws),&(ps.science_paws));
960  vircam_sci_paws_create(ps.offset_skies,&(ps.noffpaws),&(ps.offsky_paws));
961 
962  /* Check what we have and see if it makes sense. If this isn't a tile
963  and there are multiple pawprints, then signal an error */
964 
965  if (ps.science_paws[0].tilenum == -1 && ps.nscipaws > 1) {
966  cpl_msg_error(fctid,
967  "List has %" CPL_SIZE_FORMAT " pawprints. Only 1 is allowed for non tiles",
968  (cpl_size)ps.nscipaws);
969  vircam_sci_tidy(0);
970  return(-1);
971  }
972 
973  /* Define the skys that will be made */
974 
975  vircam_sci_skydefine();
976 
977  /* Print out some stuff if you want a preview */
978 
979  if (vircam_sci_config.preview_only) {
980  if (ps.science_paws[0].tilenum == -1)
981  fprintf(stdout,"This is a paw group with %" CPL_SIZE_FORMAT " files\n",
982  cpl_frameset_get_size(ps.science_frames));
983  else
984  fprintf(stdout,"This is a tile group with %" CPL_SIZE_FORMAT " files\n",
985  cpl_frameset_get_size(ps.science_frames));
986  frm = cpl_frameset_get_frame(ps.science_frames,0);
987  pp = cpl_propertylist_load(cpl_frame_get_filename(frm),0);
988  (void)vircam_pfits_get_filter(pp,filt);
989  (void)vircam_pfits_get_ndit(pp,&ndit);
990  (void)vircam_pfits_get_dit(pp,&dit);
991  (void)vircam_pfits_get_projid(pp,projid);
992  (void)vircam_pfits_get_njsteps(pp,&njsteps);
993  cpl_propertylist_delete(pp);
994 
995  fprintf(stdout,"Filter %8s, DIT: %8.1f, NDIT: %" CPL_SIZE_FORMAT ", Project: %s\n",filt,
996  dit,(cpl_size)ndit,projid);
997  fprintf(stdout,"Dark: %s\n",cpl_frame_get_filename(ps.master_dark));
998  fprintf(stdout,"Flat: %s\n",
999  cpl_frame_get_filename(ps.master_twilight_flat));
1000  fprintf(stdout,"CPM: %s\n",cpl_frame_get_filename(ps.master_conf));
1001  fprintf(stdout,"Channel table: %s\n",
1002  cpl_frame_get_filename(ps.chantab));
1003  fprintf(stdout,"A %" CPL_SIZE_FORMAT " point dither will be done\n",
1004  (cpl_size)njsteps);
1005  if (ps.science_paws[0].tilenum != -1)
1006  fprintf(stdout,"The tile has %" CPL_SIZE_FORMAT " pawprints\n",
1007  (cpl_size)ps.nscipaws);
1008  for (i = 0; i < ps.nscipaws; i++) {
1009  n = cpl_frameset_get_size(ps.science_paws[i].orig);
1010  for (j = 0; j < n; j++) {
1011  frm = cpl_frameset_get_frame(ps.science_paws[i].orig,j);
1012  fprintf(stdout,"%s sky%" CPL_SIZE_FORMAT "\n",cpl_frame_get_filename(frm),
1013  (cpl_size)(ps.science_paws[i].whichsky[j]+1));
1014  }
1015  }
1016  if (ps.noffpaws != 0) {
1017  fprintf(stdout,"There are %" CPL_SIZE_FORMAT " offset sky frames\n",
1018  cpl_frameset_get_size(ps.offset_skies));
1019  for (i = 0; i < ps.noffpaws; i++) {
1020  n = cpl_frameset_get_size(ps.offsky_paws[i].orig);
1021  for (j = 0; j < n; j++) {
1022  frm = cpl_frameset_get_frame(ps.offsky_paws[i].orig,j);
1023  fprintf(stdout,"%s sky%" CPL_SIZE_FORMAT "\n",cpl_frame_get_filename(frm),
1024  (cpl_size)(ps.offsky_paws[i].whichsky[j]+1));
1025  }
1026  }
1027  }
1028  fprintf(stdout,"\nRequested sky algorithm: %" CPL_SIZE_FORMAT "\n",
1029  (cpl_size)vircam_sci_config.skyalgo);
1030  for (i = 0; i < ps.nskys; i++) {
1031  fprintf(stdout,"Sky%" CPL_SIZE_FORMAT ": %" CPL_SIZE_FORMAT " ",
1032  (cpl_size)(i+1),(cpl_size)ps.skys[i].skyalgo);
1033  if (ps.skys[i].objmask != NULL)
1034  fprintf(stdout,"mask: %s\nFormed from:\n",
1035  cpl_frame_get_filename(ps.skys[i].objmask));
1036  else
1037  fprintf(stdout,"\nFormed from:\n");
1038  for (j = 0; j < cpl_frameset_get_size(ps.skys[i].contrib); j++) {
1039  frm = cpl_frameset_get_frame(ps.skys[i].contrib,j);
1040  fprintf(stdout," %s\n",cpl_frame_get_filename(frm));
1041  }
1042  }
1043  vircam_sci_tidy(0);
1044  return(0);
1045  }
1046 
1047  /* Get some workspace for the product frames */
1048 
1049  ps.nscience = cpl_frameset_get_size(ps.science_frames);
1050  nsci = ps.nscience;
1051  ps.product_frames_simple = cpl_malloc(ps.nscience*sizeof(cpl_frame *));
1052  for (i = 0; i < ps.nscience; i++)
1053  ps.product_frames_simple[i] = NULL;
1054  if (ps.offset_skies != NULL) {
1055  ps.noffsets = cpl_frameset_get_size(ps.offset_skies);
1056  ps.product_frames_simple_off =
1057  cpl_malloc(ps.noffsets*sizeof(cpl_frame *));
1058  for (i = 0; i < ps.noffsets; i++)
1059  ps.product_frames_simple_off[i] = NULL;
1060  } else {
1061  ps.noffsets = 0;
1062  }
1063 
1064  /* Do the stage1 processing. Loop for all extensions */
1065 
1066  cpl_msg_info(fctid,"Beginning stage1 reduction");
1067  cpl_msg_indent_more();
1068  for (j = 1; j <= VIRCAM_NEXTN; j++) {
1069  isfirst = (j == 1);
1070  gaincor_fac = (ps.gaincors)[j-1];
1071  cpl_msg_info(fctid,"Extension [%" CPL_SIZE_FORMAT "]",(cpl_size)j);
1072 
1073  /* Load up the calibration frames. We know these won't fail now
1074  so we can skip all the boring testing... */
1075 
1076  ps.fdark = vircam_fits_load(ps.master_dark,CPL_TYPE_FLOAT,j);
1077  ps.fflat = vircam_fits_load(ps.master_twilight_flat,CPL_TYPE_FLOAT,j);
1078  ps.fconf = vircam_fits_load(ps.master_conf,CPL_TYPE_INT,j);
1079  vircam_mask_load(ps.mask,j,
1080  (int)cpl_image_get_size_x(vircam_fits_get_image(ps.fconf)),
1081  (int)cpl_image_get_size_y(vircam_fits_get_image(ps.fconf)));
1082  if (offsky == -1)
1083  ps.fsky = vircam_fits_load(ps.master_sky,CPL_TYPE_FLOAT,j);
1084  ps.fchantab = vircam_tfits_load(ps.chantab,j);
1085 
1086  /* Now load up the science frames and offset skies, if needed */
1087 
1088  ps.nscience = cpl_frameset_get_size(ps.science_frames);
1089  ps.sci_fits = vircam_fits_load_list(ps.science_frames,CPL_TYPE_FLOAT,j);
1090  if (j == 1)
1091  ps.phupaf = vircam_paf_phu_items(vircam_fits_get_phu(ps.sci_fits[0]));
1092  if (offsky == 1) {
1093  ps.noffsets = cpl_frameset_get_size(ps.offset_skies);
1094  ps.offsky_fits = vircam_fits_load_list(ps.offset_skies,
1095  CPL_TYPE_FLOAT,j);
1096  } else {
1097  ps.noffsets = 0;
1098  ps.offsky_fits = NULL;
1099  }
1100 
1101  /* Loop through and mark the frames where the header says the detector
1102  wasn't live. Also check to see if the CRVAL == 0 problem is
1103  present. Check for live detectors in the offset skies too */
1104 
1105  for (i = 0; i < ps.nscience; i++) {
1106  ff = ps.sci_fits[i];
1108  if (! live)
1109  vircam_fits_set_error(ff,VIR_FATAL);
1111  vircam_fits_get_ehu(ff)) != VIR_OK) {
1112  cpl_msg_error(fctid,"Unable to correct CRVAL in %s",
1114  vircam_sci_tidy(0);
1115  return(-1);
1116  }
1117  }
1118  for (i = 0; i < ps.noffsets; i++) {
1119  ff = ps.offsky_fits[i];
1121  if (! live)
1122  vircam_fits_set_error(ff,VIR_FATAL);
1123  }
1124 
1125  /* Do the corrections now. First for the object frames. Write
1126  out intermediate versions as we go */
1127 
1128  vircam_sci_get_readnoise_gain(j,&readnoise,&gain);
1129  for (i = 0; i < ps.nscience; i++) {
1130  ff = ps.sci_fits[i];
1131  cpl_propertylist_update_float(vircam_fits_get_ehu(ff),"READNOIS",
1132  readnoise);
1133  cpl_propertylist_set_comment(vircam_fits_get_ehu(ff),"READNOIS",
1134  "[e-] Readnoise used in processing");
1135  cpl_propertylist_update_float(vircam_fits_get_ehu(ff),"GAIN",gain);
1136  cpl_propertylist_set_comment(vircam_fits_get_ehu(ff),"GAIN",
1137  "[e-/adu] Gain used in processing");
1138  if (vircam_fits_get_status(ff) == VIR_FATAL) {
1139  cpl_msg_info(fctid,"Detector is flagged dead in %s",
1141  } else {
1142  status = VIR_OK;
1143  (void)vircam_darkcor(ff,ps.fdark,1.0,&status);
1144  (void)vircam_lincor(ff,ps.fchantab,1,ndit,&status);
1145  (void)vircam_nditcor(ff,ndit,&status);
1146  (void)vircam_flatcor(ff,ps.fflat,&status);
1147  (void)vircam_gaincor(ff,gaincor_fac,&status);
1148  vircam_fits_set_error(ff,status);
1149  }
1150  frm = cpl_frameset_get_frame(ps.science_frames,i);
1151  tname = (char *)cpl_frame_get_filename(frm);
1152  vircam_sci_product_name(tname,SIMPLE_FILE,
1153  vircam_sci_config.prettynames,i+1,fname);
1154  vircam_sci_save_simple(ff,framelist,parlist,0,
1155  cpl_frameset_get_frame(ps.science_frames,i),
1156  isfirst,VIRCAM_PRO_SIMPLE_SCI,fname,
1157  ps.product_frames_simple+i);
1158  }
1159  for (i = 0; i < ps.noffsets; i++) {
1160  ff = ps.offsky_fits[i];
1161  if (vircam_fits_get_status(ff) == VIR_FATAL) {
1162  cpl_msg_info(fctid,"Detector is flagged dead in %s",
1164  } else {
1165  status = VIR_OK;
1166  (void)vircam_darkcor(ff,ps.fdark,1.0,&status);
1167  (void)vircam_lincor(ff,ps.fchantab,1,ndit,&status);
1168  (void)vircam_nditcor(ff,ndit,&status);
1169  (void)vircam_flatcor(ff,ps.fflat,&status);
1170  (void)vircam_gaincor(ff,gaincor_fac,&status);
1171  vircam_fits_set_error(ff,status);
1172  }
1173  frm = cpl_frameset_get_frame(ps.offset_skies,i);
1174  tname = (char *)cpl_frame_get_filename(frm);
1175  vircam_sci_product_name(tname,SIMPLE_FILE,
1176  vircam_sci_config.prettynames,
1177  ps.nscience+i+1,fname);
1178  vircam_sci_save_simple(ff,framelist,parlist,0,
1179  cpl_frameset_get_frame(ps.offset_skies,i),
1180  isfirst,VIRCAM_PRO_SIMPLE_SKY,fname,
1181  ps.product_frames_simple_off+i);
1182  }
1183 
1184  /* Intermediate tidy */
1185 
1186  vircam_sci_tidy(1);
1187  }
1188  for (i = 0; i < nsci; i++)
1189  freeframe(ps.product_frames_simple[i]);
1190  for (i = 0; i < ps.noffsets; i++)
1191  freeframe(ps.product_frames_simple_off[i]);
1192 
1193  cpl_msg_indent_less();
1194 
1195  /* Form the sky frames. These are saved and registered as products */
1196 
1197  cpl_msg_info(fctid,"Making skies");
1198  for (i = 0; i < ps.nskys; i++) {
1199  if (vircam_sci_makesky(framelist,parlist,&(ps.skys[i]),
1200  VIRCAM_PRO_SIMPLE_SCI) != VIR_OK) {
1201  cpl_msg_error(fctid,"Error making sky %" CPL_SIZE_FORMAT "",
1202  (cpl_size)i);
1203  vircam_sci_tidy(0);
1204  return(-1);
1205  }
1206  }
1207 
1208  /* Do sky subtraction, destripe and write them out */
1209 
1210  cpl_msg_info(fctid,"Beginning stage2 reduction");
1211  (void)vircam_sci_sky_stripe_wcs(ps.nscipaws,ps.science_paws,
1212  VIRCAM_PRO_SIMPLE_SCI,framelist,parlist);
1213  (void)vircam_sci_sky_stripe_wcs(ps.noffpaws,ps.offsky_paws,
1214  VIRCAM_PRO_SIMPLE_SKY,framelist,parlist);
1215 
1216  /* Loop for all science jitters. Jitter, WCSFIT, photcal and write out */
1217 
1218  cpl_msg_info(fctid,"Beginning group processing");
1219  cpl_msg_indent_more();
1220  for (i = 0; i < ps.nscipaws; i++) {
1221  cpl_msg_info(fctid,"Working on paw%" CPL_SIZE_FORMAT "",
1222  (cpl_size)(i+1));
1223  cpl_msg_indent_more();
1224  for (j = 1; j <= VIRCAM_NEXTN; j++) {
1225  cpl_msg_info(fctid,
1226  "Stacking paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1227  (cpl_size)(i+1),(cpl_size)j);
1228  vircam_sci_stack(&(ps.science_paws[i]),j);
1229  cpl_msg_info(fctid,
1230  "Source extraction paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1231  (cpl_size)(i+1),(cpl_size)j);
1232  vircam_sci_cat(&(ps.science_paws[i]),j);
1233  cpl_msg_info(fctid,
1234  "WCS fit paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1235  (cpl_size)(i+1),(cpl_size)j);
1236  vircam_sci_wcsfit(&(ps.science_paws[i].stack[j-1]),
1237  &(ps.science_paws[i].stackc[j-1]),
1238  &(ps.science_paws[i].cat[j-1]),1,2);
1239  (void)vircam_getstds(vircam_fits_get_ehu(ps.science_paws[i].stack[j-1]),
1240  1,current_catpath,current_cat,&stdscat,&status);
1241  (void)vircam_matchstds(vircam_tfits_get_table(ps.science_paws[i].cat[j-1]),
1242  stdscat,300.0,
1243  &(ps.science_paws[i].mstds[j-1]),&status);
1244  freetable(stdscat);
1245  }
1246  cpl_msg_indent_less();
1247  cpl_msg_info(fctid,
1248  "Doing photometric calibriation on paw%" CPL_SIZE_FORMAT "",
1249  (cpl_size)(i+1));
1250  vircam_sci_photcal(&(ps.science_paws[i]));
1251  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[i].orig,0));
1252  cpl_msg_info(fctid,"Saving paw%" CPL_SIZE_FORMAT "",(cpl_size)(i+1));
1253  cpl_msg_indent_more();
1254  for (j = 1; j <= VIRCAM_NEXTN; j++) {
1255  cpl_msg_info(fctid,
1256  "Saving image paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1257  (cpl_size)(i+1),(cpl_size)j);
1258  vircam_sci_save_stack(ps.science_paws[i].stack[j-1],framelist,
1259  parlist,template,
1260  vircam_sci_config.prettynames,i+1,
1261  &(ps.science_paws[i].product_frame_im));
1262  cpl_msg_info(fctid,"Saving confidence map paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1263  (cpl_size)(i+1),(cpl_size)j);
1264  vircam_sci_save_stack_conf(ps.science_paws[i].stackc[j-1],framelist,
1265  parlist,template,
1266  vircam_sci_config.prettynames,i+1,
1267  &(ps.science_paws[i].product_frame_conf));
1268  cpl_msg_info(fctid,
1269  "Saving catalogue paw%" CPL_SIZE_FORMAT "[%" CPL_SIZE_FORMAT "]",
1270  (cpl_size)(i+1),(cpl_size)j);
1271  vircam_sci_save_stack_cat(ps.science_paws[i].cat[j-1],
1272  framelist,parlist,template,
1273  vircam_sci_config.prettynames,i+1,
1274  &(ps.science_paws[i].product_frame_cat));
1275  }
1276  freeframe(template);
1277  cpl_msg_indent_less();
1278  vircam_sci_paw_delete(ps.science_paws+i);
1279  }
1280  cpl_msg_indent_less();
1281 
1282  /* Final cleanup */
1283 
1284  vircam_sci_tidy(0);
1285  return(0);
1286 }
1287 
1288 static void vircam_sci_photcal(pawprint *paw) {
1289  char filt[16];
1290  int status;
1291 
1292  /* Get the filter name for the pawprint */
1293 
1294  vircam_pfits_get_filter(vircam_fits_get_phu(paw->stack[0]),filt);
1295 
1296  /* Call the routine */
1297 
1298  status = VIR_OK;
1299  vircam_photcal_extinct(paw->stack,paw->mstds,paw->cat,VIRCAM_NEXTN,
1300  filt,ps.tphottab,vircam_sci_config.minphotom,
1301  ps.schlf_n,ps.schlf_s,&status);
1302 }
1303 
1304 static void vircam_sci_skydefine(void) {
1305  int i,j;
1306  cpl_frameset *newfrmset,**in;
1307  cpl_frame *template;
1308 
1309  /* Switch for the sky algorithm choices. Start with SKYNONE where
1310  we don't have to do anything as the sky frame index in the pawprints
1311  references nothing */
1312 
1313  switch (vircam_sci_config.skyalgo) {
1314  case SKYNONE:
1315  break;
1316 
1317  /* AUTO means we use the data to determine what is the best way
1318  to estimate the sky. The routine also assigns the sky to be subtracted
1319  to each object image */
1320 
1321  case AUTO:
1322  vircam_sci_choose_skyalgo(&(ps.nskys),&(ps.skys));
1323  break;
1324 
1325  /* A master sky exists. Therefore all we have to do here is to
1326  create a sky structure and then assign it to all the input objects */
1327 
1328  case SKYMASTER:
1329  ps.nskys = 1;
1330  ps.skys = cpl_malloc(sizeof(skystruct));
1331  ps.skys[0].skyframe = cpl_frame_duplicate(ps.master_sky);
1332  ps.skys[0].skyalgo = SKYMASTER;
1333  ps.skys[0].contrib = NULL;
1334  ps.skys[0].objmask = NULL;
1335  ps.skys[0].template = NULL;
1336  for (i = 0; i < ps.nscipaws; i++)
1337  vircam_sci_assign_sky_all(ps.science_paws[i],0);
1338  break;
1339 
1340  /* PAWSKY_MASK is requested. NB: there may be more than one sky because
1341  the user may have requested this algorithm for a tile. We need a
1342  section for the case where offset skies have been provided or not */
1343 
1344  case PAWSKY_MASK:
1345  if (ps.noffpaws == 0) {
1346  ps.nskys = ps.nscipaws;
1347  ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1348  for (i = 0; i < ps.nscipaws; i++) {
1349  newfrmset = cpl_frameset_duplicate(ps.science_paws[i].current);
1350  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[i].orig,0));
1351  ps.skys[i] = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,
1352  i+1);
1353  vircam_sci_assign_sky_all(ps.science_paws[i],i);
1354  }
1355  } else {
1356  ps.nskys = ps.noffpaws;
1357  ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1358  for (i = 0; i < ps.noffpaws; i++) {
1359  newfrmset = cpl_frameset_duplicate(ps.offsky_paws[i].current);
1360  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.offsky_paws[i].orig,0));
1361  ps.skys[i] = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,
1362  i+1);
1363  vircam_sci_assign_sky_all(ps.offsky_paws[i],i);
1364  }
1365  for (i = 0; i < ps.nscipaws; i++) {
1366  if (i > ps.nskys-1)
1367  j = ps.nskys - 1;
1368  else
1369  j = i;
1370  vircam_sci_assign_sky_all(ps.science_paws[i],j);
1371  }
1372  }
1373  break;
1374 
1375  /* PAWSKY_MASK_PRE is requested. NB: there may be more than one sky because
1376  the user may have requested this algorithm for a tile. Offset skies
1377  are ignored because the mask won't cover this. */
1378 
1379  case PAWSKY_MASK_PRE:
1380  ps.nskys = ps.nscipaws;
1381  ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1382  for (i = 0; i < ps.nscipaws; i++) {
1383  newfrmset = cpl_frameset_duplicate(ps.science_paws[i].current);
1384  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[i].orig,0));
1385  ps.skys[i] = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,i+1);
1386  vircam_sci_assign_sky_all(ps.science_paws[i],i);
1387  }
1388  break;
1389 
1390  /* TILESKY is requested. This results in one sky */
1391 
1392  case TILESKY:
1393  ps.nskys = 1;
1394  ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1395  if (ps.noffpaws == 0) {
1396  in = cpl_malloc(ps.nscipaws*sizeof(cpl_frameset *));
1397  for (i = 0; i < ps.nscipaws; i++)
1398  in[i] = ps.science_paws[i].current;
1399  newfrmset = vircam_sci_merge_framesets(ps.nscipaws,in);
1400  freespace(in);
1401  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[0].orig,0));
1402  ps.skys[0] = vircam_sci_crsky(TILESKY,newfrmset,template,1);
1403  for (i = 0; i < ps.nscipaws; i++)
1404  vircam_sci_assign_sky_all(ps.science_paws[i],0);
1405  } else {
1406  in = cpl_malloc(ps.noffpaws*sizeof(cpl_frameset *));
1407  for (i = 0; i < ps.noffpaws; i++)
1408  in[i] = ps.offsky_paws[i].current;
1409  newfrmset = vircam_sci_merge_framesets(ps.noffpaws,in);
1410  freespace(in);
1411  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.offsky_paws[0].orig,0));
1412  ps.skys[0] = vircam_sci_crsky(TILESKY,newfrmset,template,1);
1413  for (i = 0; i < ps.noffpaws; i++)
1414  vircam_sci_assign_sky_all(ps.offsky_paws[i],0);
1415  for (i = 0; i < ps.nscipaws; i++)
1416  vircam_sci_assign_sky_all(ps.science_paws[i],0);
1417  }
1418  break;
1419 
1420  /* TILESKY_MINUS is requested. This has to be done separately, so
1421  the information in the sky structure isn't quite what is going
1422  to happen. Offset skies are ignored */
1423 
1424  case TILESKY_MINUS:
1425  ps.nskys = 1;
1426  ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1427  in = cpl_malloc(ps.nscipaws*sizeof(cpl_frameset *));
1428  for (i = 0; i < ps.nscipaws; i++)
1429  in[i] = ps.science_paws[i].current;
1430  newfrmset = vircam_sci_merge_framesets(ps.nscipaws,in);
1431  freespace(in);
1432  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[0].orig,0));
1433  ps.skys[0] = vircam_sci_crsky(TILESKY_MINUS,newfrmset,template,1);
1434  for (i = 0; i < ps.nscipaws; i++)
1435  vircam_sci_assign_sky_all(ps.science_paws[i],0);
1436  break;
1437 
1438  /* PAWSKY_MINUS is requested. This has to be done separately, so
1439  the information in the sky structure isn't quite what is going
1440  to happen. Offset skies are ignored */
1441 
1442  case PAWSKY_MINUS:
1443  ps.nskys = 1;
1444  ps.skys = cpl_malloc(ps.nskys*sizeof(skystruct));
1445  newfrmset = cpl_frameset_duplicate(ps.science_paws[0].current);
1446  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[0].orig,0));
1447  ps.skys[0] = vircam_sci_crsky(PAWSKY_MINUS,newfrmset,template,1);
1448  vircam_sci_assign_sky_all(ps.science_paws[0],0);
1449  break;
1450  }
1451 }
1452 
1453 static void vircam_sci_cat(pawprint *paw, int extn) {
1454  int status;
1455  vir_tfits *tab;
1456 
1457  /* Do the catalogue for the current extension */
1458 
1459  status = VIR_OK;
1460  (void)vircam_imcore(paw->stack[extn-1],paw->stackc[extn-1],stk_cat.ipix,
1461  stk_cat.thresh,stk_cat.icrowd,stk_cat.rcore,
1462  stk_cat.nbsize,2,2.0,&tab,&status);
1463  paw->cat[extn-1] = tab;
1464 }
1465 
1466 static void vircam_sci_stack(pawprint *paw, int extn) {
1467  vir_fits **inf,*inconf,*out,*outc;
1468  int ninf,status,i;
1469  double sum,mjd;
1470 
1471  /* Do the stack for the current extension */
1472 
1473  inf = vircam_fits_load_list(paw->current,CPL_TYPE_FLOAT,extn);
1474  inconf = vircam_fits_load(ps.master_conf,CPL_TYPE_INT,extn);
1475  ninf = (int)cpl_frameset_get_size(paw->current);
1476  status = VIR_OK;
1477  vircam_imstack(inf,&inconf,NULL,ninf,1,stk.lthr,stk.hthr,stk.method,
1478  stk.seeing,&out,&outc,&status);
1479 
1480  /* Get the mjd of each input image. Average it and write that to the
1481  output stack header */
1482 
1483  sum = 0.0;
1484  for (i = 0; i < ninf; i++) {
1486  sum += mjd;
1487  }
1488  sum /= (double)ninf;
1489  cpl_propertylist_update_double(vircam_fits_get_ehu(out),"MJD_MEAN",sum);
1490  cpl_propertylist_set_comment(vircam_fits_get_ehu(out),"MJD_MEAN",
1491  "Mean MJD of the input images");
1492  freefitslist(inf,ninf);
1493  freefits(inconf);
1494  paw->stack[extn-1] = out;
1495  paw->stackc[extn-1] = outc;
1496 }
1497 
1498 
1499 static int vircam_sci_sky_stripe_wcs(int npaw, pawprint *paw, const char *tag,
1500  cpl_frameset *framelist,
1501  cpl_parameterlist *parlist) {
1502  int i,j,jj,k,nf,n,isfirst,ii,status,whichsky,skyminus;
1503  long nx,ny,npts;
1504  cpl_frame *curframe,*template,*product_frame;
1505  cpl_frameset *objframes;
1506  cpl_image *img,*simg;
1507  float med,sig,*sdata;
1508  vir_fits **sky_extns,*curfits[4],*tmpfits,*fconf;
1509  unsigned char *bpm[VIRCAM_NEXTN];
1510  cpl_mask *cplmasks[VIRCAM_NEXTN];
1511  const char *fctid = "vircam_sci_sky_stripe_wcs";
1512  char tmpname[BUFSIZ];
1513 
1514  /* NULL input */
1515 
1516  if (npaw == 0 || paw == NULL)
1517  return(VIR_OK);
1518 
1519  /* Set up the masking from the confidence maps */
1520 
1521  for (i = 1; i <= VIRCAM_NEXTN; i++) {
1522  vircam_mask_load(ps.mask,i,0,0);
1523  nx = vircam_mask_get_size_x(ps.mask);
1524  ny = vircam_mask_get_size_y(ps.mask);
1525  bpm[i-1] = cpl_calloc(nx*ny,sizeof(unsigned char));
1526  memmove(bpm[i-1],vircam_mask_get_data(ps.mask),
1527  nx*ny*sizeof(unsigned char));
1528  cplmasks[i-1] = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,
1529  (cpl_binary *)bpm[i-1]);
1530  }
1531 
1532  /* Loop for all the pawprints... */
1533 
1534  cpl_msg_indent_more();
1535  sky_extns = cpl_calloc(VIRCAM_NEXTN,sizeof(vir_fits *));
1536  for (j = 0; j < VIRCAM_NEXTN; j++)
1537  sky_extns[j] = NULL;
1538  for (j = 0; j < npaw; j++) {
1539 
1540  /* Do the sky subtraction for each frame in the pawprint. */
1541 
1542  objframes = paw[j].current;
1543  nf = cpl_frameset_get_size(objframes);
1544  whichsky = -1;
1545  skyminus = (ps.skys[paw[j].whichsky[0]].skyalgo == TILESKY_MINUS ||
1546  ps.skys[paw[j].whichsky[0]].skyalgo == PAWSKY_MINUS);
1547  for (jj = 0; jj < nf; jj++) {
1548  curframe = cpl_frameset_get_frame(objframes,jj);
1549  cpl_msg_info(fctid,"Beginning work on %s",
1550  cpl_frame_get_filename(curframe));
1551  template = cpl_frameset_get_frame(paw[j].orig,jj);
1552  n = 0;
1553  (void)snprintf(tmpname,BUFSIZ,"tmp_%s",
1554  cpl_frame_get_filename(curframe));
1555 
1556  /* First load up the sky extensions and normalise the data arrays
1557  to a zero median (so long as the sky correction hasn't
1558  already been done). */
1559 
1560  if (! skyminus &&
1561  (whichsky == -1 || paw[j].whichsky[jj] != whichsky)) {
1562  whichsky = paw[j].whichsky[jj];
1563  for (i = 1; i <= VIRCAM_NEXTN; i++) {
1564  freefits(sky_extns[i-1]);
1565  sky_extns[i-1] = vircam_fits_load(ps.skys[whichsky].skyframe,CPL_TYPE_FLOAT,i);
1566  img = vircam_fits_get_image(sky_extns[i-1]);
1567  sdata = cpl_image_get_data_float(img);
1568  nx = (long)cpl_image_get_size_x(img);
1569  ny = (long)cpl_image_get_size_y(img);
1570  npts = nx*ny;
1571  vircam_qmedsig(sdata,bpm[i-1],npts,5.0,3,-1000.0,65535.0,&med,&sig);
1572  for (k = 0; k < npts; k++)
1573  sdata[k] -= med;
1574  }
1575  }
1576 
1577  /* Loop for all the extensions. First do the sky subtraction
1578  (if we need to do it) */
1579 
1580  isfirst = 1;
1581  for (i = 1; i <= VIRCAM_NEXTN; i++) {
1582  curfits[n] = vircam_fits_load(curframe,CPL_TYPE_FLOAT,i);
1583  img = vircam_fits_get_image(curfits[n]);
1584  if (sky_extns[i-1] != NULL) {
1585  simg = vircam_fits_get_image(sky_extns[i-1]);
1586  cpl_image_subtract(img,(const cpl_image *)simg);
1587  }
1588 
1589  /* Reject the bad pixels from the image */
1590 
1591  cpl_image_reject_from_mask(img,cplmasks[i-1]);
1592 
1593  /* When we've done four, destripe them and then write them
1594  out in a temporary file */
1595 
1596  n++;
1597  if (n == 4) {
1598  n = 0;
1599  status = VIR_OK;
1600  vircam_destripe_four(curfits,vircam_sci_config.str_filt,
1601  &status);
1602  for (ii = 0; ii < 4; ii++) {
1603  tmpfits = vircam_fits_duplicate(curfits[ii]);
1604  vircam_fits_set_filename(tmpfits,tmpname);
1605  fconf = vircam_fits_load(ps.master_conf,CPL_TYPE_INT,
1606  i-3+ii);
1607  vircam_sci_wcsfit(&tmpfits,&fconf,NULL,1,1);
1608  vircam_sci_save_simple(tmpfits,framelist,parlist,
1609  1,template,isfirst,tag,
1610  tmpname,&product_frame);
1611  isfirst = 0;
1612  freefits(curfits[ii]);
1613  freefits(tmpfits);
1614  freefits(fconf);
1615  }
1616  }
1617  }
1618 
1619  /* When we've finished writing out the new file. Delete the
1620  old one and replace it with the new one */
1621 
1622  remove(cpl_frame_get_filename(curframe));
1623  cpl_frame_set_filename(product_frame,
1624  cpl_frame_get_filename(curframe));
1625  rename(tmpname,cpl_frame_get_filename(curframe));
1626  }
1627 
1628  /* Clear up some memory */
1629 
1630  for (i = 0; i < VIRCAM_NEXTN; i++)
1631  freefits(sky_extns[i]);
1632  }
1633  for (i = 0; i < VIRCAM_NEXTN; i++) {
1634  cpl_mask_unwrap(cplmasks[i]);
1635  freespace(bpm[i]);
1636  }
1637  freespace(sky_extns);
1638  cpl_msg_indent_less();
1639  return(VIR_OK);
1640 }
1641 
1642 static cpl_frame *vircam_sci_findtemplate(cpl_frame *in) {
1643  int i,j,imatch,jmatch,n;
1644  cpl_frame *frm;
1645 
1646  imatch = -1;
1647  jmatch = -1;
1648  for (i = 0; i < ps.nscipaws; i++) {
1649  n = cpl_frameset_get_size(ps.science_paws[i].current);
1650  for (j = 0; j < n; j++) {
1651  frm = cpl_frameset_get_frame(ps.science_paws[i].current,j);
1652  if (! strcmp(cpl_frame_get_filename(in),
1653  cpl_frame_get_filename(frm))) {
1654  imatch = i;
1655  jmatch = j;
1656  break;
1657  }
1658  }
1659  if (imatch != -1)
1660  break;
1661  }
1662  if (imatch == -1)
1663  return(NULL);
1664  else
1665  return(cpl_frameset_get_frame(ps.science_paws[imatch].orig,jmatch));
1666 }
1667 
1668 static void vircam_sci_wcsfit(vir_fits **in, vir_fits **conf,
1669  vir_tfits **incat, int nf, int level) {
1670  int status,nstd,ncat,slevel,n,i,j;
1671  float *x,*y,*ra,*dec;
1672  double r,d;
1673  vir_tfits *tcat;
1674  cpl_table *stdscat,*newstds,*cat,*tmp,*tmp2,*matchstds;
1675  cpl_propertylist *p;
1676  cpl_wcs *wcs;
1677  const char *fctid = "vircam_sci_wcsfit";
1678 
1679  /* Loop for all the images */
1680 
1681  for (j = 0; j < nf; j++) {
1682 
1683  /* If this is a level one wcsfit, then we generate a temporary
1684  catalogue */
1685 
1686  status = VIR_OK;
1687  if (level == 1)
1688  (void)vircam_imcore(in[j],conf[j],10,1.5,0,3.0,64,3,2.0,&tcat,
1689  &status);
1690  else
1691  tcat = incat[j];
1692 
1693  /* Get some standard stars */
1694 
1695  (void)vircam_getstds(vircam_fits_get_ehu(in[j]),1,
1696  current_catpath,current_cat,&stdscat,&status);
1697  if (status != VIR_OK) {
1698  freetable(stdscat);
1699  cpl_msg_error(fctid,
1700  "Failed to find any standards for %s[%" CPL_SIZE_FORMAT "]",
1701  vircam_fits_get_filename(in[j]),
1702  (cpl_size)vircam_fits_get_nexten(in[j]));
1703  if (level == 1)
1704  freetfits(tcat);
1705  return;
1706  }
1707 
1708  /* Restrict to stars with good photometry */
1709 
1710  (void)cpl_table_or_selected_float(stdscat,"j_msig",CPL_LESS_THAN,0.2);
1711  (void)cpl_table_and_selected_float(stdscat,"k_msig",CPL_LESS_THAN,0.2);
1712  newstds = cpl_table_extract_selected(stdscat);
1713  nstd = (int)cpl_table_get_nrow(newstds);
1714 
1715  /* If there are too many objects in the catalogue then first restrict
1716  ourselves by ellipticity. Cut so that there are similar numbers of
1717  objects in the standards and the object catalogues by retaining the
1718  brighter objects */
1719 
1720  cat = vircam_tfits_get_table(tcat);
1721  ncat = (int)cpl_table_get_nrow(cat);
1722  if (ncat > 500 && ncat > 2.0*nstd) {
1723  tmp = cpl_table_duplicate(cat);
1724  (void)cpl_table_or_selected_float(tmp,"Ellipticity",CPL_LESS_THAN,0.5);
1725  tmp2 = cpl_table_extract_selected(tmp);
1726  ncat = (int)cpl_table_get_nrow(tmp2);
1727  freetable(tmp);
1728  p = cpl_propertylist_new();
1729  cpl_propertylist_append_bool(p,"Isophotal_flux",TRUE);
1730  cpl_table_sort(tmp2,(const cpl_propertylist *)p);
1731  cpl_propertylist_delete(p);
1732  slevel = min(ncat,max(1,min(5000,max(500,2*nstd))));
1733  tmp = cpl_table_extract(tmp2,1,(cpl_size)slevel);
1734  freetable(tmp2);
1735  ncat = (int)cpl_table_get_nrow(tmp);
1736  cat = tmp;
1737  } else {
1738  tmp = NULL;
1739  }
1740 
1741  /* Now match this against the catalogue */
1742 
1743  (void)vircam_matchstds(cat,newstds,300.0,&matchstds,&status);
1744  freetable(stdscat);
1745  freetable(newstds);
1746  freetable(tmp);
1747  if (status != VIR_OK) {
1748  freetable(matchstds);
1749  cpl_msg_error(fctid,"Failed to match standards to catalogue");
1750  if (level == 1)
1751  freetfits(tcat);
1752  return;
1753  }
1754 
1755  /* Fit the plate solution */
1756 
1757  (void)vircam_platesol(vircam_fits_get_ehu(in[j]),
1758  vircam_tfits_get_ehu(tcat),matchstds,6,1,&status);
1759  freetable(matchstds);
1760  if (status != VIR_OK) {
1761  cpl_msg_error(fctid,"Failed to fit WCS");
1762  if (level == 1)
1763  freetfits(tcat);
1764  return;
1765  }
1766 
1767  /* Update the RA and DEC of the objects in the object catalogue */
1768 
1769  if (level == 2) {
1770  cat = vircam_tfits_get_table(tcat);
1771  n = (int)cpl_table_get_nrow(cat);
1772  wcs = cpl_wcs_new_from_propertylist(vircam_fits_get_ehu(in[j]));
1773  if (wcs == NULL) {
1774  cpl_msg_error(fctid,"Failed to fill RA and Dec in catalogue");
1775  return;
1776  }
1777  x = cpl_table_get_data_float(cat,"X_coordinate");
1778  y = cpl_table_get_data_float(cat,"Y_coordinate");
1779  ra = cpl_table_get_data_float(cat,"RA");
1780  dec = cpl_table_get_data_float(cat,"DEC");
1781  for (i = 0; i < n; i++) {
1782  vircam_xytoradec(wcs,x[i],y[i],&r,&d);
1783  ra[i] = (float)r;
1784  dec[i] = (float)d;
1785  }
1786  cpl_wcs_delete(wcs);
1787  } else {
1788  freetfits(tcat);
1789  }
1790  }
1791 }
1792 
1793 static int vircam_destripe_four(vir_fits **curfits, int stripefilt,
1794  int *status) {
1795  int i,nx,ny,n,k,m,ipstart,ipfin,ip;
1796  float *profiles[4],*meanprof,buf[4],*data,val,mad,rms;
1797  unsigned char *bpms[4],*bp;
1798  cpl_propertylist *plist;
1799 
1800  /* Inherited status */
1801 
1802  if (*status != VIR_OK)
1803  return(*status);
1804 
1805  /* Get the data size of a representative image and get some memory for the
1806  mean profile and its bad pixel mask */
1807 
1808  nx = cpl_image_get_size_x(vircam_fits_get_image(curfits[0]));
1809  ny = cpl_image_get_size_y(vircam_fits_get_image(curfits[0]));
1810  meanprof = cpl_malloc(ny*sizeof(float));
1811  bp = cpl_calloc(ny,sizeof(unsigned char));
1812 
1813  /* Loop for the four images and work out the stripe profile for each
1814  one. Trap for missing images */
1815 
1816  n = 0;
1817  for (i = 0; i < 4; i++) {
1818  if (vircam_fits_get_status(curfits[i]) == VIR_FATAL)
1819  continue;
1820  profiles[n] = cpl_malloc(ny*sizeof(float));
1821  bpms[n] = cpl_calloc(ny,sizeof(unsigned char));
1822  stripe_profile(curfits[i],stripefilt,profiles[n],bpms[n]);
1823  n++;
1824  }
1825 
1826  /* Now median the profiles. If there weren't any contributions
1827  this is presumably because all the detectors were missing
1828  so, don't bother doing the destripe. While doing the medianing,
1829  subtract the average profile from the row in each of the contributing
1830  images */
1831 
1832  if (n > 0) {
1833  for (k = 0; k < ny; k++) {
1834  m = 0;
1835  for (i = 0; i < n; i++) {
1836  if (bpms[i][k])
1837  continue;
1838  buf[m++] = profiles[i][k];
1839  }
1840  if (m != 0) {
1841  meanprof[k] = vircam_med(buf,NULL,(long)m);
1842  bp[k] = 0;
1843  } else {
1844  meanprof[k] = 0.0;
1845  bp[k] = 1;
1846  }
1847  ipstart = k*nx;
1848  ipfin = ipstart + nx;
1849  for (i = 0; i < 4; i++) {
1850  if (vircam_fits_get_status(curfits[i]) == VIR_FATAL)
1851  continue;
1852  data = cpl_image_get_data(vircam_fits_get_image(curfits[i]));
1853  for (ip = ipstart; ip < ipfin; ip++)
1854  data[ip] -= meanprof[k];
1855  }
1856  }
1857  vircam_medmad(meanprof,bp,ny,&val,&mad);
1858  rms = 1.48*mad;
1859 
1860  /* Tidy up some memory */
1861 
1862  for (i = 0; i < n; i++) {
1863  freespace(profiles[i]);
1864  freespace(bpms[i]);
1865  }
1866 
1867  } else {
1868  rms = 0.0;
1869  }
1870 
1871  /* Put some stuff in the header */
1872 
1873  for (i = 0; i < 4; i++) {
1874  if (vircam_fits_get_status(curfits[i]) == VIR_FATAL) {
1875  k = FALSE;
1876  val = 0.0;
1877  } else {
1878  k = TRUE;
1879  val = rms;
1880  }
1881  plist = vircam_fits_get_ehu(curfits[i]);
1882  cpl_propertylist_update_bool(plist,"ESO DRS STRIPECOR",k);
1883  cpl_propertylist_set_comment(plist,"ESO DRS STRIPECOR",
1884  "Stripe correction done");
1885  cpl_propertylist_update_float(plist,"ESO DRS STRIPERMS",val);
1886  cpl_propertylist_set_comment(plist,"ESO DRS STRIPERMS",
1887  "RMS of removed stripe profile");
1888  }
1889 
1890  /* Tidy up a little more */
1891 
1892  freespace(meanprof);
1893  freespace(bp);
1894 
1895  /* Get out of here */
1896 
1897  GOOD_STATUS
1898 }
1899 
1900 static void stripe_profile(vir_fits *in, int stripefilt, float *profile,
1901  unsigned char *pbpm) {
1902  float *data,*copy,*d,lcut,hcut,skymed,skynoise,rmsold,rms,val;
1903  unsigned char *bpm,*ob,*b;
1904  cpl_image *img;
1905  long nx,ny,npts;
1906  int i,j;
1907 
1908  /* Get the input data array and its bad pixel mask */
1909 
1910  img = vircam_fits_get_image(in);
1911  nx = cpl_image_get_size_x(img);
1912  ny = cpl_image_get_size_y(img);
1913  data = cpl_image_get_data(img);
1914  bpm = (unsigned char *)cpl_mask_get_data(cpl_image_get_bpm(img));
1915 
1916  /* First get an estimate of the background median and sigma */
1917 
1918  npts = nx*ny;
1919  vircam_qmedsig(data,bpm,npts,3.0,3,-65535.0,65535.0,&skymed,&skynoise);
1920 
1921  /* Get some workspace for the profile calculation */
1922 
1923  ob = cpl_calloc(ny,sizeof(unsigned char));
1924  copy = cpl_malloc(ny*sizeof(float));
1925 
1926  /* Loop for each row */
1927 
1928  d = data;
1929  b = bpm;
1930  for (i = 0; i < ny; i++) {
1931 
1932  /* Get the median of that row, ignoring any bad pixels. Iterate
1933  to clip out any objects or funny pixels */
1934 
1935  lcut = -1.0e-10;
1936  hcut = 1.0e10;
1937  rmsold = 1.0e10;
1938  for (j = 0; j < 3; j++) {
1939  vircam_medmadcut(d,b,nx,lcut,hcut,&val,&rms);
1940  if (val == CX_MAXFLOAT) {
1941  break;
1942  } else if (rms == rmsold) {
1943  break;
1944  } else {
1945  lcut = val - 3.0*skynoise;
1946  hcut = val + 3.0*skynoise;
1947  rmsold = rms;
1948  }
1949  }
1950  pbpm[i] = (val == CX_MAXFLOAT);
1951  profile[i] = (pbpm[i] ? 0.0 : val);
1952  copy[i] = profile[i];
1953  d += nx;
1954  b += nx;
1955  }
1956 
1957  /* Take out large scale variation if need be */
1958 
1959  vircam_medmad(profile,pbpm,ny,&val,&rms);
1960  rms *= 1.48;
1961  if (stripefilt && rms > 15.0) {
1962  vircam_dostat(copy,pbpm,ob,ny,25,MEDIANCALC);
1963  vircam_dostat(copy,pbpm,ob,ny,5,MEANCALC);
1964  for (i = 0; i < ny; i++) {
1965  if (! pbpm[i])
1966  profile[i] -= copy[i];
1967  else
1968  profile[i] = 0.0;
1969  }
1970  } else {
1971  for (i = 0; i < ny; i++)
1972  profile[i] -= val;
1973  }
1974 
1975  /* Tidy up and get out of here */
1976 
1977  freespace(ob);
1978  freespace(copy);
1979 }
1980 
1981 
1982 static void vircam_sci_paws_delete(int npaws, pawprint **paws) {
1983  int i;
1984 
1985  for (i = 0; i < npaws; i++)
1986  vircam_sci_paw_delete(*paws+i);
1987  freespace(*paws);
1988 }
1989 
1990 static void vircam_sci_paw_delete(pawprint *paw) {
1991  int n,i;
1992 
1993  if (paw->current == NULL)
1994  return;
1995  n = cpl_frameset_get_size(paw->current);
1996  freespace(paw->whichsky);
1997  freeframeset(paw->orig);
1998  freeframeset(paw->current);
1999  for (i = 0; i < VIRCAM_NEXTN; i++) {
2000  freefits(paw->stack[i]);
2001  freefits(paw->stackc[i]);
2002  freetfits(paw->cat[i]);
2003  freetable(paw->mstds[i]);
2004  }
2005 }
2006 
2007 static void vircam_sci_paws_create(cpl_frameset *infrms, int *npaws,
2008  pawprint **paws) {
2009  cpl_size nlab,*labels,*labels2,nlab2;
2010  cpl_frameset *copy,*testme,*tf;
2011  int i,j,nalloc,pj;
2012 
2013  /* NULL input...*/
2014 
2015  *paws = NULL;
2016  *npaws = 0;
2017  if (infrms == NULL)
2018  return;
2019 
2020  /* Create the grouping */
2021 
2022  copy = cpl_frameset_duplicate(infrms);
2023  labels = cpl_frameset_labelise(copy,vircam_sci_cmp_tstart,&nlab);
2024 
2025  /* Get memory for the pawprint groups. We will trim this down or
2026  expand it as necessary */
2027 
2028  *npaws = 0;
2029  nalloc = 8;
2030  *paws = cpl_malloc(nalloc*sizeof(pawprint));
2031 
2032  /* Now extract the groups */
2033 
2034  for (i = 0; i < nlab; i++) {
2035 
2036  /* First see if this is a tile. If it is, then break the tile up
2037  into its constituent pawprints */
2038 
2039  testme = cpl_frameset_extract(copy,labels,(cpl_size)i);
2040  if (vircam_sci_istile(cpl_frameset_get_frame(testme,0))) {
2041  pj = vircam_sci_ispj(testme);
2042  labels2 = cpl_frameset_labelise(testme,vircam_sci_cmp_jit,&nlab2);
2043  for (j = 0; j < nlab2; j++) {
2044  if (*npaws+1 > nalloc) {
2045  nalloc += 8;
2046  *paws = cpl_realloc(*paws,nalloc*sizeof(pawprint));
2047  }
2048  tf = cpl_frameset_extract(testme,labels2,(cpl_size)j);
2049  vircam_sci_paw_init(*paws+*npaws,tf,pj);
2050  freeframeset(tf);
2051  *npaws += 1;
2052  }
2053  freespace(labels2);
2054  } else {
2055  vircam_sci_paw_init(*paws+*npaws,testme,0);
2056  *npaws += 1;
2057  }
2058  freeframeset(testme);
2059  }
2060 
2061  /* Trim down allocation */
2062 
2063  *paws = cpl_realloc(*paws,*npaws*sizeof(pawprint));
2064 
2065  /* Tidy and exit */
2066 
2067  cpl_frameset_delete(copy);
2068  freespace(labels);
2069 }
2070 
2071 static int vircam_sci_istile(cpl_frame *frm) {
2072  cpl_propertylist *plist;
2073  int hasoffs,noffsets;
2074 
2075  /* If the frame has a keyword OFFSTNUM and NOFFSETS != 1 then this
2076  is part of a tile */
2077 
2078  plist = cpl_propertylist_load(cpl_frame_get_filename(frm),0);
2079  hasoffs = cpl_propertylist_has(plist,"OFFSTNUM");
2080  if (hasoffs)
2081  noffsets = cpl_propertylist_get_int(plist,"NOFFSETS");
2082  else
2083  noffsets = -1;
2084  cpl_propertylist_delete(plist);
2085  return(hasoffs && noffsets != 1);
2086 }
2087 
2088 static void vircam_sci_paw_init(pawprint *paw, cpl_frameset *frms, int ispj) {
2089  cpl_propertylist *plist;
2090  cpl_frame *fr;
2091  float exptime;
2092  int i,n;
2093 
2094  /* Initialise everything. Start with all the frames and framesets */
2095 
2096  paw->orig = cpl_frameset_duplicate(frms);
2097  paw->current = vircam_sci_update_frameset(paw->orig);
2098  n = cpl_frameset_get_size(frms);
2099  paw->whichsky = cpl_malloc(n*sizeof(int));
2100  for (i = 0; i < n; i++)
2101  paw->whichsky[i] = -1;
2102  paw->ispj = ispj;
2103  for (i = 0; i < VIRCAM_NEXTN; i++) {
2104  paw->stack[i] = NULL;
2105  paw->stackc[i] = NULL;
2106  paw->cat[i] = NULL;
2107  paw->mstds[i] = NULL;
2108  }
2109  paw->product_frame_im = NULL;
2110  paw->product_frame_conf = NULL;
2111  paw->product_frame_cat = NULL;
2112 
2113  /* Now get some useful information about the pawprint from the headers.
2114  Start with the jitter and tile numbers */
2115 
2116  fr = cpl_frameset_get_frame(frms,0);
2117  plist = cpl_propertylist_load(cpl_frame_get_filename(fr),0);
2118  (void)vircam_pfits_get_jitternum(plist,&(paw->jitternum));
2119  if (vircam_pfits_get_offsetnum(plist,&(paw->tilenum)) != VIR_OK)
2120  paw->tilenum = -1;
2121 
2122  /* Now the project ID */
2123 
2124  (void)vircam_pfits_get_projid(plist,paw->projname);
2125 
2126  /* The MJD of the start of the jitter and of the end */
2127 
2128  (void)vircam_pfits_get_mjd(plist,&(paw->mjd_start));
2129  cpl_propertylist_delete(plist);
2130  n = (int)cpl_frameset_get_size(frms);
2131  fr = cpl_frameset_get_frame(frms,n-1);
2132  plist = cpl_propertylist_load(cpl_frame_get_filename(fr),0);
2133  (void)vircam_pfits_get_mjd(plist,&(paw->mjd_end));
2134  (void)vircam_pfits_get_exptime(plist,&exptime);
2135  paw->mjd_end += exptime/(24.0*3600.0);
2136 
2137  /* Tidy and exit */
2138 
2139  cpl_propertylist_delete(plist);
2140 }
2141 
2142 static int vircam_sci_makesky(cpl_frameset *framelist,
2143  cpl_parameterlist *parlist, skystruct *sky,
2144  const char *tag) {
2145  int retval;
2146 
2147  /* Switch for the various options to sky creation. Options SKYNONE,
2148  SKYMASTER and TILESKY_MINUS we don't do anything at this point. */
2149 
2150  retval = VIR_OK;
2151  switch (sky->skyalgo) {
2152  case SKYNONE:
2153  break;
2154  case SKYMASTER:
2155  break;
2156  case PAWSKY_MINUS:
2157  retval = vircam_sci_pawsky_minus(framelist,parlist,sky->contrib,
2158  sky->template,tag,sky->fname,
2159  &(sky->skyframe));
2160  break;
2161  case TILESKY_MINUS:
2162  retval = vircam_sci_tilesky_minus(framelist,parlist,sky->contrib,
2163  sky->template,tag,sky->fname,
2164  &(sky->skyframe));
2165  break;
2166  case PAWSKY_MASK:
2167  retval = vircam_sci_pawsky_mask(framelist,parlist,sky->skyalgo,
2168  sky->contrib,sky->template,
2169  sky->fname,&(sky->skyframe));
2170  break;
2171  case PAWSKY_MASK_PRE:
2172  retval = vircam_sci_pawsky_mask(framelist,parlist,sky->skyalgo,
2173  sky->contrib,sky->template,
2174  sky->fname,&(sky->skyframe));
2175  break;
2176  case TILESKY:
2177  retval = vircam_sci_tilesky(framelist,parlist,sky->contrib,
2178  sky->template,sky->fname,&(sky->skyframe));
2179  break;
2180  }
2181  return(retval);
2182 }
2183 
2184 static int vircam_sci_tilesky_minus(cpl_frameset *framelist,
2185  cpl_parameterlist *parlist,
2186  cpl_frameset *in, cpl_frame *template,
2187  const char *tag, char *skyname,
2188  cpl_frame **skyframe) {
2189  int n,i,status,isfirst,j;
2190  vir_fits *objmaskfits,**infits,*inconf,*tmpfits,*skyout;
2191  cpl_frame **product_frames,*curframe;
2192  char tmpname[BUFSIZ];
2193  const char *fctid = "vircam_sci_tilesky_minus";
2194 
2195  n = cpl_frameset_get_size(in);
2196  objmaskfits = vircam_fits_load(ps.master_objmask,CPL_TYPE_INT,0);
2197  product_frames = cpl_malloc(n*sizeof(cpl_frame *));
2198  cpl_msg_info(fctid,"Creating sky %s",skyname);
2199  cpl_msg_indent_more();
2200  for (i = 1; i <= VIRCAM_NEXTN; i++) {
2201  cpl_msg_info(fctid,"Beginning on extn %" CPL_SIZE_FORMAT "",
2202  (cpl_size)i);
2203  infits = vircam_fits_load_list(in,CPL_TYPE_FLOAT,i);
2204  inconf = vircam_fits_load(ps.master_conf,CPL_TYPE_INT,i);
2205  status = VIR_OK;
2206  if (vircam_tilesky_minus(infits,inconf,objmaskfits,n,1,&skyout,
2207  &status) != VIR_OK) {
2208  freefitslist(infits,n);
2209  freefits(inconf);
2210  freespace(product_frames);
2211  return(VIR_FATAL);
2212  }
2213  isfirst = (i == 1);
2214  for (j = 0; j < n; j++) {
2215  tmpfits = vircam_fits_duplicate(infits[j]);
2216  (void)snprintf(tmpname,BUFSIZ,"tmp_%s",
2217  vircam_fits_get_filename(infits[j]));
2218  vircam_fits_set_filename(tmpfits,tmpname);
2219  curframe = cpl_frameset_get_frame(in,j);
2220  template = vircam_sci_findtemplate(curframe);
2221  vircam_sci_save_simple(tmpfits,framelist,parlist,0,template,
2222  isfirst,tag,tmpname,(product_frames+j));
2223  freefits(tmpfits);
2224  }
2225  vircam_sci_save_sky(skyout,framelist,parlist,skyname,template,
2226  isfirst,skyframe);
2227  freefitslist(infits,n);
2228  freefits(inconf);
2229  freefits(skyout);
2230  }
2231  cpl_msg_indent_less();
2232  for (i = 0; i < n; i++) {
2233  curframe = cpl_frameset_get_frame(in,i);
2234  template = product_frames[i];
2235  remove(cpl_frame_get_filename(curframe));
2236  rename(cpl_frame_get_filename(template),
2237  cpl_frame_get_filename(curframe));
2238  freeframe(product_frames[i]);
2239  }
2240  freespace(product_frames);
2241  freefits(objmaskfits);
2242  return(VIR_OK);
2243 }
2244 
2245 
2246 static int vircam_sci_pawsky_minus(cpl_frameset *framelist,
2247  cpl_parameterlist *parlist,
2248  cpl_frameset *in, cpl_frame *template,
2249  const char *tag, char *skyname,
2250  cpl_frame **skyframe) {
2251  int n,i,status,isfirst,j,k;
2252  vir_fits *objmaskfits,**infits,*inconf,*tmpfits,*skyout;
2253  cpl_frame **product_frames,*curframe;
2254  char tmpname[BUFSIZ];
2255  const char *fctid = "vircam_sci_pawsky_minus";
2256 
2257  n = cpl_frameset_get_size(in);
2258  if (ps.master_objmask != NULL)
2259  objmaskfits = vircam_fits_load(ps.master_objmask,CPL_TYPE_INT,0);
2260  else
2261  objmaskfits = NULL;
2262  product_frames = cpl_malloc(n*sizeof(cpl_frame *));
2263  cpl_msg_info(fctid,"Creating sky %s",skyname);
2264  cpl_msg_indent_more();
2265  for (i = 1; i <= VIRCAM_NEXTN; i++) {
2266  cpl_msg_info(fctid,"Beginning on extn %" CPL_SIZE_FORMAT "",
2267  (cpl_size)i);
2268  infits = vircam_fits_load_list(in,CPL_TYPE_FLOAT,i);
2269  inconf = vircam_fits_load(ps.master_conf,CPL_TYPE_INT,i);
2270  status = VIR_OK;
2271  if (ps.master_objmask != NULL) {
2272  for (k = 0; k < n; k++)
2273  vircam_sci_wcsfit(infits+k,&inconf,NULL,1,1);
2274  }
2275  if (vircam_pawsky_minus(infits,inconf,objmaskfits,n,1,&skyout,
2276  &status) != VIR_OK) {
2277  freefitslist(infits,n);
2278  freefits(inconf);
2279  freespace(product_frames);
2280  return(VIR_FATAL);
2281  }
2282  isfirst = (i == 1);
2283  for (j = 0; j < n; j++) {
2284  tmpfits = vircam_fits_duplicate(infits[j]);
2285  (void)snprintf(tmpname,BUFSIZ,"tmp_%s",
2286  vircam_fits_get_filename(infits[j]));
2287  vircam_fits_set_filename(tmpfits,tmpname);
2288  curframe = cpl_frameset_get_frame(in,j);
2289  template = vircam_sci_findtemplate(curframe);
2290  vircam_sci_save_simple(tmpfits,framelist,parlist,0,template,
2291  isfirst,tag,tmpname,(product_frames+j));
2292  freefits(tmpfits);
2293  }
2294  vircam_sci_save_sky(skyout,framelist,parlist,skyname,template,
2295  isfirst,skyframe);
2296  freefitslist(infits,n);
2297  freefits(inconf);
2298  freefits(skyout);
2299  }
2300  cpl_msg_indent_less();
2301  for (i = 0; i < n; i++) {
2302  curframe = cpl_frameset_get_frame(in,i);
2303  template = product_frames[i];
2304  remove(cpl_frame_get_filename(curframe));
2305  rename(cpl_frame_get_filename(template),
2306  cpl_frame_get_filename(curframe));
2307  freeframe(product_frames[i]);
2308  }
2309  freespace(product_frames);
2310  freefits(objmaskfits);
2311  return(VIR_OK);
2312 }
2313 
2314 static void vircam_sci_choose_skyalgo(int *nskys, skystruct **skys) {
2315  float halfhour;
2316  skystruct newsky;
2317  int nalloc,i,n,n2,jst,jfn,j,j_1,j_2;
2318  float dt;
2319  cpl_frameset **in,*newfrmset;
2320  cpl_frame *frm,*template;
2321 
2322  /* Initialise a few things */
2323 
2324  halfhour = 1.0/48.0;
2325 
2326  /* In most cases we're only going to create one sky here, but there
2327  is the possibility of more */
2328 
2329  *nskys = 0;
2330  nalloc = 1;
2331  *skys = cpl_malloc(nalloc*sizeof(skystruct));
2332 
2333  /* Ok start with the easy situation. If there are offset skies, then
2334  choose just straightforward pawsky_mask or tilesky depending upon
2335  how the offset skies were observed */
2336 
2337  if (ps.noffpaws > 0) {
2338  if (vircam_sci_istile(cpl_frameset_get_frame(ps.offsky_paws[0].orig,0))) {
2339 
2340  /* Merge all the current framesets into one */
2341 
2342  in = cpl_malloc(ps.noffpaws*sizeof(cpl_frameset *));
2343  for (i = 0; i < ps.noffpaws; i++)
2344  in[i] = ps.offsky_paws[i].current;
2345  newfrmset = vircam_sci_merge_framesets(ps.noffpaws,in);
2346  freespace(in);
2347 
2348  /* Create a sky structure */
2349 
2350  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.offsky_paws[0].orig,0));
2351  newsky = vircam_sci_crsky(TILESKY,newfrmset,template,1);
2352  *nskys = 1;
2353  (*skys)[*nskys-1] = newsky;
2354 
2355  /* Assign this one sky to all of the offset and science pawprint
2356  images */
2357 
2358  for (i = 0; i < ps.noffpaws; i++)
2359  vircam_sci_assign_sky_all(ps.offsky_paws[i],*nskys-1);
2360  for (i = 0; i < ps.nscipaws; i++)
2361  vircam_sci_assign_sky_all(ps.science_paws[i],*nskys-1);
2362  } else {
2363  newfrmset = cpl_frameset_duplicate(ps.offsky_paws[0].current);
2364  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.offsky_paws[0].orig,0));
2365  newsky = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,*nskys+1);
2366  *nskys += 1;
2367  (*skys)[*nskys-1] = newsky;
2368  vircam_sci_assign_sky_all(ps.offsky_paws[0],*nskys-1);
2369  vircam_sci_assign_sky_all(ps.science_paws[0],*nskys-1);
2370  }
2371 
2372  /* OK there aren't any offset skies. There are lots more choices now.
2373  So first we look to see if this is just a pawprint. */
2374 
2375  } else {
2376 
2377  /* If it's a pawprint, then look to see if it took less than half
2378  an hour to observe. If it did then split it into two, so long
2379  as there are enough images in each half to form a sky
2380  (nominally 8) */
2381 
2382  if (ps.science_paws[0].tilenum == -1) {
2383  dt = ps.science_paws[0].mjd_end - ps.science_paws[0].mjd_start;
2384  n = cpl_frameset_get_size(ps.science_paws[0].current);
2385 
2386  /* Situation where we have a pawprint lasting less than half an
2387  hour, or we have one that isn't big enough to split */
2388 
2389  if (dt < halfhour || n < 16) {
2390  newfrmset = cpl_frameset_duplicate(ps.science_paws[0].current);
2391  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[0].orig,0));
2392  newsky = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,
2393  *nskys+1);
2394  *nskys = 1;
2395  (*skys)[*nskys-1] = newsky;
2396  vircam_sci_assign_sky_all(ps.science_paws[0],*nskys-1);
2397 
2398  /* Pawprint took longer than half an hour and there are enough
2399  exposures so that we can split into two */
2400 
2401  } else {
2402  n2 = n/2;
2403  for (i = 0; i < 2; i++) {
2404  if (i == 0) {
2405  jst = 0;
2406  jfn = n2;
2407  } else {
2408  jst = n2;
2409  jfn = n;
2410  }
2411  newfrmset = cpl_frameset_new();
2412  for (j = jst; j < jfn; j++) {
2413  frm = cpl_frameset_get_frame(ps.science_paws[0].current,j);
2414  cpl_frameset_insert(newfrmset,frm);
2415  }
2416  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[0].orig,jst));
2417  newsky = vircam_sci_crsky(PAWSKY_MASK,newfrmset,template,
2418  *nskys+1);
2419  *nskys += 1;
2420  if (*nskys > nalloc) {
2421  nalloc += 1;
2422  *skys = cpl_realloc(*skys,nalloc*sizeof(skystruct));
2423  }
2424  (*skys)[*nskys-1] = newsky;
2425  for (j = jst; j < jfn; j++)
2426  ps.science_paws[0].whichsky[j] = *nskys-1;
2427  }
2428  }
2429 
2430  /* Ok this is a tile. There are a couple of options now. If it's a VIDEO tile,
2431  then default to TILESKY_MINUS, but with a split */
2432 
2433  } else {
2434  n = ps.nscipaws;
2435  dt = ps.science_paws[n-1].mjd_end - ps.science_paws[0].mjd_start;
2436  if (! strncmp(ps.science_paws[0].projname,VIDEOPROJ,10)) {
2437  n2 = ps.nscipaws/2;
2438  for (j = 0; j < 2; j++) {
2439  if (j == 0) {
2440  j_1 = 0;
2441  j_2 = n2;
2442  } else {
2443  j_1 = n2;
2444  j_2 = ps.nscipaws;
2445  }
2446  in = cpl_malloc((j_2-j_1)*sizeof(cpl_frameset *));
2447  for (i = j_1; i < j_2; i++)
2448  in[i-j_1] = ps.science_paws[i].current;
2449  newfrmset = vircam_sci_merge_framesets((j_2-j_1),in);
2450  freespace(in);
2451  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[j_1].orig,0));
2452  newsky = vircam_sci_crsky(TILESKY_MINUS,newfrmset,template,
2453  *nskys+1);
2454  *nskys += 1;
2455  if (*nskys > nalloc) {
2456  nalloc += 1;
2457  *skys = cpl_realloc(*skys,nalloc*sizeof(skystruct));
2458  }
2459  (*skys)[*nskys-1] = newsky;
2460  for (i = j_1; i < j_2; i++)
2461  vircam_sci_assign_sky_all(ps.science_paws[i],*nskys-1);
2462  }
2463 
2464  /* Look at the time difference. If the timing is less than half an
2465  hour or if this is a VMC tile, then just do a straight-forward
2466  tilesky. */
2467 
2468  } else if (dt < halfhour ||
2469  ! strncmp(ps.science_paws[0].projname,VMCPROJ,10)) {
2470  in = cpl_malloc(ps.nscipaws*sizeof(cpl_frameset *));
2471  for (i = 0; i < ps.nscipaws; i++)
2472  in[i] = ps.science_paws[i].current;
2473  newfrmset = vircam_sci_merge_framesets(ps.nscipaws,in);
2474  freespace(in);
2475 
2476  /* Create a sky structure */
2477 
2478  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[0].orig,0));
2479  newsky = vircam_sci_crsky(TILESKY,newfrmset,template,1);
2480  *nskys = 1;
2481  (*skys)[*nskys-1] = newsky;
2482 
2483  /* Assign this one sky to all of the science pawprint images */
2484 
2485  for (i = 0; i < ps.nscipaws; i++)
2486  vircam_sci_assign_sky_all(ps.science_paws[i],*nskys-1);
2487 
2488  /* OK, we have a tile that's not VMC and not VIDEO that lasts for
2489  more than half an hour. If it's the normal PJ ordering, then just
2490  do a split TILESKY */
2491 
2492  } else {
2493  if (ps.science_paws[0].ispj) {
2494  n2 = ps.nscipaws/2;
2495  for (j = 0; j < 2; j++) {
2496  if (j == 0) {
2497  j_1 = 0;
2498  j_2 = n2;
2499  } else {
2500  j_1 = n2;
2501  j_2 = ps.nscipaws;
2502  }
2503  in = cpl_malloc((j_2-j_1)*sizeof(cpl_frameset *));
2504  for (i = j_1; i < j_2; i++)
2505  in[i-j_1] = ps.science_paws[i].current;
2506  newfrmset = vircam_sci_merge_framesets((j_2-j_1),in);
2507  freespace(in);
2508  template = cpl_frame_duplicate(cpl_frameset_get_frame(ps.science_paws[j_1].orig,0));
2509  newsky = vircam_sci_crsky(TILESKY,newfrmset,template,
2510  *nskys+1);
2511  *nskys += 1;
2512  if (*nskys > nalloc) {
2513  nalloc += 1;
2514  *skys = cpl_realloc(*skys,nalloc*sizeof(skystruct));
2515  }
2516  (*skys)[*nskys-1] = newsky;
2517  for (i = j_1; i < j_2; i++)
2518  vircam_sci_assign_sky_all(ps.science_paws[i],
2519  *nskys-1);
2520  }
2521  } else {
2522  /******************* bit for jp */
2523  }
2524  } /* end of different type of tiles */
2525  } /* end of tiles */
2526 
2527  } /* end of offset sky if */
2528 }
2529 
2530 static int vircam_sci_ispj(cpl_frameset *frms) {
2531  int n,offnum,i,offnum1,offnum2;
2532  cpl_propertylist *plist,*tmp;
2533  char dateobs[32];
2534  cpl_frame *frm;
2535 
2536  /* Create a propertylist to be a hash array */
2537 
2538  plist = cpl_propertylist_new();
2539 
2540  /* Loop through the frameset. Name each property by the dateobs of
2541  the frame. Then give the value of the property the offset number */
2542 
2543  n = cpl_frameset_get_size(frms);
2544  for (i = 0; i < n; i++) {
2545  frm = cpl_frameset_get_frame(frms,i);
2546  tmp = cpl_propertylist_load(cpl_frame_get_filename(frm),0);
2547  strcpy(dateobs,cpl_propertylist_get_string(tmp,"DATE-OBS"));
2548  offnum = cpl_propertylist_get_int(tmp,"OFFSET_I");
2549  cpl_propertylist_append_int(plist,dateobs,offnum);
2550  cpl_propertylist_delete(tmp);
2551  }
2552 
2553  /* Sort the propertylist by the property name (dateobs). This should
2554  give a chronological ordering */
2555 
2556  cpl_propertylist_sort(plist,vircam_sci_cmp_property);
2557 
2558  /* Look at the first two now and see if they have the same value
2559  of the offset number. If they do, then this is in PJ order */
2560 
2561  offnum1 = cpl_property_get_int(cpl_propertylist_get(plist,0));
2562  offnum2 = cpl_property_get_int(cpl_propertylist_get(plist,1));
2563  cpl_propertylist_delete(plist);
2564  return(offnum1 == offnum2);
2565 }
2566 
2567 static int vircam_sci_cmp_property(const cpl_property *p1,
2568  const cpl_property *p2) {
2569  return(strcmp(cpl_property_get_name(p1),cpl_property_get_name(p2)));
2570 }
2571 
2572 static void vircam_sci_assign_sky_all(pawprint paw, int whichone) {
2573  int i,n;
2574 
2575  n = cpl_frameset_get_size(paw.current);
2576  for (i = 0; i < n; i++)
2577  paw.whichsky[i] = whichone;
2578 }
2579 
2580 static skystruct vircam_sci_crsky(int algorithm, cpl_frameset *frms,
2581  cpl_frame *template, int snum) {
2582  skystruct s;
2583 
2584  s.contrib = frms;
2585  if (ps.master_objmask != NULL)
2586  s.objmask = cpl_frame_duplicate(ps.master_objmask);
2587  else
2588  s.objmask = NULL;
2589  s.skyalgo = algorithm;
2590  s.skyframe = NULL;
2591  s.template = template;
2592  vircam_sci_product_name((char *)cpl_frame_get_filename(cpl_frameset_get_frame(frms,0)),
2593  SKY_FILE,vircam_sci_config.prettynames,snum,
2594  s.fname);
2595  return(s);
2596 }
2597 
2598 static cpl_frameset *vircam_sci_merge_framesets(int n, cpl_frameset **in) {
2599  int i,j,nf;
2600  cpl_frame *frm;
2601  cpl_frameset *new;
2602 
2603  /* Get a new frameset */
2604 
2605  new = cpl_frameset_new();
2606 
2607  /* Loop for each input frameset. Insert each frame into the new one */
2608 
2609  for (i = 0; i < n; i++) {
2610  nf = cpl_frameset_get_size(in[i]);
2611  for (j = 0; j < nf; j++) {
2612  frm = cpl_frame_duplicate(cpl_frameset_get_frame(in[i],j));
2613  cpl_frameset_insert(new,frm);
2614  }
2615  }
2616  return(new);
2617 }
2618 
2619 static int vircam_sci_tilesky(cpl_frameset *framelist,
2620  cpl_parameterlist *parlist, cpl_frameset *in,
2621  cpl_frame *template, char *fname,
2622  cpl_frame **product_frame) {
2623  int j,nfiles,isfirst,status;
2624  const char *fctid="vircam_sci_tilesky";
2625  vir_fits **infits,*skyout;
2626 
2627  /* Initialise product frame */
2628 
2629  *product_frame = NULL;
2630 
2631  /* Loop for each extension */
2632 
2633  nfiles = cpl_frameset_get_size(in);
2634  cpl_msg_info(fctid,"Creating sky %s",fname);
2635  cpl_msg_indent_more();
2636  for (j = 1; j <= VIRCAM_NEXTN; j++) {
2637  cpl_msg_info(fctid,"Extension [%" CPL_SIZE_FORMAT "]",(cpl_size)j);
2638  isfirst = (j == 1);
2639 
2640  /* Load up input images for this extension and associated bad
2641  pixel mask... */
2642 
2643  infits = vircam_fits_load_list(in,CPL_TYPE_FLOAT,j);
2644  vircam_mask_load(ps.mask,j,
2645  (int)cpl_image_get_size_x(vircam_fits_get_image(infits[0])),
2646  (int)cpl_image_get_size_y(vircam_fits_get_image(infits[0])));
2647  /* Form the sky for this extension */
2648 
2649  status = VIR_OK;
2650  skyout = NULL;
2651  (void)vircam_tilesky(infits,nfiles,ps.mask,&skyout,&status);
2652 
2653  /* Save the sky frame */
2654 
2655  if (vircam_sci_save_sky(skyout,framelist,parlist,fname,template,
2656  isfirst,product_frame) != VIR_OK) {
2657  freefitslist(infits,nfiles);
2658  freefits(skyout);
2659  return(VIR_FATAL);
2660  }
2661 
2662  /* Tidy up and move on to the next one */
2663 
2664  freefitslist(infits,nfiles);
2665  freefits(skyout);
2666  }
2667  cpl_msg_indent_less();
2668  return(VIR_OK);
2669 }
2670 
2671 static int vircam_sci_pawsky_mask(cpl_frameset *framelist,
2672  cpl_parameterlist *parlist, int algo,
2673  cpl_frameset *contrib, cpl_frame *template,
2674  char *fname, cpl_frame **product_frame) {
2675  int j,nfiles,status,isfirst;
2676  const char *fctid="vircam_sci_pawsky_mask";
2677  vir_fits **infits,*conf,*skyout,*opmfits;
2678 
2679  /* Output product frame */
2680 
2681  *product_frame = NULL;
2682 
2683  /* Loop for each extension */
2684 
2685  nfiles = cpl_frameset_get_size(contrib);
2686  cpl_msg_info(fctid,"Creating sky %s",fname);
2687  cpl_msg_indent_more();
2688  for (j = 1; j <= VIRCAM_NEXTN; j++) {
2689  cpl_msg_info(fctid,"Extension [%" CPL_SIZE_FORMAT "]",(cpl_size)j);
2690  isfirst = (j == 1);
2691 
2692  /* Load up input images for this extension + confidence map
2693  and associated bad pixel mask... */
2694 
2695  infits = vircam_fits_load_list(contrib,CPL_TYPE_FLOAT,j);
2696  conf = vircam_fits_load(ps.master_conf,CPL_TYPE_INT,j);
2697  vircam_mask_load(ps.mask,j,
2698  (int)cpl_image_get_size_x(vircam_fits_get_image(conf)),
2699  (int)cpl_image_get_size_y(vircam_fits_get_image(conf)));
2700 
2701  /* Form the sky for this extension */
2702 
2703  status = VIR_OK;
2704  skyout = NULL;
2705  if (algo == PAWSKY_MASK) {
2706  (void)vircam_pawsky_mask(infits,nfiles,conf,ps.mask,&skyout,
2707  psm.niter,psm.ipix,psm.thresh,psm.nbsize,
2708  psm.smkern,&status);
2709  } else {
2710  opmfits = vircam_fits_load(ps.master_objmask,CPL_TYPE_INT,1);
2711  (void)vircam_pawsky_mask_pre(infits,nfiles,conf,ps.mask,opmfits,
2712  psm.nbsize,&skyout,&status);
2713  vircam_fits_delete(opmfits);
2714  }
2715 
2716  /* Save the sky frame */
2717 
2718  if (vircam_sci_save_sky(skyout,framelist,parlist,fname,template,
2719  isfirst,product_frame) != VIR_OK) {
2720  freefitslist(infits,nfiles);
2721  freefits(conf);
2722  freefits(skyout);
2723  return(VIR_FATAL);
2724  }
2725 
2726  /* Tidy up and move on to the next one */
2727 
2728  freefitslist(infits,nfiles);
2729  freefits(conf);
2730  freefits(skyout);
2731  }
2732  cpl_msg_indent_less();
2733  return(VIR_OK);
2734 }
2735 
2736 /*---------------------------------------------------------------------------*/
2755 /*---------------------------------------------------------------------------*/
2756 
2757 extern int vircam_sci_save_sky(vir_fits *outsky, cpl_frameset *framelist,
2758  cpl_parameterlist *parlist,
2759  char *fname, cpl_frame *template, int isfirst,
2760  cpl_frame **product_frame) {
2761  cpl_propertylist *p;
2762  int isdummy;
2763  cpl_image *fim;
2764  const char *fctid = "vircam_sci_save_sky";
2765 
2766  /* Work out which frame to base the output on. If this particular
2767  sequence failed for whatever reason, there will be a dummy sky frame. */
2768 
2769  fim = vircam_fits_get_image(outsky);
2770  isdummy = (vircam_fits_get_status(outsky) != VIR_OK);
2771 
2772  /* If we need to make a PHU then do that now based on the first frame
2773  in the input frame list */
2774 
2775  if (isfirst) {
2776 
2777  /* Create a new product frame object and define some tags */
2778 
2779  *product_frame = cpl_frame_new();
2780  cpl_frame_set_filename(*product_frame,fname);
2781  cpl_frame_set_tag(*product_frame,VIRCAM_PRO_OFFSET_SKY);
2782  cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_IMAGE);
2783  cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
2784  cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
2785 
2786  /* Set up the PHU header. */
2787 
2788  p = vircam_fits_get_phu(outsky);
2789  vircam_dfs_set_product_primary_header(p,*product_frame,framelist,
2790  parlist,vircam_recipename,
2791  "PRO-1.15",template,0);
2792 
2793  /* 'Save' the PHU image */
2794 
2795  if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,p,
2796  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
2797  cpl_msg_error(fctid,"Cannot save product PHU");
2798  cpl_frame_delete(*product_frame);
2799  return(-1);
2800  }
2801  cpl_frameset_insert(framelist,*product_frame);
2802  }
2803 
2804  /* Get the extension property list */
2805 
2806  p = cpl_propertylist_duplicate(vircam_fits_get_ehu(outsky));
2807  if (isdummy)
2809 
2810  /* Fiddle with the header now */
2811 
2812  vircam_dfs_set_product_exten_header(p,*product_frame,framelist,parlist,
2813  vircam_recipename,"PRO-1.15",template);
2814  if (cpl_image_save(fim,fname,CPL_TYPE_FLOAT,p,CPL_IO_EXTEND) !=
2815  CPL_ERROR_NONE) {
2816  cpl_msg_error(fctid,"Cannot save product image extension");
2817  return(-1);
2818  }
2819 
2820  /* Quick tidy */
2821 
2822  cpl_propertylist_delete(p);
2823 
2824  /* Get out of here */
2825 
2826  return(0);
2827 }
2828 
2829 static int vircam_sci_cmp_jit(const cpl_frame *frame1,
2830  const cpl_frame *frame2) {
2831  int j_1,j_2;
2832  cpl_propertylist *pp;
2833 
2834  /* Test entries */
2835 
2836  if (frame1 == NULL || frame2 == NULL)
2837  return(-1);
2838  pp = cpl_propertylist_load(cpl_frame_get_filename(frame1),0);
2839  (void)vircam_pfits_get_jitternum(pp,&j_1);
2840  cpl_propertylist_delete(pp);
2841  pp = cpl_propertylist_load(cpl_frame_get_filename(frame2),0);
2842  (void)vircam_pfits_get_jitternum(pp,&j_2);
2843  cpl_propertylist_delete(pp);
2844 
2845  return(j_1 == j_2);
2846 }
2847 
2848 static int vircam_sci_cmp_tstart(const cpl_frame *frame1,
2849  const cpl_frame *frame2) {
2850  char ts1[80],ts2[80];
2851  cpl_propertylist *pp;
2852 
2853  /* Test entries */
2854 
2855  if (frame1 == NULL || frame2 == NULL)
2856  return(-1);
2857 
2858  /* Load the propertylist for each frame and extract the template start
2859  time */
2860 
2861  pp = cpl_propertylist_load(cpl_frame_get_filename(frame1),0);
2862  (void)vircam_pfits_get_tplstart(pp,ts1);
2863  cpl_propertylist_delete(pp);
2864  pp = cpl_propertylist_load(cpl_frame_get_filename(frame2),0);
2865  (void)vircam_pfits_get_tplstart(pp,ts2);
2866  cpl_propertylist_delete(pp);
2867 
2868  /* Compare the start times */
2869 
2870  if (strcmp(ts1,ts2))
2871  return(0);
2872  else
2873  return(1);
2874 }
2875 
2876 static int vircam_pfits_get_tplstart(cpl_propertylist *plist, char *tplstart) {
2877  strcpy(tplstart,cpl_propertylist_get_string(plist,"ESO TPL START"));
2878  if (cpl_error_get_code() == CPL_ERROR_NONE) {
2879  return(VIR_OK);
2880  } else {
2881  cpl_error_reset();
2882  return(VIR_FATAL);
2883  }
2884 }
2885 
2886 static cpl_frameset *vircam_sci_update_frameset(cpl_frameset *frms) {
2887  cpl_frameset *copy;
2888  cpl_size i,n;
2889  cpl_frame *fr;
2890  char *fname,bname[BUFSIZ];
2891 
2892  /* NULL input... */
2893 
2894  if (frms == NULL)
2895  return(NULL);
2896 
2897  /* First make a copy of the input frameset */
2898 
2899  copy = cpl_frameset_duplicate(frms);
2900 
2901  /* Now go through and change the file names */
2902 
2903  n = cpl_frameset_get_size(frms);
2904  for (i = 0; i < n; i++) {
2905  fr = cpl_frameset_get_frame(copy,i);
2906  fname = cpl_strdup(cpl_frame_get_filename(fr));
2907  vircam_sci_product_name(fname,SIMPLE_FILE,vircam_sci_config.prettynames,
2908  i+1,bname);
2909  cpl_frame_set_filename(fr,basename(bname));
2910  cpl_free(fname);
2911  }
2912 
2913  /* Get out of here */
2914 
2915  return(copy);
2916 }
2917 
2918 static int vircam_sci_testfrms(cpl_frameset *frms, int nextn_expected,
2919  int isimg) {
2920  int i,nf,nerr;
2921  cpl_frame *fr;
2922 
2923  /* Return immediately if given nonsense */
2924 
2925  if (frms == NULL)
2926  return(0);
2927 
2928  /* Loop for each frame in the frameset */
2929 
2930  nf = cpl_frameset_get_size(frms);
2931  nerr = 0;
2932  for (i = 0; i < nf; i++) {
2933  fr = cpl_frameset_get_frame(frms,i);
2934  nerr += vircam_sci_testfrm_1(fr,nextn_expected,isimg);
2935  }
2936 
2937  /* Return value */
2938 
2939  return(nerr);
2940 }
2941 
2942 static int vircam_sci_testfrm_1(cpl_frame *fr, int nextn_expected, int isimg) {
2943  int nextn,nerr,j;
2944  vir_fits *test;
2945  vir_tfits *testt;
2946  const char *fctid="vircam_sci_testfrm";
2947 
2948  /* Return immediately if given nonsense */
2949 
2950  if (fr == NULL)
2951  return(0);
2952 
2953  /* Test to see how many extensions there are and compare to see
2954  if it matches the number expected */
2955 
2956  nextn = cpl_frame_get_nextensions(fr);
2957  if (nextn != nextn_expected) {
2958  cpl_msg_error(fctid,"Frame %s has %" CPL_SIZE_FORMAT " extensions, expected %" CPL_SIZE_FORMAT "\n",
2959  cpl_frame_get_filename(fr),(cpl_size)nextn,
2960  (cpl_size)nextn_expected);
2961  return(1);
2962  }
2963 
2964  /* Test to see if you can load each of the extensions */
2965 
2966  nerr = 0;
2967  for (j = 1; j <= nextn; j++) {
2968  if (isimg) {
2969  test = vircam_fits_load(fr,CPL_TYPE_FLOAT,j);
2970  if (test == NULL) {
2971  cpl_msg_error(fctid,
2972  "Frame image %s[%" CPL_SIZE_FORMAT "] won't load\n",
2973  cpl_frame_get_filename(fr),(cpl_size)j);
2974  nerr++;
2975  continue;
2976  }
2977  freefits(test);
2978  } else {
2979  testt = vircam_tfits_load(fr,j);
2980  if (testt == NULL) {
2981  cpl_msg_error(fctid,
2982  "Frame table %s[%" CPL_SIZE_FORMAT "] won't load\n",
2983  cpl_frame_get_filename(fr),(cpl_size)j);
2984  nerr++;
2985  continue;
2986  }
2987  freetfits(testt);
2988  }
2989  }
2990  return(nerr);
2991 }
2992 
2993 /*==========================cut to other files ====================*/
2994 
2995 /*---------------------------------------------------------------------------*/
3010 /*---------------------------------------------------------------------------*/
3011 
3012 extern void vircam_sci_init(void) {
3013 
3014  /* Level 0 stuff */
3015 
3016  ps.labels = NULL;
3017  ps.master_dark = NULL;
3018  ps.master_twilight_flat = NULL;
3019  ps.master_conf = NULL;
3020  ps.master_sky = NULL;
3021  ps.master_objmask = NULL;
3022  ps.mask = NULL;
3023  ps.chantab = NULL;
3024  ps.phottab = NULL;
3025  ps.tphottab = NULL;
3026  ps.readgain_file = NULL;
3027  ps.science_frames = NULL;
3028  ps.offset_skies = NULL;
3029  ps.product_frames_simple = NULL;
3030  ps.product_frames_simple_off = NULL;
3031  ps.phupaf = NULL;
3032  ps.gaincors = NULL;
3033  ps.catpath = NULL;
3034  ps.catname = NULL;
3035  ps.nscipaws = 0;
3036  ps.science_paws = NULL;
3037  ps.noffpaws = 0;
3038  ps.offsky_paws = NULL;
3039  ps.nskys = 0;
3040  ps.skys = NULL;
3041 
3042  /* Level 1 stuff */
3043 
3044  ps.fdark = NULL;
3045  ps.fflat = NULL;
3046  ps.fconf = NULL;
3047  ps.fsky = NULL;
3048  ps.fchantab = NULL;
3049  ps.nscience = 0;
3050  ps.sci_fits = NULL;
3051  ps.noffsets = 0;
3052  ps.offsky_fits = NULL;
3053 }
3054 
3055 /*---------------------------------------------------------------------------*/
3076 /*---------------------------------------------------------------------------*/
3077 
3078 extern void vircam_sci_tidy(int level) {
3079  int i;
3080 
3081  /* Level 1 stuff */
3082 
3083  freefits(ps.fdark);
3084  freefits(ps.fflat);
3085  freefits(ps.fconf);
3086  freefits(ps.fsky);
3087  freetfits(ps.fchantab);
3088  freefitslist(ps.sci_fits,ps.nscience);
3089  freefitslist(ps.offsky_fits,ps.noffsets);
3090  ps.nscience = 0;
3091 
3092  if (level == 1)
3093  return;
3094 
3095  /* Level 0 stuff */
3096 
3097  freespace(ps.labels);
3098  freeframe(ps.master_dark);
3099  freeframe(ps.master_twilight_flat);
3100  freeframe(ps.master_conf);
3101  freeframe(ps.master_sky);
3102  freeframe(ps.master_objmask);
3103  freemask(ps.mask);
3104  freeframe(ps.chantab);
3105  freeframe(ps.phottab);
3106  freeframe(ps.readgain_file);
3107  freetable(ps.tphottab);
3108  freeframeset(ps.science_frames);
3109  freeframeset(ps.offset_skies);
3110  freepropertylist(ps.phupaf);
3111  freespace(ps.product_frames_simple); /* NB: We only have to delete */
3112  /* the arrays and not the frames */
3113  /* as these get passed back */
3114  freespace(ps.product_frames_simple_off); /* to esorex */
3115  freespace(ps.gaincors);
3116  freespace(ps.catpath);
3117  freespace(ps.catname);
3118  for (i = 0; i < ps.nskys; i++) {
3119  freeframeset(ps.skys[i].contrib);
3120  freeframe(ps.skys[i].objmask);
3121  freeframe(ps.skys[i].template);
3122  }
3123  freespace(ps.skys);
3124  freepaws(ps.science_paws,ps.nscipaws);
3125  freepaws(ps.offsky_paws,ps.noffpaws);
3126  freeframe(ps.schlf_n);
3127  freeframe(ps.schlf_s);
3128 }
3129 
3130 /*---------------------------------------------------------------------------*/
3146 /*---------------------------------------------------------------------------*/
3147 
3148 extern void vircam_sci_get_readnoise_gain(int jext, float *readnoise,
3149  float *gain) {
3150  cpl_propertylist *p_rg;
3151  const char *fctid = "vircam_sci_get_readnoise_gain";
3152 
3153  /* Load the propertylist */
3154 
3155  p_rg = cpl_propertylist_load(cpl_frame_get_filename(ps.readgain_file),
3156  (cpl_size)jext);
3157 
3158  /* Check the readnoise property type and read it */
3159 
3160  switch (cpl_propertylist_get_type(p_rg,"ESO QC READNOISE")) {
3161  case CPL_TYPE_FLOAT:
3162  *readnoise = cpl_propertylist_get_float(p_rg,"ESO QC READNOISE");
3163  break;
3164  case CPL_TYPE_DOUBLE:
3165  *readnoise = (float)cpl_propertylist_get_double(p_rg,
3166  "ESO QC READNOISE");
3167  break;
3168  default:
3169  cpl_error_reset();
3170  *readnoise = 25.0;
3171  cpl_msg_error(fctid,"Unable to get READNOISE estimate, guessing %g\n",
3172  *readnoise);
3173  }
3174 
3175  /* Now the gain */
3176 
3177  switch (cpl_propertylist_get_type(p_rg,"ESO QC CONAD")) {
3178  case CPL_TYPE_FLOAT:
3179  *gain = cpl_propertylist_get_float(p_rg,"ESO QC CONAD");
3180  break;
3181  case CPL_TYPE_DOUBLE:
3182  *gain = (float)cpl_propertylist_get_double(p_rg,"ESO QC CONAD");
3183  break;
3184  default:
3185  cpl_error_reset();
3186  *gain = 1.0;
3187  cpl_msg_error(fctid,"Unable to get GAIN estimate, guessing %g\n",
3188  *gain);
3189  }
3190  cpl_propertylist_delete(p_rg);
3191 }
3192 
3193 /*---------------------------------------------------------------------------*/
3212 /*---------------------------------------------------------------------------*/
3213 
3214 extern int vircam_sci_save_simple(vir_fits *obj, cpl_frameset *framelist,
3215  cpl_parameterlist *parlist, int isprod,
3216  cpl_frame *template, int isfirst,
3217  const char *tag, char *fname,
3218  cpl_frame **product_frame) {
3219  cpl_propertylist *plist;
3220  int isdummy;
3221  const char *fctid = "vircam_sci_save_simple";
3222 
3223  /* Get some information about this guy */
3224 
3225  isdummy = (vircam_fits_get_status(obj) != VIR_OK);
3226 
3227  /* If we need to make a PHU then do that now based on the first frame
3228  in the input frame list. Get rid of the file if it already exists */
3229 
3230  if (isfirst) {
3231  if (access(fname,F_OK))
3232  remove(fname);
3233 
3234  /* Create a new product frame object and define some tags */
3235 
3236  *product_frame = cpl_frame_new();
3237  cpl_frame_set_filename(*product_frame,fname);
3238 
3239  /**** this probably needs to be modified. Can't see them allowing
3240  the VIRCAM_PRO_SIMPLE_SCI to apply to both jmp and sci
3241  recipes... ***/
3242 
3243  cpl_frame_set_tag(*product_frame,tag);
3244  cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_IMAGE);
3245  cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
3246  cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
3247 
3248  /* Set up the PHU header */
3249 
3250  plist = vircam_fits_get_phu(obj);
3251  vircam_dfs_set_product_primary_header(plist,*product_frame,framelist,
3252  parlist,vircam_recipename,
3253  "PRO-1.15",template,1);
3254 
3255  /* 'Save' the PHU image */
3256 
3257  if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,plist,CPL_IO_DEFAULT) !=
3258  CPL_ERROR_NONE) {
3259  cpl_msg_error(fctid,"Cannot save product PHU");
3260  cpl_frame_delete(*product_frame);
3261  return(-1);
3262  }
3263  if (isprod)
3264  cpl_frameset_insert(framelist,*product_frame);
3265  }
3266 
3267  /* Get the extension property list */
3268 
3269  plist = vircam_fits_get_ehu(obj);
3270  if (isdummy)
3271  vircam_dummy_property(plist);
3272 
3273  /* Fiddle with the header now */
3274 
3275  vircam_dfs_set_product_exten_header(plist,*product_frame,framelist,parlist,
3276  vircam_recipename,"PRO-1.15",template);
3277  if (cpl_image_save(vircam_fits_get_image(obj),fname,CPL_TYPE_FLOAT,plist,
3278  CPL_IO_EXTEND) != CPL_ERROR_NONE) {
3279  cpl_msg_error(fctid,"Cannot save product image extension -- %s",
3280  cpl_error_get_message());
3281  return(-1);
3282  }
3283 
3284  /* Get out of here */
3285 
3286  return(0);
3287 }
3288 
3289 /*---------------------------------------------------------------------------*/
3308 /*---------------------------------------------------------------------------*/
3309 
3310 extern int vircam_sci_save_stack(vir_fits *stack, cpl_frameset *framelist,
3311  cpl_parameterlist *parlist,
3312  cpl_frame *template, int fnametype,
3313  int stack_num, cpl_frame **product_frame) {
3314  cpl_propertylist *plist;
3315  int isfirst,isdummy;
3316  char fname[BUFSIZ],*base,*tname;
3317  const char *fctid = "vircam_sci_save_stack";
3318 
3319  /* Get some information about this guy */
3320 
3321  isdummy = (vircam_fits_get_status(stack) != VIR_OK);
3322  isfirst = (*product_frame == NULL);
3323  tname = cpl_strdup(cpl_frame_get_filename(template));
3324  base = basename(tname);
3325  vircam_sci_product_name(base,STACK_FILE,fnametype,stack_num,fname);
3326  freespace(tname);
3327 
3328  /* If we need to make a PHU then do that now based on the first frame
3329  in the input frame list. Get rid of the file if it already exists */
3330 
3331  if (isfirst) {
3332  if (access(fname,F_OK))
3333  remove(fname);
3334 
3335  /* Create a new product frame object and define some tags */
3336 
3337  *product_frame = cpl_frame_new();
3338  cpl_frame_set_filename(*product_frame,fname);
3339 
3340  /**** this probably needs to be modified. Can't see them allowing
3341  the VIRCAM_PRO_JITTERED_SCI to apply to both jmp and sci
3342  recipes... ***/
3343 
3344  cpl_frame_set_tag(*product_frame,VIRCAM_PRO_JITTERED_SCI);
3345  cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_IMAGE);
3346  cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
3347  cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
3348 
3349  /* Set up the PHU header */
3350 
3351  plist = vircam_fits_get_phu(stack);
3352  vircam_dfs_set_product_primary_header(plist,*product_frame,
3353  framelist,parlist,
3354  vircam_recipename,
3355  "PRO-1.15",template,1);
3356 
3357  /* 'Save' the PHU image */
3358 
3359  if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,plist,
3360  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
3361  cpl_msg_error(fctid,"Cannot save product PHU");
3362  cpl_frame_delete(*product_frame);
3363  return(-1);
3364  }
3365  cpl_frameset_insert(framelist,*product_frame);
3366  }
3367 
3368  /* Get the extension property list */
3369 
3370  plist = vircam_fits_get_ehu(stack);
3371  if (isdummy)
3372  vircam_dummy_property(plist);
3373 
3374  /* Fiddle with the header now */
3375 
3376  vircam_dfs_set_product_exten_header(plist,*product_frame,framelist,
3377  parlist,vircam_recipename,
3378  "PRO-1.15",template);
3379  if (cpl_image_save(vircam_fits_get_image(stack),fname,CPL_TYPE_FLOAT,
3380  plist,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
3381  cpl_msg_error(fctid,"Cannot save product image extension -- %s",
3382  cpl_error_get_message());
3383  return(-1);
3384  }
3385 
3386  /* Get out of here */
3387 
3388  return(0);
3389 }
3390 
3391 /*---------------------------------------------------------------------------*/
3410 /*---------------------------------------------------------------------------*/
3411 
3412 extern int vircam_sci_save_stack_conf(vir_fits *stack, cpl_frameset *framelist,
3413  cpl_parameterlist *parlist,
3414  cpl_frame *template, int fnametype,
3415  int stack_num,
3416  cpl_frame **product_frame) {
3417  cpl_propertylist *plist;
3418  int isfirst,isdummy;
3419  char fname[BUFSIZ],*tname,*base;
3420  const char *fctid = "vircam_sci_save_stack_conf";
3421 
3422  /* Get some information about this guy */
3423 
3424  isdummy = (vircam_fits_get_status(stack) != VIR_OK);
3425  isfirst = (*product_frame == NULL);
3426  tname = cpl_strdup(cpl_frame_get_filename(template));
3427  base = basename(tname);
3428  vircam_sci_product_name(base,STACK_CONF,fnametype,stack_num,fname);
3429  freespace(tname);
3430 
3431  /* If we need to make a PHU then do that now based on the first frame
3432  in the input frame list. Get rid of the file if it already exists */
3433 
3434  if (isfirst) {
3435  if (access(fname,F_OK))
3436  remove(fname);
3437 
3438  /* Create a new product frame object and define some tags */
3439 
3440  *product_frame = cpl_frame_new();
3441  cpl_frame_set_filename(*product_frame,fname);
3442 
3443  /**** this probably needs to be modified. Can't see them allowing
3444  the VIRCAM_PRO_CONF_SCI to apply to both jmp and sci
3445  recipes... ***/
3446 
3447  cpl_frame_set_tag(*product_frame,VIRCAM_PRO_CONF_SCI);
3448  cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_IMAGE);
3449  cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
3450  cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
3451 
3452  /* Set up the PHU header */
3453 
3454  plist = vircam_fits_get_phu(stack);
3455  vircam_dfs_set_product_primary_header(plist,*product_frame,framelist,
3456  parlist,vircam_recipename,
3457  "PRO-1.15",template,1);
3458 
3459  /* 'Save' the PHU image */
3460 
3461  if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,plist,
3462  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
3463  cpl_msg_error(fctid,"Cannot save product PHU");
3464  cpl_frame_delete(*product_frame);
3465  return(-1);
3466  }
3467  cpl_frameset_insert(framelist,*product_frame);
3468  }
3469 
3470  /* Get the extension property list */
3471 
3472  plist = vircam_fits_get_ehu(stack);
3473  if (isdummy)
3474  vircam_dummy_property(plist);
3475 
3476  /* Fiddle with the header now */
3477 
3478  vircam_dfs_set_product_exten_header(plist,*product_frame,framelist,
3479  parlist,vircam_recipename,
3480  "PRO-1.15",template);
3481  if (cpl_image_save(vircam_fits_get_image(stack),fname,CPL_TYPE_INT,
3482  plist,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
3483  cpl_msg_error(fctid,"Cannot save product image extension -- %s",
3484  cpl_error_get_message());
3485  return(-1);
3486  }
3487 
3488  /* Get out of here */
3489 
3490  return(0);
3491 }
3492 
3493 /*---------------------------------------------------------------------------*/
3512 /*---------------------------------------------------------------------------*/
3513 
3514 extern int vircam_sci_save_stack_cat(vir_tfits *stack, cpl_frameset *framelist,
3515  cpl_parameterlist *parlist,
3516  cpl_frame *template, int fnametype,
3517  int stack_num, cpl_frame **product_frame) {
3518  cpl_propertylist *plist;
3519  int isfirst,isdummy;
3520  char fname[BUFSIZ],*tname,*base;
3521  const char *fctid = "vircam_sci_save_stack_cat";
3522 
3523  /* Get some information about this guy */
3524 
3525  isdummy = (vircam_tfits_get_status(stack) != VIR_OK);
3526  isfirst = (*product_frame == NULL);
3527  tname = cpl_strdup(cpl_frame_get_filename(template));
3528  base = basename(tname);
3529  vircam_sci_product_name(base,STACK_CAT,fnametype,stack_num,fname);
3530  freespace(tname);
3531 
3532  /* If we need to make a PHU then do that now based on the first frame
3533  in the input frame list. Get rid of the file if it already exists */
3534 
3535  if (isfirst) {
3536  if (access(fname,F_OK))
3537  remove(fname);
3538 
3539  /* Create a new product frame object and define some tags */
3540 
3541  *product_frame = cpl_frame_new();
3542  cpl_frame_set_filename(*product_frame,fname);
3543 
3544  /**** this probably needs to be modified. Can't see them allowing
3545  the VIRCAM_PRO_OBJCAT_SCI to apply to both jmp and sci
3546  recipes... ***/
3547 
3548  cpl_frame_set_tag(*product_frame,VIRCAM_PRO_OBJCAT_SCI);
3549  cpl_frame_set_type(*product_frame,CPL_FRAME_TYPE_TABLE);
3550  cpl_frame_set_group(*product_frame,CPL_FRAME_GROUP_PRODUCT);
3551  cpl_frame_set_level(*product_frame,CPL_FRAME_LEVEL_FINAL);
3552 
3553  /* Set up the PHU header */
3554 
3555  plist = vircam_tfits_get_phu(stack);
3556  vircam_dfs_set_product_primary_header(plist,*product_frame,framelist,
3557  parlist,vircam_recipename,
3558  "PRO-1.15",NULL,0);
3559 
3560  /* 'Save' the PHU image */
3561 
3562  if (cpl_image_save(NULL,fname,CPL_TYPE_UCHAR,plist,
3563  CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
3564  cpl_msg_error(fctid,"Cannot save product PHU");
3565  cpl_frame_delete(*product_frame);
3566  return(-1);
3567  }
3568  cpl_frameset_insert(framelist,*product_frame);
3569  }
3570 
3571  /* Get the extension property list */
3572 
3573  plist = vircam_tfits_get_ehu(stack);
3574  if (isdummy)
3575  vircam_dummy_property(plist);
3576 
3577  /* Fiddle with the header now */
3578 
3579  vircam_dfs_set_product_exten_header(plist,*product_frame,framelist,
3580  parlist,vircam_recipename,
3581  "PRO-1.15",NULL);
3582  if (cpl_table_save(vircam_tfits_get_table(stack),NULL,
3583  plist,fname,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
3584  cpl_msg_error(fctid,"Cannot save product table extension -- %s",
3585  cpl_error_get_message());
3586  return(-1);
3587  }
3588 
3589  /* Get out of here */
3590 
3591  return(0);
3592 }
3593 
3594 /*---------------------------------------------------------------------------*/
3623 /*---------------------------------------------------------------------------*/
3624 
3625 static void vircam_sci_product_name(char *template, int producttype,
3626  int nametype, int fnumber, char *outfname) {
3627  const char *esonames[] = {"exp_","exp_conf_","exp_cat","stack_",
3628  "stack_conf_","stack_cat_","sky_"};
3629  const char *suffix[] = {"_ex","_ex_conf","_ex_cat","_st","_st_conf",
3630  "_st_cat","sky_"};
3631  char *fname,*bname,*dot;
3632 
3633  /* If the name type is the ESO predictable sort, then it's easy. Just
3634  use the esonames defined above and append the correct number */
3635 
3636  switch (nametype) {
3637  case 0:
3638  (void)sprintf(outfname,"%s%d.fits",esonames[producttype],fnumber);
3639  break;
3640 
3641  /* If this is a temporary file, then just append tmp_ to the template
3642  name and return that */
3643 
3644  case 2:
3645  fname = cpl_strdup(template);
3646  bname = basename(fname);
3647  (void)sprintf(outfname,"tmp_%s",bname);
3648  freespace(fname);
3649  break;
3650 
3651  /* Ok, we want a pretty name... */
3652 
3653  case 1:
3654  fname = cpl_strdup(template);
3655  bname = basename(fname);
3656  if (producttype != SKY_FILE) {
3657  (void)sprintf(outfname,"%s",bname);
3658  dot = strrchr(outfname,'.');
3659  (void)sprintf(dot,"%s.fits",suffix[producttype]);
3660  } else {
3661  sprintf(outfname,"%s%s",suffix[producttype],bname);
3662  }
3663  freespace(fname);
3664  break;
3665 
3666  /* something else ?? */
3667 
3668  default:
3669  (void)strcpy(outfname,"");
3670  break;
3671  }
3672  return;
3673 }
3674 
3675 /*
3676 
3677 $Log: not supported by cvs2svn $
3678 Revision 1.9 2013/10/15 17:01:45 jim
3679 new entry
3680 
3681 
3682 */