VIRCAM Pipeline  1.3.3
imcore_phopt.c
1 /* $Id: imcore_phopt.c,v 1.6 2010-09-09 12:09:57 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: 2010-09-09 12:09:57 $
24  * $Revision: 1.6 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <math.h>
31 
32 #include <cpl.h>
33 
34 #include "floatmath.h"
35 #include "util.h"
36 #include "imcore.h"
37 #include "ap.h"
38 
39 /* Function Prototypes */
40 
41 static void dchole (double a[IMNUM+1][IMNUM+1], double b[IMNUM+1], int n);
42 static float fraction (float x, float y, float r_out);
43 
44 /* does multiple profile fitting to determine intensities */
45 
48 /*---------------------------------------------------------------------------*/
89 /*---------------------------------------------------------------------------*/
90 
91 extern void phopt(ap_t *ap, float parm[IMNUM][NPAR], int nbit, int naper,
92  float apertures[], float cflux[], float badpix[],
93  int nrcore) {
94  double aa[IMNUM+1][IMNUM+1],bb[IMNUM+1];
95  float d,arg,*map,rcirc;
96  float cn,parrad,xmin,xmax,xi,yi,ymin,ymax;
97  float t,xj,yj,cnsq,tj,xk,yk,tk;
98  int i,ii,j,kk,ix1,ix2,iy1,iy2,nx,ny,k,iaper;
99  unsigned char *mflag,mf;
100 
101  /* Set up some local variables */
102 
103  map = ap->indata;
104  mflag = ap->mflag;
105  nx = ap->lsiz;
106  ny = ap->csiz;
107 
108  /* Loop for each of the apertures */
109 
110  for (iaper = 0; iaper < naper; iaper++) {
111  rcirc = apertures[iaper];
112  parrad = rcirc + 0.5;
113  cn = 1.0/(CPL_MATH_PI*rcirc*rcirc); /* profile normalising constant */
114  cnsq = cn*cn;
115 
116  /* set up covariance matrix - analytic special case for cores */
117 
118  for(i = 0; i < nbit; i++) {
119  aa[i][i] = cn; /* overlaps totally area=pi*r**2 */
120  if(nbit > 1) {
121  xi = parm[i][1];
122  yi = parm[i][2];
123  for(j = i+1; j < nbit; j++) {
124  d = sqrtf((xi-parm[j][1])*(xi-parm[j][1])
125  + (yi-parm[j][2])*(yi-parm[j][2]));
126  if(d >= 2.0*rcirc) {
127  aa[j][i] = 0.0;
128  aa[i][j] = aa[j][i];
129  } else {
130  arg = d/(2.0*rcirc);
131  aa[j][i] = cnsq*2.0*rcirc*rcirc*
132  (acosf(arg)-arg*(sqrtf(1.0-arg*arg)));
133  aa[i][j] = aa[j][i];
134  }
135  }
136  }
137  }
138 
139  /* clear accumulators */
140 
141  for(i = 0; i < nbit; i++)
142  bb[i] = 0.0;
143 
144  /* generate image-blend outer boundaries */
145 
146  xmin = 1.0e6;
147  xmax = -1.0e6;
148  ymin = 1.0e6;
149  ymax = -1.0e6;
150  for(i = 0; i < nbit; i++) {
151  xi = parm[i][1];
152  yi = parm[i][2];
153  xmin = MIN(xmin, xi);
154  xmax = MAX(xmax, xi);
155  ymin = MIN(ymin, yi);
156  ymax = MAX(ymax, yi);
157  }
158  ix1 = MAX(0,(int)(xmin-parrad)-1);
159  ix2 = MIN(nx-1,(int)(xmax+parrad));
160  iy1 = MAX(0,(int)(ymin-parrad)-1);
161  iy2 = MIN(ny-1,(int)(ymax+parrad));
162 
163  /* now go through pixel region */
164 
165  for(ii = iy1; ii <= iy2; ii++) {
166  kk = ii*nx;
167  for(i = ix1; i <= ix2; i++) {
168  mf = mflag[kk+i];
169  if (mf == MF_ZEROCONF || mf == MF_STUPID_VALUE) {
170  for (j = 0; j < nbit; j++) {
171  xj = i - parm[j][1] + 1.0;
172  yj = ii - parm[j][2] + 1.0;
173  tj = fraction(xj,yj,rcirc);
174  aa[j][j] -= tj*tj*cnsq;
175  for (k = j + 1; k < nbit; k++) {
176  xk = i - parm[k][1] + 1.0;
177  yk = ii - parm[k][2] + 1.0;
178  tk = fraction(xk,yk,rcirc);
179  aa[k][j] -= tk*tj*cnsq;
180  aa[j][k] = aa[k][j];
181  }
182  if (iaper == nrcore)
183  badpix[j] += tj;
184  }
185  } else if (mf == MF_CLEANPIX || mf == MF_OBJPIX ||
186  mf == MF_SATURATED) {
187  t = map[kk+i];
188  for(j = 0; j < nbit; j++) {
189  xj = i - parm[j][1] + 1.0;
190  yj = ii - parm[j][2] + 1.0;
191  bb[j] += fraction(xj,yj,rcirc)*t;
192  }
193  }
194  }
195  }
196 
197  /* Trivial solution for single object */
198 
199  if (nbit == 1) {
200  cflux[iaper] = bb[0];
201 
202  /* solve for profile intensities */
203 
204  } else {
205  for (i = 0; i < nbit; i++)
206  aa[i][i] = MAX(aa[i][i],cnsq);
207  dchole(aa,bb,nbit);
208  for(i = 0; i < nbit; i++)
209  cflux[i*naper+iaper] = cn*bb[i];
210  }
211  }
212 }
213 
216 /* CHOLEsky decomposition of +ve definite symmetric matrix to solve Ax = b */
217 
218 static void dchole (double a[IMNUM+1][IMNUM+1], double b[IMNUM+1], int n) {
219  double sum, l[IMNUM+1][IMNUM+1], y[IMNUM+1];
220  double aveigv, offset;
221  int i, j, k;
222 
223 restart:
224  l[0][0] = sqrt(a[0][0]);
225 
226  for(k = 1; k < n; k++) {
227  for(j = 0; j <= k-1; j++) {
228  sum = a[j][k];
229  if(j != 0)
230  for(i = 0; i <= j-1; i++)
231  sum -= l[i][k]*l[i][j];
232  l[j][k] = sum/l[j][j];
233  }
234  sum = a[k][k];
235  for(i = 0; i <= k-1; i++)
236  sum -= l[i][k]*l[i][k];
237  if(sum <= 0.0) {
238 /* fprintf(stderr, "dchole: warning: matrix ill-conditioned\n"); */
239  aveigv = a[0][0];
240  for(i = 1; i < n; i++)
241  aveigv += a[i][i];
242  /* max eigenvalue < trace */
243  offset = 0.1*aveigv/((double) n);
244  for(i = 0; i < n; i++)
245  a[i][i] += offset;
246 /* fprintf(stderr, "dchole: Offset added to diagonal = %f\n", offset); */
247  goto restart;
248  }
249  l[k][k] = sqrt(sum);
250  }
251 
252  /* solve Ly = b */
253 
254  y[0] = b[0]/l[0][0];
255  for(i = 1; i < n; i++) {
256  sum = b[i];
257  for(k = 0; k <= i-1; k++)
258  sum -= l[k][i]*y[k];
259  y[i] = sum/l[i][i];
260  }
261 
262  /* solve L(T)x = y */
263 
264  b[n-1] = y[n-1]/l[n-1][n-1];
265  for(i = n-2; i >= 0; i--) {
266  sum = y[i];
267  for(k = i+1; k < n; k++)
268  sum -= l[i][k]*b[k];
269  b[i] = sum/l[i][i];
270  }
271 }
272 
273 /* returns fraction of pixel bounded by 0 - r_out
274  * x,y coordinates relative to centre
275  * Uses linear approximation ok if pixel located >>1 away from centre */
276 
277 static float fraction (float x, float y, float r_out) {
278  float r,t,x_a,x_b,frac,tanao2,cosa,tanp2a,sqrt2o2;
279 
280  r = sqrtf(x*x + y*y);
281  sqrt2o2 = 0.5*CPL_MATH_SQRT2;
282 
283  /* is it worth bothering? */
284 
285  if(r > r_out+sqrt2o2)
286  return(0.0);
287 
288  /* is it trivially all in? */
289 
290  if(r < r_out-sqrt2o2)
291  return(1.0);
292 
293  /* bugger - have to do some work then ... ok first ...
294  * use 8-fold symmetry to convert to 0-45 degree range */
295 
296  x = fabsf(x);
297  y = fabsf(y);
298  if(y > x) {
299  t = x;
300  x = y;
301  y = t;
302  }
303 
304  /* If the angles are too close to cardinal points, then fudge something */
305 
306  if (x > 0.0 && y > 0.0) {
307  tanao2 = 0.5*y/x;
308  tanp2a = x/y;
309  cosa = x/sqrt(x*x + y*y);
310  } else {
311  tanao2 = 0.00005;
312  tanp2a = 10000.0;
313  cosa = 1.0;
314  }
315 
316  /* only outer radius - compute linear intersections top and bot of pixel */
317 
318  x_a = x - tanao2 + (r_out - r)/cosa;
319  if(x_a < x+0.5) {
320 
321  /* intersects */
322 
323  x_b = x + tanao2 + (r_out - r)/cosa;
324 
325  /* three cases to consider */
326 
327  if(x_a < x-0.5)
328  frac = 0.5*MAX(0.0,x_b-(x-0.5))*MAX(0.0,x_b-(x-0.5))*tanp2a;
329  else {
330  if(x_b > x+0.5)
331  frac = 1.0 - 0.5*(x+0.5-x_a)*(x+0.5-x_a)*tanp2a;
332  else
333  frac = 0.5-(x-x_a)+0.5*(x_b-x_a);
334  }
335  } else /* missed entirely */
336  frac = 1.0;
337 
338  return(frac);
339 }
340 
341 /*
342 
343 $Log: not supported by cvs2svn $
344 Revision 1.5 2009/09/09 09:42:25 jim
345 modified to use CPL defined macros for constants
346 
347 Revision 1.4 2009/01/23 12:24:33 jim
348 Fixed bugs in pixel flagging
349 
350 Revision 1.3 2009/01/20 09:31:06 jim
351 Fixed problem with pixel flagging
352 
353 Revision 1.2 2008/10/13 08:11:19 jim
354 Fixed pixel masking scheme
355 
356 Revision 1.1 2005/09/13 13:25:29 jim
357 Initial entry after modifications to make cpl compliant
358 
359 
360 */