Newer
Older
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 PROF_DIRAC:
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_DISK_FLUX, &prof->flux);
break;
case PROF_SERSIC_TABEX: /* An example of tabulated profile */
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);
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
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;
}
QMALLOC(prof->pix, float, prof->npix);
if (prof->naxis>2)
{
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);
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
}
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.
float prof_add(profitstruct *profit, profstruct *prof, int extfluxfac_flag)
double xscale, yscale, saspect, ctheta,stheta, flux, scaling, bn, n;
float posin[PROFIT_MAXEXTRA], posout[2], dnaxisn[2],
fluxfac, amp,cd11,cd12,cd21,cd22, dcd11,dcd21, dx1,dx2,
x1,x10,x2, x1cin,x2cin, x1cout,x2cout, x1max,x2max,
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,rao, num;
int npix, noversamp, threshflag,
npix = profit->nmodpix;
if (prof->code==PROF_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!=PROF_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;
r2max1 = x1max*x1max*fabs(num*num / (cd12*cd12+cd22*cd22));
r2max2 = x2max*x2max*fabs(num*num / (cd11*cd11+cd21*cd21));
r2max = r2max1 < r2max2? r2max1 : r2max2;
switch(prof->code)
{
case PROF_SERSIC:
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 */
k = -bn;
hinvn = 0.5/n;
/*---- The consequence of sampling on flux is compensated by PSF normalisation*/
x10 = -x1cout - dx1;
x2 = -x2cout - dx2;
{
x1 = x10;
for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
{
x1in = cd12*x2 + cd11*x1;
x2in = cd22*x2 + cd21*x1;
ra = x1in*x1in+x2in*x2in;
if (ra>r2max)
{
*(pixin++) = 0.0;
continue;
}
val = expf(k*expf(logf(ra)*hinvn));
noversamp = (int)(val*profit->oversamp+0.1);
if (noversamp < 2)
*(pixin++) = val;
else
{
ostep = 1.0/noversamp;
dcd11 = cd11*ostep;
dcd21 = cd21*ostep;
odx = 0.5*(ostep-1.0);
x1t = x1+odx;
val = 0.0;
for (idx2=noversamp; idx2--; odx+=ostep)
{
x1in = cd12*(x2+odx) + cd11*x1t;
x2in = cd22*(x2+odx) + cd21*x1t;
for (idx1=noversamp; idx1--;)
{
rao = x1in*x1in+x2in*x2in;
val += expf(k*PROFIT_POWF(rao,hinvn));
x1in += dcd11;
x2in += dcd21;
}
}
*(pixin++) = val*ostep*ostep;
}
}
}
/*---- 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--);
}
prof->lostfluxfrac = 1.0 - prof_gammainc(2.0*n, bn*pow(r2max, hinvn));
threshflag = 0;
break;
case PROF_DEVAUCOULEURS:
/*---- The consequence of sampling on flux is compensated by PSF normalisation*/
x10 = -x1cout - dx1;
x2 = -x2cout - dx2;
{
x1 = x10;
for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
{
x1in = cd12*x2 + cd11*x1;
x2in = cd22*x2 + cd21*x1;
ra = x1in*x1in+x2in*x2in;
if (ra>r2max)
{
*(pixin++) = 0.0;
continue;
}
val = expf(-7.66924944f*PROFIT_POWF(ra,0.125));
noversamp = (int)(sqrt(val)*profit->oversamp+0.1);
if (noversamp < 2)
*(pixin++) = val;
else
{
ostep = 1.0/noversamp;
dcd11 = cd11*ostep;
dcd21 = cd21*ostep;
odx = 0.5*(ostep-1.0);
x1t = x1+odx;
val = 0.0;
for (idx2=noversamp; idx2--; odx+=ostep)
{
x1in = cd12*(x2+odx) + cd11*x1t;
x2in = cd22*(x2+odx) + cd21*x1t;
for (idx1=noversamp; idx1--;)
{
ra = x1in*x1in+x2in*x2in;
val += expf(-7.66924944f*PROFIT_POWF(ra,0.125));
x1in += dcd11;
x2in += dcd21;
}
}
*(pixin++) = val*ostep*ostep;
}
}
}
/*---- 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--);
}
prof->lostfluxfrac = 1.0-prof_gammainc(8.0, 7.66924944*pow(r2max, 0.125));
threshflag = 0;
x10 = -x1cout - dx1;
x1 = x10;
for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
x1in = cd12*x2 + cd11*x1;
x2in = cd22*x2 + cd21*x1;
ra = x1in*x1in+x2in*x2in;
if (ra>r2max)
{
*(pixin++) = 0.0;
continue;
}
val = expf(-sqrtf(ra));
noversamp = (int)(val*sqrt(profit->oversamp)+0.1);
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
if (noversamp < 2)
*(pixin++) = val;
else
{
ostep = 1.0/noversamp;
dcd11 = cd11*ostep;
dcd21 = cd21*ostep;
odx = 0.5*(ostep-1.0);
x1t = x1+odx;
val = 0.0;
for (idx2=noversamp; idx2--; odx+=ostep)
{
x1in = cd12*(x2+odx) + cd11*x1t;
x2in = cd22*(x2+odx) + cd21*x1t;
for (idx1=noversamp; idx1--;)
{
ra = x1in*x1in+x2in*x2in;
val += expf(-sqrtf(ra));
x1in += dcd11;
x2in += dcd21;
}
}
*(pixin++) = val*ostep*ostep;
}
/*---- 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--);
}
rmax = sqrt(r2max);
prof->lostfluxfrac = (1.0 + rmax)*exp(-rmax);
threshflag = 0;
break;
case PROF_ARMS:
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;
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
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;
break;
case PROF_BAR:
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;
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
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;
break;
case PROF_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;
break;
case PROF_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;
case PROF_DIRAC:
memset(prof->pix, 0, npix*sizeof(float));
prof->pix[profit->modnaxisn[0]/2
+ (profit->modnaxisn[1]/2)*profit->modnaxisn[0]] = 1.0;
prof->lostfluxfrac = 0.0;
threshflag = 0;
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;
/* For complex profiles, threshold to the brightest pixel value at border */
if (threshflag)
{
/*-- Now find truncation threshold */
/*-- Find the shortest distance to a vignet border */
rmax = x1cout;
if (rmax > (r = x2cout))
rmax = r;
rmax += 0.01;
if (rmax<1.0)
rmax = 1.0;
r2max = rmax*rmax;
rmin = rmax - 1.0;
r2min = rmin*rmin;
/*-- Find best threshold (the max around the circle with radius rmax */
dx2 = -x2cout;
thresh = -BIG;
for (ix2=profit->modnaxisn[1]; ix2--; dx2 += 1.0)
{
dx1 = -x1cout;
for (ix1=profit->modnaxisn[0]; ix1--; dx1 += 1.0)
if ((val=*(pixin++))>thresh && (r2=dx1*dx1+dx2*dx2)>r2min && r2<r2max)
thresh = val;
}
/*-- Threshold and measure the flux */
flux = 0.0;
for (i=npix; i--; pixin++)
if (*pixin >= thresh)
flux += (double)*pixin;
else
*pixin = 0.0;
}
else
flux = 0.0;
for (i=npix; i--;)
flux += (double)*(pixin++);
if (extfluxfac_flag)
fluxfac = prof->fluxfac;
else
{
if (prof->lostfluxfrac < 1.0)
flux /= (1.0 - prof->lostfluxfrac);
prof->fluxfac = fluxfac = fabs(flux)>0.0? profit->fluxfac/flux : 0.0;
}
pixin = prof->pix;
for (i=npix; i--;)
*(pixin++) *= fluxfac;
fluxfac = *prof->flux;
pixin = prof->pix;
*(pixout++) += fluxfac**(pixin++);
return *prof->flux;
/****** prof_moments **********************************************************
PROTO int prof_moments(profitstruct *profit, profstruct *prof)
PURPOSE Computes (analytically or numerically) the 2nd moments of a profile.
INPUT Profile-fitting structure,
profile structure,
optional pointer to 3xnparam Jacobian matrix.
OUTPUT Index to the profile flux for further processing.
NOTES .
AUTHOR E. Bertin (IAP)
int prof_moments(profitstruct *profit, profstruct *prof, double *jac)
double *dmx2,*dmy2,*dmxy,
m20, a2, ct,st, mx2fac, my2fac,mxyfac, dc2,ds2,dcs,
bn,bn2, n,n2, nfac,nfac2, hscale2, dmdn;
int nparam, index;
if (jac)
/*-- Clear output Jacobian */
{
nparam = profit->nparam;
memset(jac, 0, nparam*3*sizeof(double));
dmx2 = jac;
dmy2 = jac + nparam;
dmxy = jac + 2*nparam;
}
else
dmx2 = dmy2 = dmxy = NULL; /* To avoid gcc -Wall warnings */
m20 = 0.0; /* to avoid gcc -Wall warnings */
index = 0; /* to avoid gcc -Wall warnings */
if (prof->posangle)
{
a2 = *prof->aspect**prof->aspect;
ct = cos(*prof->posangle*DEG);
st = sin(*prof->posangle*DEG);
mx2fac = ct*ct + st*st*a2;
my2fac = st*st + ct*ct*a2;
mxyfac = ct*st * (1.0 - a2);
if (jac)
{
dc2 = -2.0*ct*st*DEG;
ds2 = 2.0*ct*st*DEG;
dcs = (ct*ct - st*st)*DEG;
}
else
dc2 = ds2 = dcs = 0.0; /* To avoid gcc -Wall warnings */
switch(prof->code)
{
case PROF_SERSIC:
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 */
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
nfac = prof_gamma(4.0*n) / (prof_gamma(2.0*n)*pow(bn, 2.0*n));
hscale2 = 0.5 * *prof->scale**prof->scale;
m20 = hscale2 * nfac;
if (jac)
{
dmx2[profit->paramindex[PARAM_SPHEROID_REFF]]
= *prof->scale * nfac * mx2fac;
dmy2[profit->paramindex[PARAM_SPHEROID_REFF]]
= *prof->scale * nfac * my2fac;
dmxy[profit->paramindex[PARAM_SPHEROID_REFF]]
= *prof->scale * nfac * mxyfac;
n2 = n+0.01;
bn2 = 2.0*n2 - 1.0/3.0 + 4.0/(405.0*n2) + 46.0/(25515.0*n2*n2)
+ 131.0/(1148175*n2*n2*n2); /* Ciotti & Bertin 1999 */
nfac2 = prof_gamma(4.0*n2) / (prof_gamma(2.0*n2)*pow(bn2, 2.0*n2));
dmdn = 100.0 * hscale2 * (nfac2-nfac);
dmx2[profit->paramindex[PARAM_SPHEROID_SERSICN]] = dmdn * mx2fac;
dmy2[profit->paramindex[PARAM_SPHEROID_SERSICN]] = dmdn * my2fac;
dmxy[profit->paramindex[PARAM_SPHEROID_SERSICN]] = dmdn * mxyfac;
dmx2[profit->paramindex[PARAM_SPHEROID_ASPECT]]
= 2.0 * m20 * st*st * *prof->aspect;
dmy2[profit->paramindex[PARAM_SPHEROID_ASPECT]]
= 2.0 * m20 * ct*ct * *prof->aspect;
dmxy[profit->paramindex[PARAM_SPHEROID_ASPECT]]
= -2.0 * m20 * ct*st * *prof->aspect;
dmx2[profit->paramindex[PARAM_SPHEROID_POSANG]] = m20 * (dc2+ds2*a2);
dmy2[profit->paramindex[PARAM_SPHEROID_POSANG]] = m20 * (ds2+dc2*a2);
dmxy[profit->paramindex[PARAM_SPHEROID_POSANG]] = m20 * (1.0-a2)*dcs;
}
index = profit->paramindex[PARAM_SPHEROID_FLUX];
break;
case PROF_DEVAUCOULEURS:
m20 = 10.83995 * *prof->scale**prof->scale;
if (jac)
{
dmx2[profit->paramindex[PARAM_SPHEROID_REFF]]
= 21.680 * *prof->scale * mx2fac;
dmy2[profit->paramindex[PARAM_SPHEROID_REFF]]
= 21.680 * *prof->scale * my2fac;
dmxy[profit->paramindex[PARAM_SPHEROID_REFF]]
= 21.680 * *prof->scale * mxyfac;
dmx2[profit->paramindex[PARAM_SPHEROID_ASPECT]]
= 2.0 * m20 * st*st * *prof->aspect;
dmy2[profit->paramindex[PARAM_SPHEROID_ASPECT]]
= 2.0 * m20 * ct*ct * *prof->aspect;
dmxy[profit->paramindex[PARAM_SPHEROID_ASPECT]]
= -2.0 * m20 * ct*st * *prof->aspect;
dmx2[profit->paramindex[PARAM_SPHEROID_POSANG]] = m20 * (dc2+ds2*a2);
dmy2[profit->paramindex[PARAM_SPHEROID_POSANG]] = m20 * (ds2+dc2*a2);
dmxy[profit->paramindex[PARAM_SPHEROID_POSANG]] = m20 * (1.0-a2)*dcs;
}
index = profit->paramindex[PARAM_SPHEROID_FLUX];
break;
case PROF_EXPONENTIAL:
m20 = 3.0 * *prof->scale**prof->scale;
if (jac)
{
dmx2[profit->paramindex[PARAM_DISK_SCALE]]
= 6.0 * *prof->scale * mx2fac;
dmy2[profit->paramindex[PARAM_DISK_SCALE]]
= 6.0 * *prof->scale * my2fac;
dmxy[profit->paramindex[PARAM_DISK_SCALE]]
= 6.0 * *prof->scale * mxyfac;
dmx2[profit->paramindex[PARAM_DISK_ASPECT]]
= 2.0 * m20 * st*st * *prof->aspect;
dmy2[profit->paramindex[PARAM_DISK_ASPECT]]
= 2.0 * m20 * ct*ct * *prof->aspect;
dmxy[profit->paramindex[PARAM_DISK_ASPECT]]
= -2.0 * m20 * ct*st * *prof->aspect;
dmx2[profit->paramindex[PARAM_DISK_POSANG]] = m20 * (dc2 + ds2*a2);
dmy2[profit->paramindex[PARAM_DISK_POSANG]] = m20 * (ds2 + dc2*a2);
dmxy[profit->paramindex[PARAM_DISK_POSANG]] = m20 * (1.0 - a2) * dcs;
}
index = profit->paramindex[PARAM_DISK_FLUX];
break;
case PROF_ARMS:
m20 = 1.0;
index = profit->paramindex[PARAM_ARMS_FLUX];
break;
m20 = 1.0;
index = profit->paramindex[PARAM_BAR_FLUX];
break;
m20 = 1.0;
index = profit->paramindex[PARAM_INRING_FLUX];
break;
m20 = 1.0;
index = profit->paramindex[PARAM_OUTRING_FLUX];
break;
default:
error(EXIT_FAILURE, "*Internal Error*: Unknown oriented model in ",
"prof_moments()");
break;
}
prof->mx2 = m20*mx2fac;
prof->my2 = m20*my2fac;
prof->mxy = m20*mxyfac;
}
else
prof->mx2 = prof->my2 = prof->mxy = 0.0;
return index;
/****** prof_interpolate ******************************************************
PROTO float prof_interpolate(profstruct *prof, float *posin)
PURPOSE Interpolate a multidimensional model profile at a given position.
INPUT Profile structure,
input position vector.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 10/12/2006
***/
static float prof_interpolate(profstruct *prof, float *posin)
float dpos[2+PROFIT_MAXEXTRA],
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
kernel_vector[INTERP_MAXKERNELWIDTH],
*kvector, *pixin,*pixout,
val;
long step[2+PROFIT_MAXEXTRA],
start, fac;
int linecount[2+PROFIT_MAXEXTRA],
*naxisn,
i,j,n, ival, nlines, kwidth,width, badpixflag, naxis;
naxis = prof->naxis;
naxisn = prof->naxisn;
start = 0;
fac = 1;
for (n=0; n<naxis; n++)
{
val = *(posin++);
width = *(naxisn++);
/*-- Get the integer part of the current coordinate or nearest neighbour */
ival = (prof->interptype[n]==INTERP_NEARESTNEIGHBOUR)?
(int)(val-0.50001):(int)val;
/*-- Store the fractional part of the current coordinate */
dpos[n] = val - ival;
/*-- Check if interpolation start/end exceed image boundary... */
kwidth = prof->kernelwidth[n];
ival-=kwidth/2;
if (ival<0 || ival+kwidth<=0 || ival+kwidth>width)
return 0.0;
/*-- Update starting pointer */
start += ival*fac;
/*-- Update step between interpolated regions */
step[n] = fac*(width-kwidth);
linecount[n] = 0.0;
fac *= width;
}
/* Update Interpolation kernel vectors */
make_kernel(*dpos, kernel_vector, prof->interptype[0]);
kwidth = prof->kernelwidth[0];
nlines = prof->kernelnlines;
/* First step: interpolate along NAXIS1 from the data themselves */
badpixflag = 0;
pixin = prof->pix+start;
pixout = prof->kernelbuf;
for (j=nlines; j--;)
{
val = 0.0;
kvector = kernel_vector;
for (i=kwidth; i--;)
val += *(kvector++)**(pixin++);
*(pixout++) = val;
for (n=1; n<naxis; n++)
{
pixin+=step[n-1];
if (++linecount[n]<prof->kernelwidth[n])
break;
else
linecount[n] = 0; /* No need to initialize it to 0! */
}
}
/* Second step: interpolate along other axes from the interpolation buffer */
for (n=1; n<naxis; n++)
{
make_kernel(dpos[n], kernel_vector, prof->interptype[n]);
kwidth = prof->kernelwidth[n];
pixout = pixin = prof->kernelbuf;
for (j = (nlines/=kwidth); j--;)
{
val = 0.0;
kvector = kernel_vector;
for (i=kwidth; i--;)
val += *(kvector++)**(pixin++);
*(pixout++) = val;
}
}
return prof->kernelbuf[0];
}
/****** interpolate_pix ******************************************************
PROTO void interpolate_pix(float *posin, float *pix, int naxisn,
interpenum interptype)
PURPOSE Interpolate a model profile at a given position.
INPUT Profile structure,
input position vector,
input pixmap dimension vector,
interpolation type.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 07/12/2006
***/
static float interpolate_pix(float *posin, float *pix, int *naxisn,
float buffer[INTERP_MAXKERNELWIDTH],
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
kernel[INTERP_MAXKERNELWIDTH], dpos[2],
*kvector, *pixin, *pixout,
val;
int fac, ival, kwidth, start, width, step,
i,j, n;
kwidth = interp_kernwidth[interptype];
start = 0;
fac = 1;
for (n=0; n<2; n++)
{
val = *(posin++);
width = naxisn[n];
/*-- Get the integer part of the current coordinate or nearest neighbour */
ival = (interptype==INTERP_NEARESTNEIGHBOUR)? (int)(val-0.50001):(int)val;
/*-- Store the fractional part of the current coordinate */
dpos[n] = val - ival;
/*-- Check if interpolation start/end exceed image boundary... */
ival-=kwidth/2;
if (ival<0 || ival+kwidth<=0 || ival+kwidth>width)
return 0.0;
/*-- Update starting pointer */
start += ival*fac;
/*-- Update step between interpolated regions */
fac *= width;
}
/* First step: interpolate along NAXIS1 from the data themselves */
make_kernel(dpos[0], kernel, interptype);
step = naxisn[0]-kwidth;
pixin = pix+start;
pixout = buffer;
for (j=kwidth; j--;)
{
val = 0.0;
kvector = kernel;
for (i=kwidth; i--;)
val += *(kvector++)**(pixin++);
*(pixout++) = val;
pixin += step;
}
/* Second step: interpolate along NAXIS2 from the interpolation buffer */
make_kernel(dpos[1], kernel, interptype);
pixin = buffer;
val = 0.0;
kvector = kernel;
for (i=kwidth; i--;)
val += *(kvector++)**(pixin++);
return val;
}
/****** make_kernel **********************************************************
PROTO void make_kernel(float pos, float *kernel, interpenum interptype)
PURPOSE Conpute interpolation-kernel data
INPUT Position,
Pointer to the output kernel data,
Interpolation method.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
void make_kernel(float pos, float *kernel, interpenum interptype)
float x, val, sinx1,sinx2,sinx3,cosx1;