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