Newer
Older
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);
Emmanuel Bertin
committed
prof->fluxfac = fluxfac = fabs(flux)>0.0? profit->fluxfac/fabs(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 MODEL_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 */
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
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];
case MODEL_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];
case MODEL_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];
m20 = 1.0;
index = profit->paramindex[PARAM_ARMS_FLUX];
break;
m20 = 1.0;
index = profit->paramindex[PARAM_BAR_FLUX];
break;
case MODEL_INRING:
m20 = 1.0;
index = profit->paramindex[PARAM_INRING_FLUX];
break;
case MODEL_OUTRING:
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],
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
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],
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
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;
if (interptype == INTERP_NEARESTNEIGHBOUR)
*kernel = 1;
else if (interptype == INTERP_BILINEAR)
{
*(kernel++) = 1.0-pos;
*kernel = pos;
}
else if (interptype == INTERP_LANCZOS2)
{
if (pos<1e-5 && pos>-1e-5)
{
*(kernel++) = 0.0;
*(kernel++) = 1.0;
*(kernel++) = 0.0;
*kernel = 0.0;
}
else
{
x = -PI/2.0*(pos+1.0);
sincosf(x, &sinx1, &cosx1);
sinx1 = sinf(x);
cosx1 = cosf(x);
#endif
val = (*(kernel++) = sinx1/(x*x));
x += PI/2.0;
val += (*(kernel++) = -cosx1/(x*x));
x += PI/2.0;
val += (*(kernel++) = -sinx1/(x*x));
x += PI/2.0;
val += (*kernel = cosx1/(x*x));
val = 1.0/val;
*(kernel--) *= val;
*(kernel--) *= val;
*(kernel--) *= val;
*kernel *= val;
}
}
else if (interptype == INTERP_LANCZOS3)
{
if (pos<1e-5 && pos>-1e-5)
{
*(kernel++) = 0.0;
*(kernel++) = 0.0;
*(kernel++) = 1.0;
*(kernel++) = 0.0;
*(kernel++) = 0.0;
*kernel = 0.0;
}
else
{
x = -PI/3.0*(pos+2.0);
#ifdef HAVE_SINCOSF
sincosf(x, &sinx1, &cosx1);
sinx1 = sinf(x);
cosx1 = cosf(x);
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
#endif
val = (*(kernel++) = sinx1/(x*x));
x += PI/3.0;
val += (*(kernel++) = (sinx2=-0.5*sinx1-0.866025403785*cosx1)
/ (x*x));
x += PI/3.0;
val += (*(kernel++) = (sinx3=-0.5*sinx1+0.866025403785*cosx1)
/(x*x));
x += PI/3.0;
val += (*(kernel++) = sinx1/(x*x));
x += PI/3.0;
val += (*(kernel++) = sinx2/(x*x));
x += PI/3.0;
val += (*kernel = sinx3/(x*x));
val = 1.0/val;
*(kernel--) *= val;
*(kernel--) *= val;
*(kernel--) *= val;
*(kernel--) *= val;
*(kernel--) *= val;
*kernel *= val;
}
}
else if (interptype == INTERP_LANCZOS4)
{
if (pos<1e-5 && pos>-1e-5)
{
*(kernel++) = 0.0;
*(kernel++) = 0.0;
*(kernel++) = 0.0;
*(kernel++) = 1.0;
*(kernel++) = 0.0;
*(kernel++) = 0.0;
*(kernel++) = 0.0;
*kernel = 0.0;
}
else
{
x = -PI/4.0*(pos+3.0);
sincosf(x, &sinx1, &cosx1);
sinx1 = sinf(x);
cosx1 = cosf(x);
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
#endif
val = (*(kernel++) = sinx1/(x*x));
x += PI/4.0;
val +=(*(kernel++) = -(sinx2=0.707106781186*(sinx1+cosx1))
/(x*x));
x += PI/4.0;
val += (*(kernel++) = cosx1/(x*x));
x += PI/4.0;
val += (*(kernel++) = -(sinx3=0.707106781186*(cosx1-sinx1))/(x*x));
x += PI/4.0;
val += (*(kernel++) = -sinx1/(x*x));
x += PI/4.0;
val += (*(kernel++) = sinx2/(x*x));
x += PI/4.0;
val += (*(kernel++) = -cosx1/(x*x));
x += PI/4.0;
val += (*kernel = sinx3/(x*x));
val = 1.0/val;
*(kernel--) *= val;
*(kernel--) *= val;
*(kernel--) *= val;
*(kernel--) *= val;
*(kernel--) *= val;
*(kernel--) *= val;
*(kernel--) *= val;
*kernel *= val;
}
}
else
error(EXIT_FAILURE, "*Internal Error*: Unknown interpolation type in ",
"make_kernel()");
return;
}