vircam_defringe.c

00001 /* $Id: vircam_defringe.c,v 1.6 2007/10/25 17:34:00 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: 2007/10/25 17:34:00 $
00024  * $Revision: 1.6 $
00025  * $Name:  $
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 
00041 #define NTERMAX 15
00042 #define ITERMAX 7
00043 #define OGAP 0.01
00044 #define GAPMIN 0.25
00045 #define CLIPLEV 4.0
00046 
00047 static int vircam_defringe_1(vir_fits **infiles, int nimages, vir_fits *fringe,
00048                              vir_mask *mask, int nbsize, float *scaleout,
00049                              int *status);
00050 
00053 /*---------------------------------------------------------------------------*/
00105 /*---------------------------------------------------------------------------*/
00106 
00107 extern int vircam_defringe(vir_fits **infiles, int nimages, vir_fits **fringes,
00108                            int nfringes, vir_mask *mask, int nbsize,
00109                            int *status) {
00110     float *sig_before,*scale,*idata,med,mad,ratio;
00111     unsigned char *bpm;
00112     int i,j,npts;
00113     char pname1[64],comment1[64],pname2[64],comment2[64];
00114     cpl_propertylist *ehu;
00115 
00116     /* Inherited status */
00117 
00118     if (*status != VIR_OK)
00119         return(*status);
00120 
00121     /* Get some workspace to use for working out the background sigmas */
00122 
00123     sig_before = cpl_malloc(nimages*sizeof(float));
00124     scale = cpl_malloc(nimages*sizeof(float));
00125 
00126     /* Now work out the background sigma of each image */
00127 
00128     bpm = vircam_mask_get_data(mask);
00129     npts = cpl_image_get_size_x(vircam_fits_get_image(infiles[0]))*
00130         cpl_image_get_size_y(vircam_fits_get_image(infiles[0]));
00131     for (i = 0; i < nimages; i++) {
00132         idata = cpl_image_get_data_float(vircam_fits_get_image(infiles[i]));
00133         vircam_medmad(idata,bpm,(long)npts,&med,&mad);
00134         sig_before[i] = 1.48*mad;
00135     }
00136 
00137     /* Now do the defringing */
00138 
00139     for (i = 0; i < nfringes; i++) {
00140         (void)vircam_defringe_1(infiles,nimages,fringes[i],mask,nbsize,scale,
00141                                 status);
00142 
00143         /* Create scale factor and fringe name information for headers */
00144 
00145         (void)sprintf(pname1,"ESO DRS FRINGE%d",i);
00146         (void)sprintf(comment1,"Fringe frame # %d",i);
00147         (void)sprintf(pname2,"ESO DRS FRNGSC%d",i);
00148         (void)sprintf(comment2,"Fringe scale # %d",i);
00149         
00150         /* Now loop for each image and write these to the headers */
00151         
00152         for (j = 0; j < nimages; j++) {
00153             ehu = vircam_fits_get_ehu(infiles[j]);
00154             cpl_propertylist_update_string(ehu,pname1,
00155                                            vircam_fits_get_fullname(fringes[i]));
00156             cpl_propertylist_set_comment(ehu,pname1,comment1);
00157             cpl_propertylist_update_float(ehu,pname2,scale[i]);
00158             cpl_propertylist_set_comment(ehu,pname2,comment2);
00159         }
00160     }
00161         
00162     /* Now work out the final background sigma and add the ratio of the
00163        before to after to the QC header of each image */
00164 
00165     for (i = 0; i < nimages; i++) {
00166         ehu = vircam_fits_get_ehu(infiles[i]);
00167         idata = cpl_image_get_data_float(vircam_fits_get_image(infiles[i]));
00168         vircam_medmad(idata,bpm,(long)npts,&med,&mad);
00169         ratio = sig_before[i]/(1.48*mad);
00170         cpl_propertylist_update_float(ehu,"ESO QC FRINGE_RATIO",ratio);
00171         cpl_propertylist_set_comment(ehu,"ESO QC FRINGE_RATIO",
00172                                      "Ratio RMS before to after defringing");
00173     }
00174     freespace(sig_before);
00175     freespace(scale);
00176     GOOD_STATUS
00177 }
00178 
00179 /*---------------------------------------------------------------------------*/
00210 /*---------------------------------------------------------------------------*/
00211 
00212 static int vircam_defringe_1(vir_fits **infiles, int nimages, vir_fits *fringe,
00213                              vir_mask *mask, int nbsize, float *scaleout,
00214                              int *status) {
00215     cpl_image *frback,*imback,*fringefit,*imfit;
00216     float frmed,immed,*frdata,*frorig,*wptr,*imdata,*data,scaleth,scalemin;
00217     float scaleprev,spreadmin,spreadfbest,gap,offset,clipmax,clip,spreadf;
00218     float scalefound,scale,scalelist[3],diff,spreadlist[3],a,b,c;
00219     long npts,ntot;
00220     int i,iter,nter,k,j;
00221     vir_fits *im;
00222     unsigned char *bpm;
00223 
00224     /* Inherited status */
00225 
00226     if (*status != VIR_OK)
00227         return(*status);
00228 
00229     /* Prepare the fringe frame by creating a background mask */
00230 
00231     vircam_backmap(fringe,mask,nbsize,&frback,&frmed);
00232 
00233     /* Create a fringe frame image that is background corrected and normalised
00234        to zero median */
00235 
00236     fringefit = cpl_image_subtract_create(vircam_fits_get_image(fringe),
00237                                           frback);
00238     cpl_image_subtract_scalar(fringefit,frmed);
00239     frdata = cpl_image_get_data_float(fringefit);
00240     npts = cpl_image_get_size_x(fringefit)*cpl_image_get_size_y(fringefit);
00241     frorig = cpl_image_get_data_float(vircam_fits_get_image(fringe));
00242 
00243     /* Get some workspace */
00244 
00245     wptr = cpl_malloc(npts*sizeof(float));
00246 
00247     /* Get BPM */
00248 
00249     bpm = vircam_mask_get_data(mask);
00250 
00251     /* Now loop for each of the input images */
00252 
00253     for (i = 0; i < nimages; i++) {
00254         im = infiles[i];
00255 
00256         /* Create a background map and correct for it */
00257 
00258         vircam_backmap(im,mask,nbsize,&imback,&immed);
00259         imdata = cpl_image_get_data_float(vircam_fits_get_image(im));
00260         imfit = cpl_image_subtract_create(vircam_fits_get_image(im),imback);
00261         cpl_image_subtract_scalar(imfit,immed);
00262         data = cpl_image_get_data_float(imfit);
00263 
00264         /* The overall medians are used as a first guess of the scaling 
00265            between the two images */
00266 
00267         scaleth = immed/frmed;
00268 
00269         /* Set up some values for tracking the goodness of fit */
00270 
00271         scalemin = 0.0;
00272         scaleprev = 1.0e6;
00273         spreadmin = 1.0e3;
00274         spreadfbest = 1.0e6;
00275         iter = 0;
00276         nter = 0;
00277         gap = scaleth;
00278         offset = 0.5;
00279         clipmax = 1.0e3;
00280 
00281         /* Begin the iteration loop */
00282 
00283         while (nter < NTERMAX && iter < ITERMAX && (fabs(offset)*gap > OGAP ||
00284                                                     gap > GAPMIN)) {
00285             iter++;
00286             nter++;
00287 
00288             /* Clip levels */
00289 
00290             clip = min(clipmax,CLIPLEV*1.48*spreadmin);
00291 
00292             /* Speed up convergence if sitting on top of a solution. 
00293                Slow it down if outside range */
00294 
00295             if (fabs(scalemin - scaleprev) < 0.5*gap) 
00296                 iter += 1;
00297             scaleprev = scalemin;
00298             if (fabs(offset) > 0.9)
00299                 iter -= 1;
00300             gap = scaleth*pow(2.0,(double)(1-iter));
00301 
00302             /* Initialise a few things */
00303 
00304             spreadf = 1.0e6;
00305             scalefound = 2.0;
00306             
00307             /* Do three calculations -- just below, at and just above
00308                the current best guess scale factor */
00309 
00310             for (k = 0; k < 3; k++) {
00311                 scale = scalemin + gap*(float)(k-1);
00312                 scalelist[k] = scale;
00313                 ntot = 0;
00314             
00315                 /* Do a scaled subtraction of the fringe from the data */
00316 
00317                 for (j = 0; j < npts; j++) {
00318                     if (bpm[j] == 0) {
00319                         diff = fabs(data[j] - scale*frdata[j]);
00320                         if (diff < clip)
00321                             wptr[ntot++] = diff;
00322                     }
00323                 }
00324 
00325                 /* Find the MAD */
00326 
00327                 spreadlist[k] = vircam_med(wptr,NULL,ntot);
00328                 if (spreadlist[k] < spreadf) {
00329                     spreadf = spreadlist[k]; 
00330                     scalefound = scale;
00331                 }
00332             }
00333 
00334             /* Right, how have we done on this iteration? If the spread
00335                has started to increase then this is the last iteration */
00336 
00337             if (spreadf > spreadfbest) {
00338                 nter = NTERMAX + 1;
00339 
00340             /* Otherwise interpolate to find the best solution */
00341 
00342             } else {
00343                 a = spreadlist[1];
00344                 b = 0.5*(spreadlist[2] - spreadlist[0]);
00345                 c = 0.5*(spreadlist[2] + spreadlist[0] - 2.0*spreadlist[1]);
00346                 offset = max(min((-0.5*b/c),1.0),-1.0);
00347                 spreadmin = a + b*offset + c*offset*offset;
00348                 scalemin = scalelist[1] + offset*gap;
00349                 
00350                 /* Make sure we're not going for a maximum instead of
00351                    a minimum */
00352 
00353                 if (spreadmin > spreadf) {
00354                     spreadmin = spreadf;
00355                     scalemin = scalefound;
00356                 }
00357             }
00358           
00359             /* Define the best spread found so far */
00360 
00361             spreadfbest = min(spreadfbest,spreadf);
00362 
00363         } /* End of iteration loop */
00364 
00365         /* Trap for no refinement */
00366 
00367         if (iter == 0)
00368             scalemin = scaleth;
00369             
00370         /* Subtract the fringe frame now with the defined scale factor */
00371 
00372         for (j = 0; j < npts; j++) 
00373             imdata[j] -= scalemin*(frorig[j] - frmed);
00374         scaleout[i] = scalemin;
00375 
00376         /* Tidy */
00377 
00378         freeimage(imfit);
00379         freeimage(imback);
00380     }
00381 
00382     /* Do a bit more tidying */
00383 
00384     freeimage(fringefit);
00385     freeimage(frback);
00386     freespace(wptr);
00387     GOOD_STATUS
00388 }
00389 
00392 /*
00393 
00394 $Log: vircam_defringe.c,v $
00395 Revision 1.6  2007/10/25 17:34:00  jim
00396 Modified to remove lint warnings
00397 
00398 Revision 1.5  2007/03/29 12:19:39  jim
00399 Little changes to improve documentation
00400 
00401 Revision 1.4  2007/03/01 12:42:41  jim
00402 Modified slightly after code checking
00403 
00404 Revision 1.3  2006/12/06 13:03:25  jim
00405 Oops, left some diagnostic prints in...
00406 
00407 Revision 1.2  2006/12/06 12:59:14  jim
00408 Fixed a small bug in defringe_1
00409 
00410 Revision 1.1  2006/12/01 14:09:40  jim
00411 Initial entry (not yet debugged)
00412 
00413 
00414 */

Generated on Wed Apr 10 04:01:55 2013 for VIRCAM Pipeline by  doxygen 1.5.1