vircam_imstack.c

00001 /* $Id: vircam_imstack.c,v 1.14 2010/09/09 12:11:09 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/09/09 12:11:09 $
00024  * $Revision: 1.14 $
00025  * $Name: v1-1-0 $
00026  */
00027 
00028 /* Includes */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033 
00034 #include <math.h>
00035 #include <cpl.h>
00036 #include "vircam_mods.h"
00037 #include "vircam_utils.h"
00038 #include "vircam_fits.h"
00039 #include "vircam_stats.h"
00040 #include "vircam_pfits.h"
00041 #include "vircam_wcsutils.h"
00042 #include "vircam_tfits.h"
00043 
00044 typedef struct {
00045     double     crval[2];
00046     double     crpix[2];
00047     double     cd[4];
00048     double     secd;
00049     double     tand;
00050     double     pv21;
00051     double     pv23;
00052     double     pv25;
00053     long       nx;
00054     long       ny;
00055 } mywcs;
00056 
00057 typedef struct {
00058     int        nx;
00059     int        ny;
00060     vir_fits   *fname;
00061     vir_fits   *conf;
00062     float      *data;
00063     int        *cdata;
00064     cpl_binary *bpm;
00065     mywcs      *vwcs;
00066     float      xoff;
00067     float      yoff;
00068     cpl_array  *trans;
00069     float      sky;
00070     float      skydiff;
00071     float      noise;
00072     float      expscale;
00073     float      weight;
00074 } dstrct;
00075 
00076 static dstrct *fileptrs = NULL;
00077 static vir_fits *outfits = NULL;
00078 static vir_fits *outconf = NULL;
00079 static mywcs *outwcs = NULL;
00080 
00081 static float lsig;
00082 static float hsig;
00083 static int   nxo;
00084 static int   nyo;
00085 static float *outdata;
00086 static int   *outdatac;
00087 static int   nim;
00088 static float sumweight;
00089 
00090 static void outloc(mywcs *win, double xin, double yin, mywcs *wout, 
00091                    cpl_array *trans, double *xout, double *yout);
00092 static void backgrnd_ov(void);
00093 static void skyest(float *data, int *cdata, long npts, float thresh, 
00094                    float *skymed, float *skynoise);
00095 static cpl_array *transinit(void);
00096 static void fileptrs_close(void);
00097 static cpl_table *mknewtab(vir_tfits *catref, dstrct *dd);
00098 static void output_files(void);
00099 static int stack_nn(void);
00100 static int stack_lin(void);
00101 static void do_averages(int ncontrib, float *data, float *wconf, float *conf,
00102                         unsigned char *id, float lclip, float hclip, 
00103                         float extra, short int *lowcl, short int *highcl, 
00104                         float *outval, float *outvalc);
00105 static mywcs *getwcsinfo(cpl_propertylist *plist);
00106 static void diffxy(mywcs *wref, mywcs *wprog, float *dx, float *dy);
00107 static void tidy(void);
00108 
00111 /*---------------------------------------------------------------------------*/
00171 /*---------------------------------------------------------------------------*/
00172 
00173 extern int vircam_imstack(vir_fits **inf, vir_fits **inconf, vir_tfits **cats,
00174                           int nimages, int nconfs, float lthr, float hthr,
00175                           int method, vir_fits **out, vir_fits **outc, 
00176                           int *status) {
00177 
00178     int i,nm;
00179     dstrct *dd;
00180     float expref,exposure,xoff,yoff;
00181     cpl_matrix *in;
00182     vir_tfits *catref;
00183     cpl_table *newtab,*mtab;
00184     const char *fctid = "vircam_imstack";
00185 
00186     /* Inherited status */
00187 
00188     *out = NULL;
00189     *outc = NULL;
00190     if (*status != VIR_OK)
00191         return(*status);
00192 
00193     /* Is there any point in being here? */
00194 
00195     if (nimages == 0) {
00196         cpl_msg_error(fctid,"No input files to combine");
00197         tidy();
00198         FATAL_ERROR
00199     }
00200 
00201     /* Initialise some global variables */
00202 
00203     lsig = lthr;
00204     hsig = hthr;
00205     nim = nimages;
00206 
00207     /* Initialise a useful matrix */
00208 
00209     in = cpl_matrix_new(1,2);
00210     cpl_matrix_set(in,0,0,0.0);
00211     cpl_matrix_set(in,0,1,0.0);
00212 
00213     /* Allocate file struct array and fill in some values */
00214 
00215     fileptrs = cpl_malloc(nimages*sizeof(dstrct));
00216     (void)vircam_pfits_get_exptime(vircam_fits_get_phu(inf[0]),&exposure);
00217     expref = max(0.5,exposure);
00218     catref = NULL;
00219     for (i = 0; i < nimages; i++) {
00220         dd = fileptrs + i;
00221         dd->fname = inf[i];
00222         dd->data = cpl_image_get_data_float(vircam_fits_get_image(inf[i]));
00223         if (nconfs == 0) {
00224             dd->conf = NULL;
00225         } else if (nconfs == 1) {
00226             dd->conf = inconf[0];
00227             dd->cdata = cpl_image_get_data_int(vircam_fits_get_image(inconf[0]));
00228         } else {
00229             dd->conf = inconf[i];
00230             dd->cdata = cpl_image_get_data_int(vircam_fits_get_image(inconf[i]));
00231         }
00232         (void)vircam_pfits_get_exptime(vircam_fits_get_phu(dd->fname),&exposure);
00233         dd->expscale = exposure/expref;
00234 
00235         /* Zero the bad pixel mask */
00236 
00237         cpl_image_accept_all(vircam_fits_get_image(inf[i]));
00238         dd->bpm = cpl_mask_get_data(cpl_image_get_bpm(vircam_fits_get_image(inf[i])));
00239 
00240         /* Read the WCS from the header */
00241 
00242         dd->vwcs = getwcsinfo(vircam_fits_get_ehu(inf[i]));
00243 
00244         /* Get the image size */
00245 
00246         dd->nx = cpl_image_get_size_x(vircam_fits_get_image(dd->fname));
00247         dd->ny = cpl_image_get_size_y(vircam_fits_get_image(dd->fname));
00248         
00249         /* Double check to make sure the confidence maps and images have the
00250            same dimensions */
00251 
00252         if (cpl_image_get_size_x(vircam_fits_get_image(dd->conf)) != dd->nx || 
00253             cpl_image_get_size_y(vircam_fits_get_image(dd->conf)) != dd->ny) {
00254             cpl_msg_error(fctid,"Image %s and Confidence map %s don't match",
00255                           vircam_fits_get_fullname(dd->fname),
00256                           vircam_fits_get_fullname(dd->conf));
00257             cpl_matrix_delete(in);
00258             tidy();
00259             FATAL_ERROR
00260         }
00261 
00262         /* Get a rough shift between the frames and the first one */
00263 
00264         diffxy(fileptrs->vwcs,dd->vwcs,&(dd->xoff),&(dd->yoff));
00265 
00266         /* Do we have catalogues? If so, then work out the transformation 
00267            corrections from them */
00268 
00269         if (cats != NULL) {
00270             if (catref == NULL && cats[i] != NULL)
00271                 catref = cats[i];
00272             if (i == 0 || cats[i] == NULL) {
00273                 dd->trans = transinit();
00274             } else {
00275                 newtab = mknewtab(catref,dd);           
00276                 (void)vircam_matchxy(vircam_tfits_get_table(cats[i]),newtab,
00277                                      1024,&xoff,&yoff,&nm,&mtab,status);
00278                 if (*status != VIR_OK) {
00279                     freearray(dd->trans);
00280                     dd->trans = transinit();
00281                     *status = VIR_OK;
00282                 } else { 
00283                     (void)vircam_platexy(mtab,6,&(dd->trans),status);
00284                 }
00285                 freetable(mtab);
00286                 freetable(newtab);
00287             }
00288         } else {
00289             dd->trans = NULL;
00290         }
00291     }
00292     cpl_matrix_delete(in);
00293 
00294     /* Get the background levels in the overlap regions */
00295 
00296     backgrnd_ov();
00297 
00298     /* Create the output file */
00299 
00300     output_files();
00301 
00302     /* Ok time to do the stacking. Our first job is to do a nearest neighbour
00303        stack in order to find the objects that will be rejected. If we 
00304        only want the NN algorithm, then we're done. Otherwise we can use the
00305        rejection information to restack using any other algorithm */
00306 
00307     stack_nn();
00308 
00309     /* Switch for final stacking method */
00310 
00311     switch (method) {
00312     case 0:
00313         break;
00314     case 1:
00315         stack_lin();
00316         break;
00317     default:
00318         break;
00319     }
00320 
00321     /* Add the provenance cards to the header */
00322 
00323     vircam_prov(vircam_fits_get_ehu(outfits),inf,nimages);
00324 
00325     /* Assign some output info, tidy and get out of here */
00326 
00327     *out = outfits;
00328     *outc = outconf;
00329     tidy();
00330     return(VIR_OK);
00331 }
00332 
00333 /*---------------------------------------------------------------------------*/
00349 /*---------------------------------------------------------------------------*/
00350 
00351 static int stack_lin(void) {
00352     cpl_image *outim,*outimc;
00353     double oxf,oyf;
00354     int npts,i,*cdata,ix,iy,ind1,ind,ox,oy,m,jj,ii,nn,nx,ny,n;
00355     float *workbufw,*data,wt,dx,dy,w[4],value,cval;
00356     float med,noise;
00357     dstrct *dd;
00358 
00359     /* Output file info */
00360 
00361     outim = vircam_fits_get_image(outfits);
00362     outimc = vircam_fits_get_image(outconf);
00363     nxo = cpl_image_get_size_x(outim);
00364     nyo = cpl_image_get_size_y(outim);
00365     npts = nxo*nyo;
00366 
00367     /* Get workspace for collecting info over the whole output map */
00368 
00369     workbufw = cpl_calloc(nxo*nyo,sizeof(*workbufw));
00370 
00371     /* Get output buffers */
00372 
00373     outdata = cpl_image_get_data_float(outim);
00374     outdatac = cpl_image_get_data_int(outimc);
00375 
00376     /* Initialise the output map. This is because the output data array 
00377        probably still has the results of the nearest neighbour stack */
00378 
00379     for (i = 0; i < npts; i++) {
00380         outdata[i] = 0.0;
00381         outdatac[i] = 0;
00382     }
00383 
00384     /* Ok, loop for each of the input files and collect all the information
00385        for each pixel */
00386 
00387     for (i = 0; i < nim; i++) {
00388         dd = fileptrs + i;
00389         data = dd->data;
00390         cdata = dd->cdata;
00391         wt = dd->weight;
00392         nx = dd->nx;
00393         ny = dd->ny;
00394 
00395         /* Loop for each pixel in the data array and work out where it belongs
00396            in the output array */
00397 
00398         n = 0;
00399         for (iy = 0; iy < ny; iy++) {
00400             ind1 = iy*nx;
00401             for (ix = 0; ix < nx; ix++) {
00402                 ind = ind1 + ix;
00403                 outloc(dd->vwcs,(double)ix,(double)iy,outwcs,dd->trans,
00404                        &oxf,&oyf);
00405                 if (oxf < 0.0 || oyf < 0.0)
00406                     continue;
00407                 ox = (int)oxf;
00408                 oy = (int)oyf;
00409                 if ((dd->bpm)[ind] != 0)
00410                     continue;
00411                 if (ox < 0 || ox >= nxo || oy < 0 || oy >= nyo ||
00412                     cdata[ind] == 0) 
00413                     continue;
00414                 dx = oxf - ox;
00415                 dy = oyf - oy;
00416                 w[0] = (1.0-dx)*(1.0-dy);
00417                 w[1] = dx*(1.0-dy);
00418                 w[2] = dy*(1.0-dx);
00419                 w[3] = dx*dy;
00420                 m = 0;
00421                 value = data[ind]*(dd->expscale) + dd->skydiff;
00422                 cval = (float)cdata[ind];
00423                 for (jj = 0; jj <= 1; jj++) {
00424                     for (ii = 0; ii <= 1; ii++) {
00425                         nn = (oy+jj)*nxo + ox + ii;
00426                         if (nn >= npts || ox+ii >= nxo || oy+jj >= nyo)
00427                             continue;
00428                         outdata[nn] += w[m]*value*wt*cval;
00429                         workbufw[nn] += w[m]*wt*cval;
00430                         m++;
00431                     }
00432                 }
00433             }
00434         }
00435     }
00436 
00437     /* Now do the final averaging */
00438 
00439     for (i = 0; i < npts; i++) {
00440         if (workbufw[i] != 0.0)
00441             outdata[i] /= workbufw[i];
00442         else
00443             outdata[i] = fileptrs->sky;
00444         workbufw[i] /= sumweight;
00445    }
00446     vircam_qmedsig(workbufw,NULL,npts,3.0,2,0.0,65535.0,&med,&noise);
00447     for (i = 0; i < npts; i++) {
00448         workbufw[i] *= (100.0/med);
00449         outdatac[i] = max(0,min(1000,vircam_nint(workbufw[i])));
00450     }
00451     freespace(workbufw);
00452     return(VIR_OK);
00453 }
00454 
00455 /*---------------------------------------------------------------------------*/
00471 /*---------------------------------------------------------------------------*/
00472 
00473 static int stack_nn(void) {
00474     float *workbuf,*workbufc,*workbufw,lclip,hclip,*data,wt,med,noise,outvalc;
00475     float value,*dbuf,*wbuf,*cbuf,outval,avlev,avvar,*confwork;
00476     double oxf,oyf;
00477     int *iloc,i,npts,ix,iy,ind1,ind,ox,oy,nn,bufloc,ncontrib,*lbuf;
00478     int j,*cdata,nx,ny,n,nz;
00479     short int clipped_low,clipped_high;
00480     dstrct *dd;
00481     unsigned char *id,*clipmap,*cc,*cclast,*ibuf;
00482     short int *nbuf;
00483     cpl_image *outim,*outimc;
00484 
00485     /* Output file info */
00486 
00487     outim = vircam_fits_get_image(outfits);
00488     outimc = vircam_fits_get_image(outconf);
00489     nxo = cpl_image_get_size_x(outim);
00490     nyo = cpl_image_get_size_y(outim);
00491 
00492     /* Get workspace for collecting info over the whole output map */
00493 
00494     nz = nim + 2;
00495     workbuf = cpl_calloc(nz*nxo*nyo,sizeof(*workbuf));
00496     workbufc = cpl_calloc(nz*nxo*nyo,sizeof(*workbufc));
00497     workbufw = cpl_calloc(nz*nxo*nyo,sizeof(*workbufw));
00498     id = cpl_calloc(nz*nxo*nyo,sizeof(*id));
00499     iloc = cpl_calloc(nz*nxo*nyo,sizeof(*iloc));
00500     nbuf = cpl_calloc(nxo*nyo,sizeof(*nbuf));
00501     confwork = cpl_calloc(nxo*nyo,sizeof(*confwork));
00502 
00503     /* Workspace for marking output rows with clipped pixels */
00504 
00505     clipmap = cpl_calloc(2*nxo,sizeof(*clipmap));
00506 
00507     /* Buffers for averaging an individual pixel */
00508 
00509     dbuf = cpl_calloc(2*nz,sizeof(*dbuf));
00510     wbuf = cpl_calloc(2*nz,sizeof(*wbuf));
00511     cbuf = cpl_calloc(2*nz,sizeof(*cbuf));
00512     ibuf = cpl_calloc(2*nz,sizeof(*ibuf));
00513     lbuf = cpl_calloc(2*nz,sizeof(*lbuf));
00514 
00515     /* Get output buffers */
00516 
00517     outdata = cpl_image_get_data_float(outim);
00518     outdatac = cpl_image_get_data_int(outimc);
00519 
00520     /* Rejection thresholds */
00521 
00522     lclip = fileptrs->sky - lsig*(fileptrs->noise);
00523     hclip = fileptrs->sky + hsig*(fileptrs->noise);
00524 
00525     /* Ok, loop for each of the input files and collect all the information
00526        for each pixel */
00527 
00528     for (i = 0; i < nim; i++) {
00529         dd = fileptrs + i;
00530         nx = dd->nx;
00531         ny = dd->ny;
00532         npts = nx*ny;
00533         data = dd->data;
00534         cdata = dd->cdata;
00535         wt = dd->weight;
00536 
00537         /* Loop for each pixel in the data array and work out where it belongs
00538            in the output array */
00539 
00540         n = 0;
00541         for (iy = 0; iy < ny; iy++) {
00542             ind1 = iy*nx;
00543             for (ix = 0; ix < nx; ix++) {
00544                 ind = ind1 + ix;
00545                 outloc(dd->vwcs,(double)ix,(double)iy,outwcs,dd->trans,
00546                        &oxf,&oyf);
00547                 ox = vircam_nint(oxf) - 1;
00548                 oy = vircam_nint(oyf) - 1;
00549                 if (ox < 0 || ox >= nxo || oy < 0 || oy >= nyo || 
00550                     cdata[ind] == 0)
00551                     continue;
00552                 nn = oy*nxo + ox;
00553                 bufloc = oy*nxo*nz + ox*nz + nbuf[nn];
00554                 value = data[ind]*(dd->expscale) + dd->skydiff;
00555                 workbuf[bufloc] = value;
00556                 workbufw[bufloc] = wt*(float)cdata[ind];
00557                 workbufc[bufloc] = (float)cdata[ind];
00558                 id[bufloc] = i;
00559                 nbuf[nn] += 1;
00560                 iloc[bufloc] = ind;
00561             }
00562         }
00563     }
00564 
00565 
00566     /* Now loop through the output arrays and form an initial estimate */
00567 
00568     for (iy = 0; iy < nyo; iy++) {
00569         ind1 = iy*nxo;
00570         cc = clipmap + (iy % 2)*nxo;
00571         cclast = clipmap + ((iy-1) % 2)*nxo;
00572         for (ix = 0; ix < nxo; ix++) {
00573             ind = ind1 + ix;
00574             bufloc = iy*nxo*nz + ix*nz;
00575             ncontrib = nbuf[ind];
00576             if (ncontrib == 0) {
00577                 outdata[ind] = fileptrs->sky;
00578                 outdatac[ind] = 0;
00579                 continue;
00580             } 
00581             cc[ix] = 0;
00582 
00583             /* Put some stuff in buffers for the averaging routine */
00584             
00585             for (i = 0; i < ncontrib; i++) {
00586                 dbuf[i] = workbuf[bufloc+i];
00587                 wbuf[i] = workbufw[bufloc+i];
00588                 cbuf[i] = workbufc[bufloc+i];
00589                 ibuf[i] = id[bufloc+i];
00590                 lbuf[i] = iloc[bufloc+i];
00591             }
00592 
00593             /* Do the averages with the nominal clipping */
00594 
00595             do_averages(ncontrib,dbuf,wbuf,cbuf,ibuf,lclip,hclip,0.0,
00596                         &clipped_low,&clipped_high,&outval,&outvalc);
00597             
00598             /* Store these away */
00599 
00600             outdata[ind] = outval;
00601             confwork[ind] = outvalc;
00602             cc[ix] = (clipped_high >= 0);
00603             if (clipped_low >= 0) 
00604                 ((fileptrs+ibuf[clipped_low])->bpm)[lbuf[clipped_low]] = 2;
00605             if (clipped_high >= 0) 
00606                 ((fileptrs+ibuf[clipped_high])->bpm)[lbuf[clipped_high]] = 1;
00607         }
00608 
00609         /* Look at the non-edge pixels and see if the local variation can
00610            show whether any clipping that has been done is justified. NB:
00611            we are looking at the _previous_ row here */
00612 
00613         if (iy < 2)
00614             continue;
00615         for (ix = 1; ix < nxo-1; ix++) {
00616             if (! cclast[ix])
00617                 continue;
00618             ind = (iy-1)*nxo + ix;
00619             bufloc = (iy-1)*nxo*nz + ix*nz;
00620             ncontrib = nbuf[ind];
00621             if (ncontrib == 0)
00622                 continue;
00623             avlev = 0.0;
00624             for (i = -1; i <= 1; i++) 
00625                 for (j = -1; j <= 1; j++) 
00626                     avlev += outdata[ind + i*nxo + j];
00627             avlev /= 9.0;
00628             avvar = 0.0;
00629             for (i = -1; i <= 1; i++) 
00630                 for (j = -1; j <= 1; j++) 
00631                     avvar += (float)fabs(avlev - outdata[ind + i*nxo + j]);
00632             avvar /= 9.0;
00633             if (avlev <= hclip && avvar <= 2.0*(fileptrs->sky))
00634                 continue;
00635 
00636             /* Put some stuff in buffers for the averaging routine */
00637             
00638             for (i = 0; i < ncontrib; i++) {
00639                 dbuf[i] = workbuf[bufloc+i];
00640                 wbuf[i] = workbufw[bufloc+i];
00641                 cbuf[i] = workbufc[bufloc+i];
00642                 ibuf[i] = id[bufloc+i];
00643                 lbuf[i] = iloc[bufloc+i];
00644                 (fileptrs+ibuf[i])->bpm[lbuf[i]] = 0;
00645             }
00646 
00647             /* Redo the averages with the nominal clipping */
00648 
00649             do_averages(ncontrib,dbuf,wbuf,cbuf,ibuf,lclip,hclip,avvar,
00650                         &clipped_low,&clipped_high,&outval,&outvalc);
00651 
00652             /* Store these away */
00653 
00654             outdata[ind] = outval;
00655             confwork[ind] = outvalc;
00656             if (clipped_low >= 0) 
00657                 ((fileptrs+ibuf[clipped_low])->bpm)[lbuf[clipped_low]] = 2;
00658             if (clipped_high >= 0) 
00659                 ((fileptrs+ibuf[clipped_high])->bpm)[lbuf[clipped_high]] = 1;
00660         }    
00661     }
00662 
00663     /* Now renormalise the confidence map */
00664 
00665     npts = nxo*nyo;
00666     vircam_qmedsig(confwork,NULL,npts,3.0,2,25.0,65535.0,&med,&noise);
00667     for (i = 0; i < npts; i++) {
00668         confwork[i] *= (100.0/med);
00669         outdatac[i] = max(0,min(1000,vircam_nint(confwork[i])));
00670     }
00671 
00672     /* Free up some workspace */
00673 
00674     freespace(workbuf);
00675     freespace(workbufc);
00676     freespace(workbufw);
00677     freespace(confwork);
00678     freespace(id);
00679     freespace(iloc);
00680     freespace(nbuf);
00681     freespace(clipmap);
00682     freespace(dbuf);
00683     freespace(wbuf);
00684     freespace(cbuf);
00685     freespace(ibuf);
00686     freespace(lbuf);
00687     return(VIR_OK);
00688 }
00689                     
00690 /*---------------------------------------------------------------------------*/
00728 /*---------------------------------------------------------------------------*/
00729     
00730 static void do_averages(int ncontrib, float *data, float *wconf, float *conf,
00731                         unsigned char *id, float lclip, float hclip, 
00732                         float extra, short int *lowcl, short int *highcl, 
00733                         float *outval, float *outvalc) {
00734     float minval,maxval,sum,wsum,csum,reflev,clipval;
00735     int imax,imin,i;
00736 
00737     /* Do the summation and keep track of the minimum and
00738        maximum values */
00739 
00740     minval = 1.0e10;
00741     maxval = -1.0e10;
00742     sum = 0.0;
00743     wsum = 0.0;
00744     csum = 0.0;
00745     imin = -1;
00746     imax = -1;
00747     for (i = 0; i < ncontrib; i++) {
00748         sum += data[i]*wconf[i];
00749         wsum += wconf[i];
00750         csum += conf[i];
00751         if (data[i] > maxval) {
00752             maxval = data[i];
00753             imax = i;
00754         }
00755         if (data[i] < minval) {
00756             minval = data[i];
00757             imin = i;
00758         }
00759     }
00760 
00761     /* First crack at output value */
00762 
00763     if (wsum > 0.0) {
00764         *outval = sum/wsum;
00765     } else {
00766         *outval = fileptrs->sky;
00767     }
00768 
00769     /* Look at high clipping for of cosmic rays */
00770 
00771     *highcl = -1;
00772     if (maxval > hclip && wsum > 150.0 && csum > 150.0 && 
00773         imin != -1 && imax != -1) {
00774         reflev = (sum - data[imax]*wconf[imax])/(wsum - wconf[imax]);
00775         clipval = reflev + hsig*(fileptrs+id[imax])->noise;
00776         clipval *= max(1.0,reflev)/max(1.0,(fileptrs+id[imax])->sky);
00777         clipval += extra;
00778 
00779         /* Clip the maximum point */
00780 
00781         if (maxval > clipval) {
00782             sum -= data[imax]*wconf[imax];
00783             wsum -= wconf[imax];
00784             *outval = reflev;
00785             *highcl = imax;
00786         }
00787     }
00788 
00789     /* Clip low points (presumably serious cosmetic issues on detectors) */
00790 
00791     *lowcl = -1;
00792     if (minval < lclip  && wsum > 150.0 && csum > 150.0 &&
00793         imin != -1 && imax != -1) {
00794         reflev = (sum - data[imin]*wconf[imin])/(wsum - wconf[imin]);
00795         clipval = reflev + hsig*(fileptrs+id[imin])->noise;
00796         clipval *= max(1.0,reflev)/max(1.0,(fileptrs+id[imin])->sky);
00797         if (minval < clipval) {
00798             sum -= data[imin]*wconf[imin];
00799             wsum -= wconf[imin];
00800             *outval = reflev;
00801             *lowcl = imin;
00802         }
00803     }
00804 
00805     /* Output confidence (not normalised) */
00806 
00807     *outvalc = wsum/sumweight;
00808 }
00809 
00810 /*---------------------------------------------------------------------------*/
00824 /*---------------------------------------------------------------------------*/
00825 
00826 static void output_files(void) {
00827     cpl_image *newim,*newconf;
00828     double lowerleft[2],upperleft[2],lowerright[2],upperright[2],xout,yout;
00829     double xmin,ymin,sh[2];
00830     dstrct *dd;
00831     int i,ixo,iyo;
00832 
00833     /* Initialise the first element of the results arrays since we're 
00834        doing all this relative to the first image */
00835 
00836     lowerleft[0] = 1.0;
00837     lowerleft[1] = 1.0;
00838     upperleft[0] = 1.0;
00839     upperleft[1] = (double)fileptrs->ny;
00840     lowerright[0] = (double)fileptrs->nx;
00841     lowerright[1] = 1.0;
00842     upperright[0] = (double)fileptrs->nx;
00843     upperright[1] = (double)fileptrs->ny;
00844 
00845     /* Loop for all images relative to the first one */
00846 
00847     for (i = 1; i < nim; i++) {
00848         dd = fileptrs + i;
00849         outloc(dd->vwcs,(double)1.0,(double)1.0,fileptrs->vwcs,dd->trans,
00850                &xout,&yout);
00851         lowerleft[0] = min(lowerleft[0],xout);
00852         lowerleft[1] = min(lowerleft[1],yout);
00853         outloc(dd->vwcs,(double)1.0,(double)dd->ny,fileptrs->vwcs,dd->trans,
00854                &xout,&yout);
00855         upperleft[0] = min(upperleft[0],xout);
00856         upperleft[1] = max(upperleft[1],yout);
00857         outloc(dd->vwcs,(double)dd->nx,(double)1.0,fileptrs->vwcs,dd->trans,
00858                &xout,&yout);
00859         lowerright[0] = max(lowerright[0],xout);
00860         lowerright[1] = min(lowerright[1],yout);
00861         outloc(dd->vwcs,(double)dd->nx,(double)dd->ny,fileptrs->vwcs,dd->trans,
00862                &xout,&yout);
00863         upperright[0] = max(upperright[0],xout);
00864         upperright[1] = max(upperright[1],yout);
00865     }
00866 
00867     /* Ok, what are the limits? */
00868 
00869     ixo = vircam_nint(max(lowerright[0]-lowerleft[0],upperright[0]-upperleft[0])) + 1;
00870     iyo = vircam_nint(max(upperright[1]-lowerright[1],upperleft[1]-lowerleft[1])) + 1;
00871     xmin = min(lowerleft[0],upperleft[0]);
00872     ymin = min(lowerleft[1],lowerright[1]);
00873     
00874     /* Create the image */
00875 
00876     newim = cpl_image_new(ixo,iyo,CPL_TYPE_FLOAT);
00877     outfits = vircam_fits_wrap(newim,fileptrs->fname,NULL,NULL);
00878     cpl_propertylist_update_int(vircam_fits_get_ehu(outfits),"NAXIS1",ixo);
00879     cpl_propertylist_update_int(vircam_fits_get_ehu(outfits),"NAXIS2",iyo);
00880 
00881     /* Update the reference point for the WCS */
00882 
00883     sh[0] = xmin;
00884     sh[1] = ymin;
00885     (void)vircam_crpixshift(vircam_fits_get_ehu(outfits),1.0,sh);
00886     outwcs = getwcsinfo(vircam_fits_get_ehu(outfits));
00887 
00888     /* Now create the confidence map image */
00889 
00890     newconf = cpl_image_new(ixo,iyo,CPL_TYPE_INT);
00891     outconf = vircam_fits_wrap(newconf,outfits,NULL,NULL);
00892 }
00893 
00894 /*---------------------------------------------------------------------------*/
00917 /*---------------------------------------------------------------------------*/
00918 
00919 static void diffxy(mywcs *wref, mywcs *wprog, float *dx, float *dy) {
00920     double xref,yref,xprog,yprog;
00921 
00922     /* Find the middle of the reference frame */
00923 
00924     xref = 0.5*(double)wref->nx;
00925     yref = 0.5*(double)wref->ny;
00926 
00927     /* Work out the output position */
00928 
00929     outloc(wref,xref,yref,wprog,NULL,&xprog,&yprog);
00930 
00931     /* Now the offsets */
00932 
00933     *dx = (float)(xref - xprog);
00934     *dy = (float)(yref - yprog);
00935 }
00936 
00937 /*---------------------------------------------------------------------------*/
00966 /*---------------------------------------------------------------------------*/
00967 
00968 static void outloc(mywcs *win, double xin, double yin, mywcs *wout, 
00969                    cpl_array *trans, double *xout, double *yout) {
00970     double xt,yt,xi,eta,r,rfac,aa,tandec,denom,rp,*tdata;
00971 
00972     /* Do the conversion. First to standard coordinates in the frame of
00973        the input image */
00974 
00975     xt = xin - win->crpix[0];
00976     yt = yin - win->crpix[1];
00977     xi = win->cd[0]*xt + win->cd[1]*yt;
00978     eta = win->cd[2]*xt + win->cd[3]*yt;
00979     r = sqrt(xi*xi + eta*eta);
00980     rfac = win->pv21 + win->pv23*pow(r,2.0) + win->pv25*pow(r,4.0);
00981     r /= rfac;
00982     rfac = win->pv21 + win->pv23*pow(r,2.0) + win->pv25*pow(r,4.0);
00983     xi /= rfac;
00984     eta /= rfac;
00985     aa = atan(xi*win->secd/(1.0-eta*win->tand));
00986     if (xi != 0.0) 
00987         tandec = (eta+win->tand)*sin(aa)/(xi*win->secd);
00988     else
00989         tandec = (eta+win->tand)/(1.0 - eta*win->tand);
00990 
00991     /* Now from standard coordinates in the frame of the output image */
00992 
00993     aa += (win->crval[0] - wout->crval[0]);
00994     denom = wout->tand*tandec + cos(aa);
00995     xi = wout->secd*sin(aa)/denom;
00996     eta = (tandec - wout->tand*cos(aa))/denom;
00997     rp = sqrt(xi*xi + eta*eta);
00998     rfac = wout->pv21 + wout->pv23*pow(rp,2.0) + wout->pv25*pow(rp,4.0);
00999     xi *= rfac;
01000     eta *= rfac; 
01001     denom = wout->cd[0]*wout->cd[3] - wout->cd[1]*wout->cd[2];
01002     xt = (xi*wout->cd[3] - eta*wout->cd[1])/denom + wout->crpix[0];
01003     yt = (eta*wout->cd[0] - xi*wout->cd[2])/denom + wout->crpix[1];
01004     
01005     /* If a fine tune transformation is defined, then do that now */
01006 
01007     if (trans != NULL) {
01008         tdata = cpl_array_get_data_double(trans);
01009         *xout = xt*tdata[0] + yt*tdata[1] + tdata[2];
01010         *yout = xt*tdata[3] + yt*tdata[4] + tdata[5];
01011     } else {
01012         *xout = xt;
01013         *yout = yt;
01014     }
01015 }
01016 
01017 /*---------------------------------------------------------------------------*/
01033 /*---------------------------------------------------------------------------*/
01034 
01035 static void backgrnd_ov(void) {
01036     int i,dx,dy,*cdata,n,jj,ind1,nx,ii,ind;
01037     long npts1,npts,start[2],end[2];
01038     dstrct *dd1,*dd2;
01039     float *data,sky1,skynoise1,sky2,skynoise2,frac;
01040 
01041     /* Initialise a few things */
01042 
01043     dd1 = fileptrs;
01044     npts1 = dd1->nx*dd1->ny;
01045 
01046     /* Start by working out the full background of the first frame */
01047 
01048     skyest(dd1->data,dd1->cdata,npts1,3.0,&sky1,&skynoise1);
01049     dd1->sky = sky1;
01050     dd1->noise = skynoise1;
01051     dd1->sky /= dd1->expscale;
01052     dd1->skydiff = 0.0;
01053     dd1->weight = 1.0;
01054     sumweight = 1.0;
01055 
01056     /* Now loop for all the others */    
01057 
01058     for (i = 1; i < nim; i++) {
01059         dd2 = fileptrs + i;
01060 
01061         /* Offset differences */
01062 
01063         dx = vircam_nint(dd2->xoff - dd1->xoff);
01064         dy = vircam_nint(dd2->yoff - dd1->yoff);
01065 
01066         /* Ok, here's the tricky bit. Work out the range of x and y for
01067            each of the images. The shift moves an image to the left and
01068            and down. Hence positive values of dx or dy moves the second
01069            frame further to the left of down compared to the first frame.
01070            Here are the coordinate ranges for the first image */
01071 
01072         start[0] = max(0,-dx);
01073         start[1] = max(0,-dy);
01074         end[0] = min(dd1->nx-1,(dd1->nx)-dx-1);
01075         end[1] = min(dd1->ny-1,(dd1->ny)-dy-1);
01076         nx = dd1->nx;
01077         
01078         /* How much does this cover the first image? */
01079 
01080         npts = (end[0]-start[0]+1)*(end[1]-start[1]+1);
01081         frac = (float)npts/(float)npts1;
01082 
01083         /* If the coverage is more than 50% then calculate the background
01084            in the coverage region for the first image */
01085 
01086         if (frac >= 0.5) {
01087             data = cpl_malloc(npts*sizeof(*data));
01088             cdata = cpl_malloc(npts*sizeof(*cdata));
01089             n = 0;
01090             for (jj = start[1]; jj <= end[1]; jj++) {
01091                 ind1 = jj*nx;
01092                 for (ii = start[0]; ii <= end[0]; ii++) {
01093                     ind = ind1 + ii;
01094                     data[n] = (dd1->data)[ind];
01095                     cdata[n++] = (dd1->cdata)[ind];
01096                 }
01097             }
01098             skyest(data,cdata,npts,3.0,&sky1,&skynoise1);
01099             freespace(data);
01100             freespace(cdata);
01101         } else {
01102             sky1 = dd1->sky;
01103         }
01104 
01105         /* And here are the coordinate ranges for the second image if 
01106            the coverage is more than 50%. Get the subset you need. */
01107 
01108         if (frac > 0.5) {
01109             start[0] = max(1,dx);
01110             start[1] = max(1,dy);
01111             end[0] = min(dd2->nx-1,(dd2->nx)+dx-1);
01112             end[1] = min(dd2->ny-1,(dd2->ny)+dy-1);
01113             nx = dd2->nx;
01114             npts = (end[0]-start[0]+1)*(end[1]-start[1]+1);
01115             data = cpl_malloc(npts*sizeof(*data));
01116             cdata = cpl_malloc(npts*sizeof(*cdata));
01117             n = 0;
01118             for (jj = start[1]; jj <= end[1]; jj++) {
01119                 ind1 = jj*nx;
01120                 for (ii = start[0]; ii <= end[0]; ii++) {
01121                     ind = ind1 + ii;
01122                     data[n] = dd2->data[ind];
01123                     cdata[n++] = dd2->cdata[ind];
01124                 }
01125             }
01126             skyest(data,cdata,npts,3.0,&sky2,&skynoise2);
01127             freespace(data);
01128             freespace(cdata);
01129         } else {                
01130             npts = (dd2->nx)*(dd2->ny);
01131             skyest(dd2->data,dd2->cdata,npts,3.0,&sky2,&skynoise2);
01132         }
01133 
01134         /* Store info away */
01135 
01136         dd2->sky = sky2/dd2->expscale;
01137         dd2->skydiff = sky1 - sky2;
01138         dd2->noise = skynoise2;
01139         if (dd2->noise != 0.0 && dd2->sky != 0.0) 
01140             dd2->weight = (float)(pow(dd1->noise,2.0)/pow(dd2->noise,2.0)); 
01141         else 
01142             dd2->weight = 0.0;
01143         sumweight += dd2->weight;
01144     }
01145 }
01146 
01147 /*---------------------------------------------------------------------------*/
01173 /*---------------------------------------------------------------------------*/
01174 
01175 static void skyest(float *data, int *cdata, long npts, float thresh, 
01176                    float *skymed, float *skynoise) {
01177     unsigned char *bpm;
01178     int i;
01179 
01180     /* Get a dummy bad pixel mask */
01181 
01182     bpm = cpl_calloc(npts,sizeof(*bpm));
01183     for (i = 0; i < npts; i++)
01184         bpm[i] = (cdata[i] == 0);
01185 
01186     /* Get the stats */
01187 
01188     vircam_qmedsig(data,bpm,npts,thresh,2,-1000.0,65535.0,skymed,skynoise);
01189 
01190     /* Clean up */
01191 
01192     freespace(bpm);
01193 }
01194 
01195 /*---------------------------------------------------------------------------*/
01217 /*---------------------------------------------------------------------------*/
01218 
01219 static cpl_table *mknewtab(vir_tfits *catref, dstrct *dd) {
01220     cpl_table *newtab;
01221     double xx,yy,xx2,yy2;
01222     int nr,i;
01223     float *x,*y;
01224 
01225     /* Make a copy of the input table */
01226 
01227     newtab = cpl_table_duplicate(vircam_tfits_get_table(catref));
01228     nr = cpl_table_get_nrow(newtab);
01229 
01230     /* Get the columns of interest */
01231 
01232     x = cpl_table_get_data_float(newtab,"X_coordinate");
01233     y = cpl_table_get_data_float(newtab,"Y_coordinate");
01234 
01235     /* Loop for each object */
01236 
01237     for (i = 0; i < nr; i++) {
01238         xx = (double)x[i];
01239         yy = (double)y[i];
01240         outloc(fileptrs->vwcs,xx,yy,dd->vwcs,NULL,&xx2,&yy2);
01241         x[i] = (float)xx2;
01242         y[i] = (float)yy2;
01243     }
01244     return(newtab);
01245 }
01246 
01247 /*---------------------------------------------------------------------------*/
01262 /*---------------------------------------------------------------------------*/
01263             
01264 static cpl_array *transinit(void) {
01265     double *td;
01266     cpl_array *t;
01267 
01268     t = cpl_array_new(6,CPL_TYPE_DOUBLE);
01269     td = cpl_array_get_data_double(t);
01270     td[0] = 1.0;
01271     td[1] = 0.0;
01272     td[2] = 0.0;
01273     td[3] = 0.0;
01274     td[4] = 1.0;
01275     td[5] = 0.0;
01276     return(t);
01277 }
01278 
01279 /*---------------------------------------------------------------------------*/
01292 /*---------------------------------------------------------------------------*/
01293 
01294 static void fileptrs_close(void) {
01295     int i;
01296 
01297     for (i = 0; i < nim; i++) {
01298         freespace((fileptrs+i)->vwcs);
01299         freearray((fileptrs+i)->trans);
01300     }
01301     freespace(fileptrs);
01302 }
01303 
01304 /*---------------------------------------------------------------------------*/
01320 /*---------------------------------------------------------------------------*/
01321 
01322 static mywcs *getwcsinfo(cpl_propertylist *plist) {
01323     mywcs *w;
01324     int i;
01325 
01326     /* Copy over the relevant info */
01327 
01328     w = cpl_malloc(sizeof(mywcs));
01329     (void)vircam_pfits_get_crval1(plist,&(w->crval[0]));
01330     (void)vircam_pfits_get_crval2(plist,&(w->crval[1]));
01331     (void)vircam_pfits_get_crpix1(plist,&(w->crpix[0]));
01332     (void)vircam_pfits_get_crpix2(plist,&(w->crpix[1]));
01333     (void)vircam_pfits_get_cd11(plist,&(w->cd[0]));
01334     (void)vircam_pfits_get_cd12(plist,&(w->cd[1]));
01335     (void)vircam_pfits_get_cd21(plist,&(w->cd[2]));
01336     (void)vircam_pfits_get_cd22(plist,&(w->cd[3]));
01337     (void)vircam_pfits_get_pv21(plist,&(w->pv21));
01338     (void)vircam_pfits_get_pv23(plist,&(w->pv23));
01339     (void)vircam_pfits_get_pv25(plist,&(w->pv25));
01340     (void)vircam_pfits_get_naxis1(plist,&(w->nx));
01341     (void)vircam_pfits_get_naxis2(plist,&(w->ny));
01342 
01343     /* Change angles to radians */
01344 
01345     for (i = 0; i < 2; i++) 
01346         w->crval[i] /= DEGRAD;
01347     for (i = 0; i < 4; i++)
01348         w->cd[i] /= DEGRAD;
01349 
01350     /* Add a couple of convenience values */
01351 
01352     w->tand = tan(w->crval[1]);
01353     w->secd = 1.0/cos(w->crval[1]);
01354 
01355     /* Get out of here */
01356 
01357     return(w);
01358 }
01359 
01360 static void tidy(void) {
01361     fileptrs_close();
01362     freespace(outwcs);
01363 }
01364 
01365 /* 
01366 
01367 $Log: vircam_imstack.c,v $
01368 Revision 1.14  2010/09/09 12:11:09  jim
01369 Fixed problems with docs that make doxygen barf
01370 
01371 Revision 1.13  2010/06/03 12:15:31  jim
01372 A few mods to get rid of compiler warnings
01373 
01374 Revision 1.12  2009/06/25 14:14:50  jim
01375 Fixed a little error handling problem
01376 
01377 Revision 1.11  2009/06/01 04:57:19  jim
01378 tidied up a few things
01379 
01380 Revision 1.10  2009/05/31 05:54:55  jim
01381 Nothing
01382 
01383 Revision 1.9  2009/05/31 05:42:55  jim
01384 reweighting linear interpolation
01385 
01386 Revision 1.8  2009/05/30 20:38:41  jim
01387 fixed another normalisation error
01388 
01389 Revision 1.7  2009/05/30 19:41:04  jim
01390 Fixed another small bug in the confidence map scaling
01391 
01392 Revision 1.6  2009/05/29 15:39:49  jim
01393 changed the way confidence map is normalised
01394 
01395 Revision 1.5  2009/02/20 10:52:49  jim
01396 Removed some superfluous declarations and tidied up some things to get
01397 rid of compiler warnings
01398 
01399 Revision 1.4  2009/01/28 10:55:10  jim
01400 Fixed so that if the calculation of trans array fails, then it issues a
01401 warning, but keeps going
01402 
01403 Revision 1.3  2009/01/19 14:35:43  jim
01404 Modified search radii in matching routines
01405 
01406 Revision 1.2  2008/11/25 06:19:20  jim
01407 Added routine prologues
01408 
01409 Revision 1.1  2008/11/21 10:19:16  jim
01410 New routine
01411 
01412 
01413 */

Generated on 7 Feb 2011 for VIRCAM Pipeline by  doxygen 1.6.1