/*
* growth.c
*
* Manage growth curves.
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*
* This file part of: SExtractor
*
* Copyright: (C) 1998-2010 IAP/CNRS/UPMC
* (C) 1997 ESO
* (C) 1995,1996 Sterrewacht Leiden
*
* Author: Emmanuel Bertin (IAP)
*
* License: GNU General Public License
*
* SExtractor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* SExtractor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with SExtractor. If not, see .
*
* Last modified: 11/10/2010
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include
#include
#include "define.h"
#include "globals.h"
#include "prefs.h"
#include "growth.h"
/*------------------------------- variables ---------------------------------*/
static double *growth;
static int ngrowth;
static obj2struct *obj2 = &outobj2;
/******************************** initgrowth *********************************/
/*
Allocate memory for growth curve stuff.
*/
void initgrowth()
{
QMALLOC(growth, double, GROWTH_NSTEP);
/* Quick (and dirty) fix to allow FLUX_RADIUS support */
if (FLAG(obj2.flux_radius) && !prefs.flux_radiussize)
{
QCALLOC(obj2->flux_radius, float, 1);
}
return;
}
/******************************** endgrowth **********************************/
/*
Free memory occupied by growth curve stuff.
*/
void endgrowth()
{
free(growth);
if (FLAG(obj2.flux_radius) && !prefs.flux_radiussize)
free(obj2->flux_radius);
return;
}
/****************************** makeavergrowth *******************************/
/*
Build growth curve based on averages.
*/
void makeavergrowth(picstruct *field, picstruct *wfield, objstruct *obj)
{
float *fgrowth;
double *growtht,
dx,dx1,dy,dy2,mx,my, r2,r,rlim, d, rextlim2, raper,
offsetx,offsety,scalex,scaley,scale2, ngamma, locarea,
tv, sigtv, area, pix, var, gain, dpos,step,step2, dg,
stepdens, backnoise2, prevbinmargin, nextbinmargin;
int i,j,n, x,y, x2,y2, xmin,xmax,ymin,ymax, sx,sy, w,h,
fymin,fymax, pflag,corrflag, ipos;
LONG pos;
PIXTYPE *strip,*stript, *wstrip,*wstript,
pdbkg, wthresh;
if (wfield)
wthresh = wfield->weight_thresh;
else
wthresh = 0.0; /* To avoid gcc -Wall warnings */
/* Clear the growth-curve buffer */
memset(growth, 0, (size_t)(GROWTH_NSTEP*sizeof(double)));
mx = obj->mx;
my = obj->my;
w = field->width;
h = field->stripheight;
fymin = field->ymin;
fymax = field->ymax;
pflag = (prefs.detect_type==PHOTO)? 1:0;
corrflag = (prefs.mask_type==MASK_CORRECT);
var = backnoise2 = field->backsig*field->backsig;
gain = field->gain;
/* Integration radius */
rlim = GROWTH_NSIG*obj->a;
if (rlimGROWTH_OVERSAMP*/)
{
ngrowth = (int)(rlim*GROWTH_OVERSAMP);
stepdens = ngrowth/rlim;
}
else
ngrowth = GROWTH_NSTEP;
step = 1/stepdens;
/* Critical distances (in pixels) from bin boundaries */
prevbinmargin = 0.75; /* > 1/sqrt(2) */
nextbinmargin = step - 0.75; /* ngamma;
pdbkg = exp(obj->dbkg/ngamma);
}
else
{
ngamma = 0.0;
pdbkg = 0.0;
}
tv = sigtv = area = 0.0;
scaley = scalex = 1.0/GROWTH_OVERSAMP;
scale2 = scalex*scaley;
offsetx = 0.5*(scalex-1.0);
offsety = 0.5*(scaley-1.0);
xmin = (int)(mx-raper+0.499999);
xmax = (int)(mx+raper+1.499999);
ymin = (int)(my-raper+0.499999);
ymax = (int)(my+raper+1.499999);
if (xmin < 0)
{
xmin = 0;
obj->flag |= OBJ_APERT_PB;
}
if (xmax > w)
{
xmax = w;
obj->flag |= OBJ_APERT_PB;
}
if (ymin < fymin)
{
ymin = fymin;
obj->flag |= OBJ_APERT_PB;
}
if (ymax > fymax)
{
ymax = fymax;
obj->flag |= OBJ_APERT_PB;
}
strip = field->strip;
wstrip = wstript = NULL; /* To avoid gcc -Wall warnings */
if (wfield)
wstrip = wfield->strip;
for (y=ymin; y=wthresh))
{
if (corrflag
&& (x2=(int)(2*mx+0.49999-x))>=0 && x2=fymin && y2-BIG)
{
if (wfield)
{
var = *(wstrip + pos);
if (var>=wthresh)
pix = var = 0.0;
}
}
else
{
pix = 0.0;
if (wfield)
var = 0.0;
}
}
if (pflag)
pix = exp(pix/ngamma) - pdbkg;
/*------ Check if oversampling is needed (close enough to a bin boundary) */
d = fmod(r=sqrt(r2),step);
if (dnextbinmargin)
{
dx += offsetx;
dy += offsety;
locarea = 0.0;
for (sy=GROWTH_OVERSAMP; sy--; dy+=scaley)
{
dx1 = dx;
dy2 = dy*dy;
for (sx=GROWTH_OVERSAMP; sx--; dx1+=scalex)
{
j = (int)(sqrt(dx1*dx1+dy2)*stepdens);
if (j0.0 && gain>0.0)
sigtv += pix/gain*var/backnoise2;
*/
}
}
}
/*
if (pflag)
{
tv = ngamma*(tv-area*exp(obj->dbkg/ngamma));
sigtv /= ngamma*ngamma;
}
else
{
tv -= area*obj->dbkg;
if (!wfield && gain > 0.0 && tv>0.0)
sigtv += tv/gain;
}
*/
/* Integrate the growth curve */
pix = 0.0;
growtht = growth;
for (i=ngrowth; i--;)
{
*growtht += pix;
pix = *(growtht++);
}
/* Now let's remap the growth-curve to match user's choice */
if (FLAG(obj2.flux_growth))
{
n = prefs.flux_growthsize;
if (FLAG(obj2.flux_growthstep))
obj2->flux_growthstep = rlim/n;
fgrowth = obj2->flux_growth;
step2 = (double)GROWTH_NSTEP/n;
j = 1;
for (i=n; i--; j++)
{
ipos = (int)(dpos=step2*j-0.99999);
if (dpos<0.0)
*(fgrowth++) = (float)(*growth*(0.99999+dpos));
else
{
growtht = growth + ipos;
*(fgrowth++) = (float)(*growtht+(*(growtht+1)-*growtht)*(dpos-ipos));
}
}
}
if (FLAG(obj2.mag_growth))
{
n = prefs.mag_growthsize;
if (FLAG(obj2.mag_growthstep))
obj2->mag_growthstep = rlim/n;
fgrowth = obj2->mag_growth;
step2 = (double)GROWTH_NSTEP/n;
j = 1;
for (i=n; i--; j++)
{
ipos = (int)(dpos=step2*j-0.99999);
if (dpos<0.0)
pix = *growth*(0.99999+dpos);
else
{
growtht = growth + ipos;
pix = *growtht+(*(growtht+1)-*growtht)*(dpos-ipos);
}
*(fgrowth++) = pix>0.0?(prefs.mag_zeropoint-2.5*log10(pix)):99.0;
}
}
if (FLAG(obj2.flux_radius))
{
n = ngrowth-1;
for (j=0; jflux_auto;
growtht = growth-1;
for (i=0; iflux_radius[j] = step
*(i? ((dg=*growtht - *(growtht-1)) != 0.0 ?
i + (tv - *(growtht-1))/dg
: i)
: (*growth !=0.0 ?tv/(*growth) : 0.0));
if (obj2->flux_radius[j] > rlim)
obj2->flux_radius[j] = rlim;
}
}
/* Specific to Half-light radius used by other parameters */
if (FLAG(obj2.hl_radius))
{
n = ngrowth-1;
tv = 0.5*obj2->flux_auto;
growtht = growth-1;
for (i=0; ihl_radius = fabs(step*(i? ((dg=*growtht - *(growtht-1)) != 0.0 ?
i + (tv - *(growtht-1))/dg
: i)
: (*growth !=0.0 ?tv/(*growth) : 0.0)));
if (obj2->hl_radius > rlim)
obj2->hl_radius = rlim;
if (obj2->hl_radius < GROWTH_MINHLRAD)
obj2->hl_radius = GROWTH_MINHLRAD;
}
return;
}