imcore_conf.c

00001 /* $Id: imcore_conf.c,v 1.25 2012/03/06 10:02:03 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/03/06 10:02:03 $
00024  * $Revision: 1.25 $
00025  * $Name: vcam-1_3_2 $
00026  */
00027 
00028 
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <math.h>
00033 
00034 #include <cpl.h>
00035 #include "../vircam_fits.h"
00036 #include "../vircam_pfits.h"
00037 #include "../vircam_wcsutils.h"
00038 
00039 #include "ap.h"
00040 #include "util.h"
00041 #include "imcore.h"
00042 #include "floatmath.h"
00043 #include "imcore_version.h"
00044 
00045 #define FATAL_ERR(_a) {freetable(tab); cpl_msg_error(fctid,_a); tidy(); return(VIR_FATAL);}
00046 
00047 #define NW 5
00048 
00049 static float *smoothed = NULL;
00050 static float *smoothedc = NULL;
00051 static unsigned char *mflag = NULL;
00052 static float *indata = NULL;
00053 static int *confdata = NULL;
00054 static float *confsqrt = NULL;
00055 static ap_t ap;
00056 static int freeconf = 0;
00057 
00058 static float weights[NW*NW];
00059 static float weightc[NW*NW];
00060 static long nx;
00061 static long ny;
00062 
00063 static void crweights(float);
00064 static void convolve(int);
00065 static void tidy(void);
00066 
00069 /*---------------------------------------------------------------------------*/
00144 /*---------------------------------------------------------------------------*/
00145 
00146 extern int imcore_conf(vir_fits *infile, vir_fits *conf, int ipix, 
00147                        float threshold, int icrowd, float rcore, int nbsize, 
00148                        int cattyp, float filtfwhm, vir_tfits **outcat) {
00149 
00150     int i,retval,mulpix,j,nw2,status;
00151     float fconst,nullval,skymed,skysig,thresh,xintmin,offset;
00152     float *current,isatbc,isat,junk,*currentc;
00153     long npix,nxc,nyc,npts;
00154     cpl_image *map,*cmap;
00155     cpl_propertylist *plist,*extra;
00156     char card[64];
00157     const char *fctid = "imcore_conf";
00158 
00159     /* Initialise output */
00160 
00161     *outcat = NULL;
00162 
00163     /* Useful constants */
00164 
00165     fconst = CPL_MATH_LOG2E;
00166     nullval = 0.0;
00167     cattype = cattyp;
00168     nobjects = 0;
00169 
00170     /* Open input image */
00171 
00172     map = vircam_fits_get_image(infile);
00173     if ((indata = cpl_image_get_data_float(map)) == NULL) 
00174         FATAL_ERR("Error getting image data");
00175     nx = (long)cpl_image_get_size_x(map);
00176     ny = (long)cpl_image_get_size_y(map);
00177     npts = nx*ny;
00178     if (vircam_pfits_get_gain(vircam_fits_get_ehu(infile),&gain) != VIR_OK)
00179         gain = 5.0;
00180 
00181     /* Open the associated confidence map, if it exists */
00182 
00183     if (conf != NULL) {
00184         cmap = vircam_fits_get_image(conf);
00185         if ((confdata = cpl_image_get_data(cmap)) == NULL)
00186             FATAL_ERR("Error getting confidence map data");
00187         nxc = (long)cpl_image_get_size_x(cmap);
00188         nyc = (long)cpl_image_get_size_y(cmap);
00189         if ((nx != nxc) || (ny != nyc))
00190             FATAL_ERR("Input image and confidence dimensions don't match");
00191         freeconf = 0;
00192     } else {
00193         confdata = cpl_malloc(npts*sizeof(*confdata));
00194         for (i = 0; i < npts; i++) 
00195             confdata[i] = 100;
00196         freeconf = 1;
00197         cmap = NULL;
00198     }
00199     confsqrt = cpl_malloc(npts*sizeof(*confsqrt));
00200     for (i = 0; i < npts; i++)
00201         confsqrt[i] = sqrt(0.01*(float)confdata[i]);
00202     
00203     /* Get mflag array for flagging saturated pixels */
00204 
00205     npix = nx*ny;
00206     mflag = cpl_calloc(npix,sizeof(*mflag));
00207 
00208     /* Open the ap structure and define some stuff in it */
00209 
00210     ap.lsiz = nx;
00211     ap.csiz = ny;
00212     ap.inframe = map;
00213     ap.conframe = cmap;
00214     ap.xtnum = vircam_fits_get_nexten(infile);
00215     apinit(&ap);
00216     ap.indata = indata;
00217     ap.confdata = confdata;
00218     ap.multiply = 1;
00219     ap.ipnop = ipix;
00220     ap.mflag = mflag;
00221     ap.rcore = rcore;
00222     ap.filtfwhm = filtfwhm;
00223     ap.icrowd = icrowd;
00224     ap.fconst = fconst;
00225 
00226     /* Open the output catalogue FITS table */
00227 
00228     tabinit(&ap);
00229 
00230     /* Set up the data flags */
00231 
00232     for (i = 0; i < npix; i++) 
00233         if (confdata[i] == 0)
00234             mflag[i] = MF_ZEROCONF;
00235         else if (indata[i] < STUPID_VALUE)
00236             mflag[i] = MF_STUPID_VALUE;
00237         else 
00238             mflag[i] = MF_CLEANPIX;
00239 
00240     /* Compute a saturation level before background correction. */
00241 
00242     retval = imcore_backstats(&ap,nullval,1,&skymed,&skysig,&isatbc);
00243     if (retval != VIR_OK) 
00244         FATAL_ERR("Error calculating saturation level");
00245 
00246     /* Flag up regions where the value is above the saturation level
00247        determined above. */
00248 
00249     for (i = 0; i < npix ; i++)
00250         if (mflag[i] == MF_CLEANPIX && indata[i] > isatbc)
00251             mflag[i] = MF_SATURATED;
00252 
00253     /* Compute the background variation and remove it from the data*/
00254 
00255     retval = imcore_background(&ap,nbsize,nullval);
00256     if (retval != VIR_OK) 
00257         FATAL_ERR("Error calculating background");
00258 
00259     /* Compute a saturation level after background correction. */
00260 
00261     retval = imcore_backstats(&ap,nullval,1,&skymed,&skysig,&isat);
00262     if (retval != VIR_OK) 
00263         FATAL_ERR("Error calculating saturation");
00264 
00265 
00266     /* Compute background statistics */
00267 
00268     retval = imcore_backstats(&ap,nullval,0,&skymed,&skysig,&junk);
00269     if (retval != VIR_OK) 
00270         FATAL_ERR("Error calculating background stats");
00271 
00272     /* Get the propertly list for the input file and add some info*/
00273 
00274     plist = vircam_fits_get_ehu(infile);
00275     cpl_propertylist_update_float(plist,"ESO DRS SKYLEVEL",skymed);
00276     cpl_propertylist_set_comment(plist,"ESO DRS SKYLEVEL",
00277                                  "[adu] Median sky brightness");
00278     cpl_propertylist_update_float(plist,"ESO DRS SKYNOISE",skysig);
00279     cpl_propertylist_set_comment(plist,"ESO DRS SKYNOISE",
00280                                  "[adu] Pixel noise at sky level");
00281 
00282     /* Take mean sky level out of data. Uncomment the bit below if
00283        we start working out the covariance in dribbled data. See cirdr
00284        version. */
00285 
00286     for (i = 0; i < nx*ny; i++) {
00287         indata[i] -= skymed;
00288         /* if (indata[i]*confsqrt[i] > 3.0*skysig &&  */
00289         /*     mflag[i] != MF_SATURATED && mflag[i] != MF_STUPID_VALUE)  */
00290         /*     mflag[i] = MF_3SIG; */
00291     }
00292     
00293     /* Work out isophotal detection threshold levels */
00294 
00295     thresh = threshold*skysig;
00296     
00297     /* Minimum intensity for consideration */
00298 
00299     xintmin = 1.5*thresh*((float)ipix);
00300 
00301     /* Minimum size for considering multiple images */
00302 
00303     mulpix = MAX(8,2*ipix);
00304 
00305     /* Actual areal profile levels: T, 2T, 4T, 8T,...but written wrt T
00306        i.e. threshold as a power of 2 */
00307 
00308     offset = logf(thresh)*fconst;
00309 
00310     /* Get a bit of workspace for buffers */
00311 
00312     smoothed = cpl_malloc(nx*sizeof(*smoothed));
00313     smoothedc = cpl_malloc(nx*sizeof(*smoothedc));
00314 
00315     /* Define a few things more things in ap structure */
00316 
00317     ap.mulpix = mulpix;
00318     ap.areal_offset = offset;
00319     ap.thresh = thresh;
00320     ap.xintmin = xintmin;
00321     ap.sigma = skysig;
00322     ap.background = skymed;
00323     ap.saturation = (float)isat;
00324 
00325     /* Set the weights */
00326 
00327     crweights(filtfwhm);
00328     nw2 = NW/2;
00329 
00330     /* Right, now for the extraction loop.  Begin by defining a group of
00331        three rows of data and confidence */
00332 
00333     for (j = nw2; j < ny-nw2; j++) {
00334         current = indata + j*nx;
00335         currentc = confsqrt + j*nx;
00336         convolve(j);
00337    
00338         /* Do the detection now */
00339 
00340         apline(&ap,current,currentc,smoothed,smoothedc,j,NULL);
00341 
00342         /* Make sure we're not overruning the stacks */
00343 
00344         if (ap.ibstack > (ap.maxbl - ap.lsiz))
00345             apfu(&ap);
00346         if (ap.ipstack > (ap.maxpa*3/4))
00347             for (i = 0; i < ap.maxpa*3/8; i++)
00348                 apfu(&ap);
00349 
00350         /* See if there are any images to terminate */
00351 
00352         if (ap.ipstack > 1)
00353             terminate(&ap);
00354     }
00355 
00356     /* Post process. First truncate the cpl_table to the correct size and then
00357        work out an estimate of the seeing */
00358 
00359     cpl_table_set_size(tab,nobjects);
00360     retval = do_seeing(&ap);
00361     if (retval != VIR_OK)
00362         FATAL_ERR("Error working out seeing");
00363     tabclose(&ap);
00364 
00365     /* Create a property list with extra parameters. First QC parameters */
00366 
00367     extra = cpl_propertylist_duplicate(vircam_fits_get_ehu(infile));
00368     cpl_propertylist_update_float(extra,"ESO QC SATURATION",ap.saturation);
00369     cpl_propertylist_set_comment(extra,"ESO QC SATURATION",
00370                                  "[adu] Saturation level");
00371     cpl_propertylist_update_float(extra,"ESO QC MEAN_SKY",ap.background);
00372     cpl_propertylist_set_comment(extra,"ESO QC MEAN_SKY",
00373                                  "[adu] Median sky brightness");
00374     cpl_propertylist_update_float(extra,"ESO QC SKY_NOISE",ap.sigma);
00375     cpl_propertylist_set_comment(extra,"ESO QC SKY_NOISE",
00376                                  "[adu] Pixel noise at sky level");
00377 
00378     /* Now DRS parameters */
00379 
00380     cpl_propertylist_update_float(extra,"ESO DRS THRESHOL",ap.thresh);
00381     cpl_propertylist_set_comment(extra,"ESO DRS THRESHOL",
00382                                  "[adu] Isophotal analysis threshold");
00383     cpl_propertylist_update_int(extra,"ESO DRS MINPIX",ap.ipnop);
00384     cpl_propertylist_set_comment(extra,"ESO DRS MINPIX",
00385                                  "[pixels] Minimum size for images");
00386     cpl_propertylist_update_int(extra,"ESO DRS CROWDED",ap.icrowd);
00387     cpl_propertylist_set_comment(extra,"ESO DRS CROWDED",
00388                                  "Crowded field analysis flag");
00389     cpl_propertylist_update_float(extra,"ESO DRS RCORE",ap.rcore);
00390     cpl_propertylist_set_comment(extra,"ESO DRS RCORE",
00391                                  "[pixels] Core radius for default profile fit");
00392     cpl_propertylist_update_float(extra,"ESO DRS SEEING",ap.fwhm);
00393     cpl_propertylist_set_comment(extra,"ESO DRS SEEING",
00394                                  "[pixels] Average FWHM");
00395     cpl_propertylist_update_float(extra,"ESO DRS FILTFWHM",ap.filtfwhm);
00396     cpl_propertylist_set_comment(extra,"ESO DRS FILTFWHM",
00397                                  "[pixels] FWHM of smoothing kernel");
00398     cpl_propertylist_update_int(extra,"ESO DRS XCOL",imcore_xcol);
00399     cpl_propertylist_set_comment(extra,"ESO DRS XCOL","Column for X position");
00400     cpl_propertylist_update_int(extra,"ESO DRS YCOL",imcore_ycol);
00401     cpl_propertylist_set_comment(extra,"ESO DRS YCOL","Column for Y position");
00402     cpl_propertylist_update_int(extra,"ESO DRS NXOUT",nx);
00403     cpl_propertylist_set_comment(extra,"ESO DRS NXOUT",
00404                                  "X Dimension of input image");
00405     cpl_propertylist_update_int(extra,"ESO DRS NYOUT",ny);
00406     cpl_propertylist_set_comment(extra,"ESO DRS NYOUT",
00407                                  "Y Dimension of input image");
00408     snprintf(card,64,"IMCORE version: %s",imcore_version);
00409     cpl_propertylist_append_string(extra,"HISTORY",card);
00410     
00411     /* Now wrap all this stuff up and send it back */
00412 
00413     plist = cpl_propertylist_duplicate(vircam_fits_get_phu(infile));
00414     status = VIR_OK;
00415     (void)vircam_tabwcs(extra,imcore_xcol,imcore_ycol,&status);
00416     *outcat = vircam_tfits_wrap(tab,NULL,plist,extra);
00417 
00418     /* Tidy and exit */  
00419 
00420     tidy();
00421     return(VIR_OK);
00422 }
00423 
00424 /*---------------------------------------------------------------------------*/
00441 /*---------------------------------------------------------------------------*/
00442 
00443 static void crweights(float filtfwhm) {
00444     int i,j,nw2,n;
00445     double gsigsq,di,dj;
00446     float renorm;
00447 
00448     /* Get the kernel size */
00449 
00450     nw2 = NW/2;
00451     
00452     /* Set the normalisation constants */
00453 
00454     gsigsq = 1.0/(2.0*pow(MAX(1.0,(double)filtfwhm)/2.35,2.0));
00455     renorm = 0.0;
00456 
00457     /* Now work out the weights */
00458 
00459     n = -1;
00460     for (i = -nw2; i <= nw2; i++) {
00461         di = (double)i;
00462         di *= gsigsq*di;
00463         for (j = -nw2; j <= nw2; j++) {
00464             dj = (double)j;
00465             dj *= gsigsq*dj;
00466             n++;
00467             weights[n] = (float)exp(-(di + dj));
00468             renorm += weights[n];
00469         }
00470     }
00471 
00472     /* Now normalise the weights */
00473 
00474     n = -1;
00475     for (i = -nw2; i <= nw2; i++) {
00476         for (j = -nw2; j <= nw2; j++) {
00477             n++;
00478             weights[n] /= renorm;
00479             /* weightc[n] = 0.01*weights[n]; */
00480             weightc[n] = weights[n];
00481         }
00482     }
00483 }
00484 
00485 /*---------------------------------------------------------------------------*/
00503 /*---------------------------------------------------------------------------*/
00504 
00505 static void convolve(int ir) {
00506     int i,nw2,ix,jx,jy,n;
00507     float *idata,*cdata;
00508 
00509     /* Zero the summations */
00510 
00511     for (i = 0; i < nx; i++) {
00512         smoothed[i] = 0.0;
00513         smoothedc[i] = 0.0;
00514     }
00515 
00516     /* Now big is the smoothing kernel? */
00517 
00518     nw2 = NW/2;
00519 
00520     /* Now loop for each column */
00521 
00522     for (ix = nw2; ix < nx-nw2; ix++) {
00523         n = -1;
00524         for (jy = ir-nw2; jy <= ir+nw2; jy++) {
00525             idata = indata + jy*nx;
00526             cdata = confsqrt + jy*nx;
00527             for (jx = ix-nw2; jx <= ix+nw2; jx++) {
00528                 n++;
00529                 smoothed[ix] += weights[n]*idata[jx];
00530                 smoothedc[ix] += weightc[n]*idata[jx]*cdata[jx];
00531             }
00532         }
00533     }
00534 }
00535 
00536 static void tidy(void) {
00537 
00538     if (freeconf) 
00539         freespace(confdata);
00540     freespace(confsqrt);
00541     freespace(smoothed);
00542     freespace(smoothedc);
00543     freespace(mflag);
00544     apclose(&ap);
00545 }
00546 
00549 /* 
00550 
00551 $Log: imcore_conf.c,v $
00552 Revision 1.25  2012/03/06 10:02:03  jim
00553 Made change to pixel masking
00554 
00555 Revision 1.24  2010/09/10 11:23:09  jim
00556 Fixed declaration of currentc
00557 
00558 Revision 1.23  2010/09/09 12:09:49  jim
00559 Modified to use sqrt weighting with confidence maps. Also added docs
00560 
00561 Revision 1.22  2009/09/09 09:42:25  jim
00562 modified to use CPL defined macros for constants
00563 
00564 Revision 1.21  2009/05/20 12:22:34  jim
00565 Now adds ESO DRS NXOUT and NYOUT to header
00566 
00567 Revision 1.20  2009/01/30 08:26:23  jim
00568 Now adds a global version number to header
00569 
00570 Revision 1.19  2009/01/23 12:24:33  jim
00571 Fixed bugs in pixel flagging
00572 
00573 Revision 1.18  2008/10/13 08:10:56  jim
00574 Fixed pixel masking scheme
00575 
00576 Revision 1.17  2007/05/03 11:15:34  jim
00577 Fixed little problem with table wcs
00578 
00579 Revision 1.16  2007/05/02 09:11:35  jim
00580 Modified to allow for inclusion of table WCS keywords into FITS header
00581 
00582 Revision 1.15  2007/03/01 12:38:26  jim
00583 Small modifications after a bit of code checking
00584 
00585 Revision 1.14  2006/11/27 11:56:59  jim
00586 Changed cpl_propertylist_append to cpl_propertylist_update calls
00587 
00588 Revision 1.13  2006/08/01 11:27:54  jim
00589 Modifications to imcore background estimation and to add ability to
00590 specify the smoothing kernel width
00591 
00592 Revision 1.12  2006/07/11 14:51:02  jim
00593 Fixed small bug in the range of the main loop
00594 
00595 Revision 1.11  2006/07/03 09:33:19  jim
00596 Fixed a few things to keep the compiler happy
00597 
00598 Revision 1.10  2006/06/30 21:31:09  jim
00599 MOdifications to background routines and smoothing kernel
00600 
00601 Revision 1.9  2006/06/13 14:06:10  jim
00602 Gets gain estimate from header
00603 
00604 Revision 1.8  2006/06/06 13:04:22  jim
00605 Fixed apline so that it now takes confidence map info correctly
00606 
00607 Revision 1.7  2006/05/30 12:13:53  jim
00608 Initialised nobjects
00609 
00610 Revision 1.6  2006/05/18 12:35:01  jim
00611 Fixed bug for header writing
00612 
00613 Revision 1.5  2006/03/15 10:43:42  jim
00614 Fixed a few things
00615 
00616 Revision 1.4  2006/03/01 10:31:29  jim
00617 Now uses new vir_fits objects
00618 
00619 Revision 1.3  2005/09/22 08:40:42  jim
00620 Fixed some bugs in imcore and added classification Removed some unnecessary
00621 files
00622 
00623 Revision 1.2  2005/09/20 15:07:47  jim
00624 Fixed a few bugs and added a few things
00625 
00626 Revision 1.1  2005/09/13 13:25:29  jim
00627 Initial entry after modifications to make cpl compliant
00628 
00629 
00630 */

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1