vircam_utils.c

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

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1