imcore_opm.c

00001 /* $Id: imcore_opm.c,v 1.5 2010/09/10 11:23: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/10 11:23:09 $
00024  * $Revision: 1.5 $
00025  * $Name: vcam-1_3_2 $
00026  */
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <math.h>
00031 #include <string.h>
00032 
00033 #include "ap.h"
00034 #include "util.h"
00035 #include "imcore.h"
00036 #include "floatmath.h"
00037 
00038 #include "../vircam_pfits.h"
00039 #include "../vircam_fits.h"
00040 
00041 #define FATAL_ERR(_a) {freetable(tab); cpl_msg_error(fctid,_a); tidy(); return(VIR_FATAL);}
00042 
00043 #define NW 5
00044 
00045 static float *indata = NULL;
00046 static int *confdata = NULL;
00047 static float *confsqrt = NULL;
00048 static float *smoothed = NULL;
00049 static float *smoothedc = NULL;
00050 static unsigned char *mflag = NULL;
00051 static ap_t ap;
00052 static int freeconf = 0;
00053 static float *incopy = NULL;
00054 static int *ccopy = NULL;
00055 
00056 static float weights[NW*NW];
00057 static float weightc[NW*NW];
00058 static long nx;
00059 static long ny;
00060 
00061 static void crweights(float);
00062 static void convolve(int);
00063 static void tidy(void);
00064 
00067 /*---------------------------------------------------------------------------*/
00110 /*---------------------------------------------------------------------------*/
00111 
00112 extern int imcore_opm(vir_fits *infile, vir_fits *conf, int ipix, 
00113                       float threshold, int nbsize, float filtfwhm, 
00114                       int niter) {
00115 
00116     int i,retval,j,nw2,iter,nclip,nxc,nyc;
00117     float fconst,nullval,skymed,skysig,thresh,xintmin,offset;
00118     float isat,isatbc,*current,junk,*currentc;
00119     long npix;
00120     cpl_image *map,*cmap;
00121     cpl_propertylist *plist;
00122     cpl_binary *opm;
00123     const char *fctid = "imcore_opm";
00124 
00125     /* Useful constants */
00126 
00127     fconst = CPL_MATH_LOG2E;
00128     nullval = 0.0;
00129     cattype = 4;
00130 
00131     /* Open input image */
00132 
00133     map = vircam_fits_get_image(infile);
00134     if ((indata = cpl_image_get_data_float(map)) == NULL) 
00135         FATAL_ERR("Error getting image data");
00136     nx = (long)cpl_image_get_size_x(map);
00137     ny = (long)cpl_image_get_size_y(map);
00138     npix = nx*ny;
00139     if (vircam_pfits_get_gain(vircam_fits_get_ehu(infile),&gain) != VIR_OK)
00140         gain = 5.0;
00141 
00142     /* Open the associated confidence map, if it exists */
00143 
00144     if (conf != NULL) {
00145         cmap = vircam_fits_get_image(conf);
00146         if ((confdata = cpl_image_get_data(cmap)) == NULL)
00147             FATAL_ERR("Error getting confidence map data");
00148         nxc = (long)cpl_image_get_size_x(cmap);
00149         nyc = (long)cpl_image_get_size_y(cmap);
00150         if ((nx != nxc) || (ny != nyc))
00151             FATAL_ERR("Input image and confidence dimensions don't match");
00152         freeconf = 0;
00153     } else {
00154         confdata = cpl_malloc(npix*sizeof(*confdata));
00155         for (i = 0; i < npix; i++) 
00156             confdata[i] = 100;
00157         freeconf = 1;
00158         cmap = NULL;
00159     }
00160     confsqrt = cpl_malloc(npix*sizeof(*confsqrt));
00161     for (i = 0; i < npix; i++) 
00162         confsqrt[i] = sqrt(0.01*(float)confdata[i]);
00163 
00164     /* Make a copy of each */
00165 
00166     incopy = cpl_malloc(npix*sizeof(*incopy));
00167     ccopy = cpl_malloc(npix*sizeof(*ccopy));
00168     memmove(incopy,indata,npix*sizeof(*incopy));
00169     memmove(ccopy,confdata,npix*sizeof(*ccopy));
00170 
00171     /* Get mflag array for flagging saturated pixels */
00172 
00173     mflag = cpl_calloc(npix,sizeof(*mflag));
00174 
00175     /* Open the ap structure and define some stuff in it */
00176 
00177     ap.lsiz = nx;
00178     ap.csiz = ny;
00179     ap.inframe = map;
00180     ap.conframe = cmap;
00181     ap.xtnum = vircam_fits_get_nexten(infile);
00182     apinit(&ap);
00183     ap.indata = indata;
00184     ap.confdata = confdata;
00185     ap.multiply = 1;
00186     ap.ipnop = ipix;
00187     ap.mflag = mflag;
00188     ap.fconst = fconst;
00189     ap.filtfwhm = filtfwhm;
00190 
00191     /* Open the output catalogue FITS table */
00192 
00193     tabinit(&ap);
00194 
00195     /* Set up the data flags */
00196 
00197     for (i = 0; i < npix ; i++) 
00198         if (confdata[i] == 0)
00199             mflag[i] = MF_ZEROCONF;
00200         else if (indata[i] < STUPID_VALUE)
00201             mflag[i] = MF_STUPID_VALUE;
00202         else 
00203             mflag[i] = MF_CLEANPIX;
00204 
00205     /* Compute a saturation level before background correction. */
00206 
00207     retval = imcore_backstats(&ap,nullval,1,&skymed,&skysig,&isatbc);
00208     if (retval != VIR_OK) 
00209         FATAL_ERR("Error calculating saturation level");
00210 
00211     /* Flag saturated pixels */
00212 
00213     for (i = 0; i < npix ; i++) 
00214         if (mflag[i] == MF_CLEANPIX && indata[i] > isatbc)
00215             mflag[i] = MF_SATURATED;
00216 
00217     /* Get a bit of workspace for buffers */
00218 
00219     smoothed = cpl_malloc(nx*sizeof(*smoothed));
00220     smoothedc = cpl_malloc(nx*sizeof(*smoothedc));
00221 
00222     /* Set the weights */
00223 
00224     crweights(filtfwhm);
00225     nw2 = NW/2;
00226 
00227     /* Iteration loop */
00228 
00229     for (iter = 0; iter < niter; iter++) {
00230 
00231         /* Compute the background variation and remove it from the data*/
00232 
00233         retval = imcore_background(&ap,nbsize,nullval);
00234         if (retval != VIR_OK) 
00235             FATAL_ERR("Error calculating background");
00236 
00237         /* Compute a saturation level */
00238 
00239         retval = imcore_backstats(&ap,nullval,1,&skymed,&skysig,&isat);
00240         if (retval != VIR_OK) 
00241             FATAL_ERR("Error calculating saturation");
00242 
00243         /* Compute background statistics */
00244 
00245         retval = imcore_backstats(&ap,nullval,0,&skymed,&skysig,&junk);
00246         if (retval != VIR_OK) 
00247             FATAL_ERR("Error calculating background stats");
00248 
00249         /* Get the propertly list for the input file and add some info*/
00250 
00251         plist = vircam_fits_get_ehu(infile);
00252         cpl_propertylist_update_float(plist,"ESO DRS SKYLEVEL",skymed);
00253         cpl_propertylist_set_comment(plist,"ESO DRS SKYLEVEL",
00254                                      "[adu] Median sky brightness");
00255         cpl_propertylist_update_float(plist,"ESO DRS SKYNOISE",skysig);
00256         cpl_propertylist_set_comment(plist,"ESO DRS SKYNOISE",
00257                                      "[adu] Pixel noise at sky level");
00258 
00259         /* Take mean sky level out of data */
00260 
00261         for (i = 0; i < nx*ny; i++)
00262             indata[i] -= skymed;
00263 
00264         /* Work out isophotal detection threshold levels */
00265 
00266         thresh = threshold*skysig;
00267 
00268         /* Minimum intensity for consideration */
00269 
00270         xintmin = 1.5*thresh*((float)ipix);
00271 
00272         /* Actual areal profile levels: T, 2T, 4T, 8T,...but written wrt T
00273            i.e. threshold as a power of 2 */
00274 
00275         offset = logf(thresh)*fconst;
00276 
00277         /* Define a few things more things in ap structure */
00278 
00279         ap.areal_offset = offset;
00280         ap.thresh = thresh;
00281         ap.xintmin = xintmin;
00282         ap.sigma = skysig;
00283         ap.background = skymed;
00284         ap.saturation = isat;
00285 
00286         /* Right, now for the extraction loop.  Begin by defining a group of
00287            three rows of data and confidence */
00288 
00289         for (j = nw2; j < ny-nw2; j++) {
00290             current = indata + j*nx;
00291             currentc = confsqrt + j*nx;
00292             convolve(j);
00293 
00294             /* Do the detection now */
00295 
00296             apline(&ap,current,currentc,smoothed,smoothedc,j,NULL);
00297 
00298             /* Make sure we're not overruning the stacks */
00299 
00300             if (ap.ibstack > (ap.maxbl - ap.lsiz)) 
00301                 apfu(&ap);
00302             if (ap.ipstack > (ap.maxpa*3/4)) 
00303                 for (i = 0; i < ap.maxpa*3/8; i++)
00304                     apfu(&ap);
00305 
00306             /* See if there are any images to terminate */
00307 
00308             if (ap.ipstack > 1)
00309                 terminate(&ap);
00310         }
00311     
00312         /* Restore input data to its former glory. Update confidence map */
00313     
00314         memmove(indata,incopy,npix*sizeof(*indata));
00315         nclip = 0;
00316         opm = cpl_mask_get_data(ap.opmask);
00317         for (i = 0; i < npix; i++) {
00318             if (opm[i]) {
00319                 confdata[i] = 0;
00320                 opm[i] = 0;
00321                 nclip++;
00322             }
00323         }
00324         if (nclip == 0)
00325             break;
00326     }
00327     opm = cpl_mask_get_data(ap.opmask);
00328     for (i = 0; i < npix; i++)
00329         opm[i] = (confdata[i] == 0);
00330     memmove(confdata,ccopy,npix*sizeof(*confdata));
00331     retval = tabclose(&ap);
00332 
00333     /* Tidy and exit */  
00334 
00335     tidy();
00336     return(VIR_OK);
00337 }
00338 
00339 /*---------------------------------------------------------------------------*/
00356 /*---------------------------------------------------------------------------*/
00357 
00358 static void crweights(float filtfwhm) {
00359     int i,j,nw2,n;
00360     double gsigsq,di,dj;
00361     float renorm;
00362 
00363     /* Get the kernel size */
00364 
00365     nw2 = NW/2;
00366     
00367     /* Set the normalisation constants */
00368 
00369     gsigsq = 1.0/(2.0*pow(MAX(1.0,(double)filtfwhm)/2.35,2.0));
00370     renorm = 0.0;
00371 
00372     /* Now work out the weights */
00373 
00374     n = -1;
00375     for (i = -nw2; i <= nw2; i++) {
00376         di = (double)i;
00377         di *= gsigsq*di;
00378         for (j = -nw2; j <= nw2; j++) {
00379             dj = (double)j;
00380             dj *= gsigsq*dj;
00381             n++;
00382             weights[n] = (float)exp(-(di + dj));
00383             renorm += weights[n];
00384         }
00385     }
00386 
00387     /* Now normalise the weights */
00388 
00389     n = -1;
00390     for (i = -nw2; i <= nw2; i++) {
00391         for (j = -nw2; j <= nw2; j++) {
00392             n++;
00393             weights[n] /= renorm;
00394             /* weightc[n] = 0.01*weights[n]; */
00395             weightc[n] = weights[n];
00396         }
00397     }
00398 }
00399 
00400 /*---------------------------------------------------------------------------*/
00418 /*---------------------------------------------------------------------------*/
00419 
00420 static void convolve(int ir) {
00421     int i,nw2,ix,jx,jy,n;
00422     float *idata,*cdata;
00423 
00424     /* Zero the summations */
00425 
00426     for (i = 0; i < nx; i++) {
00427         smoothed[i] = 0.0;
00428         smoothedc[i] = 0.0;
00429     }
00430 
00431     /* Now big is the smoothing kernel? */
00432 
00433     nw2 = NW/2;
00434 
00435     /* Now loop for each column */
00436 
00437     for (ix = nw2; ix < nx-nw2; ix++) {
00438         n = -1;
00439         for (jy = ir-nw2; jy <= ir+nw2; jy++) {
00440             idata = indata + jy*nx;
00441             cdata = confsqrt + jy*nx;
00442             for (jx = ix-nw2; jx <= ix+nw2; jx++) {
00443                 n++;
00444                 smoothed[ix] += weights[n]*idata[jx];
00445                 smoothedc[ix] += weightc[n]*idata[jx]*cdata[jx];
00446             }
00447         }
00448     }
00449 }
00450 
00451 static void tidy(void) {
00452 
00453     if (freeconf) 
00454         freespace(confdata);
00455     freespace(confsqrt);
00456     freespace(smoothed);
00457     freespace(smoothedc);
00458     freespace(mflag);
00459     freespace(incopy);
00460     freespace(ccopy);
00461     apclose(&ap);
00462 }
00463 
00464 /* 
00465 
00466 $Log: imcore_opm.c,v $
00467 Revision 1.5  2010/09/10 11:23:09  jim
00468 Fixed declaration of currentc
00469 
00470 Revision 1.4  2010/09/09 12:09:49  jim
00471 Modified to use sqrt weighting with confidence maps. Also added docs
00472 
00473 Revision 1.3  2010/06/03 11:40:00  jim
00474 fixed definition of tidy routine to include 'void' as argument list
00475 
00476 Revision 1.2  2009/09/09 09:42:25  jim
00477 modified to use CPL defined macros for constants
00478 
00479 Revision 1.1  2008/10/13 08:07:26  jim
00480 New entry
00481 
00482 
00483 */

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1