VIRCAM Pipeline  1.3.4
vircam/vircam_defringe.c
1 /* $Id: vircam_defringe.c,v 1.7 2012-01-27 12:25:10 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: jim $
23  * $Date: 2012-01-27 12:25:10 $
24  * $Revision: 1.7 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 /* Includes */
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <math.h>
35 #include <cpl.h>
36 #include "vircam_mods.h"
37 #include "vircam_utils.h"
38 #include "vircam_fits.h"
39 #include "vircam_stats.h"
40 
41 #define NTERMAX 15
42 #define ITERMAX 7
43 #define OGAP 0.01
44 #define GAPMIN 0.25
45 #define CLIPLEV 4.0
46 
47 static int vircam_defringe_1(vir_fits **infiles, int nimages, vir_fits *fringe,
48  vir_mask *mask, int nbsize, float *scaleout,
49  int *status);
50 
53 /*---------------------------------------------------------------------------*/
105 /*---------------------------------------------------------------------------*/
106 
107 extern int vircam_defringe(vir_fits **infiles, int nimages, vir_fits **fringes,
108  int nfringes, vir_mask *mask, int nbsize,
109  int *status) {
110  float *sig_before,*scale,*idata,med,mad,ratio;
111  unsigned char *bpm;
112  int i,j,npts;
113  char pname1[64],comment1[64],pname2[64],comment2[64];
114  cpl_propertylist *ehu;
115 
116  /* Inherited status */
117 
118  if (*status != VIR_OK)
119  return(*status);
120 
121  /* Get some workspace to use for working out the background sigmas */
122 
123  sig_before = cpl_malloc(nimages*sizeof(float));
124  scale = cpl_malloc(nimages*sizeof(float));
125 
126  /* Now work out the background sigma of each image */
127 
128  bpm = vircam_mask_get_data(mask);
129  npts = (int)cpl_image_get_size_x(vircam_fits_get_image(infiles[0]))*
130  (int)cpl_image_get_size_y(vircam_fits_get_image(infiles[0]));
131  for (i = 0; i < nimages; i++) {
132  idata = cpl_image_get_data_float(vircam_fits_get_image(infiles[i]));
133  vircam_medmad(idata,bpm,(long)npts,&med,&mad);
134  sig_before[i] = 1.48*mad;
135  }
136 
137  /* Now do the defringing */
138 
139  for (i = 0; i < nfringes; i++) {
140  (void)vircam_defringe_1(infiles,nimages,fringes[i],mask,nbsize,scale,
141  status);
142 
143  /* Create scale factor and fringe name information for headers */
144 
145  (void)sprintf(pname1,"ESO DRS FRINGE%d",i);
146  (void)sprintf(comment1,"Fringe frame # %d",i);
147  (void)sprintf(pname2,"ESO DRS FRNGSC%d",i);
148  (void)sprintf(comment2,"Fringe scale # %d",i);
149 
150  /* Now loop for each image and write these to the headers */
151 
152  for (j = 0; j < nimages; j++) {
153  ehu = vircam_fits_get_ehu(infiles[j]);
154  cpl_propertylist_update_string(ehu,pname1,
155  vircam_fits_get_fullname(fringes[i]));
156  cpl_propertylist_set_comment(ehu,pname1,comment1);
157  cpl_propertylist_update_float(ehu,pname2,scale[i]);
158  cpl_propertylist_set_comment(ehu,pname2,comment2);
159  }
160  }
161 
162  /* Now work out the final background sigma and add the ratio of the
163  before to after to the QC header of each image */
164 
165  for (i = 0; i < nimages; i++) {
166  ehu = vircam_fits_get_ehu(infiles[i]);
167  idata = cpl_image_get_data_float(vircam_fits_get_image(infiles[i]));
168  vircam_medmad(idata,bpm,(long)npts,&med,&mad);
169  ratio = sig_before[i]/(1.48*mad);
170  cpl_propertylist_update_float(ehu,"ESO QC FRINGE_RATIO",ratio);
171  cpl_propertylist_set_comment(ehu,"ESO QC FRINGE_RATIO",
172  "Ratio RMS before to after defringing");
173  }
174  freespace(sig_before);
175  freespace(scale);
176  GOOD_STATUS
177 }
178 
179 /*---------------------------------------------------------------------------*/
210 /*---------------------------------------------------------------------------*/
211 
212 static int vircam_defringe_1(vir_fits **infiles, int nimages, vir_fits *fringe,
213  vir_mask *mask, int nbsize, float *scaleout,
214  int *status) {
215  cpl_image *frback,*imback,*fringefit,*imfit;
216  float frmed,immed,*frdata,*frorig,*wptr,*imdata,*data,scaleth,scalemin;
217  float scaleprev,spreadmin,spreadfbest,gap,offset,clipmax,clip,spreadf;
218  float scalefound,scale,scalelist[3],diff,spreadlist[3],a,b,c;
219  long npts,ntot;
220  int i,iter,nter,k,j;
221  vir_fits *im;
222  unsigned char *bpm;
223 
224  /* Inherited status */
225 
226  if (*status != VIR_OK)
227  return(*status);
228 
229  /* Prepare the fringe frame by creating a background mask */
230 
231  vircam_backmap(fringe,mask,nbsize,&frback,&frmed);
232 
233  /* Create a fringe frame image that is background corrected and normalised
234  to zero median */
235 
236  fringefit = cpl_image_subtract_create(vircam_fits_get_image(fringe),
237  frback);
238  cpl_image_subtract_scalar(fringefit,frmed);
239  frdata = cpl_image_get_data_float(fringefit);
240  npts = (long)cpl_image_get_size_x(fringefit)*(long)cpl_image_get_size_y(fringefit);
241  frorig = cpl_image_get_data_float(vircam_fits_get_image(fringe));
242 
243  /* Get some workspace */
244 
245  wptr = cpl_malloc(npts*sizeof(float));
246 
247  /* Get BPM */
248 
249  bpm = vircam_mask_get_data(mask);
250 
251  /* Now loop for each of the input images */
252 
253  for (i = 0; i < nimages; i++) {
254  im = infiles[i];
255 
256  /* Create a background map and correct for it */
257 
258  vircam_backmap(im,mask,nbsize,&imback,&immed);
259  imdata = cpl_image_get_data_float(vircam_fits_get_image(im));
260  imfit = cpl_image_subtract_create(vircam_fits_get_image(im),imback);
261  cpl_image_subtract_scalar(imfit,immed);
262  data = cpl_image_get_data_float(imfit);
263 
264  /* The overall medians are used as a first guess of the scaling
265  between the two images */
266 
267  scaleth = immed/frmed;
268 
269  /* Set up some values for tracking the goodness of fit */
270 
271  scalemin = 0.0;
272  scaleprev = 1.0e6;
273  spreadmin = 1.0e3;
274  spreadfbest = 1.0e6;
275  iter = 0;
276  nter = 0;
277  gap = scaleth;
278  offset = 0.5;
279  clipmax = 1.0e3;
280 
281  /* Begin the iteration loop */
282 
283  while (nter < NTERMAX && iter < ITERMAX && (fabs(offset)*gap > OGAP ||
284  gap > GAPMIN)) {
285  iter++;
286  nter++;
287 
288  /* Clip levels */
289 
290  clip = min(clipmax,CLIPLEV*1.48*spreadmin);
291 
292  /* Speed up convergence if sitting on top of a solution.
293  Slow it down if outside range */
294 
295  if (fabs(scalemin - scaleprev) < 0.5*gap)
296  iter += 1;
297  scaleprev = scalemin;
298  if (fabs(offset) > 0.9)
299  iter -= 1;
300  gap = scaleth*pow(2.0,(double)(1-iter));
301 
302  /* Initialise a few things */
303 
304  spreadf = 1.0e6;
305  scalefound = 2.0;
306 
307  /* Do three calculations -- just below, at and just above
308  the current best guess scale factor */
309 
310  for (k = 0; k < 3; k++) {
311  scale = scalemin + gap*(float)(k-1);
312  scalelist[k] = scale;
313  ntot = 0;
314 
315  /* Do a scaled subtraction of the fringe from the data */
316 
317  for (j = 0; j < npts; j++) {
318  if (bpm[j] == 0) {
319  diff = fabs(data[j] - scale*frdata[j]);
320  if (diff < clip)
321  wptr[ntot++] = diff;
322  }
323  }
324 
325  /* Find the MAD */
326 
327  spreadlist[k] = vircam_med(wptr,NULL,ntot);
328  if (spreadlist[k] < spreadf) {
329  spreadf = spreadlist[k];
330  scalefound = scale;
331  }
332  }
333 
334  /* Right, how have we done on this iteration? If the spread
335  has started to increase then this is the last iteration */
336 
337  if (spreadf > spreadfbest) {
338  nter = NTERMAX + 1;
339 
340  /* Otherwise interpolate to find the best solution */
341 
342  } else {
343  a = spreadlist[1];
344  b = 0.5*(spreadlist[2] - spreadlist[0]);
345  c = 0.5*(spreadlist[2] + spreadlist[0] - 2.0*spreadlist[1]);
346  offset = max(min((-0.5*b/c),1.0),-1.0);
347  spreadmin = a + b*offset + c*offset*offset;
348  scalemin = scalelist[1] + offset*gap;
349 
350  /* Make sure we're not going for a maximum instead of
351  a minimum */
352 
353  if (spreadmin > spreadf) {
354  spreadmin = spreadf;
355  scalemin = scalefound;
356  }
357  }
358 
359  /* Define the best spread found so far */
360 
361  spreadfbest = min(spreadfbest,spreadf);
362 
363  } /* End of iteration loop */
364 
365  /* Trap for no refinement */
366 
367  if (iter == 0)
368  scalemin = scaleth;
369 
370  /* Subtract the fringe frame now with the defined scale factor */
371 
372  for (j = 0; j < npts; j++)
373  imdata[j] -= scalemin*(frorig[j] - frmed);
374  scaleout[i] = scalemin;
375 
376  /* Tidy */
377 
378  freeimage(imfit);
379  freeimage(imback);
380  }
381 
382  /* Do a bit more tidying */
383 
384  freeimage(fringefit);
385  freeimage(frback);
386  freespace(wptr);
387  GOOD_STATUS
388 }
389 
392 /*
393 
394 $Log: not supported by cvs2svn $
395 Revision 1.6 2007/10/25 17:34:00 jim
396 Modified to remove lint warnings
397 
398 Revision 1.5 2007/03/29 12:19:39 jim
399 Little changes to improve documentation
400 
401 Revision 1.4 2007/03/01 12:42:41 jim
402 Modified slightly after code checking
403 
404 Revision 1.3 2006/12/06 13:03:25 jim
405 Oops, left some diagnostic prints in...
406 
407 Revision 1.2 2006/12/06 12:59:14 jim
408 Fixed a small bug in defringe_1
409 
410 Revision 1.1 2006/12/01 14:09:40 jim
411 Initial entry (not yet debugged)
412 
413 
414 */
int vircam_defringe(vir_fits **infiles, int nimages, vir_fits **fringes, int nfringes, vir_mask *mask, int nbsize, int *status)
Correct input data to remove fringes.
char * vircam_fits_get_fullname(vir_fits *p)
Definition: vircam_fits.c:560
unsigned char * vircam_mask_get_data(vir_mask *m)
Definition: vircam_mask.c:535
cpl_image * vircam_fits_get_image(vir_fits *p)
Definition: vircam_fits.c:349
void vircam_medmad(float *data, unsigned char *bpm, long np, float *med, float *mad)
Definition: vircam_stats.c:625
float vircam_med(float *data, unsigned char *bpm, long npts)
Definition: vircam_stats.c:89
void vircam_backmap(vir_fits *in, vir_mask *mask, int nbsize, cpl_image **out, float *med)
cpl_propertylist * vircam_fits_get_ehu(vir_fits *p)
Definition: vircam_fits.c:457