Newer
Older
Emmanuel Bertin
committed
fittype = PARFIT_LINBOUND;
param = 4.0;
parammin = 3.5;
parammax = 6.0;
break;
case PARAM_OUTRING_WIDTH:
Emmanuel Bertin
committed
fittype = PARFIT_LINBOUND;
param = 0.3;
parammin = 0.0;
parammax = 0.5;
break;
default:
error(EXIT_FAILURE, "*Internal Error*: Unknown profile parameter in ",
"profit_resetparam()");
break;
}
if (parammin!=parammax && (param<=parammin || param>=parammax))
param = (parammin+parammax)/2.0;
Emmanuel Bertin
committed
else if (parammin==0.0 && parammax==0.0)
parammax = 1.0;
Emmanuel Bertin
committed
profit_setparam(profit, paramtype, param, parammin, parammax, fittype);
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
return;
}
/****** profit_resetparams ****************************************************
PROTO void profit_resetparams(profitstruct *profit)
PURPOSE Set the initial, lower and upper boundary values of profile parameters.
INPUT Pointer to the profit structure.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 18/09/2008
***/
void profit_resetparams(profitstruct *profit)
{
int p;
for (p=0; p<PARAM_NPARAM; p++)
profit_resetparam(profit, (paramenum)p);
return;
}
/****** profit_setparam ****************************************************
PROTO void profit_setparam(profitstruct *profit, paramenum paramtype,
Emmanuel Bertin
committed
float param, float parammin, float parammax,
parfitenum parfittype)
PURPOSE Set the actual, lower and upper boundary values of a profile parameter.
INPUT Pointer to the profit structure,
Emmanuel Bertin
committed
parameter index,
actual value,
lower boundary to the parameter,
upper boundary to the parameter,
parameter fitting type.
OUTPUT RETURN_OK if the parameter is registered, RETURN_ERROR otherwise.
AUTHOR E. Bertin (IAP)
Emmanuel Bertin
committed
VERSION 20/05/2011
***/
int profit_setparam(profitstruct *profit, paramenum paramtype,
Emmanuel Bertin
committed
float param, float parammin,float parammax,
parfitenum parfittype)
int index;
/* Check whether the parameter has already be registered */
if ((paramptr=profit->paramlist[(int)paramtype]))
{
index = profit->paramindex[(int)paramtype];
profit->paraminit[index] = param;
profit->parammin[index] = parammin;
profit->parammax[index] = parammax;
Emmanuel Bertin
committed
profit->parfittype[index] = parfittype;
return RETURN_OK;
}
else
return RETURN_ERROR;
}
/****** profit_boundtounbound *************************************************
Emmanuel Bertin
committed
PROTO int profit_boundtounbound(profitstruct *profit,
float *param, double *dparam, int index)
PURPOSE Convert parameters from bounded to unbounded space.
INPUT Pointer to the profit structure,
input array of single precision parameters,
output (incomplete) array of double precision parameters,
parameter selection index (<0 = all parameters)
Emmanuel Bertin
committed
OUTPUT Number of free parameters.
Emmanuel Bertin
committed
VERSION 20/05/2011
Emmanuel Bertin
committed
int profit_boundtounbound(profitstruct *profit,
float *param, double *dparam, int index)
Emmanuel Bertin
committed
double num,den, tparam;
if (index<0)
{
pstart = 0;
np = profit->nparam;
}
else
{
pstart = index;
np = pstart+1;
}
f = 0;
for (p=pstart ; p<np; p++)
Emmanuel Bertin
committed
switch(profit->parfittype[p])
Emmanuel Bertin
committed
case PARFIT_FIXED:
break;
case PARFIT_UNBOUND:
if (profit->parammax[p] > 0.0 || profit->parammax[p] < 0.0)
dparam[f] = param[p-pstart] / profit->parammax[p];
f++;
break;
case PARFIT_LINBOUND:
tparam = param[p-pstart];
num = tparam - profit->parammin[p];
den = profit->parammax[p] - tparam;
dparam[f] = num>1e-50? (den>1e-50? log(num/den): 50.0) : -50.0;
Emmanuel Bertin
committed
f++;
break;
case PARFIT_LOGBOUND:
tparam = log(param[p-pstart]);
num = tparam - log(profit->parammin[p]);
den = log(profit->parammax[p]) - tparam;
dparam[f] = num>1e-50? (den>1e-50? log(num/den): 50.0) : -50.0;
f++;
break;
default:
error(EXIT_FAILURE,
"*Internal Error*: Unknown parameter fitting type in ",
"profit_boundtounbound()");
Emmanuel Bertin
committed
return f;
}
/****** profit_unboundtobound *************************************************
Emmanuel Bertin
committed
PROTO int profit_unboundtobound(profitstruct *profit,
double *dparam, float *param, int index)
PURPOSE Convert parameters from unbounded to bounded space.
INPUT Pointer to the profit structure,
input (incomplete) array of double precision parameters,
output array of single precision parameters.
parameter selection index (<0 = all parameters)
Emmanuel Bertin
committed
OUTPUT Number of free parameters.
Emmanuel Bertin
committed
VERSION 20/05/2011
Emmanuel Bertin
committed
int profit_unboundtobound(profitstruct *profit,
double *dparam, float *param, int index)
if (index<0)
{
pstart = 0;
np = profit->nparam;
}
else
{
pstart = index;
np = pstart+1;
}
f = 0;
for (p=pstart; p<np; p++)
Emmanuel Bertin
committed
switch(profit->parfittype[p])
Emmanuel Bertin
committed
case PARFIT_FIXED:
param[p-pstart] = profit->paraminit[p];
break;
case PARFIT_UNBOUND:
param[p-pstart] = dparam[f]*profit->parammax[p];
f++;
break;
case PARFIT_LINBOUND:
param[p-pstart] = (profit->parammax[p] - profit->parammin[p])
/ (1.0 + exp(-(dparam[f]>50.0? 50.0
: (dparam[f]<-50.0? -50.0: dparam[f]))))
Emmanuel Bertin
committed
+ profit->parammin[p];
f++;
break;
case PARFIT_LOGBOUND:
param[p-pstart] = exp(log(profit->parammax[p]/profit->parammin[p])
/ (1.0 + exp(-(dparam[f]>50.0? 50.0
: (dparam[f]<-50.0? -50.0: dparam[f])))))
*profit->parammin[p];
f++;
break;
default:
error(EXIT_FAILURE,
"*Internal Error*: Unknown parameter fitting type in ",
"profit_unboundtobound()");
Emmanuel Bertin
committed
return f;
}
/****** profit_covarunboundtobound ********************************************
Emmanuel Bertin
committed
PROTO int profit_covarunboundtobound(profitstruct *profit,
double *dcovar, float *covar)
PURPOSE Convert covariance matrix from unbounded to bounded space.
INPUT Pointer to the profit structure,
input (incomplete) matrix of double precision covariances,
output matrix of single precision covariances.
Emmanuel Bertin
committed
OUTPUT Number of parameters that hit a boundary.
Emmanuel Bertin
committed
VERSION 20/05/2011
Emmanuel Bertin
committed
int profit_covarunboundtobound(profitstruct *profit,
double *dcovar, float *covar)
Emmanuel Bertin
committed
double *dxdy,
xmmin,maxmx, maxmmin;
float *x,*xmin,*xmax;
Emmanuel Bertin
committed
parfitenum *fittype;
Emmanuel Bertin
committed
f,f1,f2, p,p1,p2, nfree, nparam, nmin,nmax;
Emmanuel Bertin
committed
fittype = profit->parfittype;
QMALLOC16(dxdy, double, PARAM_NPARAM);
x = profit->paraminit;
xmin = profit->parammin;
xmax = profit->parammax;
Emmanuel Bertin
committed
nmin = nmax = 0;
Emmanuel Bertin
committed
switch(fittype[p])
Emmanuel Bertin
committed
case PARFIT_FIXED:
break;
case PARFIT_UNBOUND:
dxdy[f++] = xmax[p];
Emmanuel Bertin
committed
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
break;
case PARFIT_LINBOUND:
xmmin = x[p] - xmin[p];
maxmx = xmax[p] - x[p];
maxmmin = xmax[p] - xmin[p];
dxdy[f++] = xmmin * maxmx / maxmmin;
if (xmmin<0.001*maxmmin)
nmin++;
else if (maxmx<0.001*maxmmin)
nmax++;
break;
case PARFIT_LOGBOUND:
xmmin = log(x[p]/xmin[p]);
maxmx = log(xmax[p]/x[p]);
maxmmin = log(xmax[p]/xmin[p]);
dxdy[f++] = x[p] * xmmin * maxmx / maxmmin;
if (xmmin<0.001*maxmmin)
nmin++;
else if (maxmx<0.001*maxmmin)
nmax++;
break;
default:
error(EXIT_FAILURE,
"*Internal Error*: Unknown parameter fitting type in ",
"profit_boundtounbound()");
Emmanuel Bertin
committed
nfree = f;
memset(profit->covar, 0, nparam*nparam*sizeof(float));
f2 = 0;
Emmanuel Bertin
committed
if (fittype[p2]!=PARFIT_FIXED)
{
f1 = 0;
for (p1=0; p1<nparam; p1++)
Emmanuel Bertin
committed
if (fittype[p1]!=PARFIT_FIXED)
{
covar[p2*nparam+p1] = (float)(dcovar[f2*nfree+f1]*dxdy[f1]*dxdy[f2]);
f1++;
}
f2++;
}
}
Emmanuel Bertin
committed
profit->nlimmin = nmin;
profit->nlimmax = nmax;
return nmin+nmax;
}
/****** prof_init *************************************************************
PROTO profstruct prof_init(profitstruct *profit, unsigned int modeltype)
PURPOSE Allocate and initialize a new profile structure.
INPUT Pointer to the profile-fitting structure,
OUTPUT A pointer to an allocated prof structure.
NOTES -.
AUTHOR E. Bertin (IAP)
profstruct *prof_init(profitstruct *profit, unsigned int modeltype)
rmax2, re2, dy2,r2, scale, zero, k,n, hinvn;
int width,height, ixc,iyc, ix,iy, nsub,
d,s;
QCALLOC(prof, profstruct, 1);
prof->code = modeltype;
switch(modeltype)
case MODEL_BACK:
prof->name = "background offset";
prof->naxis = 2;
prof->pix = NULL;
profit_addparam(profit, PARAM_BACK, &prof->flux);
prof->typscale = 1.0;
break;
case MODEL_DIRAC:
prof->name = "point source";
prof->naxis = 2;
prof->naxisn[0] = PROFIT_MAXMODSIZE;
prof->naxisn[1] = PROFIT_MAXMODSIZE;
prof->naxisn[2] = 1;
prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
prof->typscale = 1.0;
profit_addparam(profit, PARAM_X, &prof->x[0]);
profit_addparam(profit, PARAM_Y, &prof->x[1]);
profit_addparam(profit, PARAM_DIRAC_FLUX, &prof->flux);
break;
case MODEL_SERSIC:
prof->name = "Sersic spheroid";
prof->naxis = 2;
prof->naxisn[0] = PROFIT_MAXMODSIZE;
prof->naxisn[1] = PROFIT_MAXMODSIZE;
prof->naxisn[2] = 1;
prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
QMALLOC(prof->pix, float, prof->npix);
prof->typscale = 1.0;
profit_addparam(profit, PARAM_X, &prof->x[0]);
profit_addparam(profit, PARAM_Y, &prof->x[1]);
profit_addparam(profit, PARAM_SPHEROID_FLUX, &prof->flux);
profit_addparam(profit, PARAM_SPHEROID_REFF, &prof->scale);
profit_addparam(profit, PARAM_SPHEROID_ASPECT, &prof->aspect);
profit_addparam(profit, PARAM_SPHEROID_POSANG, &prof->posangle);
profit_addparam(profit, PARAM_SPHEROID_SERSICN, &prof->extra[0]);
break;
case MODEL_DEVAUCOULEURS:
prof->name = "de Vaucouleurs spheroid";
prof->naxisn[0] = PROFIT_MAXMODSIZE;
prof->naxisn[1] = PROFIT_MAXMODSIZE;
prof->naxisn[2] = 1;
prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
QMALLOC(prof->pix, float, profit->nmodpix);
prof->typscale = 1.0;
profit_addparam(profit, PARAM_X, &prof->x[0]);
profit_addparam(profit, PARAM_Y, &prof->x[1]);
profit_addparam(profit, PARAM_SPHEROID_FLUX, &prof->flux);
profit_addparam(profit, PARAM_SPHEROID_REFF, &prof->scale);
profit_addparam(profit, PARAM_SPHEROID_ASPECT, &prof->aspect);
profit_addparam(profit, PARAM_SPHEROID_POSANG, &prof->posangle);
break;
case MODEL_EXPONENTIAL:
prof->name = "exponential disk";
prof->naxisn[0] = PROFIT_MAXMODSIZE;
prof->naxisn[1] = PROFIT_MAXMODSIZE;
prof->naxisn[2] = 1;
prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
QMALLOC(prof->pix, float, profit->nmodpix);
prof->typscale = 1.0;
profit_addparam(profit, PARAM_X, &prof->x[0]);
profit_addparam(profit, PARAM_Y, &prof->x[1]);
profit_addparam(profit, PARAM_DISK_FLUX, &prof->flux);
profit_addparam(profit, PARAM_DISK_SCALE, &prof->scale);
profit_addparam(profit, PARAM_DISK_ASPECT, &prof->aspect);
profit_addparam(profit, PARAM_DISK_POSANG, &prof->posangle);
break;
case MODEL_ARMS:
prof->name = "spiral arms";
prof->naxisn[0] = PROFIT_MAXMODSIZE;
prof->naxisn[1] = PROFIT_MAXMODSIZE;
prof->naxisn[2] = 1;
prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
QMALLOC(prof->pix, float, profit->nmodpix);
prof->typscale = 1.0;
profit_addparam(profit, PARAM_X, &prof->x[0]);
profit_addparam(profit, PARAM_Y, &prof->x[1]);
profit_addparam(profit, PARAM_DISK_SCALE, &prof->scale);
profit_addparam(profit, PARAM_DISK_ASPECT, &prof->aspect);
profit_addparam(profit, PARAM_DISK_POSANG, &prof->posangle);
profit_addparam(profit, PARAM_ARMS_FLUX, &prof->flux);
profit_addparam(profit, PARAM_ARMS_QUADFRAC, &prof->featfrac);
// profit_addparam(profit, PARAM_ARMS_SCALE, &prof->featscale);
profit_addparam(profit, PARAM_ARMS_START, &prof->featstart);
profit_addparam(profit, PARAM_ARMS_PITCH, &prof->featpitch);
// profit_addparam(profit, PARAM_ARMS_PITCHVAR, &prof->featpitchvar);
profit_addparam(profit, PARAM_ARMS_POSANG, &prof->featposang);
// profit_addparam(profit, PARAM_ARMS_WIDTH, &prof->featwidth);
break;
case MODEL_BAR:
prof->name = "bar";
prof->naxisn[0] = PROFIT_MAXMODSIZE;
prof->naxisn[1] = PROFIT_MAXMODSIZE;
prof->naxisn[2] = 1;
prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
QMALLOC(prof->pix, float, profit->nmodpix);
prof->typscale = 1.0;
profit_addparam(profit, PARAM_X, &prof->x[0]);
profit_addparam(profit, PARAM_Y, &prof->x[1]);
profit_addparam(profit, PARAM_DISK_SCALE, &prof->scale);
profit_addparam(profit, PARAM_DISK_ASPECT, &prof->aspect);
profit_addparam(profit, PARAM_DISK_POSANG, &prof->posangle);
profit_addparam(profit, PARAM_ARMS_START, &prof->featstart);
profit_addparam(profit, PARAM_BAR_FLUX, &prof->flux);
profit_addparam(profit, PARAM_BAR_ASPECT, &prof->feataspect);
profit_addparam(profit, PARAM_ARMS_POSANG, &prof->featposang);
break;
case MODEL_INRING:
prof->name = "inner ring";
prof->naxisn[0] = PROFIT_MAXMODSIZE;
prof->naxisn[1] = PROFIT_MAXMODSIZE;
prof->naxisn[2] = 1;
prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
QMALLOC(prof->pix, float, profit->nmodpix);
prof->typscale = 1.0;
profit_addparam(profit, PARAM_X, &prof->x[0]);
profit_addparam(profit, PARAM_Y, &prof->x[1]);
profit_addparam(profit, PARAM_DISK_SCALE, &prof->scale);
profit_addparam(profit, PARAM_DISK_ASPECT, &prof->aspect);
profit_addparam(profit, PARAM_DISK_POSANG, &prof->posangle);
profit_addparam(profit, PARAM_ARMS_START, &prof->featstart);
profit_addparam(profit, PARAM_INRING_FLUX, &prof->flux);
profit_addparam(profit, PARAM_INRING_WIDTH, &prof->featwidth);
profit_addparam(profit, PARAM_INRING_ASPECT, &prof->feataspect);
break;
case MODEL_OUTRING:
prof->name = "outer ring";
prof->naxisn[0] = PROFIT_MAXMODSIZE;
prof->naxisn[1] = PROFIT_MAXMODSIZE;
prof->naxisn[2] = 1;
prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
QMALLOC(prof->pix, float, profit->nmodpix);
prof->typscale = 1.0;
profit_addparam(profit, PARAM_X, &prof->x[0]);
profit_addparam(profit, PARAM_Y, &prof->x[1]);
profit_addparam(profit, PARAM_DISK_SCALE, &prof->scale);
profit_addparam(profit, PARAM_DISK_ASPECT, &prof->aspect);
profit_addparam(profit, PARAM_DISK_POSANG, &prof->posangle);
profit_addparam(profit, PARAM_OUTRING_START, &prof->featstart);
profit_addparam(profit, PARAM_OUTRING_FLUX, &prof->flux);
profit_addparam(profit, PARAM_OUTRING_WIDTH, &prof->featwidth);
break;
case MODEL_TABULATED: /* An example of tabulated profile */
prof->name = "tabulated model";
prof->naxis = 3;
width = prof->naxisn[0] = PROFIT_PROFRES;
height = prof->naxisn[1] = PROFIT_PROFRES;
nsub = prof->naxisn[2] = PROFIT_PROFSRES;
QCALLOC(prof->pix, float, width*height*nsub);
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
ixc = width/2;
iyc = height/2;
rmax2 = (ixc - 1.0)*(ixc - 1.0);
re2 = width/64.0;
prof->typscale = re2;
re2 *= re2;
zero = prof->extrazero[0] = 0.2;
scale = prof->extrascale[0]= 8.0/PROFIT_PROFSRES;
pix = prof->pix;
for (s=0; s<nsub; s++)
{
n = s*scale + zero;
hinvn = 0.5/n;
k = -1.0/3.0 + 2.0*n + 4.0/(405.0*n) + 46.0/(25515.0*n*n)
+ 131.0/(1148175*n*n*n);
for (iy=0; iy<height; iy++)
{
dy2 = (iy-iyc)*(iy-iyc);
for (ix=0; ix<width; ix++)
{
r2 = dy2 + (ix-ixc)*(ix-ixc);
*(pix++) = (r2<rmax2)? exp(-k*pow(r2/re2,hinvn)) : 0.0;
}
}
}
profit_addparam(profit, PARAM_X, &prof->x[0]);
profit_addparam(profit, PARAM_Y, &prof->x[1]);
profit_addparam(profit, PARAM_SPHEROID_FLUX, &prof->flux);
profit_addparam(profit, PARAM_SPHEROID_REFF, &prof->scale);
profit_addparam(profit, PARAM_SPHEROID_ASPECT, &prof->aspect);
profit_addparam(profit, PARAM_SPHEROID_POSANG, &prof->posangle);
profit_addparam(profit, PARAM_SPHEROID_SERSICN, &prof->extra[0]);
break;
default:
error(EXIT_FAILURE, "*Internal Error*: Unknown profile in ",
"prof_init()");
break;
}
{
prof->kernelnlines = 1;
for (d=0; d<prof->naxis; d++)
{
prof->interptype[d] = INTERP_BILINEAR;
prof->kernelnlines *=
(prof->kernelwidth[d] = interp_kernwidth[prof->interptype[d]]);
}
prof->kernelnlines /= prof->kernelwidth[0];
Emmanuel Bertin
committed
QMALLOC16(prof->kernelbuf, float, prof->kernelnlines);
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
}
return prof;
}
/****** prof_end **************************************************************
PROTO void prof_end(profstruct *prof)
PURPOSE End (deallocate) a profile structure.
INPUT Prof structure.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 09/04/2007
***/
void prof_end(profstruct *prof)
{
if (prof->pix)
{
free(prof->pix);
free(prof->kernelbuf);
}
free(prof);
return;
}
/****** prof_add **************************************************************
PROTO float prof_add(profitstruct *profit, profstruct *prof,
int extfluxfac_flag)
INPUT Profile-fitting structure,
profile structure,
flag (0 if flux correction factor is to be computed internally)
OUTPUT Total (asymptotic) flux contribution.
Emmanuel Bertin
committed
VERSION 25/07/2011
float prof_add(profitstruct *profit, profstruct *prof, int extfluxfac_flag)
Emmanuel Bertin
committed
double xscale, yscale, saspect, ctheta,stheta, flux, scaling, bn, n,
dx1cout,dx2cout, ddx1[36],ddx2[36];
float posin[PROFIT_MAXEXTRA], posout[2], dnaxisn[2],
fluxfac, amp,cd11,cd12,cd21,cd22, dx1,dx2,
x1,x10,x2, x1cin,x2cin, x1cout,x2cout, x1max,x2max, x1in,x2in,
k, hinvn, x1t,x2t, ca,sa, u,umin,
armamp,arm2amp, armrdphidr, armrdphidrvar, posang,
width, invwidth2,
r,r2,rmin, r2minxin,r2minxout, rmax, r2max,
r2max1, r2max2, r2min, invr2xdif,
val, theta, thresh, ra,rb, num,num2,den, ang,angstep,
invn, dr, krpinvn,dkrpinvn, rs,rs2,
Emmanuel Bertin
committed
a11,a12,a21,a22, invdet, dca,dsa, a0,a2,a3, p1,p2,
krspinvn, ekrspinvn, selem;
int npix, threshflag,
a,d,e,i, ix1,ix2, ix1max,ix2max, nang, nx2,
Emmanuel Bertin
committed
npix2;
npix = profit->nmodpix;
if (prof->code==MODEL_BACK)
{
amp = fabs(*prof->flux);
pixout = profit->modpix;
for (i=npix; i--;)
*(pixout++) += amp;
prof->lostfluxfrac = 0.0;
return 0.0;
}
scaling = profit->pixstep / prof->typscale;
if (prof->code!=MODEL_DIRAC)
{
/*-- Compute Profile CD matrix */
ctheta = cos(*prof->posangle*DEG);
stheta = sin(*prof->posangle*DEG);
saspect = fabs(*prof->aspect);
xscale = (*prof->scale==0.0)?
0.0 : fabs(scaling / (*prof->scale*prof->typscale));
yscale = (*prof->scale*saspect == 0.0)?
0.0 : fabs(scaling / (*prof->scale*prof->typscale*saspect));
cd11 = (float)(xscale*ctheta);
cd12 = (float)(xscale*stheta);
cd21 = (float)(-yscale*stheta);
cd22 = (float)(yscale*ctheta);
dx1 = 0.0; /* Shifting operations have been moved to profit_resample() */
dx2 = 0.0; /* Shifting operations have been moved to profit_resample() */
x1cout = (float)(profit->modnaxisn[0]/2);
x2cout = (float)(profit->modnaxisn[1]/2);
/*-- Compute the largest r^2 that fits in the frame */
num = cd11*cd22-cd12*cd21;
x1max = x1cout - 1.0;
x2max = x2cout - 1.0;
den = fabs(cd12*cd12+cd22*cd22);
num2 = x1max*x1max*num;
r2max1 = num2<PROFIT_MAXR2MAX*den? num2 / den : PROFIT_MAXR2MAX;
den = fabs(cd11*cd11+cd21*cd21);
num2 = x2max*x2max*num;
r2max2 = num2<PROFIT_MAXR2MAX*den? num2 / den : PROFIT_MAXR2MAX;
r2max = (r2max1 < r2max2? r2max1 : r2max2);
Emmanuel Bertin
committed
rmax = sqrtf(r2max);
prof->pix[profit->modnaxisn[0]/2
+ (profit->modnaxisn[1]/2)*profit->modnaxisn[0]] = 1.0;
prof->lostfluxfrac = 0.0;
threshflag = 0;
break;
case MODEL_SERSIC:
case MODEL_DEVAUCOULEURS:
case MODEL_EXPONENTIAL:
Emmanuel Bertin
committed
/*---- Compute sharp/smooth transition radius */
rs = PROFIT_SMOOTHR*(xscale>yscale?xscale:yscale);
if (rs<=0)
rs = 1.0;
rs2 = rs*rs;
/*---- The consequence of sampling on flux is compensated by PSF normalisation*/
if (prof->code==MODEL_EXPONENTIAL)
Emmanuel Bertin
committed
bn = n = 1.0;
else if (prof->code==MODEL_DEVAUCOULEURS)
Emmanuel Bertin
committed
{
n = 4.0;
bn = 7.66924944;
}
else
{
n = fabs(*prof->extra[0]);
bn = 2.0*n - 1.0/3.0 + 4.0/(405.0*n) + 46.0/(25515.0*n*n)
+ 131.0/(1148175*n*n*n); /* Ciotti & Bertin 1999 */
Emmanuel Bertin
committed
}
invn = 1.0/n;
Emmanuel Bertin
committed
k = -bn;
/*---- Compute central polynomial terms */
krspinvn = prof->code==MODEL_EXPONENTIAL? -rs : k*expf(logf(rs)*invn);
Emmanuel Bertin
committed
ekrspinvn = expf(krspinvn);
p2 = krspinvn*invn*invn;
p1 = krspinvn*p2;
a0 = (1+(1.0/6.0)*(p1+(1.0-5.0*n)*p2))*ekrspinvn;
a2 = (-1.0/2.0)*(p1+(1.0-3.0*n)*p2)/rs2*ekrspinvn;
a3 = (1.0/3.0)*(p1+(1.0-2.0*n)*p2)/(rs2*rs)*ekrspinvn;
/*---- Compute the smooth part of the profile */
x10 = -x1cout - dx1;
x2 = -x2cout - dx2;
if (prof->code==MODEL_EXPONENTIAL)
Emmanuel Bertin
committed
for (ix2=nx2; ix2--; x2+=1.0)
Emmanuel Bertin
committed
x1 = x10;
for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
Emmanuel Bertin
committed
x1in = cd12*x2 + cd11*x1;
x2in = cd22*x2 + cd21*x1;
ra = x1in*x1in+x2in*x2in;
if (ra>r2max)
Emmanuel Bertin
committed
*(pixin++) = 0.0;
continue;
Emmanuel Bertin
committed
val = ra<rs2? a0+ra*(a2+a3*sqrtf(ra)) : expf(-sqrtf(ra));
*(pixin++) = val;
Emmanuel Bertin
committed
else
for (ix2=nx2; ix2--; x2+=1.0)
Emmanuel Bertin
committed
x1 = x10;
for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
{
Emmanuel Bertin
committed
x1in = cd12*x2 + cd11*x1;
x2in = cd22*x2 + cd21*x1;
ra = x1in*x1in+x2in*x2in;
if (ra>r2max)
Emmanuel Bertin
committed
*(pixin++) = 0.0;
continue;
Emmanuel Bertin
committed
val = ra<rs2? a0+ra*(a2+a3*sqrtf(ra)) : expf(k*expf(logf(ra)*hinvn));
*(pixin++) = val;
/*---- Copy the symmetric part */
if ((npix2=(profit->modnaxisn[1]-nx2)*profit->modnaxisn[0]) > 0)
{
pixin2 = pixin - profit->modnaxisn[0] - 1;
if (!(profit->modnaxisn[0]&1))
{
*(pixin++) = 0.0;
npix2--;
}
for (i=npix2; i--;)
*(pixin++) = *(pixin2--);
}
Emmanuel Bertin
committed
/*---- Compute the sharp part of the profile */
ix1max = profit->modnaxisn[0];
ix2max = profit->modnaxisn[1];
dx1cout = x1cout + 0.4999999;
dx2cout = x2cout + 0.4999999;
invdet = 1.0/fabsf(cd11*cd22 - cd12*cd21);
a11 = cd22*invdet;
a12 = -cd12*invdet;
a21 = -cd21*invdet;
a22 = cd11*invdet;
nang = 72 / 2; /* 36 angles; only half of them are computed*/
angstep = PI/nang;
ang = 0.0;
for (a=0; a<nang; a++)
Emmanuel Bertin
committed
sincosf(ang, &dsa, &dca);
#else
dsa = sinf(ang);
dca = cosf(ang);
#endif
ddx1[a] = a11*dsa+a12*dca;
ddx2[a] = a21*dsa+a22*dca;
Emmanuel Bertin
committed
ang += angstep;
Emmanuel Bertin
committed
r = DEXPF(-4.0);
dr = DEXPF(0.05);
selem = 0.5*angstep*(dr - 1.0/dr)/(xscale*yscale);
krpinvn = k*DEXPF(-4.0*invn);
dkrpinvn = DEXPF(0.05*invn);
pixin = prof->pix;
for (; r<rs; r *= dr)
Emmanuel Bertin
committed
r2 = r*r;
val = (expf(krpinvn) - (a0 + r2*(a2+a3*r)))*r2*selem;
for (a=0; a<nang; a++)
Emmanuel Bertin
committed
ix1 = (int)(dx1cout + r*ddx1[a]);
ix2 = (int)(dx2cout + r*ddx2[a]);
if (ix1>=0 && ix1<ix1max && ix2>=0 && ix2<ix2max)
pixin[ix2*ix1max+ix1] += val;
ix1 = (int)(dx1cout - r*ddx1[a]);
ix2 = (int)(dx2cout - r*ddx2[a]);
if (ix1>=0 && ix1<ix1max && ix2>=0 && ix2<ix2max)
pixin[ix2*ix1max+ix1] += val;
Emmanuel Bertin
committed
krpinvn *= dkrpinvn;
Emmanuel Bertin
committed
prof->lostfluxfrac = prof->code==MODEL_EXPONENTIAL?
Emmanuel Bertin
committed
(1.0 + rmax)*exp(-rmax)
:1.0 - prof_gammainc(2.0*n, bn*pow(r2max, hinvn));
threshflag = 0;
r2min = *prof->featstart**prof->featstart;
r2minxin = r2min * (1.0 - PROFIT_BARXFADE) * (1.0 - PROFIT_BARXFADE);
r2minxout = r2min * (1.0 + PROFIT_BARXFADE) * (1.0 + PROFIT_BARXFADE);
if ((invr2xdif = (r2minxout - r2minxin)) > 0.0)
invr2xdif = 1.0 / invr2xdif;
else
invr2xdif = 1.0;
umin = 0.5*logf(r2minxin + 0.00001);
arm2amp = *prof->featfrac;
armamp = 1.0 - arm2amp;
armrdphidr = 1.0/tan(*prof->featpitch*DEG);
armrdphidrvar = 0.0 /**prof->featpitchvar*/;
posang = *prof->featposang*DEG;
width = fabs(*prof->featwidth);
width = 3.0;
x1 = -x1cout - dx1;
x2 = -x2cout - dx2;
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
for (ix2=profit->modnaxisn[1]; ix2--; x2+=1.0)
{
x1t = cd12*x2 + cd11*x1;
x2t = cd22*x2 + cd21*x1;
for (ix1=profit->modnaxisn[0]; ix1--;)
{
r2 = x1t*x1t+x2t*x2t;
if (r2>r2minxin)
{
u = 0.5*logf(r2 + 0.00001);
theta = (armrdphidr+armrdphidrvar*(u-umin))*u+posang;
ca = cosf(theta);
sa = sinf(theta);
x1in = (x1t*ca - x2t*sa);
x2in = (x1t*sa + x2t*ca);
amp = expf(-sqrtf(x1t*x1t+x2t*x2t));
if (r2<r2minxout)
amp *= (r2 - r2minxin)*invr2xdif;
ra = x1in*x1in/r2;
rb = x2in*x2in/r2;
*(pixin++) = amp * (armamp*PROFIT_POWF(ra,width)
+ arm2amp*PROFIT_POWF(rb,width));
}
else
*(pixin++) = 0.0;
x1t += cd11;
x2t += cd21;
}
}
prof->lostfluxfrac = 0.0;
threshflag = 1;
r2min = *prof->featstart**prof->featstart;
r2minxin = r2min * (1.0 - PROFIT_BARXFADE) * (1.0 - PROFIT_BARXFADE);
r2minxout = r2min * (1.0 + PROFIT_BARXFADE) * (1.0 + PROFIT_BARXFADE);
if ((invr2xdif = (r2minxout - r2minxin)) > 0.0)
invr2xdif = 1.0 / invr2xdif;
else
invr2xdif = 1.0;
invwidth2 = fabs(1.0 / (*prof->featstart**prof->feataspect));
posang = *prof->featposang*DEG;
ca = cosf(posang);
sa = sinf(posang);
x1 = -x1cout - dx1;
x2 = -x2cout - dx2;
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
for (ix2=profit->modnaxisn[1]; ix2--; x2+=1.0)
{
x1t = cd12*x2 + cd11*x1;
x2t = cd22*x2 + cd21*x1;
for (ix1=profit->modnaxisn[0]; ix1--;)
{
r2 = x1t*x1t+x2t*x2t;
if (r2<r2minxout)
{
x1in = x1t*ca - x2t*sa;
x2in = invwidth2*(x1t*sa + x2t*ca);
*(pixin++) = (r2>r2minxin) ?
(r2minxout - r2)*invr2xdif*expf(-x2in*x2in)
: expf(-x2in*x2in);
}
else
*(pixin++) = 0.0;
x1t += cd11;
x2t += cd21;
}
}
prof->lostfluxfrac = 0.0;
threshflag = 1;
case MODEL_INRING:
rmin = *prof->featstart;
r2minxin = *prof->featstart-4.0**prof->featwidth;
if (r2minxin < 0.0)
r2minxin = 0.0;
r2minxin *= r2minxin;
r2minxout = *prof->featstart+4.0**prof->featwidth;
r2minxout *= r2minxout;
invwidth2 = 0.5 / (*prof->featwidth**prof->featwidth);
cd22 /= *prof->feataspect;
cd21 /= *prof->feataspect;
x1 = -x1cout - dx1;
x2 = -x2cout - dx2;
for (ix2=profit->modnaxisn[1]; ix2--; x2+=1.0)
{
x1t = cd12*x2 + cd11*x1;
x2t = cd22*x2 + cd21*x1;
for (ix1=profit->modnaxisn[0]; ix1--;)
{
r2 = x1t*x1t+x2t*x2t;
if (r2>r2minxin && r2<r2minxout)
{
r = sqrt(r2) - rmin;
*(pixin++) = expf(-invwidth2*r*r);
}
else
*(pixin++) = 0.0;
x1t += cd11;
x2t += cd21;
}
}
prof->lostfluxfrac = 0.0;
threshflag = 1;
case MODEL_OUTRING:
rmin = *prof->featstart;
r2minxin = *prof->featstart-4.0**prof->featwidth;
if (r2minxin < 0.0)
r2minxin = 0.0;
r2minxin *= r2minxin;
r2minxout = *prof->featstart+4.0**prof->featwidth;
r2minxout *= r2minxout;
invwidth2 = 0.5 / (*prof->featwidth**prof->featwidth);
x1 = -x1cout - dx1;
x2 = -x2cout - dx2;
for (ix2=profit->modnaxisn[1]; ix2--; x2+=1.0)
{
x1t = cd12*x2 + cd11*x1;
x2t = cd22*x2 + cd21*x1;
for (ix1=profit->modnaxisn[0]; ix1--;)
{
r2 = x1t*x1t+x2t*x2t;
if (r2>r2minxin && r2<r2minxout)
{
r = sqrt(r2) - rmin;
*(pixin++) = expf(-invwidth2*r*r);
}
else
*(pixin++) = 0.0;
x1t += cd11;
x2t += cd21;
}
}
prof->lostfluxfrac = 0.0;
threshflag = 1;
break;
default:
/*---- Tabulated profile: remap each pixel */
/*---- Initialize multi-dimensional counters */
for (d=0; d<2; d++)
{
posout[d] = 1.0; /* FITS convention */
dnaxisn[d] = profit->modnaxisn[d] + 0.99999;
}
for (e=0; e<prof->naxis - 2; e++)
{
d = 2+e;
/*------ Compute position along axis */
posin[d] = (*prof->extra[e]-prof->extrazero[e])/prof->extrascale[e]+1.0;
/*------ Keep position within boundaries and let interpolation do the rest */
if (posin[d] < 0.99999)
{
if (prof->extracycleflag[e])
posin[d] += (float)prof->naxisn[d];
else if (posin[d] > (float)prof->naxisn[d])
{
if (prof->extracycleflag[e])
posin[d] = (prof->extracycleflag[e])?
fmod(posin[d], (float)prof->naxisn[d])
: (float)prof->naxisn[d];
x1cin = (float)(prof->naxisn[0]/2);
x2cin = (float)(prof->naxisn[1]/2);
for (i=npix; i--;)
{
x1 = posout[0] - x1cout - 1.0 - dx1;
x2 = posout[1] - x2cout - 1.0 - dx2;
posin[0] = cd11*x1 + cd12*x2 + x1cin + 1.0;
posin[1] = cd21*x1 + cd22*x2 + x2cin + 1.0;
*(pixin++) = prof_interpolate(prof, posin);
for (d=0; d<2; d++)
if ((posout[d]+=1.0) < dnaxisn[d])
break;
else
posout[d] = 1.0;
}
prof->lostfluxfrac = 0.0;
threshflag = 1;