VIRCAM Pipeline  1.3.4
vircam_photcal.c
1 /* $Id: vircam_photcal.c,v 1.39 2013-10-15 16:50:04 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2005 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-15 16:50:04 $
24  * $Revision: 1.39 $
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 <cpl.h>
35 #include <math.h>
36 #include <string.h>
37 
38 #include "vircam_mods.h"
39 #include "vircam_utils.h"
40 #include "vircam_pfits.h"
41 #include "vircam_stats.h"
42 #include "vircam_fits.h"
43 
44 typedef struct {
45  char *filt;
46  char **columns;
47  int ncolumns;
48  float extinct;
49  float *coloureq;
50  float offset;
51  float extcoef;
52  int nmags;
53 } photstrct;
54 
55 static photstrct p;
56 
57 typedef struct {
58  double crval[2];
59  double crpix[2];
60  double cd[4];
61  double secd;
62  double tand;
63  double pv21;
64  double pv23;
65  double pv25;
66  int nx;
67  int ny;
68  int istan;
69 } mywcs;
70 
71 #define NOMPIXSIZE 0.34
72 #define INITALLOC 1024
73 #define SZBUF 1024
74 
75 static double pixsize (cpl_propertylist *plist);
76 static int vircam_phot_open(cpl_table *phottab, char *filt);
77 static void vircam_phot_close(void);
78 static int extract_columns(cpl_table *tab);
79 static int extract_coleq(cpl_table *tab);
80 static void write_hdr_1(cpl_propertylist *p, int nresim, float med3, float sig3,
81  float lim3, float med5, float sig5, float lim5,
82  float extinct, float skybrt, int ncut, int doqc);
83 
84 static void modifytab(cpl_table *intab, vir_fits *im, float saturate,
85  int minstars, cpl_image *schl_n, cpl_image *schl_s,
86  int *method, cpl_table **outtab);
87 static void getextinct(cpl_image *schl_n, cpl_image *schl_s, double ra,
88  double dec, float *jext, float *hext, float *kext,
89  float *ebv);
90 static mywcs *getwcs(vir_fits *in);
91 static void radectolb(double ra, double dec, float epoch, double *gal_l,
92  double *gal_b);
93 static float distort_corr(double x, double y, mywcs *w);
94 
95 
98 /*---------------------------------------------------------------------------*/
182 /*---------------------------------------------------------------------------*/
183 
184 extern int vircam_photcal(vir_fits **images, cpl_table **mstds,
185  cpl_propertylist **pl, int nimages, char *filt,
186  cpl_table *phottab, int *status) {
187  float **stdmagptr,*resall3,*resall5,cdfudge,saturate,apcor3,apcor5,exptime;
188  float airmass,*catcore3,*catcore5,*resim3,*resim5,cf,fluxmag3,fluxmag5;
189  float refmag,extinct,dm3,dm5,med3,mad,cut,lcut,hcut,med5,sig3,sig5;
190  float rcore,lim3,lim5,dx,skylev,skbrt;
191  int nresall,nalloc_resall,i,j,k,ncat,nresim,ncut;
192  char junk[SZBUF];
193  const char *fctid = "vircam_photcal";
194  vir_fits *im;
195  cpl_propertylist *ehu_im,*ehu_cat;
196  cpl_table *stds,*cl;
197 
198  /* Inherited status */
199 
200  if (*status != VIR_OK)
201  return(*status);
202 
203  /* Check for nonsense errors */
204 
205  if (nimages <= 0) {
206  cpl_msg_error(fctid,"No images included in photometric calibration");
207  FATAL_ERROR
208  }
209 
210  /* Set up the structure that will give us the colour equations for
211  this filter later on */
212 
213  if (vircam_phot_open(phottab,filt) != VIR_OK)
214  FATAL_ERROR
215 
216  /* Get a workspace to hold the pointers to the magnitude columns */
217 
218  stdmagptr = cpl_malloc(p.ncolumns*sizeof(float *));
219 
220  /* Get some workspace to hold all the zeropoints for all the images
221  in the input list. This is an initial allocation and more can be
222  made available later if needed */
223 
224  resall3 = cpl_malloc(INITALLOC*sizeof(float));
225  resall5 = cpl_malloc(INITALLOC*sizeof(float));
226  nresall = 0;
227  nalloc_resall = INITALLOC;
228 
229  /* Loop for the input images and catalogues. Create some shorthand
230  variables and work out what the zeropoint fudge factor will be
231  based on the sampling of the current frame and the nominal sampling
232  of a VIRCAM image */
233 
234  for (i = 0; i < nimages; i++) {
235  im = images[i];
236  ehu_im = vircam_fits_get_ehu(im);
237  stds = mstds[i];
238  ehu_cat = pl[i];
239  cdfudge = 2.5*log10((double)pixsize(ehu_im)/NOMPIXSIZE);
240 
241  /* Are there any? */
242 
243  ncat = (int)cpl_table_get_nrow(stds);
244  if (ncat <= 3) {
245  cpl_msg_warning(fctid,"Too few standards available");
246  cpl_error_reset();
247  write_hdr_1(ehu_im,ncat,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,1);
248  write_hdr_1(ehu_cat,ncat,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0);
249  continue;
250  }
251 
252  /* Now for the input catalogues. Start by getting some useful info
253  from the header */
254 
255  saturate = cpl_propertylist_get_float(ehu_cat,"ESO QC SATURATION");
256  apcor3 = cpl_propertylist_get_float(ehu_cat,"APCOR3");
257  apcor5 = cpl_propertylist_get_float(ehu_cat,"APCOR5");
258  rcore = cpl_propertylist_get_float(ehu_cat,"ESO DRS RCORE");
259  skylev = cpl_propertylist_get_float(ehu_cat,"ESO DRS SKYLEVEL");
260  dx = pixsize(ehu_im);
261  (void)vircam_pfits_get_exptime(ehu_cat,&exptime);
262  (void)vircam_pfits_get_airmass(vircam_fits_get_phu(im),&airmass);
263  if (cpl_error_get_code() != CPL_ERROR_NONE) {
264  cpl_msg_error(fctid,"Unable to get header info");
265  cpl_error_reset();
266  continue;
267  }
268 
269  /* Get objects that are not saturated and aren't too elliptical */
270 
271  cpl_table_select_all(stds);
272  (void)cpl_table_and_selected_float(stds,"Ellipticity",CPL_LESS_THAN,
273  0.5);
274  (void)cpl_table_and_selected_float(stds,"Peak_height",CPL_LESS_THAN,
275  saturate);
276  if (cpl_error_get_code() != CPL_ERROR_NONE) {
277  cpl_msg_error(fctid,"Unable to select data from matched stds tab");
278  cpl_error_reset();
279  continue;
280  }
281 
282  /* Get all objects where the magnitude errors are less than 0.1 */
283 
284  for (j = 0; j < p.ncolumns; j++) {
285  (void)snprintf(junk,SZBUF,"%ssig",(p.columns)[j]);
286  (void)cpl_table_and_selected_float(stds,junk,CPL_LESS_THAN,0.1);
287  }
288 
289  /* Now extract all those that have passed the test. If none are left
290  then issue a warning and move on to the next one */
291 
292  cl = cpl_table_extract_selected(stds);
293  ncat = (int)cpl_table_get_nrow(cl);
294  if (ncat <= 3) {
295  cpl_msg_warning(fctid,"Too few good standards available");
296  cpl_table_delete(cl);
297  cpl_error_reset();
298  write_hdr_1(ehu_im,ncat,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,1);
299  write_hdr_1(ehu_cat,ncat,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0);
300  continue;
301  }
302 
303  /* Dereference some of the columns */
304 
305  catcore3 = cpl_table_get_data_float(cl,"Aper_flux_3");
306  catcore5 = cpl_table_get_data_float(cl,"Aper_flux_5");
307  for (j = 0; j < p.ncolumns; j++)
308  stdmagptr[j] = cpl_table_get_data_float(cl,(p.columns)[j]);
309 
310  /* Get some workspace for the results arrays for this image */
311 
312  resim3 = cpl_malloc(ncat*sizeof(float));
313  resim5 = cpl_malloc(ncat*sizeof(float));
314  nresim = 0;
315 
316  /* Loop for all the standards */
317 
318  extinct = p.extinct*(airmass - 1.0);
319  for (j = 0; j < ncat; j++) {
320 
321  /* Do core magnitude calculation */
322 
323  cf = catcore3[j]/exptime;
324  if (cf < 1.0)
325  cf = 1.0;
326  fluxmag3 = 2.5*log10((double)cf) + apcor3;
327  cf = catcore5[j]/exptime;
328  if (cf < 1.0)
329  cf = 1.0;
330  fluxmag5 = 2.5*log10((double)cf) + apcor5;
331 
332  /* Work out a reference magnitude */
333 
334  refmag = p.offset;
335  for (k = 0; k < p.nmags; k++)
336  refmag += ((p.coloureq)[k]*stdmagptr[k][j]);
337 
338  /* Work out zero points and store them away for later */
339 
340  dm3 = refmag + fluxmag3 + extinct;
341  dm5 = refmag + fluxmag5 + extinct;
342  resim3[nresim] = dm3 + cdfudge;
343  resim5[nresim++] = dm5 + cdfudge;
344  resall3[nresall] = dm3 + cdfudge;
345  resall5[nresall++] = dm5 + cdfudge;
346  if (nresall == nalloc_resall) {
347  nalloc_resall += INITALLOC;
348  resall3 = cpl_realloc(resall3,nalloc_resall*sizeof(float));
349  resall5 = cpl_realloc(resall5,nalloc_resall*sizeof(float));
350  }
351  }
352 
353  /* Ok, what is the mean zeropoint for this image? */
354 
355  (void)vircam_medmad(resim3,NULL,(long)nresim,&med3,&mad);
356  cut = max(3.0*1.48*mad,0.1);
357  lcut = med3 - cut;
358  hcut = med3 + cut;
359  (void)vircam_meansigcut(resim3,NULL,nresim,lcut,hcut,&med3,&sig3);
360  ncut = 0;
361  for (j = 0; j < nresim; j++)
362  if (resim3[j] < lcut || resim3[j] > hcut)
363  ncut++;
364  (void)vircam_medmad(resim5,NULL,(long)nresim,&med5,&mad);
365  cut = max(3.0*1.48*mad,0.1);
366  lcut = med5 - cut;
367  hcut = med5 + cut;
368  (void)vircam_meansigcut(resim5,NULL,nresim,lcut,hcut,&med5,&sig5);
369 
370  /* Delete some workspace */
371 
372  freespace(resim3);
373  freespace(resim5);
374  freetable(cl);
375 
376  /* Calculate the limiting magnitudes */
377 
378  lim3 = med3 - 2.5*log10((5.0*sig3*rcore*sqrt(CPL_MATH_PI))/exptime) -
379  apcor3 - extinct;
380  lim5 = med5 - 2.5*log10((5.0*sig5*rcore*sqrt(CPL_MATH_PI))/exptime) -
381  apcor5 - extinct;
382 
383  /* Calculate sky brightness */
384 
385  skbrt = lim3 - 2.5*log10(skylev/(exptime*dx*dx)) - extinct;
386 
387  /* Write out header stuff. First for the image and then for the
388  catalogue. NB: QC is not allowed to appear in the catalogue */
389 
390  write_hdr_1(ehu_im,nresim,med3,sig3,lim3,med5,sig5,lim5,p.extinct,
391  skbrt,ncut,1);
392  write_hdr_1(ehu_cat,nresim,med3,sig3,lim3,med5,sig5,lim5,p.extinct,
393  skbrt,ncut,0);
394  }
395 
396  /* Ok, what is the mean zeropoint for all images? */
397 
398  if (nresall > 0) {
399  (void)vircam_medmad(resall3,NULL,(long)nresall,&med3,&mad);
400  cut = max(3.0*1.48*mad,0.1);
401  lcut = med3 - cut;
402  hcut = med3 + cut;
403  (void)vircam_meansigcut(resall3,NULL,nresall,lcut,hcut,&med3,&sig3);
404  (void)vircam_medmad(resall5,NULL,(long)nresall,&med5,&mad);
405  cut = max(3.0*1.48*mad,0.1);
406  lcut = med5 - cut;
407  hcut = med5 + cut;
408  (void)vircam_meansigcut(resall5,NULL,nresall,lcut,hcut,&med5,&sig5);
409  } else {
410  med3 = 0.0;
411  sig3 = 0.0;
412  med5 = 0.0;
413  sig5 = 0.0;
414  }
415 
416  /* Delete some workspace */
417 
418  freespace(resall3);
419  freespace(resall5);
420  freespace(stdmagptr);
421  vircam_phot_close();
422 
423  /* Write these results to the header of the images and the catalogues.
424  First the images */
425 
426  for (i = 0; i < nimages; i++) {
427  im = images[i];
428  ehu_im = vircam_fits_get_ehu(im);
429  stds = mstds[i];
430  ehu_cat = pl[i];
431  cpl_propertylist_update_int(ehu_im,"ESO DRS MAGNZPTALL",nresall);
432  cpl_propertylist_set_comment(ehu_im,"ESO DRS MAGNZPTALL",
433  "number of stars in all magzpt calc");
434  cpl_propertylist_update_double(ehu_im,"ESO DRS ZPALL1",med3);
435  cpl_propertylist_set_comment(ehu_im,"ESO DRS ZPALL1",
436  "[mag] zeropoint 1*rcore all group images");
437  cpl_propertylist_update_double(ehu_im,"ESO DRS ZPSIGALL1",sig3);
438  cpl_propertylist_set_comment(ehu_im,"ESO DRS ZPSIGALL1",
439  "[mag] zeropoint sigma 1*rcore all group images");
440  cpl_propertylist_update_double(ehu_im,"ESO DRS ZPALL2",med5);
441  cpl_propertylist_set_comment(ehu_im,"ESO DRS ZPALL2",
442  "[mag] zeropoint 2*rcore all group images");
443  cpl_propertylist_update_double(ehu_im,"ESO DRS ZPSIGALL2",sig5);
444  cpl_propertylist_set_comment(ehu_im,"ESO DRS ZPSIGALL2",
445  "[mag] zeropoint sigma 2*rcore all group images");
446 
447  /* Now the catalogues */
448 
449  cpl_propertylist_update_int(ehu_cat,"ESO DRS MAGNZPTALL",nresall);
450  cpl_propertylist_set_comment(ehu_cat,"ESO DRS MAGNZPTALL",
451  "number of stars in all magzpt calc");
452  cpl_propertylist_update_double(ehu_cat,"ESO DRS ZPALL1",med3);
453  cpl_propertylist_set_comment(ehu_cat,"ESO DRS ZPALL1",
454  "[mag] zeropoint 1*rcore all group images");
455  cpl_propertylist_update_double(ehu_cat,"ESO DRS ZPSIGALL1",sig3);
456  cpl_propertylist_set_comment(ehu_cat,"ESO DRS ZPSIGALL1",
457  "[mag] zeropoint sigma 1*rcore all group images");
458  cpl_propertylist_update_double(ehu_cat,"ESO DRS ZPALL2",med5);
459  cpl_propertylist_set_comment(ehu_cat,"ESO DRS ZPALL2",
460  "[mag] zeropoint 2*rcore all group images");
461  cpl_propertylist_update_double(ehu_cat,"ESO DRS ZPSIGALL2",sig5);
462  cpl_propertylist_set_comment(ehu_cat,"ESO DRS ZPSIGALL2",
463  "[mag] zeropoint sigma 2*rcore all group images");
464  }
465 
466  /* Get out of here */
467 
468  GOOD_STATUS
469 
470 }
471 
472 /* NB: This routine should be used only for a pawprint or a tile. Not for
473  a whole night. */
474 
475 extern int vircam_photcal_extinct(vir_fits **images, cpl_table **mstds,
476  vir_tfits **cats, int nimages,
477  char *filt, cpl_table *phottab, int minstars,
478  cpl_frame *schlf_n, cpl_frame *schlf_s,
479  int *status) {
480  float **stdmagptr,*resall3,*resall5,cdfudge,saturate,apcor3,apcor5,exptime;
481  float airmass,*catcore3,*catcore5,*resim3,*resim5,cf,fluxmag3,fluxmag5;
482  float refmag,extinct,dm3,dm5,med3,mad,med5,sig3,sig5;
483  float rcore,lim3,lim5,dx,skylev,skbrt,*ebmvall,*zps3,*zps5,medebv,med;
484  float sig3det,sig5det,*ebmv;
485  int nresall,nalloc_resall,i,j,k,ncat,nresim,ncut,nresimtot,method;
486  int ngood;
487  const char *fctid = "vircam_photcal_extinct";
488  vir_fits *im;
489  cpl_propertylist *ehu_im,*ehu_cat;
490  cpl_table *stds,*cl;
491  cpl_image *schl_n,*schl_s;
492 
493  /* Inherited status */
494 
495  if (*status != VIR_OK)
496  return(*status);
497 
498  /* Check for nonsense errors */
499 
500  if (nimages <= 0) {
501  cpl_msg_error(fctid,"No images included in photometric calibration");
502  FATAL_ERROR
503  }
504 
505  /* Get the Schlegel maps */
506 
507  schl_n = cpl_image_load(cpl_frame_get_filename(schlf_n),CPL_TYPE_FLOAT,
508  0,0);
509  schl_s = cpl_image_load(cpl_frame_get_filename(schlf_s),CPL_TYPE_FLOAT,
510  0,0);
511  if (cpl_error_get_code() != CPL_ERROR_NONE) {
512  cpl_msg_error(fctid,"Unable to read Schlegel maps");
513  freeimage(schl_n);
514  freeimage(schl_s);
515  FATAL_ERROR
516  }
517 
518  /* Set up the structure that will give us the colour equations for
519  this filter later on */
520 
521  if (vircam_phot_open(phottab,filt) != VIR_OK)
522  FATAL_ERROR
523 
524  /* Get a workspace to hold the pointers to the magnitude columns */
525 
526  stdmagptr = cpl_malloc(p.ncolumns*sizeof(float *));
527 
528  /* Get some workspace to hold all the zeropoints for all the images
529  in the input list. This is an initial allocation and more can be
530  made available later if needed */
531 
532  resall3 = cpl_malloc(INITALLOC*sizeof(float));
533  resall5 = cpl_malloc(INITALLOC*sizeof(float));
534  ebmvall = cpl_malloc(INITALLOC*sizeof(float));
535  nresall = 0;
536  nalloc_resall = INITALLOC;
537  zps3 = cpl_malloc(nimages*sizeof(float));
538  zps5 = cpl_malloc(nimages*sizeof(float));
539  ngood = 0;
540  nresimtot = 0;
541  ncut = 0;
542 
543  /* Loop for the input images and catalogues. Create some shorthand
544  variables and work out what the zeropoint fudge factor will be
545  based on the sampling of the current frame and the nominal sampling
546  of a VIRCAM image */
547 
548  for (i = 0; i < nimages; i++) {
549  im = images[i];
550  ehu_im = vircam_fits_get_ehu(im);
551  stds = mstds[i];
552  ehu_cat = vircam_tfits_get_ehu(cats[i]);
553  cdfudge = 2.5*log10((double)pixsize(ehu_im)/NOMPIXSIZE);
554 
555  /* Are there any? */
556 
557  ncat = (int)cpl_table_get_nrow(stds);
558  if (ncat <= 3) {
559  cpl_msg_warning(fctid,"Too few standards available");
560  cpl_error_reset();
561  write_hdr_1(ehu_im,ncat,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,1);
562  write_hdr_1(ehu_cat,ncat,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0);
563  continue;
564  }
565 
566  /* Now for the input catalogues. Start by getting some useful info
567  from the header */
568 
569  saturate = cpl_propertylist_get_float(ehu_cat,"ESO QC SATURATION");
570  apcor3 = cpl_propertylist_get_float(ehu_cat,"APCOR3");
571  apcor5 = cpl_propertylist_get_float(ehu_cat,"APCOR5");
572  rcore = cpl_propertylist_get_float(ehu_cat,"ESO DRS RCORE");
573  skylev = cpl_propertylist_get_float(ehu_cat,"ESO DRS SKYLEVEL");
574  dx = pixsize(ehu_im);
575  (void)vircam_pfits_get_exptime(ehu_cat,&exptime);
576  (void)vircam_pfits_get_airmass(vircam_fits_get_phu(im),&airmass);
577  if (cpl_error_get_code() != CPL_ERROR_NONE) {
578  cpl_msg_error(fctid,"Unable to get header info");
579  cpl_error_reset();
580  continue;
581  }
582 
583  /* Get objects that are not saturated and aren't too elliptical */
584 
585  modifytab(stds,im,saturate,minstars,schl_n,schl_s,&method,&cl);
586  if (cl == NULL) {
587  cpl_msg_error(fctid,"Unable to select data from matched stds tab");
588  cpl_error_reset();
589  write_hdr_1(ehu_im,ncat,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,1);
590  write_hdr_1(ehu_cat,ncat,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0);
591  continue;
592  }
593 
594  /* Dereference some of the columns */
595 
596  ncat = (int)cpl_table_get_nrow(cl);
597  catcore3 = cpl_table_get_data_float(cl,"Aper_flux_3");
598  catcore5 = cpl_table_get_data_float(cl,"Aper_flux_5");
599  ebmv = cpl_table_get_data_float(cl,"ebmv");
600  for (j = 0; j < p.ncolumns; j++)
601  stdmagptr[j] = cpl_table_get_data_float(cl,(p.columns)[j]);
602 
603  /* Get some workspace for the results arrays for this image */
604 
605  resim3 = cpl_malloc(ncat*sizeof(float));
606  resim5 = cpl_malloc(ncat*sizeof(float));
607  nresim = 0;
608 
609  /* Loop for all the standards */
610 
611  extinct = p.extinct*(airmass - 1.0);
612  for (j = 0; j < ncat; j++) {
613 
614  /* Do core magnitude calculation */
615 
616  cf = catcore3[j]/exptime;
617  if (cf < 1.0)
618  cf = 1.0;
619  fluxmag3 = 2.5*log10((double)cf) + apcor3;
620  cf = catcore5[j]/exptime;
621  if (cf < 1.0)
622  cf = 1.0;
623  fluxmag5 = 2.5*log10((double)cf) + apcor5;
624 
625  /* Work out a reference magnitude */
626 
627  refmag = p.offset;
628  for (k = 0; k < p.nmags; k++)
629  refmag += ((p.coloureq)[k]*stdmagptr[k][j]);
630  refmag += min(10.0,ebmv[j])*p.extcoef;
631 
632  /* Work out zero points and store them away for later */
633 
634  dm3 = refmag + fluxmag3 + extinct;
635  dm5 = refmag + fluxmag5 + extinct;
636  resim3[nresim] = dm3 + cdfudge;
637  resim5[nresim++] = dm5 + cdfudge;
638  ebmvall[nresall] = ebmv[j];
639  resall3[nresall] = dm3 + cdfudge;
640  resall5[nresall++] = dm5 + cdfudge;
641  if (nresall == nalloc_resall) {
642  nalloc_resall += INITALLOC;
643  resall3 = cpl_realloc(resall3,nalloc_resall*sizeof(float));
644  resall5 = cpl_realloc(resall5,nalloc_resall*sizeof(float));
645  ebmvall = cpl_realloc(ebmvall,nalloc_resall*sizeof(float));
646  }
647  }
648 
649  /* Ok, what is the mean zeropoint for this image? */
650 
651  (void)vircam_medmad(resim3,NULL,(long)nresim,&med3,&mad);
652  sig3 = mad*1.48;
653  (void)vircam_medmad(resim5,NULL,(long)nresim,&med5,&mad);
654  sig5 = mad*1.48;
655  zps3[ngood] = med3;
656  zps5[ngood++] = med5;
657 
658  /* How many stars were cut from the original file? */
659 
660  nresimtot += cpl_table_get_nrow(cl);
661  ncut += cpl_table_get_nrow(stds) - nresim;
662 
663  /* Delete some workspace */
664 
665  freespace(resim3);
666  freespace(resim5);
667  freetable(cl);
668 
669  /* Calculate the limiting magnitudes */
670 
671  lim3 = med3 - 2.5*log10((5.0*sig3*rcore*sqrt(CPL_MATH_PI))/exptime) -
672  apcor3 - extinct;
673  lim5 = med5 - 2.5*log10((5.0*sig5*rcore*sqrt(CPL_MATH_PI))/exptime) -
674  apcor5 - extinct;
675 
676  /* Calculate sky brightness */
677 
678  skbrt = lim3 - 2.5*log10(skylev/(exptime*dx*dx)) - extinct;
679 
680  /* Write out header stuff. First for the image and then for the
681  catalogue. NB: QC is not allowed to appear in the catalogue */
682 
683  write_hdr_1(ehu_im,nresim,med3,sig3,lim3,med5,sig5,lim5,p.extinct,
684  skbrt,ncut,0);
685  write_hdr_1(ehu_cat,nresim,med3,sig3,lim3,med5,sig5,lim5,p.extinct,
686  skbrt,ncut,0);
687  cpl_propertylist_update_double(ehu_im,"ESO QC LIMITING_MAG",lim3);
688  cpl_propertylist_set_comment(ehu_im,"ESO QC LIMITING_MAG",
689  "[mag] 5 sigma limiting mag.");
690  cpl_propertylist_update_double(ehu_im,"ESO QC SKYBRIGHT",skbrt);
691  cpl_propertylist_set_comment(ehu_im,"ESO QC SKYBRIGHT",
692  "[mag/arcsec**2] sky brightness");
693  }
694 
695  /* Ok, what is the mean zeropoint for all images? */
696 
697  if (nresall > 0) {
698  (void)vircam_medmad(resall3,NULL,(long)nresall,&med3,&mad);
699  sig3 = mad*1.48;
700  (void)vircam_medmad(resall5,NULL,(long)nresall,&med5,&mad);
701  sig5 = mad*1.48;
702  (void)vircam_medmad(ebmvall,NULL,(long)nresall,&medebv,&mad);
703  } else {
704  med3 = 0.0;
705  sig3 = 0.0;
706  med5 = 0.0;
707  sig5 = 0.0;
708  }
709 
710  /* If there were good images, then calculate the RMS of the detector
711  level zeropoints in both apertures */
712 
713  if (ngood > 0) {
714  (void)vircam_medmad(zps3,NULL,(long)ngood,&med,&mad);
715  sig3det = mad*1.48;
716  (void)vircam_medmad(zps5,NULL,(long)ngood,&med,&mad);
717  sig5det = mad*1.48;
718  } else {
719  sig3det = 0.0;
720  sig5det = 0.0;
721  }
722 
723  /* Delete some workspace */
724 
725  freespace(resall3);
726  freespace(resall5);
727  freespace(ebmvall);
728  freespace(stdmagptr);
729  freespace(zps3);
730  freespace(zps5);
731  freeimage(schl_n);
732  freeimage(schl_s);
733  vircam_phot_close();
734 
735  /* Write these results to the header of the images and the catalogues.
736  First the images */
737 
738  for (i = 0; i < nimages; i++) {
739  im = images[i];
740  ehu_im = vircam_fits_get_ehu(im);
741  stds = mstds[i];
742  ehu_cat = vircam_tfits_get_ehu(cats[i]);
743  cpl_propertylist_update_int(ehu_im,"ESO DRS MAGNZPTALL",nresall);
744  cpl_propertylist_set_comment(ehu_im,"ESO DRS MAGNZPTALL",
745  "number of stars in all magzpt calc");
746  cpl_propertylist_update_double(ehu_im,"ESO DRS ZPALL1",med3);
747  cpl_propertylist_set_comment(ehu_im,"ESO DRS ZPALL1",
748  "[mag] zeropoint 1*rcore all images");
749  cpl_propertylist_update_double(ehu_im,"ESO DRS ZPSIGALL1",sig3);
750  cpl_propertylist_set_comment(ehu_im,"ESO DRS ZPSIGALL1",
751  "[mag] zeropoint sigma 1*rcore all images");
752  cpl_propertylist_update_double(ehu_im,"ESO DRS ZPALL2",med5);
753  cpl_propertylist_set_comment(ehu_im,"ESO DRS ZPALL2",
754  "[mag] zeropoint 2*rcore all images");
755  cpl_propertylist_update_double(ehu_im,"ESO DRS ZPSIGALL2",sig5);
756  cpl_propertylist_set_comment(ehu_im,"ESO DRS ZPSIGALL2",
757  "[mag] zeropoint sigma 2*rcore all images");
758  cpl_propertylist_update_double(ehu_im,"ESO DRS MEDEBV",medebv);
759  cpl_propertylist_set_comment(ehu_im,"ESO DRS MEDEBV",
760  "[mag] median galactic colour excess");
761  cpl_propertylist_update_double(ehu_im,"ESO DRS SIGDET1",sig3det);
762  cpl_propertylist_set_comment(ehu_im,"ESO DRS SIGDET1",
763  "[mag] sigma det-level zpt 1*rcore");
764  cpl_propertylist_update_double(ehu_im,"ESO DRS SIGDET2",sig5det);
765  cpl_propertylist_set_comment(ehu_im,"ESO DRS SIGDET2",
766  "[mag] sigma det-level zpt 2*rcore");
767  cpl_propertylist_update_double(ehu_im,"ESO QC MAGZPT",med3);
768  cpl_propertylist_set_comment(ehu_im,"ESO QC MAGZPT",
769  "[mag] photometric zeropoint");
770  cpl_propertylist_update_double(ehu_im,"ESO QC MAGZERR",sig3det);
771  cpl_propertylist_set_comment(ehu_im,"ESO QC MAGZERR",
772  "[mag] photometric zeropoint error");
773  cpl_propertylist_update_int(ehu_im,"ESO QC MAGNZPT",nresimtot);
774  cpl_propertylist_set_comment(ehu_im,"ESO QC MAGNZPT",
775  "number of stars in magzpt calc");
776  cpl_propertylist_update_int(ehu_im,"ESO QC MAGNCUT",ncut);
777  cpl_propertylist_set_comment(ehu_im,"ESO QC MAGNCUT",
778  "number of stars cut from magzpt calc");
779 
780 
781  /* Now the catalogues */
782 
783  cpl_propertylist_update_int(ehu_cat,"ESO DRS MAGNZPTALL",nresall);
784  cpl_propertylist_set_comment(ehu_cat,"ESO DRS MAGNZPTALL",
785  "number of stars in all magzpt calc");
786  cpl_propertylist_update_double(ehu_cat,"ESO DRS ZPALL1",med3);
787  cpl_propertylist_set_comment(ehu_cat,"ESO DRS ZPALL1",
788  "[mag] zeropoint 1*rcore all group images");
789  cpl_propertylist_update_double(ehu_cat,"ESO DRS ZPSIGALL1",sig3);
790  cpl_propertylist_set_comment(ehu_cat,"ESO DRS ZPSIGALL1",
791  "[mag] zeropoint sigma 1*rcore all group images");
792  cpl_propertylist_update_double(ehu_cat,"ESO DRS ZPALL2",med5);
793  cpl_propertylist_set_comment(ehu_cat,"ESO DRS ZPALL2",
794  "[mag] zeropoint 2*rcore all group images");
795  cpl_propertylist_update_double(ehu_cat,"ESO DRS ZPSIGALL2",sig5);
796  cpl_propertylist_set_comment(ehu_cat,"ESO DRS ZPSIGALL2",
797  "[mag] zeropoint sigma 2*rcore all group images");
798  cpl_propertylist_update_double(ehu_cat,"ESO DRS MEDEBV",medebv);
799  cpl_propertylist_set_comment(ehu_cat,"ESO DRS MEDEBV",
800  "[mag] median galactic colour excess");
801  cpl_propertylist_update_double(ehu_cat,"ESO DRS SIGDET1",sig3det);
802  cpl_propertylist_set_comment(ehu_cat,"ESO DRS SIGDET1",
803  "[mag] sigma det-level zpt 1*rcore");
804  cpl_propertylist_update_double(ehu_cat,"ESO DRS SIGDET2",sig5det);
805  cpl_propertylist_set_comment(ehu_cat,"ESO DRS SIGDET2",
806  "[mag] sigma det-level zpt 2*rcore");
807  cpl_propertylist_update_double(ehu_cat,"ESO QC MAGZPT",med3);
808  cpl_propertylist_set_comment(ehu_cat,"ESO QC MAGZPT",
809  "[mag] photometric zeropoint");
810  cpl_propertylist_update_double(ehu_cat,"ESO QC MAGZERR",sig3det);
811  cpl_propertylist_set_comment(ehu_cat,"ESO QC MAGZERR",
812  "[mag] photometric zeropoint error");
813  cpl_propertylist_update_int(ehu_cat,"ESO QC MAGNZPT",nresimtot);
814  cpl_propertylist_set_comment(ehu_cat,"ESO QC MAGNZPT",
815  "number of stars in magzpt calc");
816  cpl_propertylist_update_int(ehu_cat,"ESO QC MAGNCUT",ncut);
817  cpl_propertylist_set_comment(ehu_cat,"ESO QC MAGNCUT",
818  "number of stars cut from magzpt calc");
819  }
820 
821  /* Get out of here */
822 
823  GOOD_STATUS
824 
825 }
826 
827 /*---------------------------------------------------------------------------*/
878 /*---------------------------------------------------------------------------*/
879 
880 extern int vircam_illum(vir_fits **images, cpl_table **mstds,
881  cpl_propertylist **pl, int nimages, char *filt,
882  cpl_table *phottab, int nbsize, cpl_table **illcor,
883  float *illcor_rms,int *status) {
884  const char *fctid = "vircam_illum";
885  char junk[SZBUF];
886  float **stdmagptr,fracx,fracy,**results,cdfudge,saturate,apcor3,exptime;
887  float airmass,*catcore3,*xx,*yy,extinct,cf,fluxmag3,refmag,dm3,med,mad;
888  float xmin,xmax,ymin,ymax,*resall,medall,lcut,hcut,sig,cut,*good;
889  int nx,ny,ifracx,ifracy,nbsizx,nbsizy,nbx,nby,*nres,*nall,i,j,ncat,k;
890  int ix,iy,ind,nresall,nallocall,ngood;
891  vir_fits *im;
892  cpl_propertylist *ehu_im,*ehu_cat;
893  cpl_table *stds,*cl;
894 
895  /* Inherited status */
896 
897  *illcor = NULL;
898  *illcor_rms = 0.0;
899  if (*status != VIR_OK)
900  return(*status);
901 
902  /* Check for nonsense errors */
903 
904  if (nimages <= 0) {
905  cpl_msg_error(fctid,"No images included in photometric calibration");
906  FATAL_ERROR
907  }
908 
909  /* Set up the structure that will give us the colour equations for
910  this filter later on */
911 
912  if (vircam_phot_open(phottab,filt) != VIR_OK)
913  FATAL_ERROR
914 
915  /* Get a workspace to hold the pointers to the magnitude columns */
916 
917  stdmagptr = cpl_malloc(p.ncolumns*sizeof(float *));
918 
919  /* Check to see if nbsize is close to exact divisor */
920 
921  nx = (int)cpl_image_get_size_x(vircam_fits_get_image(images[0]));
922  ny = (int)cpl_image_get_size_y(vircam_fits_get_image(images[0]));
923  fracx = ((float)nx)/((float)nbsize);
924  fracy = ((float)ny)/((float)nbsize);
925  ifracx = (int)(fracx + 0.1);
926  ifracy = (int)(fracy + 0.1);
927  nbsizx = nx/ifracx;
928  nbsizy = ny/ifracy;
929  nbsize = max(vircam_nint(0.9*nbsize),min(nbsize,min(nbsizx,nbsizy)));
930  nbsize = min(nx,min(ny,nbsize)); /* trap for small maps */
931 
932  /* Divide the map into partitions */
933 
934  nbx = nx/nbsize;
935  nby = ny/nbsize;
936 
937  /* Get some workspace to hold all the zeropoints for all the images
938  in the input list. This is an initial allocation and more can be
939  made available later if needed */
940 
941  results = cpl_malloc(nbx*nby*sizeof(float *));
942  good = cpl_malloc(nbx*nby*sizeof(float));
943  nres = cpl_calloc(nbx*nby,sizeof(int));
944  nall = cpl_malloc(nbx*nby*sizeof(int));
945  for (i = 0; i < nbx*nby; i++) {
946  results[i] = cpl_malloc(INITALLOC*sizeof(float));
947  nall[i] = INITALLOC;
948  }
949  resall = cpl_malloc(INITALLOC*sizeof(float));
950  nresall = 0;
951  nallocall = INITALLOC;
952 
953  /* Set up the output illumination correction table */
954 
955  *illcor = vircam_illcor_newtab(nbx*nby);
956 
957  /* Loop for the input images and catalogues. Create some shorthand
958  variables and work out what the zeropoint fudge factor will be
959  based on the sampling of the current frame and the nominal sampling
960  of a VIRCAM image */
961 
962  for (i = 0; i < nimages; i++) {
963  im = images[i];
964  ehu_im = vircam_fits_get_ehu(im);
965  stds = mstds[i];
966  if (stds == NULL)
967  continue;
968  ehu_cat = pl[i];
969  cdfudge = 2.5*log10((double)pixsize(ehu_im)/NOMPIXSIZE);
970 
971  /* Now for the input catalogues. Start by getting some useful info
972  from the header */
973 
974  saturate = cpl_propertylist_get_float(ehu_cat,"ESO QC SATURATION");
975  apcor3 = cpl_propertylist_get_float(ehu_cat,"APCOR3");
976  (void)vircam_pfits_get_exptime(vircam_fits_get_phu(im),&exptime);
977  (void)vircam_pfits_get_airmass(vircam_fits_get_phu(im),&airmass);
978  if (cpl_error_get_code() != CPL_ERROR_NONE) {
979  cpl_msg_error(fctid,"Unable to get header info for %s",
981  cpl_error_reset();
982  continue;
983  }
984 
985  /* Get objects that are not saturated and aren't too elliptical */
986 
987  cpl_table_select_all(stds);
988  (void)cpl_table_and_selected_float(stds,"Ellipticity",CPL_LESS_THAN,
989  0.5);
990  (void)cpl_table_and_selected_float(stds,"Peak_height",CPL_LESS_THAN,
991  saturate);
992  if (cpl_error_get_code() != CPL_ERROR_NONE) {
993  cpl_msg_error(fctid,"Unable select data from matched stds tab %s",
995  cpl_error_reset();
996  continue;
997  }
998 
999  /* Get all objects where the magnitude errors are less than 0.1 */
1000 
1001  for (j = 0; j < p.ncolumns; j++) {
1002  (void)snprintf(junk,SZBUF,"%ssig",(p.columns)[j]);
1003  (void)cpl_table_and_selected_float(stds,junk,CPL_LESS_THAN,0.1);
1004  }
1005 
1006  /* Now extract all those that have passed the test. If none are left
1007  then issue a warning and move on to the next one */
1008 
1009  cl = cpl_table_extract_selected(stds);
1010  ncat = (int)cpl_table_get_nrow(cl);
1011  if (ncat == 0) {
1012  cpl_msg_error(fctid,"No good standards available for %s",
1014  cpl_table_delete(cl);
1015  cpl_error_reset();
1016  continue;
1017  }
1018 
1019  /* Dereference some of the columns */
1020 
1021  catcore3 = cpl_table_get_data_float(cl,"Aper_flux_3");
1022  xx = cpl_table_get_data_float(cl,"X_coordinate");
1023  yy = cpl_table_get_data_float(cl,"Y_coordinate");
1024  for (j = 0; j < p.ncolumns; j++)
1025  stdmagptr[j] = cpl_table_get_data_float(cl,(p.columns)[j]);
1026 
1027  /* Loop for all the standards */
1028 
1029  extinct = p.extinct*(airmass - 1.0);
1030  for (j = 0; j < ncat; j++) {
1031 
1032  /* Do core magnitude calculation */
1033 
1034  cf = catcore3[j]/exptime;
1035  if (cf < 1.0)
1036  cf = 1.0;
1037  fluxmag3 = 2.5*log10((double)cf) + apcor3;
1038 
1039  /* Work out a reference magnitude */
1040 
1041  refmag = p.offset;
1042  for (k = 0; k < p.nmags; k++)
1043  refmag += ((p.coloureq)[k]*stdmagptr[k][j]);
1044 
1045  /* Work out zero point */
1046 
1047  dm3 = refmag + fluxmag3 + extinct + cdfudge;
1048 
1049  /* What cell does this belong to? */
1050 
1051  ix = (int)(xx[j]/(float)nbsize);
1052  iy = (int)(yy[j]/(float)nbsize);
1053  ind = iy*nbx + ix;
1054  if (nres[ind] == nall[ind] - 1) {
1055  results[ind] = cpl_realloc(results[ind],
1056  (nall[ind]+INITALLOC)*sizeof(float));
1057  nall[ind] += INITALLOC;
1058  }
1059  results[ind][nres[ind]] = dm3;
1060  nres[ind] += 1;
1061 
1062  /* Add this into the global solution too */
1063 
1064  if (nresall == nallocall) {
1065  resall = cpl_realloc(resall,(nallocall+INITALLOC)*sizeof(float));
1066  nallocall += INITALLOC;
1067  }
1068  resall[nresall++] = dm3;
1069  }
1070 
1071  /* Get rid of the table subset */
1072 
1073  freetable(cl);
1074  }
1075 
1076  /* What is the global zero point ? */
1077 
1078  if (nresall != 0) {
1079  (void)vircam_medmad(resall,NULL,(long)nresall,&medall,&mad);
1080  cut = max(3.0*1.48*mad,0.1);
1081  lcut = medall - cut;
1082  hcut = medall + cut;
1083  (void)vircam_meansigcut(resall,NULL,(long)nresall,lcut,hcut,
1084  &medall,&sig);
1085  }
1086 
1087  /* Ok, what is the mean zeropoint for each cell. Do all of this stuff
1088  even if nresall == 0 so that we at least have a table with all
1089  zeros at the end of this */
1090 
1091  ngood = 0;
1092  for (i = 0; i < nbx*nby; i++) {
1093  if (nres[i] > 0) {
1094  (void)vircam_medmad(results[i],NULL,(long)nres[i],&med,&mad);
1095  cut = max(3.0*1.48*mad,0.3);
1096  lcut = med - cut;
1097  hcut = med + cut;
1098  (void)vircam_meansigcut(results[i],NULL,(long)nres[i],lcut,hcut,
1099  &med,&sig);
1100  med -= medall;
1101  good[ngood++] = med;
1102  } else {
1103  med = -99.0;
1104  }
1105 
1106  /* Where are we in the map? */
1107 
1108  iy = i/nbx;
1109  ix = i - iy*nbx;
1110  xmin = ix*nbsize;
1111  xmax = xmin + nbsize - 1;
1112  if (ix == nbx)
1113  xmax = nx;
1114  ymin = iy*nbsize;
1115  ymax = ymin + nbsize - 1;
1116  if (iy == nby)
1117  ymax = ny;
1118 
1119  /* Write out the results into illumination table */
1120 
1121  cpl_table_set_float(*illcor,"xmin",(cpl_size)i,xmin);
1122  cpl_table_set_float(*illcor,"xmax",(cpl_size)i,xmax);
1123  cpl_table_set_float(*illcor,"ymin",(cpl_size)i,ymin);
1124  cpl_table_set_float(*illcor,"ymax",(cpl_size)i,ymax);
1125  cpl_table_set_float(*illcor,"illcor",(cpl_size)i,med);
1126  }
1127 
1128  /* Get the RMS of the map */
1129 
1130  if (ngood > 0)
1131  vircam_medsig(good,NULL,(long)ngood,&med,illcor_rms);
1132  else
1133  *illcor_rms = 0.0;
1134 
1135  /* Delete some workspace */
1136 
1137  for (i = 0; i < nbx*nby; i++)
1138  freespace(results[i]);
1139  freespace(results);
1140  freespace(nres);
1141  freespace(nall);
1142  freespace(stdmagptr);
1143  freespace(resall);
1144  freespace(good);
1145  vircam_phot_close();
1146 
1147  /* Set out the appropriate return status */
1148 
1149  if (nresall != 0)
1150  GOOD_STATUS
1151  else
1152  WARN_RETURN
1153 
1154 }
1155 
1156 /*---------------------------------------------------------------------------*/
1173 /*---------------------------------------------------------------------------*/
1174 
1175 static double pixsize (cpl_propertylist *plist) {
1176  double cd1_1,cd1_2,pix;
1177 
1178  if (vircam_pfits_get_cd11(plist,&cd1_1) != VIR_OK ||
1179  vircam_pfits_get_cd12(plist,&cd1_2) != VIR_OK) {
1180  pix = NOMPIXSIZE;
1181  } else {
1182  pix = 3600.0*sqrt(cd1_1*cd1_1 + cd1_2*cd1_2);
1183  }
1184  return(pix);
1185 }
1186 
1187 /*---------------------------------------------------------------------------*/
1210 /*---------------------------------------------------------------------------*/
1211 
1212 static int vircam_phot_open(cpl_table *phottab, char *filt) {
1213  const char *fctid = "vircam_phot_open";
1214  int ns,nerr,null;
1215  cpl_table *subset;
1216  const char *req_cols[5] = {"filter","extinction","offset","columns",
1217  "coleq"};
1218 
1219  /* Initialise a few things */
1220 
1221  p.coloureq = NULL;
1222  p.columns = NULL;
1223  p.nmags = 0;
1224  p.ncolumns = 0;
1225  p.offset = 0.0;
1226 
1227  /* Check the table and make sure it has all the required columns */
1228 
1229  nerr = 0;
1230  for (ns = 0; ns < 5; ns++) {
1231  if (! cpl_table_has_column(phottab,req_cols[ns])) {
1232  cpl_msg_error(fctid,"Photometry table missing column %s",
1233  req_cols[ns]);
1234  nerr++;
1235  }
1236  }
1237  if (nerr > 0)
1238  return(VIR_FATAL);
1239 
1240  /* Search the table and find the rows that matches the filter */
1241 
1242  ns = (int)cpl_table_and_selected_string(phottab,"filter",CPL_EQUAL_TO,filt);
1243  if (ns <= 0) {
1244  cpl_msg_error(fctid,"Unable to match photometry table to filter %s",
1245  filt);
1246  return(VIR_FATAL);
1247  } else if (ns > 1) {
1248  cpl_msg_error(fctid,"More than one row matches filter %s",filt);
1249  }
1250 
1251  /* Read the information from the selected row */
1252 
1253  subset = cpl_table_extract_selected(phottab);
1254  p.filt = (char *)cpl_table_get_string(subset,"filter",0);
1255  p.extinct = cpl_table_get_float(subset,"extinction",0,&null);
1256  p.offset = cpl_table_get_float(subset,"offset",0,&null);
1257 
1258  /* for pipeline backward compatibility with old table structure */
1259  if(cpl_table_has_column(subset, "extcoef")){
1260  p.extcoef = cpl_table_get_float(subset,"extcoef",0,&null);
1261  } else {
1262  cpl_msg_warning(cpl_func,"Table column extcoef not found in the table, "
1263  "assuming an extinction coefficient of Zero");
1264  p.extcoef = 0.;
1265  }
1266 
1267  if (extract_columns(subset) != VIR_OK) {
1268  freetable(subset);
1269  return(VIR_FATAL);
1270  }
1271  if (extract_coleq(subset) != VIR_OK) {
1272  freetable(subset);
1273  return(VIR_FATAL);
1274  }
1275  freetable(subset);
1276 
1277  /* Get out of here */
1278 
1279  return(VIR_OK);
1280 }
1281 
1282 
1283 /*---------------------------------------------------------------------------*/
1297 /*---------------------------------------------------------------------------*/
1298 
1299 static void vircam_phot_close(void) {
1300  int j;
1301 
1302  for (j = 0; j < p.ncolumns; j++)
1303  freespace((p.columns)[j]);
1304  freespace(p.columns);
1305  freespace(p.coloureq);
1306 }
1307 
1308 /*---------------------------------------------------------------------------*/
1325 /*---------------------------------------------------------------------------*/
1326 
1327 static int extract_columns(cpl_table *tab) {
1328  int nv,i,j;
1329  char *v,*w;
1330 
1331  /* Get the relevant value from the table */
1332 
1333  v = cpl_strdup(cpl_table_get_string(tab,"columns",0));
1334 
1335  /* Count the number of commas in the string to see how many
1336  columns there are */
1337 
1338  nv = 1;
1339  j = strlen(v);
1340  for (i = 0; i < j; i++)
1341  if (v[i] == ',')
1342  nv++;
1343  p.ncolumns = nv;
1344 
1345  /* Now parse the string into the column names */
1346 
1347  p.columns = cpl_malloc(nv*sizeof(char *));
1348  for (i = 0; i < nv; i++) {
1349  if (i == 0)
1350  w = strtok(v,",");
1351  else
1352  w = strtok(NULL,",");
1353  (p.columns)[i] = cpl_strdup(w);
1354  }
1355  freespace(v);
1356  return(VIR_OK);
1357 }
1358 
1359 /*---------------------------------------------------------------------------*/
1376 /*---------------------------------------------------------------------------*/
1377 
1378 static int extract_coleq(cpl_table *tab) {
1379  int nv,i,j;
1380  char *v,*w;
1381 
1382  /* Get the relevant value from the table */
1383 
1384  v = cpl_strdup(cpl_table_get_string(tab,"coleq",0));
1385 
1386  /* Count the number of commas in the string to see how many
1387  columns there are */
1388 
1389  nv = 1;
1390  j = strlen(v);
1391  for (i = 0; i < j; i++)
1392  if (v[i] == ',')
1393  nv++;
1394  p.nmags = nv;
1395 
1396  /* Now parse the string into the colour equation values */
1397 
1398  p.coloureq = cpl_malloc(nv*sizeof(float));
1399  for (i = 0; i < nv; i++) {
1400  if (i == 0)
1401  w = strtok(v,",");
1402  else
1403  w = strtok(NULL,",");
1404  (p.coloureq)[i] = (float)atof(w);
1405  }
1406  freespace(v);
1407  return(VIR_OK);
1408 }
1409 
1410 static void write_hdr_1(cpl_propertylist *pl, int nresim, float med3,
1411  float sig3, float lim3, float med5, float sig5,
1412  float lim5, float extinct, float skybrt, int ncut,
1413  int doqc) {
1414 
1415  /* Write these results to the header of the image and the catalogue.
1416  First the QC headers for the image. These are not allowed to be
1417  copied into the catalogue headers...*/
1418 
1419  if (doqc) {
1420  cpl_propertylist_update_double(pl,"ESO QC MAGZPT",med3);
1421  cpl_propertylist_set_comment(pl,"ESO QC MAGZPT",
1422  "[mag] photometric zeropoint");
1423  cpl_propertylist_update_double(pl,"ESO QC MAGZERR",sig3);
1424  cpl_propertylist_set_comment(pl,"ESO QC MAGZERR",
1425  "[mag] photometric zeropoint error");
1426  cpl_propertylist_update_int(pl,"ESO QC MAGNZPT",nresim);
1427  cpl_propertylist_set_comment(pl,"ESO QC MAGNZPT",
1428  "number of stars in magzpt calc");
1429  cpl_propertylist_update_int(pl,"ESO QC MAGNCUT",ncut);
1430  cpl_propertylist_set_comment(pl,"ESO QC MAGNCUT",
1431  "number of stars cut from magzpt calc");
1432  cpl_propertylist_update_double(pl,"ESO QC LIMITING_MAG",lim3);
1433  cpl_propertylist_set_comment(pl,"ESO QC LIMITING_MAG",
1434  "[mag] 5 sigma limiting mag.");
1435  cpl_propertylist_update_double(pl,"ESO QC SKYBRIGHT",skybrt);
1436  cpl_propertylist_set_comment(pl,"ESO QC SKYBRIGHT",
1437  "[mag/arcsec**2] sky brightness");
1438  }
1439 
1440  /* Now the DRS headers for the image */
1441 
1442  cpl_propertylist_update_int(pl,"ESO DRS MAGNZPTIM",nresim);
1443  cpl_propertylist_set_comment(pl,"ESO DRS MAGNZPTIM",
1444  "number of stars in image magzpt calc");
1445 
1446  cpl_propertylist_update_double(pl,"ESO DRS ZPIM1",med3);
1447  cpl_propertylist_set_comment(pl,"ESO DRS ZPIM1",
1448  "[mag] zeropoint 1*rcore this image only");
1449  cpl_propertylist_update_double(pl,"ESO DRS ZPSIGIM1",sig3);
1450  cpl_propertylist_set_comment(pl,"ESO DRS ZPSIGIM1",
1451  "[mag] zeropoint sigma 1*rcore this image only");
1452  cpl_propertylist_update_double(pl,"ESO DRS LIMIT_MAG1",lim3);
1453  cpl_propertylist_set_comment(pl,"ESO DRS LIMIT_MAG1",
1454  "[mag] 5 sigma limiting mag 1*rcore.");
1455  cpl_propertylist_update_double(pl,"ESO DRS ZPIM2",med5);
1456  cpl_propertylist_set_comment(pl,"ESO DRS ZPIM2",
1457  "[mag] zeropoint 2*rcore this image only");
1458  cpl_propertylist_update_double(pl,"ESO DRS ZPSIGIM2",sig5);
1459  cpl_propertylist_set_comment(pl,"ESO DRS ZPSIGIM2",
1460  "[mag] zeropoint sigma 2*rcore this image only");
1461  cpl_propertylist_update_double(pl,"ESO DRS LIMIT_MAG2",lim5);
1462  cpl_propertylist_set_comment(pl,"ESO DRS LIMIT_MAG2",
1463  "[mag] 5 sigma limiting mag core5.");
1464  cpl_propertylist_update_double(pl,"ESO DRS EXTINCT",extinct);
1465  cpl_propertylist_set_comment(pl,"ESO DRS EXTINCT",
1466  "[mag] Assumed extinction.");
1467  cpl_propertylist_update_double(pl,"ESO DRS SKYBRIGHT",skybrt);
1468  cpl_propertylist_set_comment(pl,"ESO DRS SKYBRIGHT",
1469  "[mag/arcsec**2] sky brightness");
1470 }
1471 
1472 static void modifytab(cpl_table *intab, vir_fits *im, float saturate,
1473  int minstars, cpl_image *schl_n, cpl_image *schl_s,
1474  int *method, cpl_table **outtab) {
1475  cpl_table *tmptab;
1476  float satcut,*ebmv,*jmk,*jmag,*kmag,jext,hext,kext,ebv;
1477  float *jmk_corr,*flux1,*flux2,*x,*y,distcor,*ra,*dec;
1478  int i,nrows;
1479  mywcs *w;
1480  const char *fctid = "modifytab";
1481 
1482  /* Initialise the return values */
1483 
1484  *method = 0;
1485  *outtab = NULL;
1486 
1487  /* Find the peak height column and the sky column. Make a new column
1488  that is the peak height and sky combined. This is to be used in
1489  a saturation cut */
1490 
1491  tmptab = cpl_table_duplicate(intab);
1492  nrows = (int)cpl_table_get_nrow(tmptab);
1493  cpl_table_duplicate_column(tmptab,"Pkandsky",tmptab,"Peak_height");
1494  cpl_table_add_columns(tmptab,"Pkandsky","Sky_level");
1495 
1496  /* Do an initial selection based on peak_height (saturation), ellipticity,
1497  stellar class and classification statistic */
1498 
1499  satcut = 0.9*saturate;
1500  cpl_table_select_all(tmptab);
1501  cpl_table_and_selected_float(tmptab,"Ellipticity",CPL_LESS_THAN,0.5);
1502  cpl_table_and_selected_float(tmptab,"Pkandsky",CPL_LESS_THAN,satcut);
1503  cpl_table_and_selected_float(tmptab,"Classification",CPL_EQUAL_TO,-1.0);
1504  cpl_table_and_selected_float(tmptab,"Statistic",CPL_LESS_THAN,3.0);
1505 
1506  /* Count how many we've got. If there are too few left, then get out of
1507  here and signal an error */
1508 
1509  if (cpl_table_count_selected(tmptab) < minstars) {
1510  cpl_table_delete(tmptab);
1511  cpl_msg_error(fctid,"Matched standards has too few stars that are"
1512  " not saturated or have low enough ellipticity");
1513  return;
1514  }
1515 
1516  /* Ok, so cull the rows that we didn't like */
1517 
1518  cpl_table_not_selected(tmptab);
1519  cpl_table_erase_selected(tmptab);
1520  cpl_table_select_all(tmptab);
1521  nrows = cpl_table_get_nrow(tmptab);
1522 
1523  /* Now create three more columns for the colour excess, J-K and the
1524  absorption corrected value of J-K */
1525 
1526  cpl_table_duplicate_column(tmptab,"ebmv",tmptab,"Peak_height");
1527  cpl_table_duplicate_column(tmptab,"jmk",tmptab,"Peak_height");
1528  cpl_table_duplicate_column(tmptab,"jmk_corr",tmptab,"Peak_height");
1529 
1530  /* Get the data arrays for these new columns and use the Schlegel maps
1531  to work out values for them */
1532 
1533  ebmv = cpl_table_get_data_float(tmptab,"ebmv");
1534  jmk = cpl_table_get_data_float(tmptab,"jmk");
1535  jmk_corr = cpl_table_get_data_float(tmptab,"jmk_corr");
1536  jmag = cpl_table_get_data_float(tmptab,"j_m");
1537  kmag = cpl_table_get_data_float(tmptab,"k_m");
1538  ra = cpl_table_get_data_float(tmptab,"RA");
1539  dec = cpl_table_get_data_float(tmptab,"Dec");
1540  for (i = 0; i < nrows; i++) {
1541  getextinct(schl_n,schl_s,(double)(ra[i]),(double)(dec[i]),&jext,
1542  &hext,&kext,&ebv);
1543  jmk[i] = jmag[i] - kmag[i];
1544  jmk_corr[i] = jmk[i] - jext + kext;
1545  if (jmk[i] < 0.0)
1546  ebmv[i] = max(0.0,ebv - (0.5-jmk_corr[i])/0.53);
1547  else
1548  ebmv[i] = ebv;
1549  }
1550 
1551  /* Ok, now cut on colour and corrected colour and see how many stars
1552  you have left */
1553 
1554  *method = 1;
1555  cpl_table_and_selected_float(tmptab,"jmk_corr",CPL_NOT_LESS_THAN,0.0);
1556  cpl_table_and_selected_float(tmptab,"jmk_corr",CPL_NOT_GREATER_THAN,1.0);
1557  cpl_table_and_selected_float(tmptab,"jmk",CPL_LESS_THAN,2.0);
1558  if (cpl_table_count_selected(tmptab) > minstars) {
1559  *outtab = cpl_table_extract_selected(tmptab);
1560  cpl_table_delete(tmptab);
1561  return;
1562  }
1563 
1564  /* If that cut is too severe, then try relaxing it a bit */
1565 
1566  *method = 2;
1567  cpl_table_select_all(tmptab);
1568  cpl_table_and_selected_float(tmptab,"jmk_corr",CPL_NOT_GREATER_THAN,1.0);
1569  cpl_table_and_selected_float(tmptab,"jmk",CPL_NOT_LESS_THAN,0.0);
1570  if (cpl_table_count_selected(tmptab) > minstars) {
1571  *outtab = cpl_table_extract_selected(tmptab);
1572  cpl_table_delete(tmptab);
1573  return;
1574  }
1575 
1576  /* If that cuts too many, then just take everything we have and run
1577  with it */
1578 
1579  *method = 3;
1580  cpl_table_unselect_all(tmptab);
1581  *outtab = cpl_table_duplicate(tmptab);
1582  cpl_table_delete(tmptab);
1583 
1584  /* Work out the photometric distortion due to the camera optics and
1585  correct the two fluxes we need to use */
1586 
1587  w = getwcs(im);
1588  flux1 = cpl_table_get_data_float(*outtab,"Aper_flux_3");
1589  flux2 = cpl_table_get_data_float(*outtab,"Aper_flux_5");
1590  x = cpl_table_get_data_float(*outtab,"X_coordinate");
1591  y = cpl_table_get_data_float(*outtab,"Y_coordinate");
1592  nrows = cpl_table_get_nrow(*outtab);
1593  for (i = 0; i < nrows; i++) {
1594  distcor = distort_corr((double)x[i],(double)y[i],w);
1595  flux1[i] *= distcor;
1596  flux2[i] *= distcor;
1597  }
1598  freespace(w);
1599  return;
1600 }
1601 
1602 static void getextinct(cpl_image *schl_n, cpl_image *schl_s, double ra,
1603  double dec, float *jext, float *hext, float *kext,
1604  float *ebv) {
1605  double gal_l,gal_b,sin_b,cos_l,sin_l;
1606  cpl_image *schl;
1607  float x,y,*schl_data,xx,yy,delx,dely;
1608  int ix,iy,iarg1,iarg2,iarg3,iarg4,nx,ny;
1609 
1610  /* Get the galactic coordinates for this ra and dec */
1611 
1612  radectolb(ra,dec,2000.0,&gal_l,&gal_b);
1613  gal_l *= CPL_MATH_DEG_RAD;
1614  gal_b *= CPL_MATH_DEG_RAD;
1615 
1616  /* Get the relevant Schlegel data */
1617 
1618  schl = (gal_b >= 0.0 ? schl_n : schl_s);
1619  schl_data = cpl_image_get_data_float(schl);
1620 
1621  /* Get the x,y coordinates for this position. This formula is taken
1622  from the original Schlegel article */
1623 
1624  sin_b = sin(gal_b);
1625  cos_l = cos(gal_l);
1626  sin_l = sin(gal_l);
1627  if (gal_b >= 0.0) {
1628  x = 2048.0*sqrt(1.0 - sin_b)*cos_l + 2047.5;
1629  y = -2048.0*sqrt(1.0 - sin_b)*sin_l + 2047.5;
1630  } else {
1631  x = 2048.0*sqrt(1.0 + sin_b)*cos_l + 2047.5;
1632  y = 2048.0*sqrt(1.0 + sin_b)*sin_l + 2047.5;
1633  }
1634 
1635  /* Get the pixel and the ones next to it */
1636 
1637  nx = (int)cpl_image_get_size_x(schl_n);
1638  ny = (int)cpl_image_get_size_y(schl_n);
1639  ix = min(nx-2,max(0,(int)x));
1640  iy = min(ny-2,max(0,(int)y));
1641  delx = x - (int)x;
1642  dely = y - (int)y;
1643  iarg1 = iy*nx + ix;
1644  iarg2 = iarg1 + 1;
1645  iarg3 = iarg1 + nx;
1646  iarg4 = iarg2 + nx;
1647 
1648  /* Get the values and do the interpolation. Use Bonifacio et al
1649  (2000) correction */
1650 
1651  xx = (1.0 - delx)*schl_data[iarg1] + delx*schl_data[iarg2];
1652  yy = (1.0 - delx)*schl_data[iarg3] + delx*schl_data[iarg4];
1653  *ebv = (1.0 - dely)*xx + dely*yy;
1654  if (*ebv > 0.1)
1655  *ebv = 0.1 + 0.65*(*ebv - 0.1);
1656 
1657  /* Now the wavelength dependent extinctions. The coeffs are from
1658  Schlegel for UKIRT. NB: Roca-Pinto uses 0.25 for K and Majewski
1659  uses 0.82, 0.48, 0.28 */
1660 
1661  *jext = 0.90*(*ebv);
1662  *hext = 0.58*(*ebv);
1663  *kext = 0.37*(*ebv);
1664 }
1665 
1666 static void radectolb(double ra, double dec, float epoch, double *gal_l,
1667  double *gal_b) {
1668  double ti,tf,s,z,h,arcsecrad,ra2,dec2,cosdec1,sindec1,cosra1s,sinra1s;
1669  double cos_h,sin_h,x1,x2,sinb,cosdec2,sindec2,costheta,sintheta;
1670  double cosdra,sindra,ra1,dec1,sinra2,cosra2;
1671  double a0=282.25,theta=62.6,gal_l0=33.0;
1672  float equin=1950;
1673 
1674  /* Start by precessing coordinates to 1950 using IAU 1976 precession
1675  quuantities */
1676 
1677  ti = (double)(epoch - 2000.0)/100.0;
1678  tf = (double)(equin - 2000.0)/100.0 - ti;
1679  s = (2306.2181 - 1.39656*ti - 0.000139*ti*ti)*tf +
1680  (0.30188 - 0.000344*ti)*tf*tf + 0.17998*tf*tf*tf;
1681  z = s + (0.79280 + 0.000410*ti)*tf*tf + 0.000205*tf*tf*tf;
1682  h = (2004.3109 - 0.85330*ti - 0.000217*ti*ti)*tf -
1683  (0.42665 + 0.000217*ti)*tf*tf - 0.041833*tf*tf*tf;
1684 
1685  /* Convert to radians */
1686 
1687  arcsecrad = 1.0/(CPL_MATH_DEG_RAD*3600.0);
1688  s *= arcsecrad;
1689  z *= arcsecrad;
1690  h *= arcsecrad;
1691  ra1 = ra/CPL_MATH_DEG_RAD;
1692  dec1 = dec/CPL_MATH_DEG_RAD;
1693 
1694  /* Apply precession to give new RA and Dec in radians */
1695 
1696  cosdec1 = cos(dec1);
1697  sindec1 = sin(dec1);
1698  cosra1s = cos(ra1+s);
1699  sinra1s = sin(ra1+s);
1700  cos_h = cos(h);
1701  sin_h = sin(h);
1702  dec2 = asin(cosdec1*cosra1s*sin_h + sindec1*cos_h);
1703  cosdec2 = cos(dec2);
1704  sinra2 = cosdec1*sinra1s/cosdec2;
1705  cosra2 = (cosdec1*cosra1s*cos_h - sindec1*sin_h)/cosdec2;
1706  ra2 = atan2(sinra2,cosra2) + z;
1707 
1708  /* Check to make sure the new RA isn't negative */
1709 
1710  if (ra2 < 0.0)
1711  ra2 += CPL_MATH_2PI;
1712 
1713  /* Convert galactic reference poles to radians */
1714 
1715  a0 /= CPL_MATH_DEG_RAD;
1716  theta /= CPL_MATH_DEG_RAD;
1717  gal_l0 /= CPL_MATH_DEG_RAD;
1718 
1719  /* Do the conversion now */
1720 
1721  sindec2 = sin(dec2);
1722  costheta = cos(theta);
1723  sintheta = sin(theta);
1724  cosdra = cos(ra2 - a0);
1725  sindra = sin(ra2 - a0);
1726  x1 = cosdec2*cosdra;
1727  x2 = cosdec2*sindra*costheta + sindec2*sintheta;
1728  *gal_l = atan2(x2,x1) + gal_l0;
1729  if (*gal_l < 0)
1730  *gal_l += CPL_MATH_2PI;
1731  sinb = sindec2*costheta - cosdec2*sindra*sintheta;
1732  *gal_b = asin(sinb);
1733 }
1734 
1735 static mywcs *getwcs(vir_fits *in) {
1736  mywcs *w;
1737  cpl_propertylist *plist;
1738  int i;
1739 
1740  /* Get the memory and the data from the propertylist */
1741 
1742  plist = vircam_fits_get_ehu(in);
1743  w = cpl_malloc(sizeof(mywcs));
1744  if (strstr(cpl_propertylist_get_string(plist,"CTYPE1"),"TAN") == NULL)
1745  w->istan = 0;
1746  else
1747  w->istan = 1;
1748  w->crval[0] = cpl_propertylist_get_double(plist,"CRVAL1");
1749  w->crval[1] = cpl_propertylist_get_double(plist,"CRVAL2");
1750  w->crpix[0] = cpl_propertylist_get_double(plist,"CRPIX1");
1751  w->crpix[1] = cpl_propertylist_get_double(plist,"CRPIX2");
1752  w->cd[0] = cpl_propertylist_get_double(plist,"CD1_1");
1753  w->cd[1] = cpl_propertylist_get_double(plist,"CD1_2");
1754  w->cd[2] = cpl_propertylist_get_double(plist,"CD2_1");
1755  w->cd[3] = cpl_propertylist_get_double(plist,"CD2_2");
1756  if (! w->istan) {
1757  if (cpl_propertylist_has(plist,"PV2_1"))
1758  w->pv21 = cpl_propertylist_get_double(plist,"PV2_1");
1759  else
1760  w->pv21 = 1.0;
1761  if (cpl_propertylist_has(plist,"PV2_3"))
1762  w->pv23 = cpl_propertylist_get_double(plist,"PV2_3");
1763  else
1764  w->pv23 = -0.3333333333;
1765  if (cpl_propertylist_has(plist,"PV2_5"))
1766  w->pv25 = cpl_propertylist_get_double(plist,"PV2_5");
1767  else
1768  w->pv25 = 0.0;
1769  } else {
1770  w->pv21 = 1.0;
1771  w->pv23 = -0.33333333;
1772  w->pv25 = 0.0;
1773  }
1774  w->nx = cpl_image_get_size_x(vircam_fits_get_image(in));
1775  w->ny = cpl_image_get_size_y(vircam_fits_get_image(in));
1776 
1777  /* Change angles to radians */
1778 
1779  for (i = 0; i < 2; i++)
1780  w->crval[i] /= CPL_MATH_DEG_RAD;
1781  for (i = 0; i < 4; i++)
1782  w->cd[i] /= CPL_MATH_DEG_RAD;
1783 
1784  /* Add a couple of convenience values */
1785 
1786  w->tand = tan(w->crval[1]);
1787  w->secd = 1.0/cos(w->crval[1]);
1788 
1789  /* Now the store away WCS... */
1790 
1791  return(w);
1792 }
1793 
1794 static float distort_corr(double x, double y, mywcs *w) {
1795  double xi,xn,r,rprime,drprime_bydr,dc,tanr;
1796 
1797  xi = (x - w->crpix[0])*(w->cd[0]) + (y - w->crpix[1])*(w->cd[1]);
1798  xn = (x - w->crpix[0])*(w->cd[2]) + (y - w->crpix[1])*(w->cd[3]);
1799  r = sqrt(xi*xi + xn*xn);
1800  if (r == 0.0) {
1801  dc = 1.0;
1802  } else {
1803  if (! w->istan) {
1804  rprime = r*w->pv21 + pow(r,(double)3.0)*w->pv23 +
1805  pow(r,(double)5.0)*w->pv25;
1806  drprime_bydr = w->pv21 + 3.0*pow(r,(double)2.0)*w->pv23 +
1807  5.0*pow(r,(double)4.0)*w->pv25;
1808  tanr = tan(rprime);
1809  dc = tanr*drprime_bydr*(1.0 + tanr*tanr)/r;
1810  } else {
1811  tanr = tan(r);
1812  dc = (1.0 + tanr*tanr)*tanr/r;
1813  }
1814  }
1815  return(dc);
1816 }
1817 
1820 /*
1821 
1822 $Log: not supported by cvs2svn $
1823 Revision 1.38 2012/01/27 12:25:10 jim
1824 Fixed some casts
1825 
1826 Revision 1.37 2012/01/15 17:40:09 jim
1827 Minor modifications to take into accout the changes in cpl API for v6
1828 
1829 Revision 1.36 2010/09/09 12:11:09 jim
1830 Fixed problems with docs that make doxygen barf
1831 
1832 Revision 1.35 2010/06/07 12:42:40 jim
1833 Modifications to get rid of compiler gripes
1834 
1835 Revision 1.34 2009/09/21 11:58:15 jim
1836 Calculates sky brightness now and writes to QC header
1837 
1838 Revision 1.33 2009/09/09 09:47:55 jim
1839 uses CPL defined macros for constants
1840 
1841 Revision 1.32 2008/11/26 18:21:46 jim
1842 Fixed bug in pixsize routine where there was a missing factor of 3600.0
1843 
1844 Revision 1.31 2008/11/25 06:21:56 jim
1845 nothing
1846 
1847 Revision 1.30 2008/11/24 21:31:23 jim
1848 Fixed to deal with situations with catalogues with no rows
1849 
1850 Revision 1.29 2007/10/25 17:34:01 jim
1851 Modified to remove lint warnings
1852 
1853 Revision 1.28 2007/10/19 06:55:06 jim
1854 Modifications made to use new method for directing the recipes to the
1855 standard catalogues using the sof
1856 
1857 Revision 1.27 2007/05/15 08:52:01 jim
1858 Fixed little bug in the clipping for the final magnitude zeropoint
1859 
1860 Revision 1.26 2007/05/02 09:12:02 jim
1861 Added extinction to DRS
1862 
1863 Revision 1.25 2007/03/29 12:19:39 jim
1864 Little changes to improve documentation
1865 
1866 Revision 1.24 2007/03/06 11:56:56 jim
1867 Removed some QC parameters from the catalogues
1868 
1869 Revision 1.23 2007/03/01 12:42:42 jim
1870 Modified slightly after code checking
1871 
1872 Revision 1.22 2007/02/25 06:34:20 jim
1873 Plugged memory leak
1874 
1875 Revision 1.21 2007/01/08 19:11:34 jim
1876 Fixed incorrect FITS key comments
1877 
1878 Revision 1.20 2006/12/19 13:30:34 jim
1879 Initialise the output
1880 
1881 Revision 1.19 2006/12/04 21:07:47 jim
1882 Null value in illumination correction is changed to -99.0
1883 
1884 Revision 1.18 2006/12/01 14:10:06 jim
1885 trivial change to docs
1886 
1887 Revision 1.17 2006/11/28 22:10:22 jim
1888 Added illcor_rms to calling sequence of vircam_illum
1889 
1890 Revision 1.16 2006/11/28 20:53:08 jim
1891 Added vircam_illum
1892 
1893 Revision 1.15 2006/11/27 12:03:12 jim
1894 changed calls from cpl_propertylist_append to cpl_propertylist_update
1895 
1896 Revision 1.14 2006/11/10 10:13:58 jim
1897 Fixed error in docs
1898 
1899 Revision 1.13 2006/10/02 13:47:33 jim
1900 Added missing .h file to include list
1901 
1902 Revision 1.12 2006/07/04 09:19:05 jim
1903 replaced all sprintf statements with snprintf
1904 
1905 Revision 1.11 2006/07/03 09:33:18 jim
1906 Fixed a few things to keep the compiler happy
1907 
1908 Revision 1.10 2006/06/13 14:09:09 jim
1909 Better explanation of photcal tables might be wrong
1910 
1911 Revision 1.9 2006/06/12 11:30:55 jim
1912 Removed zeropoint column from photcal table
1913 
1914 Revision 1.8 2006/06/09 11:26:26 jim
1915 Small changes to keep lint happy
1916 
1917 Revision 1.7 2006/06/06 13:07:14 jim
1918 Modified some DRS keyword names
1919 
1920 Revision 1.6 2006/05/31 14:23:32 jim
1921 Fixed error message reset call
1922 
1923 Revision 1.5 2006/05/31 11:40:09 jim
1924 Added more QC and DRS parameters. Also added calculation of limiting
1925 magnitudes. Tidied up some more docs
1926 
1927 Revision 1.4 2006/05/30 14:27:54 jim
1928 Added illcor parameter to call for photcal
1929 
1930 Revision 1.3 2006/05/26 15:05:09 jim
1931 Fixed lots of little bugs
1932 
1933 Revision 1.2 2006/05/18 09:48:28 jim
1934 Added docs
1935 
1936 Revision 1.1 2006/05/17 12:05:30 jim
1937 new file
1938 
1939 
1940 */
cpl_table * vircam_illcor_newtab(int nrows)
void vircam_medsig(float *data, unsigned char *bpm, long np, float *med, float *sig)
Definition: vircam_stats.c:756
int vircam_illum(vir_fits **images, cpl_table **mstds, cpl_propertylist **pl, int nimages, char *filt, cpl_table *phottab, int nbsize, cpl_table **illcor, float *illcor_rms, int *status)
Work out the illumination correction.
cpl_propertylist * vircam_tfits_get_ehu(vir_tfits *p)
Definition: vircam_tfits.c:473
int vircam_pfits_get_exptime(const cpl_propertylist *plist, float *exptime)
Get the value of exposure time.
Definition: vircam_pfits.c:245
int vircam_meansigcut(float *data, unsigned char *bpm, long npts, float lcut, float hcut, float *mean, float *sig)
Definition: vircam_stats.c:451
char * vircam_fits_get_fullname(vir_fits *p)
Definition: vircam_fits.c:560
cpl_image * vircam_fits_get_image(vir_fits *p)
Definition: vircam_fits.c:349
int vircam_pfits_get_cd12(const cpl_propertylist *plist, double *cd12)
Get the value of cd1_2.
Definition: vircam_pfits.c:150
void vircam_medmad(float *data, unsigned char *bpm, long np, float *med, float *mad)
Definition: vircam_stats.c:625
cpl_propertylist * vircam_fits_get_phu(vir_fits *p)
Definition: vircam_fits.c:416
cpl_propertylist * vircam_fits_get_ehu(vir_fits *p)
Definition: vircam_fits.c:457
int vircam_pfits_get_airmass(const cpl_propertylist *plist, float *airmass)
Get the value of the airmass.
Definition: vircam_pfits.c:405
int vircam_pfits_get_cd11(const cpl_propertylist *plist, double *cd11)
Get the value of cd1_1.
Definition: vircam_pfits.c:135
int vircam_photcal(vir_fits **images, cpl_table **mstds, cpl_propertylist **pl, int nimages, char *filt, cpl_table *phottab, int *status)
Work out the photometric zeropoint.