VIRCAM Pipeline  1.3.3
imcore_radii.c
1 /* $Id: imcore_radii.c,v 1.8 2013-10-15 16:22:30 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: 2013-10-15 16:22:30 $
24  * $Revision: 1.8 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #include <stdio.h>
29 #include <math.h>
30 
31 #include "imcore.h"
32 #include "imcore_radii.h"
33 #include "floatmath.h"
34 #include "util.h"
35 #include "ap.h"
36 
37 static float fraction (float x, float y, float r_out);
38 
41 /*---------------------------------------------------------------------------*/
74 /*---------------------------------------------------------------------------*/
75 
76 extern float imcore_halflight(float rcores[], float cflux[], float halflight,
77  float peak, int naper) {
78  float delr,halfrad;
79  int i,gotone;
80 
81  /* Work out the half-light value from either isophotal flux or the
82  flux at Rcore. The find out roughly where the curve of growth
83  exceeds this */
84 
85  gotone = 0;
86  for (i = 0; i < naper; i++) {
87  if (cflux[i] > halflight) {
88  gotone = 1;
89  break;
90  }
91  }
92  if (! gotone)
93  i = naper - 1;
94 
95  /* Now work out what the radius of half light is */
96 
97  if (i == 0) {
98  delr = (cflux[i] - halflight)/MAX(1.0,cflux[i]-peak);
99  halfrad = rcores[0]*(1.0 - delr) + delr*sqrt(1.0/M_PI);
100  } else {
101  delr = (cflux[i] - halflight)/MAX(1.0,(cflux[i] - cflux[i-1]));
102  halfrad = rcores[i-1]*delr + rcores[i]*(1.0-delr);
103  }
104  return(halfrad);
105 }
106 
107 /*---------------------------------------------------------------------------*/
140 /*---------------------------------------------------------------------------*/
141 
142 extern float imcore_exprad(float thresh, float peak, float areal0,
143  float rcores[], int naper) {
144  float pk,r_t,rad;
145 
146  /* Work out the radius... */
147 
148  pk = MAX(1.5*thresh,peak);
149  r_t = sqrtf(areal0/CPL_MATH_PI);
150  rad = 5.0*r_t/logf(pk/thresh);
151  rad = MAX(r_t,MIN(5.0*r_t,MIN(rad,rcores[naper-1])));
152  return(rad);
153 }
154 
155 /*---------------------------------------------------------------------------*/
186 /*---------------------------------------------------------------------------*/
187 
188 extern float imcore_kronrad(float areal0, float rcores[], float cflux[],
189  int naper) {
190  int i,imax;
191  float r_t,rad,wt,sum;
192 
193  /* Work out the radius... */
194 
195  r_t = sqrtf(areal0/CPL_MATH_PI);
196  rad = 0.5*rcores[0]*cflux[0];
197  sum = cflux[0];
198  imax = MIN(naper,7);
199  for (i = 1; i < imax; i++) {
200  wt = MAX(0.0,cflux[i]-cflux[i-1]);
201  rad += 0.5*(rcores[i] + rcores[i-1])*wt;
202  sum += wt;
203  }
204  rad /= sum;
205  rad = MAX(r_t,MIN(5.0*r_t,MIN(2.0*rad,rcores[naper-1])));
206  return(rad);
207 }
208 
209 /*---------------------------------------------------------------------------*/
240 /*---------------------------------------------------------------------------*/
241 
242 extern float imcore_petrad (float areal0, float rcores[], float cflux[],
243  int naper) {
244  int j;
245  float eta,r_t,etaold,r1,r2,r3,r4,r5,r_petr;
246 
247  /* Work out petrosian radius */
248 
249  r_t = sqrtf(areal0/CPL_MATH_PI);
250  eta = 1.0;
251  etaold = eta;
252  j = 1;
253  while (eta > 0.2 && j < naper) {
254  etaold = eta;
255  r1 = rcores[j]*rcores[j]/(rcores[j-1]*rcores[j-1]) - 1.0;
256  r2 = cflux[j]/cflux[j-1] - 1.0;
257  eta = r2/r1;
258  j++;
259  }
260  if (j == naper) {
261  r_petr = rcores[naper-1];
262  } else {
263  r1 = rcores[j]*rcores[j];
264  r2 = rcores[j-1]*rcores[j-1];
265  r3 = rcores[j-2]*rcores[j-2];
266  r4 = (etaold - 0.2)/(etaold - eta);
267  r5 = (0.2 - eta)/(etaold - eta);
268  r_petr = r4*sqrt(0.5*(r1 + r2)) + r5*sqrt(0.5*(r2 + r3));
269  }
270  r_petr = MAX(r_t,MIN(5.0*r_t,MIN(2.0*r_petr,rcores[naper-1])));
271  return(r_petr);
272 }
273 
274 /*---------------------------------------------------------------------------*/
314 /*---------------------------------------------------------------------------*/
315 
316 void imcore_flux(ap_t *ap, float parm[IMNUM][NPAR], int nbit, float apers[],
317  float fluxes[], int nr, float rcores[], float rfluxes[]) {
318  float *map,t,xj,yj,sumiso,sumcf,delr;
319  unsigned char *mflag,mf;
320  long nx,ny;
321  int xmin,xmax,ymin,ymax,ix1,ix2,iy1,iy2,i,j,kk,n;
322 
323  /* Set up some local variables */
324 
325  map = ap->indata;
326  mflag = ap->mflag;
327  nx = ap->lsiz;
328  ny = ap->csiz;
329 
330  /* Section for nbit == 1 */
331 
332  if (nbit == 1) {
333 
334  /* Generate image-blend outer boundaries */
335 
336  xmin = parm[0][1] - apers[0] - 0.5;
337  xmax = parm[0][1] + apers[0] + 0.5;
338  ymin = parm[0][2] - apers[0] - 0.5;
339  ymax = parm[0][2] + apers[0] + 0.5;
340  ix1 = MAX(0,(int)xmin-1);
341  ix2 = MIN(nx-1,(int)xmax);
342  iy1 = MAX(0,(int)ymin-1);
343  iy2 = MIN(ny-1,(int)ymax);
344 
345  /* Now go through pixel region and add up the contributions inside
346  the aperture */
347 
348  fluxes[0] = 0.0;
349  for(j = iy1; j <= iy2; j++) {
350  kk = j*nx;
351  for(i = ix1; i <= ix2; i++) {
352  mf = mflag[kk+i];
353  if (mf == MF_CLEANPIX || mf == MF_OBJPIX ||
354  mf == MF_SATURATED) {
355  t = map[kk+i];
356  xj = (float)i - parm[0][1] + 1.0;
357  yj = (float)j - parm[0][2] + 1.0;
358  fluxes[0] += fraction(xj,yj,apers[0])*t;
359  }
360  }
361  }
362  if (fluxes[0] <= 0)
363  fluxes[0] = parm[0][0];
364 
365  /* Section for blended images */
366 
367  } else {
368 
369  /* Interpolate circular aperture fluxes */
370 
371  sumiso = 0.0;
372  sumcf = 0.0;
373  for (j = 0; j < nbit; j++) {
374  sumiso += parm[j][0];
375  n = 1;
376  while (rcores[n] < apers[j] && n < nr-1)
377  n++;
378  delr = (rcores[n] - apers[j])/(rcores[n] - rcores[n-1]);
379  fluxes[j] = rfluxes[j*nr+n]*(1.0 - delr) + rfluxes[j*nr+n-1]*delr;
380  sumcf += fluxes[j];
381  }
382 
383  /* Constrain the result so that the ratios are the same as for the
384  isophotal fluxes */
385 
386  for (j = 0; j < nbit; j++) {
387  fluxes[j] = sumcf*parm[j][0]/MAX(1.0,sumiso);
388  if (fluxes[j] < 0.0)
389  fluxes[j] = parm[j][0];
390  }
391  }
392 }
393 
396 /* returns fraction of pixel bounded by 0 - r_out
397  * x,y coordinates relative to centre
398  * Uses linear approximation ok if pixel located >>1 away from centre */
399 
400 static float fraction (float x, float y, float r_out) {
401  float r,t,x_a,x_b,frac,tanao2,cosa,tanp2a,sqrt2o2;
402 
403  r = sqrtf(x*x + y*y);
404  sqrt2o2 = 0.5*CPL_MATH_SQRT2;
405 
406  /* is it worth bothering? */
407 
408  if(r > r_out+sqrt2o2)
409  return(0.0);
410 
411  /* is it trivially all in? */
412 
413  if(r < r_out-sqrt2o2)
414  return(1.0);
415 
416  /* bugger - have to do some work then ... ok first ...
417  * use 8-fold symmetry to convert to 0-45 degree range */
418 
419  x = fabsf(x);
420  y = fabsf(y);
421  if(y > x) {
422  t = x;
423  x = y;
424  y = t;
425  }
426 
427  /* If the angles are too close to cardinal points, then fudge something */
428 
429  if (x > 0.0 && y > 0.0) {
430  tanao2 = 0.5*y/x;
431  tanp2a = x/y;
432  cosa = x/sqrt(x*x + y*y);
433  } else {
434  tanao2 = 0.00005;
435  tanp2a = 10000.0;
436  cosa = 1.0;
437  }
438 
439  /* only outer radius - compute linear intersections top and bot of pixel */
440 
441  x_a = x - tanao2 + (r_out - r)/cosa;
442  if(x_a < x+0.5) {
443 
444  /* intersects */
445 
446  x_b = x + tanao2 + (r_out - r)/cosa;
447 
448  /* three cases to consider */
449 
450  if(x_a < x-0.5)
451  frac = 0.5*MAX(0.0,x_b-(x-0.5))*MAX(0.0,x_b-(x-0.5))*tanp2a;
452  else {
453  if(x_b > x+0.5)
454  frac = 1.0 - 0.5*(x+0.5-x_a)*(x+0.5-x_a)*tanp2a;
455  else
456  frac = 0.5-(x-x_a)+0.5*(x_b-x_a);
457  }
458  } else /* missed entirely */
459  frac = 1.0;
460 
461  return(frac);
462 }
463 
464 /*
465 
466 $Log: not supported by cvs2svn $
467 Revision 1.7 2010/09/09 12:09:57 jim
468 Added docs
469 
470 Revision 1.6 2009/09/09 09:42:25 jim
471 modified to use CPL defined macros for constants
472 
473 Revision 1.5 2009/02/20 10:49:58 jim
474 Removed superfluous declarations
475 
476 Revision 1.4 2009/01/30 08:27:02 jim
477 New version of imcore_flux and updated radius estimates
478 
479 Revision 1.3 2009/01/23 12:24:33 jim
480 Fixed bugs in pixel flagging
481 
482 Revision 1.2 2008/10/24 10:59:17 jim
483 Modified flux calculation so that inverse trig functions get sensible input
484 
485 Revision 1.1 2005/09/13 13:25:30 jim
486 Initial entry after modifications to make cpl compliant
487 
488 
489 */