VIRCAM Pipeline  1.3.3
vircam_utils.c
1 /* $Id: vircam_utils.c,v 1.77 2013-10-15 16:54:41 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:54:41 $
24  * $Revision: 1.77 $
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 <sys/time.h>
35 #include <time.h>
36 #include <libgen.h>
37 #include <string.h>
38 #include <unistd.h>
39 
40 #include <cpl.h>
41 #include <math.h>
42 
43 #include "vircam_utils.h"
44 #include "vircam_stats.h"
45 #include "vircam_fits.h"
46 #include "vircam_pfits.h"
47 #include "catalogue/imcore.h"
48 
49 #define SZKEY 32
50 #define SZVAL 64
51 
52 /* Define some columns for illumination correction tables */
53 
54 #define NI_COLS 5
55 static const char *illcor_cols[NI_COLS] = {"xmin","xmax","ymin","ymax",
56  "illcor"};
57 
58 /* Static subroutine prototypes */
59 
60 static float madfunc(int npts, float *xt, float *yt, float b);
61 
75 /*---------------------------------------------------------------------------*/
90 /*---------------------------------------------------------------------------*/
91 
92 extern const char *vircam_get_license(void) {
93  const char *vircam_license =
94  "This file is part of the VIRCAM Instrument Pipeline\n"
95  "Copyright (C) 2006 Cambridge Astronomy Survey Unit\n"
96  "\n"
97  "This program is free software; you can redistribute it and/or modify\n"
98  "it under the terms of the GNU General Public License as published by\n"
99  "the Free Software Foundation; either version 2 of the License, or\n"
100  "(at your option) any later version.\n"
101  "\n"
102  "This program is distributed in the hope that it will be useful,\n"
103  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
104  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
105  "GNU General Public License for more details.\n"
106  "\n"
107  "You should have received a copy of the GNU General Public License\n"
108  "along with this program; if not, write to the Free Software\n"
109  "Foundation, Inc., 59 Temple Place, Suite 330, Boston, \n"
110  "MA 02111-1307 USA";
111  return(vircam_license);
112 }
113 
114 
115 /*---------------------------------------------------------------------------*/
139 /*---------------------------------------------------------------------------*/
140 
141 extern int vircam_compare_tags(const cpl_frame *frame1,
142  const cpl_frame *frame2) {
143  char *v1,*v2;
144 
145  /* Test entries */
146 
147  if (frame1 == NULL || frame2 == NULL)
148  return(-1);
149 
150  /* Get the tags */
151 
152  if ((v1 = (char *)cpl_frame_get_tag(frame1)) == NULL)
153  return(-1);
154  if ((v2 = (char *)cpl_frame_get_tag(frame2)) == NULL)
155  return(-1);
156 
157  /* Compare the tags */
158 
159  if (strcmp(v1,v2))
160  return(0);
161  else
162  return(1);
163 }
164 
165 /*---------------------------------------------------------------------------*/
191 /*---------------------------------------------------------------------------*/
192 
193 extern cpl_frameset *vircam_frameset_subgroup(cpl_frameset *frameset,
194  cpl_size *labels, cpl_size nlab,
195  const char *tag) {
196  int i;
197  cpl_frameset *cur_set,*ret_set;
198  cpl_frame *cur_frame;
199  char *cur_tag;
200 
201 
202  ret_set = NULL;
203  for (i = 0; i < nlab; i++) {
204  cur_set = cpl_frameset_extract(frameset,labels,(cpl_size)i);
205  if (cur_set == NULL)
206  break;
207  cur_frame = cpl_frameset_get_frame(cur_set,0);
208  cur_tag = (char *)cpl_frame_get_tag(cur_frame);
209  if (!strcmp(cur_tag,tag)) {
210  ret_set = cur_set;
211  break;
212  }
213  cpl_frameset_delete(cur_set);
214  }
215  return(ret_set);
216 }
217 
218 /*---------------------------------------------------------------------------*/
245 /*---------------------------------------------------------------------------*/
246 
247 extern cpl_frame *vircam_frameset_subgroup_1(cpl_frameset *frameset,
248  cpl_size *labels, cpl_size nlab,
249  const char *tag) {
250  cpl_frameset *cur_set;
251  cpl_frame *cur_frame,*new_frame;
252 
253  if ((cur_set = vircam_frameset_subgroup(frameset,labels,nlab,tag)) == NULL) {
254  return(NULL);
255  } else {
256  cur_frame = cpl_frameset_get_frame(cur_set,0);
257  new_frame = cpl_frame_duplicate(cur_frame);
258  cpl_frameset_delete(cur_set);
259  return(new_frame);
260  }
261 }
262 
263 /*---------------------------------------------------------------------------*/
283 /*---------------------------------------------------------------------------*/
284 
285 extern int vircam_frameset_fexists (cpl_frameset *frameset) {
286  int nf,i,nerr;
287  cpl_frame *cur;
288  const char *fname;
289  const char *fctid = "vircam_frameset_fexists";
290 
291  /* Check for NULL input */
292 
293  if (frameset == NULL) {
294  cpl_msg_error(fctid,"Input frameset is NULL");
295  return(VIR_FATAL);
296  }
297 
298  /* Get the size of the frameset */
299 
300  nf = cpl_frameset_get_size(frameset);
301  if (nf == 0) {
302  cpl_msg_error(fctid,"Input frameset has size of zero");
303  return(VIR_FATAL);
304  }
305 
306  /* Loop through the frameset and see if the file is accessible */
307 
308  nerr = 0;
309  for (i = 0; i < nf; i++) {
310  cur = cpl_frameset_get_frame(frameset,i);
311  fname = cpl_frame_get_filename(cur);
312  if (access(fname,F_OK) != 0) {
313  cpl_msg_error(fctid,"File: %s doesn't exist",fname);
314  nerr++;
315  }
316  }
317 
318  /* If there were any missing then return bad status */
319 
320  if (nerr != 0)
321  return(VIR_FATAL);
322  else
323  return(VIR_OK);
324 }
325 
326 /*---------------------------------------------------------------------------*/
351 /*---------------------------------------------------------------------------*/
352 
353 extern void vircam_exten_range(int inexten, const cpl_frame *fr, int *out1,
354  int *out2) {
355  int nvircam = 16,n,nmax;
356  const char *fctid = "vircam_exten_range";
357 
358  /* Right, how many frames actually exist? */
359 
360  n = cpl_frame_get_nextensions(fr);
361 
362  /* If there are less than the cannonical number, then issue a warning
363  message here */
364 
365  if (n < nvircam) {
366  cpl_msg_warning(fctid,
367  "Only %" CPL_SIZE_FORMAT " extensions out of %" CPL_SIZE_FORMAT " are present",
368  (cpl_size)n,(cpl_size)nvircam);
369  nmax = n;
370  } else {
371  nmax = nvircam;
372  }
373 
374  /* If the extension number requested is zero, then do all the extensions
375  that are available */
376 
377  if (inexten == 0) {
378  *out1 = 1;
379  *out2 = nmax;
380 
381  /* Otherwise, check that the requested extension is actually present */
382 
383  } else {
384 
385  if (inexten > nmax) {
386  cpl_msg_error(fctid,
387  "Requested extension %" CPL_SIZE_FORMAT " is not present",
388  (cpl_size)inexten);
389  *out1 = -1;
390  *out2 = -1;
391  } else {
392  *out1 = inexten;
393  *out2 = inexten;
394  }
395  }
396  return;
397 }
398 
399 /*---------------------------------------------------------------------------*/
425 /*---------------------------------------------------------------------------*/
426 
427 extern void vircam_madfit(int npts, float *xdata, float *ydata,
428  float *intercept, float *slope) {
429  int j;
430  float sx,sy,sxx,sxy,det,aa,bb,temp,chisq,sigb,b1,f1,b2,f2,f;
431 
432  /* Do a linear least squares for a first estimate */
433 
434  sx = 0.0;
435  sy = 0.0;
436  sxx = 0.0;
437  sxy = 0.0;
438  for (j = 0; j < npts; j++) {
439  sx += xdata[j];
440  sy += ydata[j];
441  sxx += xdata[j]*xdata[j];
442  sxy += xdata[j]*ydata[j];
443  }
444  det = (float)npts*sxx - sx*sx;
445  if (det == 0.0) {
446  *slope = 0.0;
447  *intercept = 0.0;
448  return;
449  }
450  aa = (sxx*sy - sx*sxy)/det;
451  bb = ((float)npts*sxy - sx*sy)/det;
452  chisq = 0.0;
453  for (j = 0; j < npts; j++) {
454  temp = ydata[j] - (aa + bb*xdata[j]);
455  chisq += temp*temp;
456  }
457  sigb = sqrt(chisq/det);
458  if (sigb == 0.0) {
459  *slope = bb;
460  *intercept = aa;
461  return;
462  }
463 
464  /* Now bracket the solution */
465 
466  b1 = bb;
467  f1 = madfunc(npts,xdata,ydata,b1);
468  b2 = bb + ((f1 > 0.0) ? fabs(3.0*sigb) : -fabs(3.0*sigb));
469  f2 = madfunc(npts,xdata,ydata,b2);
470  while (f1*f2 > 0.0) {
471  bb = 2.0*b2 - b1;
472  b1 = b2;
473  f1 = f2;
474  b2 = bb;
475  f2 = madfunc(npts,xdata,ydata,b2);
476  }
477 
478  /* Iterate to find the minimum value */
479 
480  sigb = 0.01*sigb;
481  while (fabs(b2 - b1) > sigb) {
482  bb = 0.5*(b1 + b2);
483  if (bb == b1 || bb == b2)
484  break;
485  f = madfunc(npts,xdata,ydata,bb);
486  if (f*f1 >= 0.0) {
487  f1 = f;
488  b1 = bb;
489  } else {
490  f2 = f;
491  b2 = bb;
492  }
493  }
494  *intercept = aa;
495  *slope = bb;
496 }
497 
498 /*---------------------------------------------------------------------------*/
521 /*---------------------------------------------------------------------------*/
522 
523 
524 static float madfunc(int npts, float *xt, float *yt, float b) {
525  float *arr,aa,d,sum;
526  int j;
527 
528  arr = cpl_malloc(npts*sizeof(*arr));
529  for (j = 0; j < npts; j++)
530  arr[j] = yt[j] - b*xt[j];
531  aa = vircam_med(arr,NULL,(long)npts);
532  sum = 0.0;
533  for (j = 0; j < npts; j++) {
534  d = yt[j] - (b*xt[j] + aa);
535  sum += d > 0.0 ? xt[j] : -xt[j];
536  }
537  cpl_free(arr);
538  return(sum);
539 }
540 
541 /*---------------------------------------------------------------------------*/
568 /*---------------------------------------------------------------------------*/
569 
570 extern void vircam_linfit(int npts, double *xdata, double *ydata,
571  double *intercept, double *slope, double *sig) {
572  int j;
573  double sx,sy,sxx,sxy,det,aa,bb,temp,sum,sumsq;
574 
575  /* Do a linear least squares */
576 
577  sx = 0.0;
578  sy = 0.0;
579  sxx = 0.0;
580  sxy = 0.0;
581  for (j = 0; j < npts; j++) {
582  sx += xdata[j];
583  sy += ydata[j];
584  sxx += xdata[j]*xdata[j];
585  sxy += xdata[j]*ydata[j];
586  }
587  det = (double)npts*sxx - sx*sx;
588  if (det == 0.0) {
589  *slope = 0.0;
590  *intercept = 0.0;
591  *sig = 0.0;
592  return;
593  }
594 
595  /* Intercept and slope */
596 
597  aa = (sxx*sy - sx*sxy)/det;
598  bb = ((double)npts*sxy - sx*sy)/det;
599 
600  /* Work out RMS of fit */
601 
602  sum = 0.0;
603  sumsq = 0.0;
604  for (j = 0; j < npts; j++) {
605  temp = ydata[j] - (aa + bb*xdata[j]);
606  sum += temp;
607  sumsq += temp*temp;
608  }
609  sum /= (double)npts;
610 
611  /* Set return values */
612 
613  *sig = sqrt(sumsq/(double)npts - sum*sum);
614  *slope = bb;
615  *intercept = aa;
616 }
617 
618 /*---------------------------------------------------------------------------*/
642 /*---------------------------------------------------------------------------*/
643 
644 extern int vircam_solve_gauss(double **a, double *b, int m) {
645  double temp,big,pivot,rmax;
646  int i,iu,j,k,jl,ib,ir;
647  int l = 0;
648 
649  iu = m - 1;
650  for (i = 0; i < iu; i++) {
651  big = 0.0;
652 
653  /* find largest remaining term in ith column for pivot */
654 
655  for (k = i; k < m; k++) {
656  rmax = fabs(a[i][k]);
657  if (rmax > big) {
658  big = rmax;
659  l = k;
660  }
661  }
662 
663  /* check for non-zero term */
664 
665  if (big == 0.0) {
666  for (ib = 0; ib < m; ib++)
667  b[ib] = 0.0;
668  cpl_msg_error("vircam_solve_gauss","Zero Determinant\n");
669  return(VIR_FATAL);
670  }
671 
672  if (i != l) {
673 
674  /* switch rows */
675 
676  for (j = 0; j < m; j++) {
677  temp = a[j][i];
678  a[j][i] = a[j][l];
679  a[j][l] = temp;
680  }
681  temp = b[i];
682  b[i] = b[l];
683  b[l] = temp;
684  }
685 
686 
687  /* pivotal reduction */
688 
689  pivot = a[i][i];
690  jl = i+1;
691 
692  for (j = jl; j < m; j++) {
693  temp = a[i][j]/pivot;
694  b[j] -= temp*b[i];
695  for (k = i; k < m; k++)
696  a[k][j] -= temp*a[k][i];
697  }
698  }
699 
700  /* back substitution for solution */
701 
702  for (i = 0; i < m; i++) {
703  ir = m - 1 - i;
704  if (a[ir][ir] != 0.0) {
705  temp = b[ir];
706  if (ir != m - 1) {
707  for (j = 1; j <= i; j++) {
708  k = m - j;
709  temp -= a[k][ir]*b[k];
710  }
711  }
712  b[ir] = temp/a[ir][ir];
713  } else
714  b[ir] = 0.0;
715  }
716  return(VIR_OK);
717 }
718 
719 /*---------------------------------------------------------------------------*/
757 /*---------------------------------------------------------------------------*/
758 
759 extern int vircam_polyfit(const cpl_array *xarray, const cpl_array *yarray,
760  int ncoefs, int ilim, int niter, float lclip,
761  float hclip, cpl_array **polycf, double *sigfit) {
762  const char *fctid = "vircam_polyfit";
763  int npts,iter,i,j,nnew,k,retval,n;
764  double *xdata,*ydata,*pdata,*res,**a,*b,temp,sum,sumsq,val;
765  double lcut,hcut;
766  unsigned char *pm;
767 
768  /* Initialise a few things */
769 
770  *polycf = NULL;
771  *sigfit = -1.0;
772 
773  /* How many data points do we have? */
774 
775  npts = (int)cpl_array_get_size(xarray);
776 
777  /* Do we have enough points for the required order of the fit? */
778 
779  if (npts < ncoefs) {
780  cpl_msg_warning(fctid,
781  "Not data for fit, Npts = %" CPL_SIZE_FORMAT ", Ncoefs = %" CPL_SIZE_FORMAT,
782  (cpl_size)npts,(cpl_size)ncoefs);
783  return(VIR_FATAL);
784  }
785 
786  /* Create some arrays */
787 
788  a = cpl_malloc(ncoefs*sizeof(double *));
789  b = cpl_calloc(ncoefs,sizeof(double));
790  for (i = 0; i < ncoefs; i++)
791  a[i] = cpl_calloc(ncoefs,sizeof(double));
792  pm = cpl_calloc(npts,sizeof(unsigned char));
793  res = cpl_malloc(npts*sizeof(double));
794 
795  /* Get pointers to the input arrays */
796 
797  xdata = (double *)cpl_array_get_data_double_const(xarray);
798  ydata = (double *)cpl_array_get_data_double_const(yarray);
799 
800  /* Get an output array */
801 
802  *polycf = cpl_array_new((cpl_size)ncoefs,CPL_TYPE_DOUBLE);
803  pdata = cpl_array_get_data_double(*polycf);
804 
805  /* Iteration loop */
806 
807  for (iter = 0; iter <= niter; iter++) {
808 
809  /* Zero some accumulators */
810 
811  for (i = 0; i < ncoefs; i++) {
812  for (j = 0; j < ncoefs; j++)
813  a[i][j] = 0.0;
814  b[i] = 0.0;
815  }
816  nnew = 0;
817 
818  /* Cumulate sums */
819 
820  for (i = 0; i < npts; i++) {
821  if (pm[i] == 1)
822  continue;
823  for (k = 0; k < ncoefs; k++) {
824  temp = 1.0;
825  if (k + ilim != 0)
826  temp = pow(xdata[i],(double)(k+ilim));
827  b[k] += ydata[i]*temp;
828  for (j = 0; j <= k; j++) {
829  temp = 1.0;
830  if (k + j + 2*ilim != 0)
831  temp = pow(xdata[i],(double)(k+j+2*ilim));
832  a[j][k] += temp;
833  }
834  }
835  }
836  for (k = 1; k < ncoefs; k++)
837  for (j = 0; j < k; j++)
838  a[k][j] = a[j][k];
839 
840  /* Solve linear equations */
841 
842  retval = vircam_solve_gauss(a,b,ncoefs);
843  if (retval != VIR_OK) {
844  cpl_msg_warning(fctid,"Fit failed");
845  freearray(*polycf);
846  freespace2(a,ncoefs);
847  freespace(b);
848  freespace(pm);
849  freespace(res);
850  return(VIR_FATAL);
851  }
852 
853  /* Ok, assuming this is OK, then fill the polynomial coefficients */
854 
855  for (i = 0; i < ncoefs; i++)
856  pdata[i] = b[i];
857 
858  /* Calculate the fit quality */
859 
860  sum = 0.0;
861  sumsq = 0.0;
862  n = 0;
863  for (i = 0; i < npts; i++) {
864  if (pm[i] == 1)
865  continue;
866  val = 0.0;
867  for (j = 0; j < ncoefs; j++)
868  val += pdata[j]*pow(xdata[i],(double)j+ilim);
869  res[i] = val - ydata[i];
870  sum += res[i];
871  sumsq += pow(res[i],2.0);
872  n++;
873  }
874  sum /= (double)n;
875  *sigfit = sqrt(sumsq/(double)n - sum*sum);
876 
877  /* If this is not the last iteration, then do some clipping */
878 
879  lcut = sum - lclip*(*sigfit);
880  hcut = sum + hclip*(*sigfit);
881  if (iter < niter) {
882  for (i = 0; i < npts; i++) {
883  if (pm[i] == 1)
884  continue;
885  if (res[i] > hcut || res[i] < lcut) {
886  nnew++;
887  pm[i] = 1;
888  }
889  }
890  }
891 
892  /* If no new points have been clipped, then get out of here now... */
893 
894  if (nnew == 0)
895  break;
896  }
897 
898  /* Tidy up and get out of here */
899 
900  freespace2(a,ncoefs);
901  freespace(b);
902  freespace(pm);
903  freespace(res);
904  return(VIR_OK);
905 }
906 
907 /*---------------------------------------------------------------------------*/
948 /*---------------------------------------------------------------------------*/
949 
950 extern void vircam_difference_image(cpl_image *master, cpl_image *prog,
951  unsigned char *bpm, cpl_table *chantab,
952  int ncells, int oper, float *global_diff,
953  float *global_rms, cpl_image **diffim,
954  cpl_table **diffimstats) {
955  float *ddata,*work,mean,sig,med,mad;
956  long nx,ny,npts;
957  int nrows,i,nc1,nc2,nr,ixmin,ixmax,iymin,iymax,cnum,cx,cy,idx,idy;
958  int icx,icy,indy1,indy2,indx1,indx2,jp,jcx,jj,jcy,ii,ncx,ncy;
959  const char *fctid = "vircam_difference_image";
960 
961  /* Initialise the output */
962 
963  *diffim = NULL;
964  *diffimstats = NULL;
965  *global_diff = 0.0;
966  *global_rms = 0.0;
967 
968  /* Is there a programme frame or a master? */
969 
970  if (prog == NULL || master == NULL)
971  return;
972 
973  /* Start by subtracting the master image from the programme image */
974 
975  switch (oper) {
976  case 1:
977  *diffim = cpl_image_subtract_create(prog,master);
978  break;
979  case 2:
980  *diffim = cpl_image_divide_create(prog,master);
981  break;
982  default:
983  *diffim = NULL;
984  cpl_msg_error(fctid,"Invalid operation requested %" CPL_SIZE_FORMAT,
985  (cpl_size)oper);
986  break;
987  }
988  if (*diffim == NULL)
989  return;
990 
991  /* Work out a median difference */
992 
993  ddata = cpl_image_get_data_float(*diffim);
994  nx = (int)cpl_image_get_size_x(*diffim);
995  ny = (int)cpl_image_get_size_y(*diffim);
996  npts = nx*ny;
997  vircam_medmad(ddata,bpm,npts,global_diff,global_rms);
998  *global_rms *= 1.48;
999 
1000  /* Is there a channel table? */
1001 
1002  if (chantab == NULL)
1003  return;
1004 
1005  /* Before going any further, check that the channel table has all of
1006  the columns we need */
1007 
1008  if (! cpl_table_has_column(chantab,"ixmin") ||
1009  ! cpl_table_has_column(chantab,"ixmax") ||
1010  ! cpl_table_has_column(chantab,"iymin") ||
1011  ! cpl_table_has_column(chantab,"iymax") ||
1012  ! cpl_table_has_column(chantab,"channum")) {
1013  cpl_msg_error(fctid,"Channel table is missing one of the required columns");
1014 
1015  return;
1016  }
1017 
1018  /* Work out how to divide the channels */
1019 
1020  switch (ncells) {
1021  case 1:
1022  nc1 = 1;
1023  nc2 = 1;
1024  break;
1025  case 2:
1026  nc1 = 2;
1027  nc2 = 1;
1028  break;
1029  case 4:
1030  nc1 = 4;
1031  nc2 = 1;
1032  break;
1033  case 8:
1034  nc1 = 8;
1035  nc2 = 1;
1036  break;
1037  case 16:
1038  nc1 = 16;
1039  nc2 = 1;
1040  break;
1041  case 32:
1042  nc1 = 16;
1043  nc2 = 2;
1044  break;
1045  case 64:
1046  nc1 = 32;
1047  nc2 = 2;
1048  break;
1049  default:
1050  nc1 = 32;
1051  nc2 = 2;
1052  break;
1053  }
1054 
1055  /* Create a difference image stats table */
1056 
1057  nrows = (int)cpl_table_count_selected(chantab);
1058  *diffimstats = vircam_create_diffimg_stats(nrows*nc1*nc2);
1059 
1060  /* Loop for each data channel now */
1061 
1062  nr = 0;
1063  for (i = 0; i < nrows; i++) {
1064  ixmin = cpl_table_get_int(chantab,"ixmin",(cpl_size)i,NULL);
1065  ixmax = cpl_table_get_int(chantab,"ixmax",(cpl_size)i,NULL);
1066  iymin = cpl_table_get_int(chantab,"iymin",(cpl_size)i,NULL);
1067  iymax = cpl_table_get_int(chantab,"iymax",(cpl_size)i,NULL);
1068  cnum = cpl_table_get_int(chantab,"channum",(cpl_size)i,NULL);
1069 
1070  /* Which is the long axis? If the channels are rectangular then
1071  divide the long axis by the greater number of cells. If the number
1072  of cells is less than 8, then just divide the long axis. If the
1073  channel is square, then divide the X axis more finely */
1074 
1075  cx = ixmax - ixmin + 1;
1076  cy = iymax - iymin + 1;
1077  if (cx > cy) {
1078  ncx = max(nc1,nc2);
1079  ncy = min(nc1,nc2);
1080  } else if (cx < cy) {
1081  ncy = max(nc1,nc2);
1082  ncx = min(nc1,nc2);
1083  } else {
1084  ncx = max(nc1,nc2);
1085  ncy = min(nc1,nc2);
1086  }
1087 
1088  /* How big is the cell? */
1089 
1090  idy = cy/ncy;
1091  idx = cx/ncx;
1092  work = cpl_malloc(idx*idy*sizeof(*work));
1093 
1094  /* Now loop for aach cell */
1095 
1096  for (icy = 0; icy < ncy; icy++) {
1097  indy1 = idy*icy;
1098  indy2 = min(iymax,indy1+idy-1);
1099  for (icx = 0; icx < ncx; icx++) {
1100  indx1 = idx*icx;
1101  indx2 = min(ixmax,indx1+idx-1);
1102  jp = 0;
1103  for (jcy = indy1; jcy < indy2; jcy++) {
1104  jj = jcy*nx;
1105  for (jcx = indx1; jcx < indx2; jcx++) {
1106  ii = jj + jcx;
1107  if (bpm != NULL && bpm[ii] == 0)
1108  work[jp++] = ddata[ii];
1109  }
1110  }
1111  (void)vircam_meansig(work,NULL,(long)jp,&mean,&sig);
1112  (void)vircam_medmad(work,NULL,(long)jp,&med,&mad);
1113  cpl_table_set_int(*diffimstats,"xmin",(cpl_size)nr,indx1+1);
1114  cpl_table_set_int(*diffimstats,"xmax",(cpl_size)nr,indx2+1);
1115  cpl_table_set_int(*diffimstats,"ymin",(cpl_size)nr,indy1+1);
1116  cpl_table_set_int(*diffimstats,"ymax",(cpl_size)nr,indy2+1);
1117  cpl_table_set_int(*diffimstats,"chan",(cpl_size)nr,cnum);
1118  cpl_table_set_float(*diffimstats,"mean",(cpl_size)nr,mean);
1119  cpl_table_set_float(*diffimstats,"median",(cpl_size)nr,med);
1120  cpl_table_set_float(*diffimstats,"variance",(cpl_size)nr,
1121  (sig*sig));
1122  cpl_table_set_float(*diffimstats,"mad",(cpl_size)(nr++),mad);
1123  }
1124  }
1125  cpl_free(work);
1126  }
1127 }
1128 
1129 /*---------------------------------------------------------------------------*/
1146 /*---------------------------------------------------------------------------*/
1147 
1148 cpl_table *vircam_create_diffimg_stats(int nrows) {
1149  cpl_table *diffimstats;
1150 
1151  diffimstats = cpl_table_new((cpl_size)nrows);
1152  cpl_table_new_column(diffimstats,"xmin",CPL_TYPE_INT);
1153  cpl_table_set_column_unit(diffimstats,"xmin","pixels");
1154  cpl_table_new_column(diffimstats,"xmax",CPL_TYPE_INT);
1155  cpl_table_set_column_unit(diffimstats,"xmax","pixels");
1156  cpl_table_new_column(diffimstats,"ymin",CPL_TYPE_INT);
1157  cpl_table_set_column_unit(diffimstats,"ymin","pixels");
1158  cpl_table_new_column(diffimstats,"ymax",CPL_TYPE_INT);
1159  cpl_table_set_column_unit(diffimstats,"ymax","pixels");
1160  cpl_table_new_column(diffimstats,"chan",CPL_TYPE_INT);
1161  cpl_table_set_column_unit(diffimstats,"chan","pixels");
1162  cpl_table_new_column(diffimstats,"mean",CPL_TYPE_FLOAT);
1163  cpl_table_set_column_unit(diffimstats,"mean","ADU");
1164  cpl_table_new_column(diffimstats,"median",CPL_TYPE_FLOAT);
1165  cpl_table_set_column_unit(diffimstats,"median","ADU");
1166  cpl_table_new_column(diffimstats,"variance",CPL_TYPE_FLOAT);
1167  cpl_table_set_column_unit(diffimstats,"variance","ADU**2");
1168  cpl_table_new_column(diffimstats,"mad",CPL_TYPE_FLOAT);
1169  cpl_table_set_column_unit(diffimstats,"mad","ADU");
1170  return(diffimstats);
1171 }
1172 
1173 
1174 /*---------------------------------------------------------------------------*/
1198 /*---------------------------------------------------------------------------*/
1199 
1200 extern void vircam_sort(float **a, int n, int m) {
1201  int increment,i,j,k;
1202  float *t;
1203 
1204  t = cpl_malloc(m*sizeof(*t));
1205 
1206  increment = n/2;
1207  while (increment > 0) {
1208  for (i = increment; i < n; i++) {
1209  j = i;
1210  for (k = 0; k < m; k++)
1211  t[k] = a[k][i];
1212  while ((j >= increment) && (a[0][j-increment] > t[0])) {
1213  for (k = 0; k < m; k++)
1214  a[k][j] = a[k][j-increment];
1215  j = j - increment;
1216  }
1217  for (k = 0; k < m; k++)
1218  a[k][j] = t[k];
1219  }
1220  if (increment == 2)
1221  increment = 1;
1222  else
1223  increment = (int)((float)increment/2.2);
1224  }
1225  cpl_free(t);
1226 }
1227 
1228 /*---------------------------------------------------------------------------*/
1245 /*---------------------------------------------------------------------------*/
1246 
1247 extern long vircam_getnpts(cpl_image *in) {
1248  int nx,ny;
1249  long npts;
1250  const char *fctid = "vircam_getnpts";
1251 
1252  if ((nx = (int)cpl_image_get_size_x(in)) == -1) {
1253  cpl_msg_error(fctid,"NULL image input");
1254  return(0);
1255  }
1256  if ((ny = (int)cpl_image_get_size_y(in)) == -1) {
1257  cpl_msg_error(fctid,"NULL image input");
1258  return(0);
1259  }
1260  npts = (long)nx*ny;
1261  return(npts);
1262 }
1263 
1264 /*---------------------------------------------------------------------------*/
1295 /*---------------------------------------------------------------------------*/
1296 
1297 extern int vircam_fndmatch(float x, float y, float *xlist, float *ylist,
1298  int nlist, float err) {
1299  int isp,ifp,indx,i;
1300  float errsq,errmin,dx,dy,poserr;
1301 
1302  /* Find lower limit index */
1303 
1304  isp = 0;
1305  ifp = nlist - 1;
1306  errsq = err*err;
1307  indx = (isp + ifp)/2;
1308  while (ifp-isp >= 2) {
1309  if (ylist[indx] < y - err) {
1310  isp = indx;
1311  indx = (indx+ifp)/2;
1312  } else if (ylist[indx] > y - err) {
1313  ifp = indx;
1314  indx = (indx+isp)/2;
1315  } else {
1316  isp = indx;
1317  break;
1318  }
1319  }
1320 
1321  /* Now find nearest one within limit */
1322 
1323  indx = -1;
1324  errmin = errsq;
1325  for (i = isp; i < nlist; i++) {
1326  if (ylist[i] > y+err)
1327  break;
1328  dx = x - xlist[i];
1329  dy = y - ylist[i];
1330  poserr = dx*dx + dy*dy;
1331  if (poserr < errsq) {
1332  if (poserr <= errmin) {
1333  indx = i;
1334  errmin = poserr;
1335  }
1336  }
1337  }
1338  return(indx);
1339 }
1340 
1341 /*---------------------------------------------------------------------------*/
1360 /*---------------------------------------------------------------------------*/
1361 
1362 extern int *vircam_dummy_confidence(long n) {
1363  int *cdata,i;
1364 
1365  cdata = cpl_malloc(n*sizeof(*cdata));
1366  for (i = 0; i < n; i++)
1367  cdata[i] = 100;
1368  return(cdata);
1369 }
1370 
1371 /*---------------------------------------------------------------------------*/
1394 /*---------------------------------------------------------------------------*/
1395 
1396 extern int vircam_compare_dims(cpl_image *im1, cpl_image *im2) {
1397 
1398  if (cpl_image_get_size_x(im1) != cpl_image_get_size_x(im2) ||
1399  cpl_image_get_size_y(im1) != cpl_image_get_size_y(im2))
1400  return(VIR_FATAL);
1401  else
1402  return(VIR_OK);
1403 }
1404 
1405 /*---------------------------------------------------------------------------*/
1426 /*---------------------------------------------------------------------------*/
1427 
1428 extern void vircam_prov(cpl_propertylist *p, vir_fits **inlist, int n) {
1429  int i;
1430  char keyword[SZKEY],value[SZVAL],*fn,*base;
1431 
1432  /* Delete all the provenance keywords that might already exist */
1433 
1434  cpl_propertylist_erase_regexp(p,"ESO DRS PROV*",0);
1435 
1436  /* Add the new provenance keywords */
1437 
1438  for (i = 0; i < n; i++) {
1439  (void)snprintf(keyword,SZKEY,"ESO DRS PROV%04d",i+1);
1440  fn = cpl_strdup(vircam_fits_get_fullname(inlist[i]));
1441  base = basename(fn);
1442  (void)snprintf(value,SZVAL,"%s",base);
1443  cpl_free(fn);
1444  cpl_propertylist_update_string(p,keyword,value);
1445  (void)snprintf(value,SZVAL,"Input file # %d",i+1);
1446  cpl_propertylist_set_comment(p,keyword,value);
1447  }
1448 }
1449 
1450 /*---------------------------------------------------------------------------*/
1468 /*---------------------------------------------------------------------------*/
1469 
1470 extern void vircam_merge_propertylists(cpl_propertylist *p1,
1471  cpl_propertylist *p2) {
1472  int i;
1473  const char *name;
1474 
1475  /* Return if either propertylist is NULL */
1476 
1477  if (p1 == NULL || p2 == NULL)
1478  return;
1479 
1480  /* Erase any common properties so that you don't get a clash with
1481  data types. Then copy each property from the second list into
1482  the first one */
1483 
1484  for (i = 0; i < cpl_propertylist_get_size(p2); i++) {
1485  name = cpl_property_get_name(cpl_propertylist_get(p2,i));
1486  if (cpl_propertylist_has(p1,name))
1487  cpl_propertylist_erase(p1,name);
1488  }
1489  cpl_propertylist_append(p1,p2);
1490 
1491 }
1492 
1493 /*---------------------------------------------------------------------------*/
1512 /*---------------------------------------------------------------------------*/
1513 
1514 extern void vircam_dummy_property(cpl_propertylist *p) {
1515 
1516  /* Check for silly input */
1517 
1518  if (p == NULL)
1519  return;
1520 
1521  /* Add the property now */
1522 
1523  cpl_propertylist_update_bool(p,"ESO DRS IMADUMMY",TRUE);
1524  cpl_propertylist_set_comment(p,"ESO DRS IMADUMMY",
1525  "This is a dummy product");
1526  return;
1527 }
1528 
1529 /*---------------------------------------------------------------------------*/
1545 /*---------------------------------------------------------------------------*/
1546 
1547 extern int vircam_is_dummy(cpl_propertylist *p) {
1548 
1549  /* Check for silly input */
1550 
1551  if (p == NULL)
1552  return(0);
1553 
1554  /* Check the propertylist and return the result */
1555 
1556  return(cpl_propertylist_has(p,"ESO DRS IMADUMMY"));
1557 }
1558 
1559 /*---------------------------------------------------------------------------*/
1597 /*---------------------------------------------------------------------------*/
1598 
1599 extern void vircam_overexp(vir_fits **fitslist, int *n, int ndit, float lthr,
1600  float hthr, int ditch, float *minv, float *maxv,
1601  float *avev) {
1602  int i,m;
1603  cpl_image *im;
1604  double val,dndit,sum;
1605 
1606  /* Loop for each of the fits items */
1607 
1608  dndit = (double)ndit;
1609  m = 0;
1610  *minv = 1.0e10;
1611  *maxv = -1.0e10;
1612  sum = 0.0;
1613  for (i = 0; i < *n; i++) {
1614  im = vircam_fits_get_image(fitslist[i]);
1615  val = cpl_image_get_median_window(im,500,500,1000,1000);
1616  val /= ndit;
1617  *minv = min(*minv,val);
1618  *maxv = max(*maxv,val);
1619  sum += val;
1620  if (val > lthr && val < hthr) {
1621  fitslist[m++] = fitslist[i];
1622  } else {
1623  if (ditch)
1624  vircam_fits_delete(fitslist[i]);
1625  }
1626  }
1627  for (i = m; i < *n; i++)
1628  fitslist[i] = NULL;
1629  *avev = sum/(double)*n;
1630  *n = m;
1631 }
1632 
1633 /*---------------------------------------------------------------------------*/
1650 /*---------------------------------------------------------------------------*/
1651 
1652 extern cpl_image *vircam_dummy_image(vir_fits *model) {
1653  cpl_image *im;
1654 
1655  /* Copy the input model image */
1656 
1657  im = cpl_image_duplicate(vircam_fits_get_image(model));
1658 
1659  /* Now change it all to zeros */
1660 
1661  cpl_image_multiply_scalar(im,0.0);
1662 
1663  /* Return the result */
1664 
1665  return(im);
1666 }
1667 
1668 /*---------------------------------------------------------------------------*/
1685 /*---------------------------------------------------------------------------*/
1686 
1687 extern cpl_table *vircam_dummy_catalogue(int type) {
1688 
1689  cattype = type;
1690  tabinit(NULL);
1691  return(tab);
1692 }
1693 
1694 
1695 /*---------------------------------------------------------------------------*/
1712 /*---------------------------------------------------------------------------*/
1713 
1714 extern cpl_table *vircam_illcor_newtab(int nrows) {
1715  cpl_table *illcor;
1716  int i;
1717 
1718  /* Create the table structure and fill in the columns */
1719 
1720  illcor = cpl_table_new((cpl_size)nrows);
1721  for (i = 0; i < NI_COLS; i++)
1722  cpl_table_new_column(illcor,illcor_cols[i],CPL_TYPE_FLOAT);
1723  return(illcor);
1724 }
1725 
1726 /*---------------------------------------------------------------------------*/
1750 /*---------------------------------------------------------------------------*/
1751 
1752 extern void vircam_timestamp(char *out, int n) {
1753  struct timeval tv;
1754  struct tm *tm;
1755  float sec;
1756 
1757  /* Get the Greenwich Mean Time */
1758 
1759  (void)gettimeofday(&tv,NULL);
1760  tm = gmtime(&(tv.tv_sec));
1761  sec = (float)tm->tm_sec + 1.0e-6*(float)tv.tv_usec;
1762 
1763  /* Now format it */
1764 
1765  (void)snprintf(out,n,"%04d-%02d-%02dT%02d:%02d:%07.4f",1900+tm->tm_year,
1766  tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,sec);
1767 }
1768 
1769 /*---------------------------------------------------------------------------*/
1798 /*---------------------------------------------------------------------------*/
1799 
1800 extern void vircam_backmap(vir_fits *in, vir_mask *mask, int nbsize,
1801  cpl_image **out, float *med) {
1802  int i,j,nx,ny,ifracx,ifracy,nbsizx,nbsizy,nbx,nby,*nps,jx,jy;
1803  int jy1,jy2,np,nout,jyp1,jxp1,jz1,jz2,jz3,jz4,nbsize2;
1804  float fracx,fracy,*bmap,**rowpoints,*data,*ptr,dely,delx,t1,t2;
1805  unsigned char *bpm;
1806 
1807  /* Check to see if nbsize is close to exact divisor */
1808 
1809  nx = (int)cpl_image_get_size_x(vircam_fits_get_image(in));
1810  ny = (int)cpl_image_get_size_y(vircam_fits_get_image(in));
1811  fracx = ((float)nx)/((float)nbsize);
1812  fracy = ((float)ny)/((float)nbsize);
1813  ifracx = (int)(fracx + 0.1);
1814  ifracy = (int)(fracy + 0.1);
1815  nbsizx = nx/ifracx;
1816  nbsizy = ny/ifracy;
1817  nbsize = max(vircam_nint(0.9*nbsize),min(nbsize,min(nbsizx,nbsizy)));
1818  nbsize = min(nx,min(ny,nbsize)); /* trap for small maps */
1819  nbsize2 = nbsize/2;
1820 
1821  /* Divide the map into partitions */
1822 
1823  nbx = nx/nbsize;
1824  nby = ny/nbsize;
1825 
1826  /* Get some space for to use for accumulating stats */
1827 
1828  bmap = cpl_malloc(nbx*nby*sizeof(float));
1829  rowpoints = cpl_malloc(nbx*sizeof(float *));
1830  nps = cpl_malloc(nbx*sizeof(int));
1831 
1832  /* Get the data from the input file and the mask */
1833 
1834  data = cpl_image_get_data_float(vircam_fits_get_image(in));
1835  bpm = vircam_mask_get_data(mask);
1836 
1837  /* Work out the global median */
1838 
1839  *med = vircam_med(data,bpm,(long)(nx*ny));
1840 
1841  /* For each cell allocate some nbsize*nbsize pixels in the row pointers.
1842  It's ok to do this here since this will be the maximum that each cell
1843  will have... */
1844 
1845  for (i = 0; i < nbx; i++)
1846  rowpoints[i] = cpl_malloc(nbsize*nbsize*sizeof(float));
1847 
1848  /* Loop for each row of cells and work out which rows in the input
1849  map these relate to */
1850 
1851  for (jy = 0; jy < nby; jy++) {
1852  jy1 = jy*nbsize;
1853  jy2 = min((jy+1)*nbsize - 1,ny-1);
1854 
1855  /* Zero the counter for each cell */
1856 
1857  for (jx = 0; jx < nbx; jx++)
1858  nps[jx] = 0;
1859 
1860  /* Loop for the strip of the input map covered by this row of cells.
1861  Work out which cell the current pixel is in and then put it into
1862  the correct accumulator assuming the bad pixel mask says it's ok */
1863 
1864  for (j = jy1; j <= jy2; j++) {
1865  for (i = 0; i < nx; i++) {
1866  jx = min(nbx-1,i/nbsize);
1867  if (bpm[j*nx + i] == 0) {
1868  ptr = rowpoints[jx];
1869  np = nps[jx];
1870  ptr[np++] = data[j*nx + i];
1871  nps[jx] = np;
1872  }
1873  }
1874  }
1875 
1876  /* Now do the medians for each of the cells in this row */
1877 
1878  for (jx = 0; jx < nbx; jx++) {
1879  bmap[jy*nbx+jx] = vircam_med(rowpoints[jx],NULL,(long)(nps[jx]));
1880  if (bmap[jy*nbx+jx] != CX_MAXFLOAT) {
1881  bmap[jy*nbx+jx] -= *med;
1882  } else {
1883  bmap[jy*nbx+jx] = 0.0;
1884  }
1885  }
1886  }
1887 
1888  /* Free up some workspace */
1889 
1890  for (jx = 0; jx < nbx; jx++)
1891  freespace(rowpoints[jx]);
1892  freespace(rowpoints);
1893  freespace(nps);
1894 
1895  /* Create a new image for the output array */
1896 
1897  *out = cpl_image_new((cpl_size)nx,(cpl_size)ny,CPL_TYPE_FLOAT);
1898  ptr = cpl_image_get_data_float(*out);
1899 
1900  /* Ok, we now have the block averaged background map. Do a two point
1901  interpolation to create the full map now */
1902 
1903  nout = 0;
1904  for (j = 1; j <= ny; j++) {
1905  jy = (j + nbsize2)/nbsize;
1906  jyp1 = jy + 1;
1907  jy = min(nby,max(1,jy));
1908  jyp1 = min(nby,jyp1);
1909  dely = (float)(j - nbsize*jy + nbsize2)/(float)nbsize;
1910  dely = max(0.0,min(1.0,dely));
1911  for (i = 1; i <= nx; i++) {
1912  jx = (i + nbsize2)/nbsize;
1913  jxp1 = jx + 1;
1914  jx = min(nbx,max(1,jx));
1915  jxp1 = min(nbx,jxp1);
1916  delx = (float)(i - nbsize*jx + nbsize2)/(float)nbsize;
1917  delx = max(0.0,min(1.0,delx));
1918  jz1 = (jy - 1)*nbx + jx;
1919  jz2 = (jyp1 - 1)*nbx + jx;
1920  if (jx == nbx) {
1921  jz3 = jz1;
1922  jz4 = jz2;
1923  } else {
1924  jz3 = jz1 + 1;
1925  jz4 = jz2 + 1;
1926  }
1927  t1 = (1.0 - delx)*bmap[jz1-1] + delx*bmap[jz3-1];
1928  t2 = (1.0 - delx)*bmap[jz2-1] + delx*bmap[jz4-1];
1929  ptr[nout++] = (1.0 - dely)*t1 + dely*t2;
1930  }
1931  }
1932 
1933  /* Tidy up before leaving... */
1934 
1935  freespace(bmap)
1936 }
1937 
1938 /*---------------------------------------------------------------------------*/
1959 /*---------------------------------------------------------------------------*/
1960 
1961 extern int vircam_findcol(cpl_propertylist *p, const char *col) {
1962 
1963  if (!strcmp(col,"X")) {
1964  if (cpl_propertylist_has(p,"ESO DRS XCOL"))
1965  return(cpl_propertylist_get_int(p,"ESO DRS XCOL"));
1966  else
1967  return(-1);
1968  } else if (!strcmp(col,"Y")) {
1969  if (cpl_propertylist_has(p,"ESO DRS YCOL"))
1970  return(cpl_propertylist_get_int(p,"ESO DRS YCOL"));
1971  else
1972  return(-1);
1973  }
1974  return(-1);
1975 }
1976 
1977 /*---------------------------------------------------------------------------*/
1998 /*---------------------------------------------------------------------------*/
1999 
2000 extern void vircam_rename_property(cpl_propertylist *p, const char *oldname,
2001  char *newname) {
2002  cpl_propertylist *temp;
2003  cpl_property *property;
2004 
2005  /* First get the old property. Note that we have to do this in a
2006  particularly silly way since you cannot reference an individual property
2007  in a propertylist by its name. You can only do it by its index
2008  number. Remeber to change this when CPL comes to it's senses... */
2009 
2010  if (! cpl_propertylist_has(p,oldname))
2011  return;
2012  temp = cpl_propertylist_new();
2013  cpl_propertylist_copy_property(temp,p,oldname);
2014  property = cpl_propertylist_get(temp,0);
2015 
2016  /* Now change its name */
2017 
2018  cpl_property_set_name(property,newname);
2019 
2020  /* Now insert this into the propertylist and delete the old one */
2021 
2022  cpl_propertylist_append(p,temp);
2023  cpl_propertylist_erase(p,oldname);
2024  cpl_propertylist_delete(temp);
2025 }
2026 
2027 /*---------------------------------------------------------------------------*/
2055 /*---------------------------------------------------------------------------*/
2056 
2057 extern int vircam_catpars(cpl_frame *indx, char **catpath, char **catname) {
2058  cpl_propertylist *p;
2059  char *fname;
2060  int status;
2061  const char *fctid = "vircam_catpars",*unk = "unknown";
2062 
2063  /* Initialise a few things */
2064 
2065  *catpath = NULL;
2066  *catname = NULL;
2067 
2068  /* First get the full path to the indx file and make sure it exists */
2069 
2070  fname = cpl_strdup(cpl_frame_get_filename(indx));
2071  if (access((const char *)fname,R_OK) != 0) {
2072  cpl_msg_error(fctid,"Can't access index file %s",fname);
2073  cpl_free(fname);
2074  return(VIR_FATAL);
2075  }
2076  *catpath = cpl_strdup(dirname(fname));
2077 
2078  /* Load the propertylist if you can. If you can't then signal a fatal
2079  error since this probably means the whole file is messed up */
2080 
2081  if ((p = cpl_propertylist_load(cpl_frame_get_filename(indx),0)) == NULL) {
2082  freespace(*catpath);
2083  cpl_msg_error(fctid,"Can't load index file header %s",
2084  cpl_frame_get_filename(indx));
2085  cpl_free(fname);
2086  return(VIR_FATAL);
2087  }
2088 
2089  /* If there is a catalogue name in the header then send it back. If there
2090  isn't then give a default name and send a warning */
2091 
2092  if (cpl_propertylist_has(p,"CATNAME")) {
2093  *catname = cpl_strdup(cpl_propertylist_get_string(p,"CATNAME"));
2094  status = VIR_OK;
2095  } else {
2096  *catname = cpl_strdup(unk);
2097  cpl_msg_warning(fctid,"Property CATNAME not in index file header %s",
2098  cpl_frame_get_filename(indx));
2099  status = VIR_WARN;
2100  }
2101  cpl_free(fname);
2102  freepropertylist(p);
2103 
2104  /* Get out of here */
2105 
2106  return(status);
2107 }
2108 
2109 /*---------------------------------------------------------------------------*/
2140 /*---------------------------------------------------------------------------*/
2141 
2142 extern int vircam_gaincor_calc(cpl_frame *frame, int *n, float **cors,
2143  int *status) {
2144  float sum,val;
2145  int i,ngood;
2146  unsigned char *iflag;
2147  cpl_propertylist *p;
2148 
2149  /* Inherited status */
2150 
2151  if (*status != VIR_OK)
2152  return(*status);
2153 
2154  /* Find the number of extensions in the file and allocate some workspace
2155  to hold the results. Allocate a small workspace to flag dummy
2156  extensions */
2157 
2158  *n = cpl_frame_get_nextensions(frame);
2159  *cors = cpl_malloc(*n*sizeof(float));
2160  iflag = cpl_calloc(*n,sizeof(iflag));
2161 
2162  /* Ok, loop through the extensions and read the propertylists */
2163 
2164  sum = 0.0;
2165  ngood = 0;
2166  for (i = 0; i < *n; i++) {
2167  p = cpl_propertylist_load(cpl_frame_get_filename(frame),(cpl_size)(i+1));
2168  if (cpl_propertylist_has(p,"ESO DRS IMADUMMY")) {
2169  iflag[i] = 1;
2170  } else if (! cpl_propertylist_has(p,"ESO DRS MEDFLAT")) {
2171  iflag[i] = 1;
2172  } else {
2173  val = cpl_propertylist_get_double(p,"ESO DRS MEDFLAT");
2174  if (val == 0.0) {
2175  iflag[i] = 1;
2176  } else {
2177  sum += val;
2178  (*cors)[i] = val;
2179  ngood++;
2180  }
2181  }
2182  cpl_propertylist_delete(p);
2183  }
2184 
2185  /* If any of them are good, then work out what the average is and
2186  create the correction factors. If the image was a dummy or
2187  there was no MEDFLAT keyword in the header, then just give it
2188  a factor of 1 */
2189 
2190  if (ngood > 0)
2191  sum /= (float)ngood;
2192  for (i = 0; i < *n; i++) {
2193  if (iflag[i] == 0) {
2194  (*cors)[i] = sum/(*cors)[i];
2195  } else {
2196  (*cors)[i] = 1.0;
2197  }
2198  }
2199  cpl_free(iflag);
2200 
2201  /* Get out of here */
2202 
2203  GOOD_STATUS
2204 }
2205 
2206 /*---------------------------------------------------------------------------*/
2232 /*---------------------------------------------------------------------------*/
2233 
2234 extern int vircam_check_crval(cpl_propertylist *phu, cpl_propertylist *ehu) {
2235  double crval1,crval2;
2236  cpl_property *p;
2237 
2238  /* Get the values of CRVAL1,2 from the extension header. If it doesn't
2239  exist, then signal an error */
2240 
2241  if ((vircam_pfits_get_crval1(ehu,&crval1) != VIR_OK) ||
2242  (vircam_pfits_get_crval2(ehu,&crval2) != VIR_OK))
2243  return(VIR_FATAL);
2244 
2245  /* If the values are both zero, then grab the values from the primary
2246  and silently update the extension header. NB: have to do this silly
2247  song and dance where we create new properties, rename the old ones,
2248  insert the new ones in the correct place and then erase the old
2249  ones because CPL won't do the update if it thinks the original
2250  CRVALs are floats rather than a double (which it inevitably will,
2251  since this is where CRVAL has been set identically to zero...) */
2252 
2253  if (fabs(crval1) < 1.0e-6 && fabs(crval2) < 1.0e-6) {
2254  if ((vircam_pfits_get_ra(phu,&crval1) != VIR_OK) ||
2255  (vircam_pfits_get_dec(phu,&crval2) != VIR_OK))
2256  return(VIR_FATAL);
2257  p = cpl_propertylist_get_property(ehu,"CRVAL1");
2258  cpl_property_set_name(p,"OLDCR1");
2259  p = cpl_propertylist_get_property(ehu,"CRVAL2");
2260  cpl_property_set_name(p,"OLDCR2");
2261  cpl_propertylist_insert_after_double(ehu,"OLDCR2","CRVAL1",crval1);
2262  cpl_propertylist_insert_after_double(ehu,"CRVAL1","CRVAL2",crval2);
2263  cpl_propertylist_erase(ehu,"OLDCR1");
2264  cpl_propertylist_erase(ehu,"OLDCR2");
2265  }
2266 
2267  /* Get out of here */
2268 
2269  return(VIR_OK);
2270 }
2271 
2274 /*
2275 
2276 $Log: not supported by cvs2svn $
2277 Revision 1.76 2012/01/27 12:25:10 jim
2278 Fixed some casts
2279 
2280 Revision 1.75 2012/01/16 12:32:18 jim
2281 A few more changes to fit in with cpl6
2282 
2283 Revision 1.74 2012/01/15 17:40:09 jim
2284 Minor modifications to take into accout the changes in cpl API for v6
2285 
2286 Revision 1.73 2010/12/09 13:23:56 jim
2287 Minor doc fix
2288 
2289 Revision 1.72 2010/09/09 12:11:09 jim
2290 Fixed problems with docs that make doxygen barf
2291 
2292 Revision 1.71 2010/06/30 12:42:00 jim
2293 A few fixes to stop compiler compaints
2294 
2295 Revision 1.70 2010/06/07 12:42:40 jim
2296 Modifications to get rid of compiler gripes
2297 
2298 Revision 1.69 2010/03/22 06:07:24 jim
2299 Fixed bug in vircam_overexp
2300 
2301 Revision 1.68 2010/03/22 06:04:14 jim
2302 vircam_overexp now works out the ensemble stats on all frames rather than
2303 just those that are between the threshold levels.
2304 
2305 Revision 1.67 2010/01/31 19:30:45 jim
2306 Fixed bug in where global MAD wasn't being multiplied by 1.48 to turn it
2307 into an global RMS in the difference image routine
2308 
2309 Revision 1.66 2009/09/21 11:57:27 jim
2310 Modified vircam_overexp to pass back ensemble stats.
2311 
2312 Revision 1.65 2009/06/08 08:07:13 jim
2313 Fixed bugs in vircam_polyfit, where clipping loop was being done one too few
2314 times and where the error estimate was being done incorrectly
2315 
2316 Revision 1.64 2009/05/20 12:21:52 jim
2317 modified _propertylist_merge to avoid clash of data types
2318 
2319 Revision 1.63 2009/02/23 10:45:13 jim
2320 Fixed vircam_backmap so that if there were no points in a bin the it does
2321 something sensible to the value
2322 
2323 Revision 1.62 2009/02/20 11:35:11 jim
2324 Fixed bug in vircam_polyfit which stopped the iteration scheme.
2325 
2326 Revision 1.61 2008/12/08 06:39:45 jim
2327 Added new routine vircam_check_crval
2328 
2329 Revision 1.60 2008/11/25 18:55:36 jim
2330 rewrote vircam_sort to be a bit more reliable
2331 
2332 Revision 1.59 2008/11/02 14:35:07 jim
2333 Fixed teensy problem with two error messages
2334 
2335 Revision 1.58 2008/10/13 08:16:57 jim
2336 Fixed call to cpl_msg_warning
2337 
2338 Revision 1.57 2008/10/01 04:58:30 jim
2339 Added vircam_frameset_fexists
2340 
2341 Revision 1.56 2008/07/10 13:04:03 jim
2342 Fixed some comments
2343 
2344 Revision 1.55 2008/05/06 12:15:02 jim
2345 Changed vircam_catpars to check that we can read the index file and to send
2346 out error messages if there are problems
2347 
2348 Revision 1.54 2008/05/06 08:38:29 jim
2349 Modified call to cpl_propertylist_get_ from float to double in
2350 vircam_gaincor_calc.
2351 
2352 Revision 1.53 2007/11/14 14:47:53 jim
2353 vircam_linfit now works only with doubles
2354 
2355 Revision 1.52 2007/11/14 10:46:07 jim
2356 Fixed bugs in vircam_polyfit
2357 
2358 Revision 1.51 2007/10/25 17:33:31 jim
2359 Modified to add vircam_polyfit and to remove lint warnings
2360 
2361 Revision 1.50 2007/10/19 09:25:10 jim
2362 Fixed problems with missing includes
2363 
2364 Revision 1.49 2007/10/19 06:55:06 jim
2365 Modifications made to use new method for directing the recipes to the
2366 standard catalogues using the sof
2367 
2368 Revision 1.48 2007/10/15 12:50:28 jim
2369 Modified for compatibility with cpl_4.0
2370 
2371 Revision 1.47 2007/07/09 13:21:06 jim
2372 Changed argument list to vircam_exten_range to include a cpl_frame
2373 
2374 Revision 1.46 2007/05/08 10:41:01 jim
2375 Added vircam_gaincor_calc
2376 
2377 Revision 1.45 2007/05/03 11:15:33 jim
2378 Fixed little problem with table wcs
2379 
2380 Revision 1.44 2007/05/02 09:14:48 jim
2381 Added vircam_findcol and vircam_rename_property
2382 
2383 Revision 1.43 2007/03/01 12:42:42 jim
2384 Modified slightly after code checking
2385 
2386 Revision 1.42 2007/02/14 12:53:34 jim
2387 Removed vircam_paf_print_header
2388 
2389 Revision 1.41 2007/02/07 10:12:15 jim
2390 Removed vircam_ndit_correct as it is now no longer necessary
2391 
2392 Revision 1.40 2007/01/15 12:36:27 jim
2393 Fixed bug in nditcor where factor was being divided by instead of multiplied
2394 
2395 Revision 1.39 2006/12/06 12:58:41 jim
2396 Fixed a small bug in vircam_backmap
2397 
2398 Revision 1.38 2006/12/01 14:08:33 jim
2399 added vircam_backmap
2400 
2401 Revision 1.37 2006/11/28 20:52:17 jim
2402 Added vircam_illcor_newtab
2403 
2404 Revision 1.36 2006/11/27 12:00:17 jim
2405 cosmetic changes
2406 
2407 Revision 1.35 2006/10/05 09:23:00 jim
2408 Small modifications to a couple of cpl calls to bring them into line with
2409 cpl v3.0
2410 
2411 Revision 1.34 2006/08/27 20:28:15 jim
2412 added vircam_is_dummy
2413 
2414 Revision 1.33 2006/08/21 09:09:29 jim
2415 Added routines vircam_create_diffimg_stats and vircam_dummy_property
2416 
2417 Revision 1.32 2006/07/11 14:53:58 jim
2418 Fixed vircam_ndit_correct so that images with bad status are not corrected
2419 
2420 Revision 1.31 2006/07/04 09:19:06 jim
2421 replaced all sprintf statements with snprintf
2422 
2423 Revision 1.30 2006/06/30 21:32:09 jim
2424 Fixed bug in vircam_prov so that sprintf is replaced by snprintf
2425 
2426 Revision 1.29 2006/06/20 18:59:51 jim
2427 Fixed small bug in vircam_ndit_correct
2428 
2429 Revision 1.28 2006/06/09 22:24:47 jim
2430 Added vircam_ndit_correct
2431 
2432 Revision 1.27 2006/06/09 11:26:26 jim
2433 Small changes to keep lint happy
2434 
2435 Revision 1.26 2006/06/06 13:07:54 jim
2436 Change the stats routine used in vircam_difference_image
2437 
2438 Revision 1.25 2006/05/30 13:31:47 jim
2439 Added vircam_timestamp
2440 
2441 Revision 1.24 2006/05/24 13:35:49 jim
2442 Added vircam_dummy_image and vircam_dummy_catalogue
2443 
2444 Revision 1.23 2006/05/04 15:16:33 jim
2445 Fixed memory bug in vircam_overexp
2446 
2447 Revision 1.22 2006/04/20 11:29:41 jim
2448 Added vircam_overexp
2449 
2450 Revision 1.21 2006/03/22 11:42:32 jim
2451 Moved some routines into vircam_mask
2452 
2453 Revision 1.20 2006/03/15 10:43:42 jim
2454 Fixed a few things
2455 
2456 Revision 1.19 2006/03/08 14:32:22 jim
2457 Lots of little modifications
2458 
2459 Revision 1.18 2006/03/01 10:31:29 jim
2460 Now uses new vir_fits objects
2461 
2462 Revision 1.17 2006/02/18 11:48:55 jim
2463 *** empty log message ***
2464 
2465 Revision 1.16 2006/01/23 10:30:50 jim
2466 Mainly documentation mods
2467 
2468 Revision 1.15 2005/12/14 22:17:33 jim
2469 Updated docs
2470 
2471 Revision 1.14 2005/12/01 16:26:03 jim
2472 Added vircam_dummy_confidence
2473 
2474 Revision 1.13 2005/11/25 15:33:22 jim
2475 Some code fixes to keep splint happy
2476 
2477 Revision 1.12 2005/11/25 09:56:15 jim
2478 Tidied up some more documentation
2479 
2480 Revision 1.11 2005/11/25 09:36:23 jim
2481 Added vircam_linfit
2482 
2483 Revision 1.10 2005/11/07 13:15:16 jim
2484 Fixed lots of bugs and added some error checking
2485 
2486 Revision 1.9 2005/11/03 15:16:28 jim
2487 Lots of changes mainly to strengthen error reporting
2488 
2489 Revision 1.8 2005/11/03 13:28:50 jim
2490 All sorts of changes to tighten up error handling
2491 
2492 Revision 1.7 2005/10/14 13:21:04 jim
2493 Added some new routines
2494 
2495 Revision 1.6 2005/09/20 15:07:46 jim
2496 Fixed a few bugs and added a few things
2497 
2498 Revision 1.5 2005/09/07 12:47:22 jim
2499 renamed a malloc and free to the cpl equivallent
2500 
2501 Revision 1.4 2005/08/10 09:55:05 jim
2502 Modified vircam_madfit so that if determinant is zero, then it sends a
2503 zero slope and intercept back
2504 
2505 Revision 1.3 2005/08/10 08:42:00 jim
2506 Modified vircam_madfit so that if the initial least squares fit gets a
2507 perfect result, then it just returns with those values rather than to try
2508 and do the median fit
2509 
2510 Revision 1.2 2005/08/09 15:30:00 jim
2511 vircam_exten_range had number of chips wrong!
2512 
2513 Revision 1.1.1.1 2005/08/05 08:29:09 jim
2514 Initial import
2515 
2516 
2517 */
2518