vircam_utils.c

00001 /* $Id: vircam_utils.c,v 1.73 2010/12/09 13:23:56 jim Exp $
00002  *
00003  * This file is part of the VIRCAM Pipeline
00004  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: jim $
00023  * $Date: 2010/12/09 13:23:56 $
00024  * $Revision: 1.73 $
00025  * $Name: v1-1-0 $
00026  */
00027 
00028 /* Includes */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033 
00034 #include <sys/time.h>
00035 #include <time.h>
00036 #include <libgen.h>
00037 #include <string.h>
00038 #include <unistd.h>
00039 
00040 #include <cpl.h>
00041 #include <math.h>
00042 
00043 #include "vircam_utils.h"
00044 #include "vircam_stats.h"
00045 #include "vircam_fits.h"
00046 #include "vircam_pfits.h"
00047 #include "catalogue/imcore.h"
00048 
00049 #define SZKEY 32
00050 #define SZVAL 64
00051 
00052 /* Define some columns for illumination correction tables */
00053 
00054 #define NI_COLS 5
00055 static const char *illcor_cols[NI_COLS] = {"xmin","xmax","ymin","ymax",
00056                                            "illcor"};
00057 
00058 /* Static subroutine prototypes */
00059 
00060 static float madfunc(int npts, float *xt, float *yt, float b);
00061 
00075 /*---------------------------------------------------------------------------*/
00090 /*---------------------------------------------------------------------------*/
00091 
00092 extern const char *vircam_get_license(void) {
00093     const char  *vircam_license = 
00094         "This file is part of the VIRCAM Instrument Pipeline\n"
00095         "Copyright (C) 2006 Cambridge Astronomy Survey Unit\n"
00096         "\n"
00097         "This program is free software; you can redistribute it and/or modify\n"
00098         "it under the terms of the GNU General Public License as published by\n"
00099         "the Free Software Foundation; either version 2 of the License, or\n"
00100         "(at your option) any later version.\n"
00101         "\n"
00102         "This program is distributed in the hope that it will be useful,\n"
00103         "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00104         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
00105         "GNU General Public License for more details.\n"
00106         "\n"
00107         "You should have received a copy of the GNU General Public License\n"
00108         "along with this program; if not, write to the Free Software\n"
00109         "Foundation, Inc., 59 Temple Place, Suite 330, Boston, \n"
00110         "MA  02111-1307  USA";
00111     return(vircam_license);
00112 }
00113 
00114 
00115 /*---------------------------------------------------------------------------*/
00139 /*---------------------------------------------------------------------------*/
00140 
00141 extern int vircam_compare_tags(const cpl_frame *frame1, 
00142                                const cpl_frame *frame2) {
00143     char *v1,*v2;
00144 
00145     /* Test entries */
00146 
00147     if (frame1 == NULL || frame2 == NULL) 
00148         return(-1);
00149 
00150     /* Get the tags */
00151 
00152     if ((v1 = (char *)cpl_frame_get_tag(frame1)) == NULL) 
00153         return(-1);
00154     if ((v2 = (char *)cpl_frame_get_tag(frame2)) == NULL) 
00155         return(-1);
00156 
00157     /* Compare the tags */
00158 
00159     if (strcmp(v1,v2)) 
00160         return(0);
00161     else 
00162         return(1);
00163 }
00164 
00165 /*---------------------------------------------------------------------------*/
00191 /*---------------------------------------------------------------------------*/
00192 
00193 extern cpl_frameset *vircam_frameset_subgroup(cpl_frameset *frameset, 
00194                                               int *labels, int nlab, 
00195                                               const char *tag) {
00196     int i;
00197     cpl_frameset *cur_set,*ret_set;
00198     cpl_frame *cur_frame;
00199     char *cur_tag;
00200 
00201     ret_set = NULL;
00202     for (i = 0; i < nlab; i++) {
00203         cur_set = cpl_frameset_extract(frameset,labels,i);
00204         if (cur_set == NULL)
00205             break;
00206         cur_frame = cpl_frameset_get_frame(cur_set,0);
00207         cur_tag = (char *)cpl_frame_get_tag(cur_frame);
00208         if (!strcmp(cur_tag,tag)) {
00209             ret_set = cur_set;
00210             break;
00211         }
00212         cpl_frameset_delete(cur_set);
00213     }
00214     return(ret_set);
00215 }
00216 
00217 /*---------------------------------------------------------------------------*/
00244 /*---------------------------------------------------------------------------*/
00245 
00246 extern cpl_frame *vircam_frameset_subgroup_1(cpl_frameset *frameset, 
00247                                              int *labels, int nlab, 
00248                                              const char *tag) {
00249     cpl_frameset *cur_set;
00250     cpl_frame *cur_frame,*new_frame;
00251 
00252     if ((cur_set = vircam_frameset_subgroup(frameset,labels,nlab,tag)) == NULL) {
00253         return(NULL);
00254     } else {
00255         cur_frame = cpl_frameset_get_frame(cur_set,0);
00256         new_frame = cpl_frame_duplicate(cur_frame);
00257         cpl_frameset_delete(cur_set);
00258         return(new_frame);
00259     }
00260 }
00261 
00262 /*---------------------------------------------------------------------------*/
00282 /*---------------------------------------------------------------------------*/
00283 
00284 extern int vircam_frameset_fexists (cpl_frameset *frameset) {
00285     int nf,i,nerr;
00286     cpl_frame *cur;
00287     const char *fname;
00288     const char *fctid = "vircam_frameset_fexists";
00289 
00290     /* Check for NULL input */
00291 
00292     if (frameset == NULL) {
00293         cpl_msg_error(fctid,"Input frameset is NULL");
00294         return(VIR_FATAL);
00295     }
00296 
00297     /* Get the size of the frameset */
00298 
00299     nf = cpl_frameset_get_size(frameset);
00300     if (nf == 0) {
00301         cpl_msg_error(fctid,"Input frameset has size of zero");
00302         return(VIR_FATAL);
00303     }
00304 
00305     /* Loop through the frameset and see if the file is accessible */
00306 
00307     nerr = 0;
00308     for (i = 0; i < nf; i++) {
00309         cur = cpl_frameset_get_frame(frameset,i);
00310         fname = cpl_frame_get_filename(cur);
00311         if (access(fname,F_OK) != 0) {
00312             cpl_msg_error(fctid,"File: %s doesn't exist",fname);
00313             nerr++;
00314         }
00315     }
00316 
00317     /* If there were any missing then return bad status */
00318 
00319     if (nerr != 0)
00320         return(VIR_FATAL);
00321     else
00322         return(VIR_OK);
00323 }
00324 
00325 /*---------------------------------------------------------------------------*/
00350 /*---------------------------------------------------------------------------*/
00351 
00352 extern void vircam_exten_range(int inexten, const cpl_frame *fr, int *out1, 
00353                                int *out2) {
00354     int nvircam = 16,n,nmax;
00355     const char *fctid = "vircam_exten_range";
00356 
00357     /* Right, how many frames actually exist? */
00358 
00359     n = cpl_frame_get_nextensions(fr);
00360 
00361     /* If there are less than the cannonical number, then issue a warning
00362        message here */
00363 
00364     if (n < nvircam) {
00365         cpl_msg_warning(fctid,"Only %d extensions out of %d are present",
00366                         n,nvircam);
00367         nmax = n;
00368     } else {
00369         nmax = nvircam;
00370     }
00371 
00372     /* If the extension number requested is zero, then do all the extensions
00373        that are available */
00374     
00375     if (inexten == 0) {
00376         *out1 = 1;
00377         *out2 = nmax;
00378 
00379     /* Otherwise, check that the requested extension is actually present */
00380 
00381     } else {
00382 
00383         if (inexten > nmax) {
00384             cpl_msg_error(fctid,"Requested extension %d is not present",
00385                           inexten);
00386             *out1 = -1;
00387             *out2 = -1;
00388         } else {
00389             *out1 = inexten;
00390             *out2 = inexten;
00391         }
00392     }
00393     return;
00394 }
00395 
00396 /*---------------------------------------------------------------------------*/
00422 /*---------------------------------------------------------------------------*/
00423 
00424 extern void vircam_madfit(int npts, float *xdata, float *ydata, 
00425                           float *intercept, float *slope) {
00426     int j;
00427     float sx,sy,sxx,sxy,det,aa,bb,temp,chisq,sigb,b1,f1,b2,f2,f;
00428 
00429     /* Do a linear least squares for a first estimate */
00430 
00431     sx = 0.0;
00432     sy = 0.0;
00433     sxx = 0.0;
00434     sxy = 0.0;
00435     for (j = 0; j < npts; j++) {
00436         sx += xdata[j];
00437         sy += ydata[j];
00438         sxx += xdata[j]*xdata[j];
00439         sxy += xdata[j]*ydata[j];
00440     }
00441     det = (float)npts*sxx - sx*sx;
00442     if (det == 0.0) {
00443         *slope = 0.0;
00444         *intercept = 0.0;
00445         return;
00446     }
00447     aa = (sxx*sy - sx*sxy)/det;
00448     bb = ((float)npts*sxy - sx*sy)/det;
00449     chisq = 0.0;
00450     for (j = 0; j < npts; j++) {
00451         temp = ydata[j] - (aa + bb*xdata[j]);
00452         chisq += temp*temp;
00453     }
00454     sigb = sqrt(chisq/det);
00455     if (sigb == 0.0) {
00456         *slope = bb;
00457         *intercept = aa;
00458         return;
00459     }
00460 
00461     /* Now bracket the solution */
00462 
00463     b1 = bb;
00464     f1 = madfunc(npts,xdata,ydata,b1);
00465     b2 = bb + ((f1 > 0.0) ? fabs(3.0*sigb) : -fabs(3.0*sigb));
00466     f2 = madfunc(npts,xdata,ydata,b2);
00467     while (f1*f2 > 0.0) {
00468         bb = 2.0*b2 - b1;
00469         b1 = b2;
00470         f1 = f2;
00471         b2 = bb;
00472         f2 = madfunc(npts,xdata,ydata,b2);
00473     }
00474 
00475     /* Iterate to find the minimum value */
00476 
00477     sigb = 0.01*sigb;
00478     while (fabs(b2 - b1) > sigb) {
00479         bb = 0.5*(b1 + b2);
00480         if (bb == b1 || bb == b2) 
00481             break;
00482         f = madfunc(npts,xdata,ydata,bb);
00483         if (f*f1 >= 0.0) {
00484             f1 = f;
00485             b1 = bb;
00486         } else {
00487             f2 = f;
00488             b2 = bb;
00489         }
00490     }
00491     *intercept = aa;
00492     *slope = bb;
00493 }
00494 
00495 /*---------------------------------------------------------------------------*/
00518 /*---------------------------------------------------------------------------*/
00519 
00520 
00521 static float madfunc(int npts, float *xt, float *yt, float b) {
00522     float *arr,aa,d,sum;
00523     int j;
00524 
00525     arr = cpl_malloc(npts*sizeof(*arr));
00526     for (j = 0; j < npts; j++) 
00527         arr[j] = yt[j] - b*xt[j];
00528     aa = vircam_med(arr,NULL,(long)npts);
00529     sum = 0.0;
00530     for (j = 0; j < npts; j++) {
00531         d = yt[j] - (b*xt[j] + aa);
00532         sum += d > 0.0 ? xt[j] : -xt[j];
00533     }
00534     cpl_free(arr);
00535     return(sum);
00536 }
00537 
00538 /*---------------------------------------------------------------------------*/
00565 /*---------------------------------------------------------------------------*/
00566 
00567 extern void vircam_linfit(int npts, double *xdata, double *ydata, 
00568                           double *intercept, double *slope, double *sig) {
00569     int j;
00570     double sx,sy,sxx,sxy,det,aa,bb,temp,sum,sumsq;
00571 
00572     /* Do a linear least squares */
00573 
00574     sx = 0.0;
00575     sy = 0.0;
00576     sxx = 0.0;
00577     sxy = 0.0;
00578     for (j = 0; j < npts; j++) {
00579         sx += xdata[j];
00580         sy += ydata[j];
00581         sxx += xdata[j]*xdata[j];
00582         sxy += xdata[j]*ydata[j];
00583     }
00584     det = (double)npts*sxx - sx*sx;
00585     if (det == 0.0) {
00586         *slope = 0.0;
00587         *intercept = 0.0;
00588         *sig = 0.0;
00589         return;
00590     }
00591 
00592     /* Intercept and slope */
00593 
00594     aa = (sxx*sy - sx*sxy)/det;
00595     bb = ((double)npts*sxy - sx*sy)/det;
00596 
00597     /* Work out RMS of fit */
00598 
00599     sum = 0.0;
00600     sumsq = 0.0;
00601     for (j = 0; j < npts; j++) {
00602         temp = ydata[j] - (aa + bb*xdata[j]);
00603         sum += temp;
00604         sumsq += temp*temp;
00605     }
00606     sum /= (double)npts;
00607 
00608     /* Set return values */
00609 
00610     *sig = sqrt(sumsq/(double)npts - sum*sum);
00611     *slope = bb;
00612     *intercept = aa;
00613 }
00614 
00615 /*---------------------------------------------------------------------------*/
00639 /*---------------------------------------------------------------------------*/
00640 
00641 extern int vircam_solve_gauss(double **a, double *b, int m) {
00642     double temp,big,pivot,rmax;
00643     int i,iu,j,k,jl,ib,ir;
00644     int l = 0;
00645 
00646     iu = m - 1;
00647     for (i = 0; i < iu; i++) {
00648         big = 0.0;
00649 
00650         /* find largest remaining term in ith column for pivot */
00651 
00652         for (k = i; k < m; k++) {
00653             rmax = fabs(a[i][k]);
00654             if (rmax > big) {
00655                 big = rmax;
00656                 l = k;
00657             }
00658         }
00659 
00660         /* check for non-zero term */
00661 
00662         if (big == 0.0) {
00663             for (ib = 0; ib < m; ib++)
00664                 b[ib] = 0.0;
00665             cpl_msg_error("vircam_solve_gauss","Zero Determinant\n");
00666             return(VIR_FATAL);
00667         }
00668 
00669         if (i != l) {
00670 
00671             /* switch rows */
00672 
00673             for (j = 0; j < m; j++) {
00674                 temp = a[j][i];
00675                 a[j][i] = a[j][l];
00676                 a[j][l] = temp;
00677             }
00678             temp = b[i];
00679             b[i] = b[l];
00680             b[l] = temp;
00681         }
00682 
00683 
00684         /* pivotal reduction */
00685 
00686         pivot = a[i][i];
00687         jl = i+1;
00688 
00689         for (j = jl; j < m; j++) {
00690             temp = a[i][j]/pivot;
00691             b[j] -= temp*b[i];
00692             for (k = i; k < m; k++)
00693                 a[k][j] -= temp*a[k][i];
00694         }
00695     }
00696 
00697     /* back substitution for solution */
00698 
00699     for (i = 0; i < m; i++) {
00700         ir = m - 1 - i;
00701         if (a[ir][ir] != 0.0) {
00702             temp = b[ir];
00703             if (ir != m - 1) {
00704                 for (j = 1; j <= i; j++) {
00705                     k = m - j;
00706                     temp -= a[k][ir]*b[k];
00707                 }
00708             }
00709             b[ir] = temp/a[ir][ir];
00710         } else
00711             b[ir] = 0.0;
00712     }
00713     return(VIR_OK);
00714 }
00715 
00716 /*---------------------------------------------------------------------------*/
00754 /*---------------------------------------------------------------------------*/
00755 
00756 extern int vircam_polyfit(const cpl_array *xarray, const cpl_array *yarray, 
00757                           int ncoefs, int ilim, int niter, float lclip, 
00758                           float hclip, cpl_array **polycf, double *sigfit) {
00759     const char *fctid = "vircam_polyfit";
00760     int npts,iter,i,j,nnew,k,retval,n;
00761     double *xdata,*ydata,*pdata,*res,**a,*b,temp,sum,sumsq,val;
00762     double lcut,hcut;
00763     unsigned char *pm;
00764 
00765     /* Initialise a few things */
00766 
00767     *polycf = NULL;
00768     *sigfit = -1.0;
00769 
00770     /* How many data points do we have? */
00771 
00772     npts = cpl_array_get_size(xarray);
00773 
00774     /* Do we have enough points for the required order of the fit? */
00775 
00776     if (npts < ncoefs) {
00777         cpl_msg_warning(fctid,"Not data for fit, Npts = %d, Ncoefs = %d",
00778                         npts,ncoefs);
00779         return(VIR_FATAL);
00780     }
00781 
00782     /* Create some arrays */
00783 
00784     a = cpl_malloc(ncoefs*sizeof(double *));
00785     b = cpl_calloc(ncoefs,sizeof(double));
00786     for (i = 0; i < ncoefs; i++) 
00787         a[i] = cpl_calloc(ncoefs,sizeof(double));
00788     pm = cpl_calloc(npts,sizeof(unsigned char));
00789     res = cpl_malloc(npts*sizeof(double));
00790 
00791     /* Get pointers to the input arrays */
00792 
00793     xdata = (double *)cpl_array_get_data_double_const(xarray);
00794     ydata = (double *)cpl_array_get_data_double_const(yarray);
00795 
00796     /* Get an output array */
00797 
00798     *polycf = cpl_array_new(ncoefs,CPL_TYPE_DOUBLE);
00799     pdata = cpl_array_get_data_double(*polycf);
00800 
00801     /* Iteration loop */
00802 
00803     for (iter = 0; iter <= niter; iter++) {
00804 
00805         /* Zero some accumulators */
00806 
00807         for (i = 0; i < ncoefs; i++)  {
00808             for (j = 0; j < ncoefs; j++) 
00809                 a[i][j] = 0.0;
00810             b[i] = 0.0;
00811         }
00812         nnew = 0;
00813 
00814         /* Cumulate sums */
00815  
00816         for (i = 0; i < npts; i++) {
00817             if (pm[i] == 1)
00818                 continue;
00819             for (k = 0; k < ncoefs; k++) {
00820                 temp = 1.0;
00821                 if (k + ilim != 0)
00822                     temp = pow(xdata[i],(double)(k+ilim));
00823                 b[k] += ydata[i]*temp;
00824                 for (j = 0; j <= k; j++) {
00825                     temp = 1.0;
00826                     if (k + j + 2*ilim != 0)
00827                         temp = pow(xdata[i],(double)(k+j+2*ilim));
00828                     a[j][k] += temp;
00829                 }
00830             }
00831         }
00832         for (k = 1; k < ncoefs; k++) 
00833             for (j = 0; j < k; j++) 
00834                 a[k][j] = a[j][k];
00835 
00836         /* Solve linear equations */
00837 
00838         retval = vircam_solve_gauss(a,b,ncoefs);
00839         if (retval != VIR_OK) {
00840             cpl_msg_warning(fctid,"Fit failed");
00841             freearray(*polycf);
00842             freespace2(a,ncoefs);
00843             freespace(b);
00844             freespace(pm);
00845             freespace(res);
00846             return(VIR_FATAL);
00847         }
00848 
00849         /* Ok, assuming this is OK, then fill the polynomial coefficients */
00850 
00851         for (i = 0; i < ncoefs; i++)
00852             pdata[i] = b[i];
00853 
00854         /* Calculate the fit quality */
00855 
00856         sum = 0.0;
00857         sumsq = 0.0;
00858         n = 0;
00859         for (i = 0; i < npts; i++) {
00860             if (pm[i] == 1)
00861                 continue;
00862             val = 0.0;
00863             for (j = 0; j < ncoefs; j++)                
00864                 val += pdata[j]*pow(xdata[i],(double)j+ilim);
00865             res[i] = val - ydata[i];
00866             sum += res[i];
00867             sumsq += pow(res[i],2.0);
00868             n++;
00869         }
00870         sum /= (double)n;
00871         *sigfit = sqrt(sumsq/(double)n - sum*sum);
00872 
00873         /* If this is not the last iteration, then do some clipping */
00874 
00875         lcut = sum - lclip*(*sigfit);
00876         hcut = sum + hclip*(*sigfit);
00877         if (iter < niter) {
00878             for (i = 0; i < npts; i++) {
00879                 if (pm[i] == 1) 
00880                     continue;
00881                 if (res[i] > hcut || res[i] < lcut) {
00882                     nnew++;
00883                     pm[i] = 1;
00884                 }
00885             }
00886         }
00887         
00888         /* If no new points have been clipped, then get out of here now... */
00889 
00890         if (nnew == 0) 
00891             break;
00892     }
00893 
00894     /* Tidy up and get out of here */
00895 
00896     freespace2(a,ncoefs);
00897     freespace(b);
00898     freespace(pm);
00899     freespace(res);
00900     return(VIR_OK);
00901 }
00902 
00903 /*---------------------------------------------------------------------------*/
00944 /*---------------------------------------------------------------------------*/
00945 
00946 extern void vircam_difference_image(cpl_image *master, cpl_image *prog, 
00947                                     unsigned char *bpm, cpl_table *chantab, 
00948                                     int ncells, int oper, float *global_diff, 
00949                                     float *global_rms, cpl_image **diffim, 
00950                                     cpl_table **diffimstats) {
00951     float *ddata,*work,mean,sig,med,mad;
00952     long nx,ny,npts;
00953     int nrows,i,nc1,nc2,nr,ixmin,ixmax,iymin,iymax,cnum,cx,cy,idx,idy;
00954     int icx,icy,indy1,indy2,indx1,indx2,jp,jcx,jj,jcy,ii,ncx,ncy;
00955     const char *fctid = "vircam_difference_image";
00956 
00957     /* Initialise the output */
00958 
00959     *diffim = NULL;
00960     *diffimstats = NULL;
00961     *global_diff = 0.0;
00962     *global_rms = 0.0;
00963 
00964     /* Is there a programme frame or a master? */
00965 
00966     if (prog == NULL || master == NULL)
00967         return;
00968 
00969     /* Start by subtracting the master image from the programme image */
00970 
00971     switch (oper) {
00972     case 1:
00973         *diffim = cpl_image_subtract_create(prog,master);
00974         break;
00975     case 2:
00976         *diffim = cpl_image_divide_create(prog,master);
00977         break;
00978     default:
00979         *diffim = NULL;
00980         cpl_msg_error(fctid,"Invalid operation requested %d",oper);
00981         break;
00982     }      
00983     if (*diffim == NULL)
00984         return;
00985 
00986     /* Work out a median difference */
00987 
00988     ddata = cpl_image_get_data_float(*diffim);
00989     nx = cpl_image_get_size_x(*diffim);
00990     ny = cpl_image_get_size_y(*diffim);
00991     npts = nx*ny;
00992     vircam_medmad(ddata,bpm,npts,global_diff,global_rms);
00993     *global_rms *= 1.48;
00994 
00995     /* Is there a channel table? */
00996 
00997     if (chantab == NULL)
00998         return;
00999 
01000     /* Before going any further, check that the channel table has all of 
01001        the columns we need */
01002 
01003     if (! cpl_table_has_column(chantab,"ixmin") ||
01004         ! cpl_table_has_column(chantab,"ixmax") ||
01005         ! cpl_table_has_column(chantab,"iymin") ||
01006         ! cpl_table_has_column(chantab,"iymax") ||
01007         ! cpl_table_has_column(chantab,"channum")) {
01008             cpl_msg_error(fctid,"Channel table is missing one of the required columns");
01009 
01010             return;
01011     }
01012 
01013     /* Work out how to divide the channels */
01014 
01015     switch (ncells) {
01016     case 1:
01017         nc1 = 1;
01018         nc2 = 1;
01019         break;
01020     case 2:
01021         nc1 = 2;
01022         nc2 = 1;
01023         break;
01024     case 4:
01025         nc1 = 4;
01026         nc2 = 1;
01027         break;
01028     case 8:
01029         nc1 = 8;
01030         nc2 = 1;
01031         break;
01032     case 16:
01033         nc1 = 16;
01034         nc2 = 1;
01035         break;
01036     case 32:
01037         nc1 = 16;
01038         nc2 = 2;
01039         break;
01040     case 64:
01041         nc1 = 32;
01042         nc2 = 2;
01043         break;
01044     default:
01045         nc1 = 32;
01046         nc2 = 2;
01047         break;
01048     }
01049 
01050     /* Create a difference image stats table */
01051 
01052     nrows = cpl_table_count_selected(chantab);
01053     *diffimstats = vircam_create_diffimg_stats(nrows*nc1*nc2);
01054 
01055     /* Loop for each data channel now */
01056 
01057     nr = 0;
01058     for (i = 0; i < nrows; i++) {
01059         ixmin = cpl_table_get_int(chantab,"ixmin",i,NULL);
01060         ixmax = cpl_table_get_int(chantab,"ixmax",i,NULL);
01061         iymin = cpl_table_get_int(chantab,"iymin",i,NULL);
01062         iymax = cpl_table_get_int(chantab,"iymax",i,NULL);
01063         cnum = cpl_table_get_int(chantab,"channum",i,NULL);
01064 
01065         /* Which is the long axis? If the channels are rectangular then
01066            divide the long axis by the greater number of cells. If the number
01067            of cells is less than 8, then just divide the long axis. If the
01068            channel is square, then divide the X axis more finely */
01069 
01070         cx = ixmax - ixmin + 1;
01071         cy = iymax - iymin + 1;
01072         if (cx > cy) {
01073             ncx = max(nc1,nc2);
01074             ncy = min(nc1,nc2);
01075         } else if (cx < cy) {
01076             ncy = max(nc1,nc2);
01077             ncx = min(nc1,nc2);
01078         } else {
01079             ncx = max(nc1,nc2);
01080             ncy = min(nc1,nc2);
01081         }
01082         
01083         /* How big is the cell? */
01084 
01085         idy = cy/ncy;
01086         idx = cx/ncx;
01087         work = cpl_malloc(idx*idy*sizeof(*work));
01088 
01089         /* Now loop for aach cell */
01090 
01091         for (icy = 0; icy < ncy; icy++) {
01092             indy1 = idy*icy;
01093             indy2 = min(iymax,indy1+idy-1);
01094             for (icx = 0; icx < ncx; icx++) {
01095                 indx1 = idx*icx;
01096                 indx2 = min(ixmax,indx1+idx-1);
01097                 jp = 0;
01098                 for (jcy = indy1; jcy < indy2; jcy++) {
01099                     jj = jcy*nx;
01100                     for (jcx = indx1; jcx < indx2; jcx++) {
01101                         ii = jj + jcx;
01102                         if (bpm != NULL && bpm[ii] == 0)
01103                             work[jp++] = ddata[ii];
01104                     }
01105                 }
01106                 (void)vircam_meansig(work,NULL,(long)jp,&mean,&sig);
01107                 (void)vircam_medmad(work,NULL,(long)jp,&med,&mad);
01108                 cpl_table_set_int(*diffimstats,"xmin",nr,indx1+1);
01109                 cpl_table_set_int(*diffimstats,"xmax",nr,indx2+1);
01110                 cpl_table_set_int(*diffimstats,"ymin",nr,indy1+1);
01111                 cpl_table_set_int(*diffimstats,"ymax",nr,indy2+1);
01112                 cpl_table_set_int(*diffimstats,"chan",nr,cnum);
01113                 cpl_table_set_float(*diffimstats,"mean",nr,mean);
01114                 cpl_table_set_float(*diffimstats,"median",nr,med);
01115                 cpl_table_set_float(*diffimstats,"variance",nr,(sig*sig));
01116                 cpl_table_set_float(*diffimstats,"mad",nr++,mad);
01117             }
01118         }
01119         cpl_free(work);
01120     }
01121 }               
01122 
01123 /*---------------------------------------------------------------------------*/
01140 /*---------------------------------------------------------------------------*/
01141 
01142 cpl_table *vircam_create_diffimg_stats(int nrows) {
01143     cpl_table *diffimstats;
01144 
01145     diffimstats = cpl_table_new(nrows);
01146     cpl_table_new_column(diffimstats,"xmin",CPL_TYPE_INT);
01147     cpl_table_set_column_unit(diffimstats,"xmin","pixels");
01148     cpl_table_new_column(diffimstats,"xmax",CPL_TYPE_INT);
01149     cpl_table_set_column_unit(diffimstats,"xmax","pixels");
01150     cpl_table_new_column(diffimstats,"ymin",CPL_TYPE_INT);
01151     cpl_table_set_column_unit(diffimstats,"ymin","pixels");
01152     cpl_table_new_column(diffimstats,"ymax",CPL_TYPE_INT);
01153     cpl_table_set_column_unit(diffimstats,"ymax","pixels");
01154     cpl_table_new_column(diffimstats,"chan",CPL_TYPE_INT);
01155     cpl_table_set_column_unit(diffimstats,"chan","pixels");
01156     cpl_table_new_column(diffimstats,"mean",CPL_TYPE_FLOAT);
01157     cpl_table_set_column_unit(diffimstats,"mean","ADU");
01158     cpl_table_new_column(diffimstats,"median",CPL_TYPE_FLOAT);
01159     cpl_table_set_column_unit(diffimstats,"median","ADU");
01160     cpl_table_new_column(diffimstats,"variance",CPL_TYPE_FLOAT);
01161     cpl_table_set_column_unit(diffimstats,"variance","ADU**2");
01162     cpl_table_new_column(diffimstats,"mad",CPL_TYPE_FLOAT);
01163     cpl_table_set_column_unit(diffimstats,"mad","ADU");
01164     return(diffimstats);
01165 }
01166 
01167 
01168 /*---------------------------------------------------------------------------*/
01192 /*---------------------------------------------------------------------------*/
01193 
01194 extern void vircam_sort(float **a, int n, int m) {
01195     int increment,i,j,k;
01196     float *t;
01197 
01198     t = cpl_malloc(m*sizeof(*t));
01199 
01200     increment = n/2;
01201     while (increment > 0) {
01202         for (i = increment; i < n; i++) {
01203             j = i;
01204             for (k = 0; k < m; k++)
01205                 t[k] = a[k][i];
01206             while ((j >= increment) && (a[0][j-increment] > t[0])) {
01207                 for (k = 0; k < m; k++) 
01208                     a[k][j] = a[k][j-increment];
01209                 j = j - increment;
01210             }
01211             for (k = 0; k < m; k++) 
01212                 a[k][j] = t[k];
01213         }
01214         if (increment == 2) 
01215             increment = 1;
01216         else
01217             increment = (int)((float)increment/2.2);
01218     }
01219     cpl_free(t);
01220 }
01221 
01222 /*---------------------------------------------------------------------------*/
01239 /*---------------------------------------------------------------------------*/
01240 
01241 extern long vircam_getnpts(cpl_image *in) {
01242     int nx,ny;
01243     long npts;
01244     const char *fctid = "vircam_getnpts";
01245 
01246     if ((nx = cpl_image_get_size_x(in)) == -1) {
01247         cpl_msg_error(fctid,"NULL image input");
01248         return(0);
01249     }
01250     if ((ny = cpl_image_get_size_y(in)) == -1) {
01251         cpl_msg_error(fctid,"NULL image input");
01252         return(0);
01253     }
01254     npts = (long)nx*ny;
01255     return(npts);
01256 }
01257 
01258 /*---------------------------------------------------------------------------*/
01289 /*---------------------------------------------------------------------------*/
01290 
01291 extern int vircam_fndmatch(float x, float y, float *xlist, float *ylist, 
01292                            int nlist, float err) {
01293     int isp,ifp,indx,i;
01294     float errsq,errmin,dx,dy,poserr;
01295 
01296     /* Find lower limit index */
01297 
01298     isp = 0;
01299     ifp = nlist - 1;
01300     errsq = err*err;
01301     indx = (isp + ifp)/2;
01302     while (ifp-isp >= 2) {
01303         if (ylist[indx] < y - err) {
01304             isp = indx;
01305             indx = (indx+ifp)/2;
01306         } else if (ylist[indx] > y - err) {
01307             ifp = indx;
01308             indx = (indx+isp)/2;
01309         } else {
01310             isp = indx;
01311             break;
01312         }
01313     }
01314 
01315     /* Now find nearest one within limit */
01316 
01317     indx = -1;
01318     errmin = errsq;
01319     for (i = isp; i < nlist; i++) {
01320         if (ylist[i] > y+err)
01321             break;
01322         dx = x - xlist[i];
01323         dy = y - ylist[i];
01324         poserr = dx*dx + dy*dy;
01325         if (poserr < errsq) {
01326             if (poserr <= errmin) {
01327                 indx = i;
01328                 errmin = poserr;
01329             }
01330         }
01331     }
01332     return(indx);
01333 }
01334 
01335 /*---------------------------------------------------------------------------*/
01354 /*---------------------------------------------------------------------------*/
01355 
01356 extern int *vircam_dummy_confidence(long n) {
01357     int *cdata,i;
01358  
01359     cdata = cpl_malloc(n*sizeof(*cdata));
01360     for (i = 0; i < n; i++)
01361         cdata[i] = 100;
01362     return(cdata);
01363 }
01364 
01365 /*---------------------------------------------------------------------------*/
01388 /*---------------------------------------------------------------------------*/
01389 
01390 extern int vircam_compare_dims(cpl_image *im1, cpl_image *im2) {
01391     
01392     if ((cpl_image_get_size_x(im1) != cpl_image_get_size_x(im2)) ||
01393         cpl_image_get_size_y(im1) != cpl_image_get_size_y(im2))
01394         return(VIR_FATAL);
01395     else
01396         return(VIR_OK);
01397 }
01398    
01399 /*---------------------------------------------------------------------------*/
01420 /*---------------------------------------------------------------------------*/
01421 
01422 extern void vircam_prov(cpl_propertylist *p, vir_fits **inlist, int n) {
01423     int i;
01424     char keyword[SZKEY],value[SZVAL],*fn,*base;
01425 
01426     /* Delete all the provenance keywords that might already exist */
01427 
01428     cpl_propertylist_erase_regexp(p,"ESO DRS PROV*",0);
01429 
01430     /* Add the new provenance keywords */
01431 
01432     for (i = 0; i < n; i++) {
01433         (void)snprintf(keyword,SZKEY,"ESO DRS PROV%04d",i+1);
01434         fn = cpl_strdup(vircam_fits_get_fullname(inlist[i]));
01435         base = basename(fn);
01436         (void)snprintf(value,SZVAL,"%s",base);
01437         cpl_free(fn);
01438         cpl_propertylist_update_string(p,keyword,value);
01439         (void)snprintf(value,SZVAL,"Input file # %d",i+1);
01440         cpl_propertylist_set_comment(p,keyword,value);
01441     }
01442 }
01443 
01444 /*---------------------------------------------------------------------------*/
01462 /*---------------------------------------------------------------------------*/
01463 
01464 extern void vircam_merge_propertylists(cpl_propertylist *p1, 
01465                                        cpl_propertylist *p2) {
01466     int i;
01467     const char *name;
01468     
01469     /* Return if either propertylist is NULL */
01470 
01471     if (p1 == NULL || p2 == NULL)
01472         return;
01473 
01474     /* Erase any common properties so that you don't get a clash with
01475        data types. Then copy each property from the second list into 
01476        the first one */
01477 
01478     for (i = 0; i < cpl_propertylist_get_size(p2); i++) {
01479         name = cpl_property_get_name(cpl_propertylist_get(p2,i));
01480         if (cpl_propertylist_has(p1,name)) 
01481             cpl_propertylist_erase(p1,name);
01482     }
01483     cpl_propertylist_append(p1,p2);
01484 
01485 }
01486 
01487 
01488 
01489 /*---------------------------------------------------------------------------*/
01508 /*---------------------------------------------------------------------------*/
01509 
01510 extern void vircam_dummy_property(cpl_propertylist *p) {
01511 
01512     /* Check for silly input */
01513 
01514     if (p == NULL)
01515         return;
01516 
01517     /* Add the property now */
01518 
01519     cpl_propertylist_update_bool(p,"ESO DRS IMADUMMY",TRUE);
01520     cpl_propertylist_set_comment(p,"ESO DRS IMADUMMY",
01521                                  "This is a dummy product");
01522     return;
01523 }
01524 
01525 /*---------------------------------------------------------------------------*/
01541 /*---------------------------------------------------------------------------*/
01542 
01543 extern int vircam_is_dummy(cpl_propertylist *p) {
01544 
01545     /* Check for silly input */
01546 
01547     if (p == NULL)
01548         return(0);
01549 
01550     /* Check the propertylist and return the result */
01551 
01552     return(cpl_propertylist_has(p,"ESO DRS IMADUMMY"));
01553 }
01554 
01555 /*---------------------------------------------------------------------------*/
01593 /*---------------------------------------------------------------------------*/
01594 
01595 extern void vircam_overexp(vir_fits **fitslist, int *n, int ndit, float lthr, 
01596                            float hthr, int ditch, float *minv, float *maxv,
01597                            float *avev) {
01598     int i,m;
01599     cpl_image *im;
01600     double val,dndit,sum;
01601 
01602     /* Loop for each of the fits items */
01603 
01604     dndit = (double)ndit;
01605     m = 0;
01606     *minv = 1.0e10;
01607     *maxv = -1.0e10;
01608     sum = 0.0;
01609     for (i = 0; i < *n; i++) {
01610         im = vircam_fits_get_image(fitslist[i]);
01611         val = cpl_image_get_median_window(im,500,500,1000,1000);
01612         val /= ndit;
01613         *minv = min(*minv,val);
01614         *maxv = max(*maxv,val);
01615         sum += val;
01616         if (val > lthr && val < hthr) {
01617             fitslist[m++] = fitslist[i];
01618         } else {
01619             if (ditch) 
01620                 vircam_fits_delete(fitslist[i]);
01621         }
01622     }
01623     for (i = m; i < *n; i++)
01624         fitslist[i] = NULL;
01625     *avev = sum/(double)*n;
01626     *n = m;
01627 }
01628 
01629 /*---------------------------------------------------------------------------*/
01646 /*---------------------------------------------------------------------------*/
01647 
01648 extern cpl_image *vircam_dummy_image(vir_fits *model) {
01649     cpl_image *im;
01650 
01651     /* Copy the input model image */
01652 
01653     im = cpl_image_duplicate(vircam_fits_get_image(model));
01654 
01655     /* Now change it all to zeros */
01656 
01657     cpl_image_multiply_scalar(im,0.0);
01658 
01659     /* Return the result */
01660 
01661     return(im);
01662 }
01663 
01664 /*---------------------------------------------------------------------------*/
01681 /*---------------------------------------------------------------------------*/
01682 
01683 extern cpl_table *vircam_dummy_catalogue(int type) {
01684 
01685     cattype = type;
01686     tabinit(NULL);
01687     return(tab);
01688 }
01689 
01690 
01691 /*---------------------------------------------------------------------------*/
01708 /*---------------------------------------------------------------------------*/
01709 
01710 extern cpl_table *vircam_illcor_newtab(int nrows) {
01711     cpl_table *illcor;
01712     int i;
01713 
01714     /* Create the table structure and fill in the columns */
01715 
01716     illcor = cpl_table_new(nrows);
01717     for (i = 0; i < NI_COLS; i++) 
01718         cpl_table_new_column(illcor,illcor_cols[i],CPL_TYPE_FLOAT);
01719     return(illcor);
01720 }
01721 
01722 /*---------------------------------------------------------------------------*/
01746 /*---------------------------------------------------------------------------*/
01747 
01748 extern void vircam_timestamp(char *out, int n) {
01749     struct timeval tv;
01750     struct tm *tm;
01751     float sec;
01752     
01753     /* Get the Greenwich Mean Time */
01754 
01755     (void)gettimeofday(&tv,NULL);
01756     tm = gmtime(&(tv.tv_sec));
01757     sec = (float)tm->tm_sec + 1.0e-6*(float)tv.tv_usec;
01758 
01759     /* Now format it */
01760 
01761     (void)snprintf(out,n,"%04d-%02d-%02dT%02d:%02d:%07.4f",1900+tm->tm_year,
01762                    tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,sec);
01763 }
01764 
01765 /*---------------------------------------------------------------------------*/
01794 /*---------------------------------------------------------------------------*/
01795 
01796 extern void vircam_backmap(vir_fits *in, vir_mask *mask, int nbsize, 
01797                            cpl_image **out, float *med) {
01798     int i,j,nx,ny,ifracx,ifracy,nbsizx,nbsizy,nbx,nby,*nps,jx,jy;
01799     int jy1,jy2,np,nout,jyp1,jxp1,jz1,jz2,jz3,jz4,nbsize2;
01800     float fracx,fracy,*bmap,**rowpoints,*data,*ptr,dely,delx,t1,t2;
01801     unsigned char *bpm;
01802 
01803     /* Check to see if nbsize is close to exact divisor */
01804 
01805     nx = cpl_image_get_size_x(vircam_fits_get_image(in));
01806     ny = cpl_image_get_size_y(vircam_fits_get_image(in));
01807     fracx = ((float)nx)/((float)nbsize);
01808     fracy = ((float)ny)/((float)nbsize);
01809     ifracx = (int)(fracx + 0.1);
01810     ifracy = (int)(fracy + 0.1);
01811     nbsizx = nx/ifracx;
01812     nbsizy = ny/ifracy;
01813     nbsize = max(vircam_nint(0.9*nbsize),min(nbsize,min(nbsizx,nbsizy)));
01814     nbsize = min(nx,min(ny,nbsize)); /* trap for small maps */
01815     nbsize2 = nbsize/2;
01816 
01817     /* Divide the map into partitions */
01818 
01819     nbx = nx/nbsize;
01820     nby = ny/nbsize;
01821 
01822     /* Get some space for to use for accumulating stats */
01823 
01824     bmap = cpl_malloc(nbx*nby*sizeof(float));
01825     rowpoints = cpl_malloc(nbx*sizeof(float *));
01826     nps = cpl_malloc(nbx*sizeof(int));
01827 
01828     /* Get the data from the input file and the mask */
01829 
01830     data = cpl_image_get_data_float(vircam_fits_get_image(in));
01831     bpm = vircam_mask_get_data(mask);
01832 
01833     /* Work out the global median */
01834 
01835     *med = vircam_med(data,bpm,(long)(nx*ny));
01836 
01837     /* For each cell allocate some nbsize*nbsize pixels in the row pointers.
01838        It's ok to do this here since this will be the maximum that each cell
01839        will have... */
01840 
01841     for (i = 0; i < nbx; i++) 
01842         rowpoints[i] = cpl_malloc(nbsize*nbsize*sizeof(float));
01843     
01844     /* Loop for each row of cells and work out which rows in the input
01845        map these relate to */
01846 
01847     for (jy = 0; jy < nby; jy++) {
01848         jy1 = jy*nbsize;
01849         jy2 = min((jy+1)*nbsize - 1,ny-1);
01850 
01851         /* Zero the counter for each cell */
01852 
01853         for (jx = 0; jx < nbx; jx++)
01854             nps[jx] = 0;
01855 
01856         /* Loop for the strip of the input map covered by this row of cells.
01857            Work out which cell the current pixel is in and then put it into
01858            the correct accumulator assuming the bad pixel mask says it's ok */
01859 
01860         for (j = jy1; j <= jy2; j++) {
01861             for (i = 0; i < nx; i++) {
01862                 jx = min(nbx-1,i/nbsize);
01863                 if (bpm[j*nx + i] == 0) {
01864                     ptr = rowpoints[jx];
01865                     np = nps[jx];
01866                     ptr[np++] = data[j*nx + i];
01867                     nps[jx] = np;
01868                 }
01869             }
01870         }
01871 
01872         /* Now do the medians for each of the cells in this row */
01873 
01874         for (jx = 0; jx < nbx; jx++) {
01875             bmap[jy*nbx+jx] = vircam_med(rowpoints[jx],NULL,(long)(nps[jx]));
01876             if (bmap[jy*nbx+jx] != CX_MAXFLOAT) {
01877                 bmap[jy*nbx+jx] -= *med;
01878             } else {
01879                 bmap[jy*nbx+jx] = 0.0;
01880             }
01881         }
01882     }
01883 
01884     /* Free up some workspace */
01885 
01886     for (jx = 0; jx < nbx; jx++) 
01887         freespace(rowpoints[jx]);
01888     freespace(rowpoints);
01889     freespace(nps);
01890 
01891     /* Create a new image for the output array */
01892 
01893     *out = cpl_image_new(nx,ny,CPL_TYPE_FLOAT);
01894     ptr = cpl_image_get_data_float(*out);
01895 
01896     /* Ok, we now have the block averaged background map. Do a two point
01897        interpolation to create the full map now */
01898 
01899     nout = 0;
01900     for (j = 1; j <= ny; j++) {
01901         jy = (j + nbsize2)/nbsize;
01902         jyp1 = jy + 1;
01903         jy = min(nby,max(1,jy));
01904         jyp1 = min(nby,jyp1);
01905         dely = (float)(j - nbsize*jy + nbsize2)/(float)nbsize;
01906         dely = max(0.0,min(1.0,dely));
01907         for (i = 1; i <= nx; i++) {
01908             jx = (i + nbsize2)/nbsize;
01909             jxp1 = jx + 1;
01910             jx = min(nbx,max(1,jx));
01911             jxp1 = min(nbx,jxp1);
01912             delx = (float)(i - nbsize*jx + nbsize2)/(float)nbsize;
01913             delx = max(0.0,min(1.0,delx));
01914             jz1 = (jy - 1)*nbx + jx;
01915             jz2 = (jyp1 - 1)*nbx + jx;
01916             if (jx == nbx) {
01917                 jz3 = jz1;
01918                 jz4 = jz2;
01919             } else {
01920                 jz3 = jz1 + 1;
01921                 jz4 = jz2 + 1;
01922             }
01923             t1 = (1.0 - delx)*bmap[jz1-1] + delx*bmap[jz3-1];
01924             t2 = (1.0 - delx)*bmap[jz2-1] + delx*bmap[jz4-1];
01925             ptr[nout++] = (1.0 - dely)*t1 + dely*t2;
01926         }
01927     }
01928 
01929     /* Tidy up before leaving... */
01930 
01931     freespace(bmap)
01932 }
01933 
01934 /*---------------------------------------------------------------------------*/
01955 /*---------------------------------------------------------------------------*/
01956 
01957 extern int vircam_findcol(cpl_propertylist *p, const char *col) {
01958 
01959     if (!strcmp(col,"X")) {
01960         if (cpl_propertylist_has(p,"ESO DRS XCOL"))
01961             return(cpl_propertylist_get_int(p,"ESO DRS XCOL"));
01962         else 
01963             return(-1);
01964     } else if (!strcmp(col,"Y")) {
01965         if (cpl_propertylist_has(p,"ESO DRS YCOL"))
01966             return(cpl_propertylist_get_int(p,"ESO DRS YCOL"));
01967         else 
01968             return(-1);
01969     }
01970     return(-1);
01971 }
01972 
01973 /*---------------------------------------------------------------------------*/
01994 /*---------------------------------------------------------------------------*/
01995 
01996 extern void vircam_rename_property(cpl_propertylist *p, const char *oldname,
01997                                    char *newname) {
01998     cpl_propertylist *temp;
01999     cpl_property *property;
02000 
02001     /* First get the old property. Note that we have to do this in a 
02002        particularly silly way since you cannot reference an individual property
02003        in a propertylist by its name. You can only do it by its index 
02004        number. Remeber to change this when CPL comes to it's senses... */
02005 
02006     if (! cpl_propertylist_has(p,oldname))
02007         return;
02008     temp = cpl_propertylist_new();
02009     cpl_propertylist_copy_property(temp,p,oldname);
02010     property = cpl_propertylist_get(temp,0);
02011 
02012     /* Now change its name */
02013 
02014     cpl_property_set_name(property,newname);
02015 
02016     /* Now insert this into the propertylist and delete the old one */
02017 
02018     cpl_propertylist_append(p,temp);
02019     cpl_propertylist_erase(p,oldname);
02020     cpl_propertylist_delete(temp);
02021 }
02022 
02023 /*---------------------------------------------------------------------------*/
02051 /*---------------------------------------------------------------------------*/
02052 
02053 extern int vircam_catpars(cpl_frame *indx, char **catpath, char **catname) {
02054     cpl_propertylist *p;
02055     char *fname;
02056     int status;
02057     const char *fctid = "vircam_catpars",*unk = "unknown";
02058 
02059     /* Initialise a few things */
02060 
02061     *catpath = NULL;
02062     *catname = NULL;
02063 
02064     /* First get the full path to the indx file and make sure it exists */
02065 
02066     fname = cpl_strdup(cpl_frame_get_filename(indx));
02067     if (access((const char *)fname,R_OK) != 0) {
02068         cpl_msg_error(fctid,"Can't access index file %s",fname);
02069         cpl_free(fname);
02070         return(VIR_FATAL);
02071     }
02072     *catpath = cpl_strdup(dirname(fname));
02073 
02074     /* Load the propertylist if you can. If you can't then signal a fatal
02075        error since this probably means the whole file is messed up */
02076 
02077     if ((p = cpl_propertylist_load(cpl_frame_get_filename(indx),0)) == NULL) {
02078         freespace(*catpath);
02079         cpl_msg_error(fctid,"Can't load index file header %s",
02080                       cpl_frame_get_filename(indx));
02081         cpl_free(fname);
02082         return(VIR_FATAL);
02083     }
02084         
02085     /* If there is a catalogue name in the header then send it back. If there
02086        isn't then give a default name and send a warning */
02087 
02088     if (cpl_propertylist_has(p,"CATNAME")) {
02089         *catname = cpl_strdup(cpl_propertylist_get_string(p,"CATNAME"));
02090         status = VIR_OK;
02091     } else {
02092         *catname = cpl_strdup(unk);
02093         cpl_msg_warning(fctid,"Property CATNAME not in index file header %s",
02094                         cpl_frame_get_filename(indx));
02095         status = VIR_WARN;
02096     }
02097     cpl_free(fname);
02098     freepropertylist(p);
02099 
02100     /* Get out of here */
02101 
02102     return(status);
02103 }
02104 
02105 /*---------------------------------------------------------------------------*/
02136 /*---------------------------------------------------------------------------*/
02137 
02138 extern int vircam_gaincor_calc(cpl_frame *frame, int *n, float **cors,
02139                                int *status) {
02140     float sum,val;
02141     int i,ngood;
02142     unsigned char *iflag;
02143     cpl_propertylist *p;
02144 
02145     /* Inherited status */
02146 
02147     if (*status != VIR_OK)
02148         return(*status);
02149 
02150     /* Find the number of extensions in the file and allocate some workspace
02151        to hold the results. Allocate a small workspace to flag dummy 
02152        extensions */
02153 
02154     *n = cpl_frame_get_nextensions(frame);
02155     *cors = cpl_malloc(*n*sizeof(float));
02156     iflag = cpl_calloc(*n,sizeof(iflag));
02157 
02158     /* Ok, loop through the extensions and read the propertylists */
02159 
02160     sum = 0.0;
02161     ngood = 0;
02162     for (i = 0; i < *n; i++) {
02163         p = cpl_propertylist_load(cpl_frame_get_filename(frame),i+1);
02164         if (cpl_propertylist_has(p,"ESO DRS IMADUMMY")) {
02165             iflag[i] = 1;
02166         } else if (! cpl_propertylist_has(p,"ESO DRS MEDFLAT")) {
02167             iflag[i] = 1;
02168         } else {
02169             val = cpl_propertylist_get_double(p,"ESO DRS MEDFLAT");
02170             if (val == 0.0) {
02171                 iflag[i] = 1;
02172             } else {
02173                 sum += val;
02174                 (*cors)[i] = val;
02175                 ngood++;
02176             }
02177         }
02178         cpl_propertylist_delete(p);
02179     }
02180 
02181     /* If any of them are good, then work out what the average is and
02182        create the correction factors. If the image was a dummy or
02183        there was no MEDFLAT keyword in the header, then just give it
02184        a factor of 1 */
02185 
02186     if (ngood > 0)
02187         sum /= (float)ngood;
02188     for (i = 0; i < *n; i++) {
02189         if (iflag[i] == 0) {
02190             (*cors)[i] = sum/(*cors)[i];
02191         } else {
02192             (*cors)[i] = 1.0;
02193         }
02194     }
02195     cpl_free(iflag);
02196 
02197     /* Get out of here */
02198 
02199     GOOD_STATUS
02200 }
02201 
02202 /*---------------------------------------------------------------------------*/
02228 /*---------------------------------------------------------------------------*/
02229 
02230 extern int vircam_check_crval(cpl_propertylist *phu, cpl_propertylist *ehu) {
02231     double crval1,crval2;
02232     cpl_property *p;
02233 
02234     /* Get the values of CRVAL1,2 from the extension header. If it doesn't
02235        exist, then signal an error */
02236 
02237     if ((vircam_pfits_get_crval1(ehu,&crval1) != VIR_OK) ||
02238         (vircam_pfits_get_crval2(ehu,&crval2) != VIR_OK))
02239         return(VIR_FATAL);
02240 
02241     /* If the values are both zero, then grab the values from the primary
02242        and silently update the extension header. NB: have to do this silly
02243        song and dance where we create new properties, rename the old ones,
02244        insert the new ones in the correct place and then erase the old 
02245        ones because CPL won't do the update if it thinks the original 
02246        CRVALs are floats rather than a double (which it inevitably will, 
02247        since this is where CRVAL has been set identically to zero...) */
02248 
02249     if (fabs(crval1) < 1.0e-6 && fabs(crval2) < 1.0e-6) {
02250         if ((vircam_pfits_get_ra(phu,&crval1) != VIR_OK) ||
02251             (vircam_pfits_get_dec(phu,&crval2) != VIR_OK))
02252             return(VIR_FATAL);
02253         p = cpl_propertylist_get_property(ehu,"CRVAL1");
02254         cpl_property_set_name(p,"OLDCR1");
02255         p = cpl_propertylist_get_property(ehu,"CRVAL2");
02256         cpl_property_set_name(p,"OLDCR2");
02257         cpl_propertylist_insert_after_double(ehu,"OLDCR2","CRVAL1",crval1);
02258         cpl_propertylist_insert_after_double(ehu,"CRVAL1","CRVAL2",crval2);
02259         cpl_propertylist_erase(ehu,"OLDCR1");
02260         cpl_propertylist_erase(ehu,"OLDCR2");
02261     }
02262     
02263     /* Get out of here */
02264 
02265     return(VIR_OK);
02266 }
02267         
02270 /*
02271 
02272 $Log: vircam_utils.c,v $
02273 Revision 1.73  2010/12/09 13:23:56  jim
02274 Minor doc fix
02275 
02276 Revision 1.72  2010/09/09 12:11:09  jim
02277 Fixed problems with docs that make doxygen barf
02278 
02279 Revision 1.71  2010/06/30 12:42:00  jim
02280 A few fixes to stop compiler compaints
02281 
02282 Revision 1.70  2010/06/07 12:42:40  jim
02283 Modifications to get rid of compiler gripes
02284 
02285 Revision 1.69  2010/03/22 06:07:24  jim
02286 Fixed bug in vircam_overexp
02287 
02288 Revision 1.68  2010/03/22 06:04:14  jim
02289 vircam_overexp now works out the ensemble stats on all frames rather than
02290 just those that are between the threshold levels.
02291 
02292 Revision 1.67  2010/01/31 19:30:45  jim
02293 Fixed bug in where global MAD wasn't being multiplied by 1.48 to turn it
02294 into an global RMS in the difference image routine
02295 
02296 Revision 1.66  2009/09/21 11:57:27  jim
02297 Modified vircam_overexp to pass back ensemble stats.
02298 
02299 Revision 1.65  2009/06/08 08:07:13  jim
02300 Fixed bugs in vircam_polyfit, where clipping loop was being done one too few
02301 times and where the error estimate was being done incorrectly
02302 
02303 Revision 1.64  2009/05/20 12:21:52  jim
02304 modified _propertylist_merge to avoid clash of data types
02305 
02306 Revision 1.63  2009/02/23 10:45:13  jim
02307 Fixed vircam_backmap so that if there were no points in a bin the it does
02308 something sensible to the value
02309 
02310 Revision 1.62  2009/02/20 11:35:11  jim
02311 Fixed bug in vircam_polyfit which stopped the iteration scheme.
02312 
02313 Revision 1.61  2008/12/08 06:39:45  jim
02314 Added new routine vircam_check_crval
02315 
02316 Revision 1.60  2008/11/25 18:55:36  jim
02317 rewrote vircam_sort to be a bit more reliable
02318 
02319 Revision 1.59  2008/11/02 14:35:07  jim
02320 Fixed teensy problem with two error messages
02321 
02322 Revision 1.58  2008/10/13 08:16:57  jim
02323 Fixed call to cpl_msg_warning
02324 
02325 Revision 1.57  2008/10/01 04:58:30  jim
02326 Added vircam_frameset_fexists
02327 
02328 Revision 1.56  2008/07/10 13:04:03  jim
02329 Fixed some comments
02330 
02331 Revision 1.55  2008/05/06 12:15:02  jim
02332 Changed vircam_catpars to check that we can read the index file and to send
02333 out error messages if there are problems
02334 
02335 Revision 1.54  2008/05/06 08:38:29  jim
02336 Modified call to cpl_propertylist_get_ from float to double in
02337 vircam_gaincor_calc.
02338 
02339 Revision 1.53  2007/11/14 14:47:53  jim
02340 vircam_linfit now works only with doubles
02341 
02342 Revision 1.52  2007/11/14 10:46:07  jim
02343 Fixed bugs in vircam_polyfit
02344 
02345 Revision 1.51  2007/10/25 17:33:31  jim
02346 Modified to add vircam_polyfit and to remove lint warnings
02347 
02348 Revision 1.50  2007/10/19 09:25:10  jim
02349 Fixed problems with missing includes
02350 
02351 Revision 1.49  2007/10/19 06:55:06  jim
02352 Modifications made to use new method for directing the recipes to the
02353 standard catalogues using the sof
02354 
02355 Revision 1.48  2007/10/15 12:50:28  jim
02356 Modified for compatibility with cpl_4.0
02357 
02358 Revision 1.47  2007/07/09 13:21:06  jim
02359 Changed argument list to vircam_exten_range to include a cpl_frame
02360 
02361 Revision 1.46  2007/05/08 10:41:01  jim
02362 Added vircam_gaincor_calc
02363 
02364 Revision 1.45  2007/05/03 11:15:33  jim
02365 Fixed little problem with table wcs
02366 
02367 Revision 1.44  2007/05/02 09:14:48  jim
02368 Added vircam_findcol and vircam_rename_property
02369 
02370 Revision 1.43  2007/03/01 12:42:42  jim
02371 Modified slightly after code checking
02372 
02373 Revision 1.42  2007/02/14 12:53:34  jim
02374 Removed vircam_paf_print_header
02375 
02376 Revision 1.41  2007/02/07 10:12:15  jim
02377 Removed vircam_ndit_correct as it is now no longer necessary
02378 
02379 Revision 1.40  2007/01/15 12:36:27  jim
02380 Fixed bug in nditcor where factor was being divided by instead of multiplied
02381 
02382 Revision 1.39  2006/12/06 12:58:41  jim
02383 Fixed a small bug in vircam_backmap
02384 
02385 Revision 1.38  2006/12/01 14:08:33  jim
02386 added vircam_backmap
02387 
02388 Revision 1.37  2006/11/28 20:52:17  jim
02389 Added vircam_illcor_newtab
02390 
02391 Revision 1.36  2006/11/27 12:00:17  jim
02392 cosmetic changes
02393 
02394 Revision 1.35  2006/10/05 09:23:00  jim
02395 Small modifications to a couple of cpl calls to bring them into line with
02396 cpl v3.0
02397 
02398 Revision 1.34  2006/08/27 20:28:15  jim
02399 added vircam_is_dummy
02400 
02401 Revision 1.33  2006/08/21 09:09:29  jim
02402 Added routines vircam_create_diffimg_stats and vircam_dummy_property
02403 
02404 Revision 1.32  2006/07/11 14:53:58  jim
02405 Fixed vircam_ndit_correct so that images with bad status are not corrected
02406 
02407 Revision 1.31  2006/07/04 09:19:06  jim
02408 replaced all sprintf statements with snprintf
02409 
02410 Revision 1.30  2006/06/30 21:32:09  jim
02411 Fixed bug in vircam_prov so that sprintf is replaced by snprintf
02412 
02413 Revision 1.29  2006/06/20 18:59:51  jim
02414 Fixed small bug in vircam_ndit_correct
02415 
02416 Revision 1.28  2006/06/09 22:24:47  jim
02417 Added vircam_ndit_correct
02418 
02419 Revision 1.27  2006/06/09 11:26:26  jim
02420 Small changes to keep lint happy
02421 
02422 Revision 1.26  2006/06/06 13:07:54  jim
02423 Change the stats routine used in vircam_difference_image
02424 
02425 Revision 1.25  2006/05/30 13:31:47  jim
02426 Added vircam_timestamp
02427 
02428 Revision 1.24  2006/05/24 13:35:49  jim
02429 Added vircam_dummy_image and vircam_dummy_catalogue
02430 
02431 Revision 1.23  2006/05/04 15:16:33  jim
02432 Fixed memory bug in vircam_overexp
02433 
02434 Revision 1.22  2006/04/20 11:29:41  jim
02435 Added vircam_overexp
02436 
02437 Revision 1.21  2006/03/22 11:42:32  jim
02438 Moved some routines into vircam_mask
02439 
02440 Revision 1.20  2006/03/15 10:43:42  jim
02441 Fixed a few things
02442 
02443 Revision 1.19  2006/03/08 14:32:22  jim
02444 Lots of little modifications
02445 
02446 Revision 1.18  2006/03/01 10:31:29  jim
02447 Now uses new vir_fits objects
02448 
02449 Revision 1.17  2006/02/18 11:48:55  jim
02450 *** empty log message ***
02451 
02452 Revision 1.16  2006/01/23 10:30:50  jim
02453 Mainly documentation mods
02454 
02455 Revision 1.15  2005/12/14 22:17:33  jim
02456 Updated docs
02457 
02458 Revision 1.14  2005/12/01 16:26:03  jim
02459 Added vircam_dummy_confidence
02460 
02461 Revision 1.13  2005/11/25 15:33:22  jim
02462 Some code fixes to keep splint happy
02463 
02464 Revision 1.12  2005/11/25 09:56:15  jim
02465 Tidied up some more documentation
02466 
02467 Revision 1.11  2005/11/25 09:36:23  jim
02468 Added vircam_linfit
02469 
02470 Revision 1.10  2005/11/07 13:15:16  jim
02471 Fixed lots of bugs and added some error checking
02472 
02473 Revision 1.9  2005/11/03 15:16:28  jim
02474 Lots of changes mainly to strengthen error reporting
02475 
02476 Revision 1.8  2005/11/03 13:28:50  jim
02477 All sorts of changes to tighten up error handling
02478 
02479 Revision 1.7  2005/10/14 13:21:04  jim
02480 Added some new routines
02481 
02482 Revision 1.6  2005/09/20 15:07:46  jim
02483 Fixed a few bugs and added a few things
02484 
02485 Revision 1.5  2005/09/07 12:47:22  jim
02486 renamed a malloc and free to the cpl equivallent
02487 
02488 Revision 1.4  2005/08/10 09:55:05  jim
02489 Modified vircam_madfit so that if determinant is zero, then it sends a
02490 zero slope and intercept back
02491 
02492 Revision 1.3  2005/08/10 08:42:00  jim
02493 Modified vircam_madfit so that if the initial least squares fit gets a
02494 perfect result, then it just returns with those values rather than to try
02495 and do the median fit
02496 
02497 Revision 1.2  2005/08/09 15:30:00  jim
02498 vircam_exten_range had number of chips wrong!
02499 
02500 Revision 1.1.1.1  2005/08/05 08:29:09  jim
02501 Initial import
02502 
02503 
02504 */
02505 

Generated on 7 Feb 2011 for VIRCAM Pipeline by  doxygen 1.6.1