Newer
Older
float *profit_residuals(profitstruct *profit, picstruct *field,
picstruct *wfield, float dynparam, float *param, float *resi)
{
int p;
memset(profit->modpix, 0,
profit->modnaxisn[0]*profit->modnaxisn[1]*sizeof(float));
for (p=0; p<profit->nparam; p++)
profit->param[p] = param[p];
/* Simple PSF shortcut */
if (profit->nprof == 1 && profit->prof[0]->code == PROF_DIRAC)
profit_resample(profit, profit->psfpix, profit->lmodpix,
*profit->prof[0]->flux);
profit->flux = *profit->prof[0]->flux;
}
else
{
profit->flux = 0.0;
for (p=0; p<profit->nprof; p++)
profit->flux += prof_add(profit->prof[p], profit);
profit_convolve(profit, profit->modpix);
profit_resample(profit, profit->modpix, profit->lmodpix, 1.0);
}
profit_compresi(profit, dynparam, resi);
return resi;
}
/****** profit_compresi ******************************************************
PROTO float *prof_compresi(profitstruct *profit, float dynparam,
float *resi)
PURPOSE Compute the vector of residuals between the data and the galaxy
profile model.
INPUT Profile-fitting structure,
dynamic-compression parameter (0=no compression),
vector of residuals (output).
OUTPUT Vector of residuals.
NOTES -.
AUTHOR E. Bertin (IAP)
float *profit_compresi(profitstruct *profit, float dynparam, float *resi)
double error;
float *resit;
PIXTYPE *objpix, *objweight, *lmodpix,
val,val2,wval, invsig;
/* Compute vector of residuals */
resit = resi;
objpix = profit->objpix;
objweight = profit->objweight;
lmodpix = profit->lmodpix;
error = 0.0;
npix = profit->objnaxisn[0]*profit->objnaxisn[1];
if (dynparam > 0.0)
invsig = (PIXTYPE)(1.0/dynparam);
for (i=npix; i--; lmodpix++)
{
val = *(objpix++);
if ((wval=*(objweight++))>0.0)
{
val2 = (val - *lmodpix)*wval*invsig;
val2 = val2>0.0? logf(1.0+val2) : -logf(1.0-val2);
profit->chi2 = dynparam*dynparam*error;
}
else
{
for (i=npix; i--; lmodpix++)
{
val = *(objpix++);
if ((wval=*(objweight++))>0.0)
{
val2 = (val - *lmodpix)*wval;
*(resit++) = val2;
error += val2*val2;
}
}
profit->chi2 = error;
}
return resi;
}
/****** profit_resample ******************************************************
PROTO void prof_resample(profitstruct *profit, float *inpix,
PIXTYPE *outpix)
PURPOSE Resample the current full resolution model to image resolution.
INPUT Profile-fitting structure.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 09/10/2009
void profit_resample(profitstruct *profit, float *inpix, PIXTYPE *outpix,
float factor)
double flux;
float posin[2], posout[2], dnaxisn[2],
xcout,ycout, xcin,ycin, invpixstep, pix, off,step;
int d,i, ix,iy,ns;
xcout = (float)(profit->objnaxisn[0]/2) + 1.0; /* FITS convention */
if ((dx=(profit->paramlist[PARAM_X])))
xcout += *dx;
ycout = (float)(profit->objnaxisn[1]/2) + 1.0; /* FITS convention */
if ((dy=(profit->paramlist[PARAM_Y])))
ycout += *dy;
xcin = (profit->modnaxisn[0]/2) + 1.0; /* FITS convention */
ycin = (profit->modnaxisn[1]/2) + 1.0; /* FITS convention */
invpixstep = profit->subsamp/profit->pixstep;
/* Initialize multi-dimensional counters */
for (d=0; d<2; d++)
{
posout[d] = 1.0; /* FITS convention */
dnaxisn[d] = profit->objnaxisn[d]+0.5;
}
/* Remap each pixel (and rebin if necessary) */
ns=(int)profit->subsamp;
if (ns>1)
step = 1.0/profit->subsamp;
off = 0.5*(step - 1.0);
xcin += off;
ycin += off;
for (i=profit->objnaxisn[0]*profit->objnaxisn[1]; i--;)
{
posin[0] = (posout[0] - xcout)*invpixstep + xcin;
posin[1] = (posout[1] - ycout)*invpixstep + ycin;
pix = 0.0;
for (iy=ns; iy--; posin[1] += step)
for (ix=ns; ix--; posin[0] += step)
pix += (PIXTYPE)(factor*interpolate_pix(posin, inpix,
profit->modnaxisn, INTERP_LANCZOS3));
flux += (*(outpix++) = pix);
for (d=0; d<2; d++)
if ((posout[d]+=1.0) < dnaxisn[d])
break;
else
posout[d] = 1.0;
}
else
for (i=profit->objnaxisn[0]*profit->objnaxisn[1]; i--;)
{
posin[0] = (posout[0] - xcout)*invpixstep + xcin;
posin[1] = (posout[1] - ycout)*invpixstep + ycin;
flux += ((*(outpix++) = (PIXTYPE)(factor*interpolate_pix(posin, inpix,
profit->modnaxisn, INTERP_LANCZOS3))));
for (d=0; d<2; d++)
if ((posout[d]+=1.0) < dnaxisn[d])
break;
else
posout[d] = 1.0;
}
return;
}
/****** profit_convolve *******************************************************
PROTO void profit_convolve(profitstruct *profit, float *modpix)
PURPOSE Convolve a model image with the local PSF.
INPUT Pointer to the profit structure,
Pointer to the image raster.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 15/09/2008
***/
void profit_convolve(profitstruct *profit, float *modpix)
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
{
if (!profit->psfdft)
profit_makedft(profit);
fft_conv(modpix, profit->psfdft, profit->modnaxisn);
return;
}
/****** profit_makedft *******************************************************
PROTO void profit_makedft(profitstruct *profit)
PURPOSE Create the Fourier transform of the descrambled PSF component.
INPUT Pointer to the profit structure.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 22/04/2008
***/
void profit_makedft(profitstruct *profit)
{
psfstruct *psf;
float *mask,*maskt, *ppix;
float dx,dy, r,r2,rmin,rmin2,rmax,rmax2,rsig,invrsig2;
int width,height,npix,offset, psfwidth,psfheight,psfnpix,
cpwidth, cpheight,hcpwidth,hcpheight, i,j,x,y;
if (!(psf=profit->psf))
return;
psfwidth = profit->modnaxisn[0];
psfheight = profit->modnaxisn[1];
psfnpix = psfwidth*psfheight;
width = profit->modnaxisn[0];
height = profit->modnaxisn[1];
npix = width*height;
QCALLOC(mask, float, npix);
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
cpwidth = (width>psfwidth)?psfwidth:width;
hcpwidth = cpwidth>>1;
cpwidth = hcpwidth<<1;
offset = width - cpwidth;
cpheight = (height>psfheight)?psfheight:height;
hcpheight = cpheight>>1;
cpheight = hcpheight<<1;
/* Frame and descramble the PSF data */
ppix = profit->psfpix + (psfheight/2)*psfwidth + psfwidth/2;
maskt = mask;
for (j=hcpheight; j--; ppix+=psfwidth)
{
for (i=hcpwidth; i--;)
*(maskt++) = *(ppix++);
ppix -= cpwidth;
maskt += offset;
for (i=hcpwidth; i--;)
*(maskt++) = *(ppix++);
}
ppix = profit->psfpix + ((psfheight/2)-hcpheight)*psfwidth + psfwidth/2;
maskt += width*(height-cpheight);
for (j=hcpheight; j--; ppix+=psfwidth)
{
for (i=hcpwidth; i--;)
*(maskt++) = *(ppix++);
ppix -= cpwidth;
maskt += offset;
for (i=hcpwidth; i--;)
*(maskt++) = *(ppix++);
}
/* Truncate to a disk that has diameter = (box width) */
rmax = cpwidth - 1.0 - hcpwidth;
if (rmax > (r=hcpwidth))
rmax = r;
if (rmax > (r=cpheight-1.0-hcpheight))
rmax = r;
if (rmax > (r=hcpheight))
rmax = r;
if (rmax<1.0)
rmax = 1.0;
rmax2 = rmax*rmax;
rsig = psf->fwhm/profit->pixstep;
invrsig2 = 1/(2*rsig*rsig);
rmin = rmax - (3*rsig); /* 3 sigma annulus (almost no aliasing) */
rmin2 = rmin*rmin;
maskt = mask;
dy = 0.0;
for (y=hcpheight; y--; dy+=1.0)
{
dx = 0.0;
for (x=hcpwidth; x--; dx+=1.0, maskt++)
if ((r2=dx*dx+dy*dy)>rmin2)
*maskt *= (r2>rmax2)?0.0:expf((2*rmin*sqrtf(r2)-r2-rmin2)*invrsig2);
dx = -hcpwidth;
maskt += offset;
for (x=hcpwidth; x--; dx+=1.0, maskt++)
if ((r2=dx*dx+dy*dy)>rmin2)
*maskt *= (r2>rmax2)?0.0:expf((2*rmin*sqrtf(r2)-r2-rmin2)*invrsig2);
}
dy = -hcpheight;
maskt += width*(height-cpheight);
for (y=hcpheight; y--; dy+=1.0)
{
dx = 0.0;
for (x=hcpwidth; x--; dx+=1.0, maskt++)
if ((r2=dx*dx+dy*dy)>rmin2)
*maskt *= (r2>rmax2)?0.0:expf((2*rmin*sqrtf(r2)-r2-rmin2)*invrsig2);
dx = -hcpwidth;
maskt += offset;
for (x=hcpwidth; x--; dx+=1.0, maskt++)
if ((r2=dx*dx+dy*dy)>rmin2)
*maskt *= (r2>rmax2)?0.0:expf((2*rmin*sqrtf(r2)-r2-rmin2)*invrsig2);
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
}
/* Finally move to Fourier space */
profit->psfdft = fft_rtf(mask, profit->modnaxisn);
free(mask);
return;
}
/****** profit_copyobjpix *****************************************************
PROTO int profit_copyobjpix(profitstruct *profit, picstruct *field,
picstruct *wfield)
PURPOSE Copy a piece of the input field image to a profit structure.
INPUT Pointer to the profit structure,
Pointer to the field structure,
Pointer to the field weight structure.
OUTPUT The number of valid pixels copied.
NOTES Global preferences are used.
AUTHOR E. Bertin (IAP)
Emmanuel Bertin
committed
VERSION 01/12/2009
***/
int profit_copyobjpix(profitstruct *profit, picstruct *field,
picstruct *wfield)
{
Emmanuel Bertin
committed
float dx, dy2, dr2, rad2;
PIXTYPE *pixin,*spixin, *wpixin,*swpixin, *pixout,*wpixout,
backnoise2, invgain, satlevel, wthresh, pix,spix, wpix,swpix;
int i,x,y, xmin,xmax,ymin,ymax, w,h,dw, npix, off, gainflag,
Emmanuel Bertin
committed
badflag, sflag, sx,sy,sn,sw, ix,iy;
/* First put the image background to -BIG */
pixout = profit->objpix;
wpixout = profit->objweight;
Emmanuel Bertin
committed
for (i=profit->objnaxisn[0]*profit->objnaxisn[1]; i--;)
{
*(pixout++) = -BIG;
*(wpixout++) = 0.0;
}
/* Don't go further if out of frame!! */
ix = profit->ix;
iy = profit->iy;
if (ix<0 || ix>=field->width || iy<field->ymin || iy>=field->ymax)
return 0;
backnoise2 = field->backsig*field->backsig;
sn = (int)profit->subsamp;
Emmanuel Bertin
committed
sflag = (sn>1);
w = profit->objnaxisn[0]*sn;
h = profit->objnaxisn[1]*sn;
if (sflag)
backnoise2 *= (PIXTYPE)sn;
invgain = (field->gain > 0.0) ? 1.0/field->gain : 0.0;
satlevel = field->satur_level - profit->obj->bkg;
rad2 = h/2.0;
if (rad2 > w/2.0)
rad2 = w/2.0;
rad2 *= rad2;
/* Set the image boundaries */
pixout = profit->objpix;
wpixout = profit->objweight;
ymin = iy-h/2;
ymax = ymin + h;
if (ymin<field->ymin)
{
Emmanuel Bertin
committed
off = (field->ymin-ymin-1)/sn + 1;
pixout += off*profit->objnaxisn[0];
wpixout += off*profit->objnaxisn[0];
ymin += off*sn;
Emmanuel Bertin
committed
ymax -= ((ymax-field->ymax-1)/sn + 1)*sn;
Emmanuel Bertin
committed
dw = 0;
Emmanuel Bertin
committed
off = (xmax-field->width-1)/sn + 1;
dw += off;
xmax -= off*sn;
Emmanuel Bertin
committed
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
off = (-xmin-1)/sn + 1;
pixout += off;
wpixout += off;
dw += off;
xmin += off*sn;
}
/* Make sure the input frame size is a multiple of the subsampling step */
if (sflag)
{
/*
if (((rem=ymax-ymin)%sn))
{
ymin += rem/2;
ymax -= (rem-rem/2);
}
if (((rem=xmax-xmin)%sn))
{
xmin += rem/2;
pixout += rem/2;
wpixout += rem/2;
dw += rem;
xmax -= (rem-rem/2);
}
*/
sw = field->width;
}
/* Copy the right pixels to the destination */
npix = 0;
if (wfield)
{
wthresh = wfield->weight_thresh;
gainflag = prefs.weightgain_flag;
Emmanuel Bertin
committed
if (sflag)
Emmanuel Bertin
committed
/*---- Sub-sampling case */
for (y=ymin; y<ymax; y+=sn, pixout+=dw,wpixout+=dw)
Emmanuel Bertin
committed
for (x=xmin; x<xmax; x+=sn)
Emmanuel Bertin
committed
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
pix = wpix = 0.0;
badflag = 0;
for (sy=0; sy<sn; sy++)
{
dy2 = (y+sy-iy);
dy2 *= dy2;
dx = (x-ix);
spixin = &PIX(field, x, y+sy);
swpixin = &PIX(wfield, x, y+sy);
for (sx=sn; sx--;)
{
dr2 = dy2 + dx*dx;
dx++;
spix = *(spixin++);
swpix = *(swpixin++);
if (dr2<rad2 && spix>-BIG && spix<satlevel && swpix<wthresh)
{
pix += spix;
wpix += swpix;
}
else
badflag=1;
}
}
*(pixout++) = pix;
if (!badflag) /* A single bad pixel ruins is all (saturation, etc.)*/
{
*(wpixout++) = 1.0 / sqrt(wpix+(pix>0.0?
(gainflag? pix*wpix/backnoise2:pix)*invgain : 0.0));
Emmanuel Bertin
committed
npix++;
}
else
*(wpixout++) = 0.0;
Emmanuel Bertin
committed
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
else
for (y=ymin; y<ymax; y++, pixout+=dw,wpixout+=dw)
{
dy2 = y-iy;
dy2 *= dy2;
pixin = &PIX(field, xmin, y);
wpixin = &PIX(wfield, xmin, y);
for (x=xmin; x<xmax; x++)
{
dx = x-ix;
dr2 = dy2 + dx*dx;
pix = *(pixin++);
wpix = *(wpixin++);
if (dr2<rad2 && pix>-BIG && pix<satlevel && wpix<wthresh)
{
*(pixout++) = pix;
*(wpixout++) = 1.0 / sqrt(wpix+(pix>0.0?
(gainflag? pix*wpix/backnoise2:pix)*invgain : 0.0));
npix++;
}
else
*(pixout++) = *(wpixout++) = 0.0;
}
}
Emmanuel Bertin
committed
{
if (sflag)
Emmanuel Bertin
committed
/*---- Sub-sampling case */
for (y=ymin; y<ymax; y+=sn, pixout+=dw, wpixout+=dw)
Emmanuel Bertin
committed
for (x=xmin; x<xmax; x+=sn)
Emmanuel Bertin
committed
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
pix = 0.0;
badflag = 0;
for (sy=0; sy<sn; sy++)
{
dy2 = y+sy-iy;
dy2 *= dy2;
dx = x-ix;
spixin = &PIX(field, x, y+sy);
for (sx=sn; sx--;)
{
dr2 = dy2 + dx*dx;
dx++;
spix = *(spixin++);
if (dr2<rad2 && spix>-BIG && spix<satlevel)
pix += spix;
else
badflag=1;
}
}
*(pixout++) = pix;
if (!badflag) /* A single bad pixel ruins is all (saturation, etc.)*/
{
*(wpixout++) = 1.0 / sqrt(backnoise2 + (pix>0.0?pix*invgain:0.0));
npix++;
}
else
*(wpixout++) = 0.0;
Emmanuel Bertin
committed
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
else
for (y=ymin; y<ymax; y++, pixout+=dw,wpixout+=dw)
{
dy2 = y-iy;
dy2 *= dy2;
pixin = &PIX(field, xmin, y);
for (x=xmin; x<xmax; x++)
{
dx = x-ix;
dr2 = dy2 + dx*dx;
pix = *(pixin++);
if (dr2<rad2 && pix>-BIG && pix<satlevel)
{
*(pixout++) = pix;
*(wpixout++) = 1.0 / sqrt(backnoise2 + (pix>0.0?pix*invgain : 0.0));
npix++;
}
else
*(pixout++) = *(wpixout++) = 0.0;
}
}
}
return npix;
}
/****** profit_spiralindex ****************************************************
PROTO float profit_spiralindex(profitstruct *profit)
PURPOSE Compute the spiral index of a galaxy image (positive for arms
extending counter-clockwise and negative for arms extending CW, 0 for
no spiral pattern).
INPUT Profile-fitting structure.
OUTPUT Vector of residuals.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 18/09/2008
***/
float profit_spiralindex(profitstruct *profit)
{
objstruct *obj;
obj2struct *obj2;
float *dx,*dy, *fdx,*fdy, *gdx,*gdy, *gdxt,*gdyt, *pix,
fwhm, invtwosigma2, hw,hh, ohw,ohh, x,y,xstart, tx,ty,txstart,
gx,gy, r2, spirindex, invsig, val, sep;
PIXTYPE *fpix;
int i,j, npix;
npix = profit->objnaxisn[0]*profit->objnaxisn[1];
obj = profit->obj;
obj2 = profit->obj2;
/* Compute simple derivative vectors at a fraction of the object scale */
fwhm = obj2->hl_radius * 2.0 / 4.0;
if (fwhm < 2.0)
fwhm = 2.0;
sep = 2.0;
invtwosigma2 = -(2.35*2.35/(2.0*fwhm*fwhm));
hw = (float)(profit->objnaxisn[0]/2);
hh = (float)(profit->objnaxisn[1]/2);
ohh = profit->objnaxisn[1] - hh;
txstart = -hw;
ty = -hh;
QMALLOC(dx, float, npix);
pix = dx;
for (j=profit->objnaxisn[1]; j--; ty+=1.0)
{
tx = txstart;
y = ty < -0.5? ty + hh : ty - ohh;
for (i=profit->objnaxisn[0]; i--; tx+=1.0)
{
x = tx < -0.5? tx + hw : tx - ohw;
*(pix++) = exp(invtwosigma2*((x+sep)*(x+sep)+y*y))
- exp(invtwosigma2*((x-sep)*(x-sep)+y*y));
}
}
QMALLOC(dy, float, npix);
pix = dy;
ty = -hh;
for (j=profit->objnaxisn[1]; j--; ty+=1.0)
{
tx = txstart;
y = ty < -0.5? ty + hh : ty - ohh;
for (i=profit->objnaxisn[0]; i--; tx+=1.0)
{
x = tx < -0.5? tx + hw : tx - ohw;
*(pix++) = exp(invtwosigma2*(x*x+(y+sep)*(y+sep)))
- exp(invtwosigma2*(x*x+(y-sep)*(y-sep)));
}
}
QMALLOC(gdx, float, npix);
gdxt = gdx;
fpix = profit->objpix;
invsig = npix/profit->sigma;
for (i=npix; i--; fpix++)
{
val = *fpix > -1e29? *fpix*invsig : 0.0;
*(gdxt++) = (val>0.0? log(1.0+val) : -log(1.0-val));
}
gdy = NULL; /* to avoid gcc -Wall warnings */
QMEMCPY(gdx, gdy, float, npix);
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
fdx = fft_rtf(dx, profit->objnaxisn);
fft_conv(gdx, fdx, profit->objnaxisn);
fdy = fft_rtf(dy, profit->objnaxisn);
fft_conv(gdy, fdy, profit->objnaxisn);
/* Compute estimator */
invtwosigma2 = -1.18*1.18 / (2.0*obj2->hl_radius*obj2->hl_radius);
xstart = -hw - obj->mx + (int)(obj->mx+0.49999);
y = -hh - obj->my + (int)(obj->my+0.49999);;
spirindex = 0.0;
gdxt = gdx;
gdyt = gdy;
for (j=profit->objnaxisn[1]; j--; y+=1.0)
{
x = xstart;
for (i=profit->objnaxisn[0]; i--; x+=1.0)
{
gx = *(gdxt++);
gy = *(gdyt++);
if ((r2=x*x+y*y)>0.0)
spirindex += (x*y*(gx*gx-gy*gy)+gx*gy*(y*y-x*x))/r2
* exp(invtwosigma2*r2);
}
}
free(dx);
free(dy);
free(fdx);
free(fdy);
free(gdx);
free(gdy);
return spirindex;
}
/****** profit_moments ****************************************************
PROTO void profit_moments(profitstruct *profit, obj2struct *obj2)
PURPOSE Compute the 2nd order moments from the unconvolved object model.
INPUT Profile-fitting structure,
Pointer to obj2 structure.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 17/09/2009
void profit_moments(profitstruct *profit, obj2struct *obj2)
double mx,my, sum, mx2,my2,mxy, den, temp,temp2,pmx2,theta;
float *pix,
hw,hh, x,y, xstart, val, r2max;
hw = (float)(profit->modnaxisn[0]/2);
hh = (float)(profit->modnaxisn[1]/2);
r2max = hw<hh? hw*hw : hh*hh;
xstart = -hw;
y = -hh;
pix = profit->modpix;
mx2 = my2 = mxy = mx = my = sum = 0.0;
for (iy=profit->modnaxisn[1]; iy--; y+=1.0)
{
x = xstart;
for (ix=profit->modnaxisn[0]; ix--; x+=1.0)
if (y*y+x*x <= r2max)
{
val = *(pix++);
sum += val;
mx += val*x;
my += val*y;
mx2 += val*x*x;
mxy += val*x*y;
my2 += val*y*y;
}
else
pix++;
}
if (sum <= 1.0/BIG)
sum = 1.0;
mx /= sum;
my /= sum;
obj2->prof_mx2 = mx2 = mx2/sum - mx*mx;
obj2->prof_my2 = my2 = my2/sum - my*my;
obj2->prof_mxy = mxy = mxy/sum - mx*my;
/* Handle fully correlated profiles (which cause a singularity...) */
if ((temp2=mx2*my2-mxy*mxy)<0.00694)
mx2 += 0.0833333;
my2 += 0.0833333;
temp2 = mx2*my2-mxy*mxy;
}
if (FLAG(obj2.prof_e1))
{
if (mx2+my2 > 1.0/BIG)
{
obj2->prof_pol1 = (mx2 - my2) / (mx2+my2);
obj2->prof_pol2 = 2.0*mxy / (mx2 + my2);
if (temp2>=0.0)
den = mx2+my2+2.0*sqrt(temp2);
else
den = mx2+my2;
obj2->prof_e1 = (mx2 - my2) / den;
obj2->prof_e2 = 2.0*mxy / den;
}
obj2->prof_pol1 = obj2->prof_pol2 = obj2->prof_e1 = obj2->prof_e2 = 0.0;
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
if (FLAG(obj2.prof_cxx))
{
obj2->prof_cxx = (float)(my2/temp2);
obj2->prof_cyy = (float)(mx2/temp2);
obj2->prof_cxy = (float)(-2*mxy/temp2);
}
if (FLAG(obj2.prof_a))
{
if ((fabs(temp=mx2-my2)) > 0.0)
theta = atan2(2.0 * mxy,temp) / 2.0;
else
theta = PI/4.0;
temp = sqrt(0.25*temp*temp+mxy*mxy);
pmx2 = 0.5*(mx2+my2);
obj2->prof_a = (float)sqrt(pmx2 + temp);
obj2->prof_b = (float)sqrt(pmx2 - temp);
obj2->prof_theta = theta*180.0/PI;
}
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
/****** profit_surface ****************************************************
PROTO void profit_surface(profitstruct *profit, obj2struct *obj2,
double lostfluxfrac)
PURPOSE Compute surface brightnesses from the unconvolved object model.
INPUT Pointer to the profile-fitting structure,
Pointer to obj2 structure,
Fraction of total flux lost in model.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 21/09/2009
***/
void profit_surface(profitstruct *profit, obj2struct *obj2,
double lostfluxfrac)
{
double dsum,dhsum,dsumoff, dhval, frac, seff;
float *spix, *spixt;
int i, npix, neff;
npix = profit->modnaxisn[0]*profit->modnaxisn[1];
/* Sort model pixel values */
spix = NULL; /* to avoid gcc -Wall warnings */
QMEMCPY(profit->modpix, spix, float, npix);
hmedian(spix, npix);
obj2->peak_prof = spix[npix-1];
if (FLAG(obj2.fluxeff_prof))
{
/*-- Build a cumulative distribution */
dsum = 0.0;
spixt = spix;
for (i=npix; i--;)
dsum += (double)*(spixt++);
/*-- Find matching surface brightness */
if (lostfluxfrac > 1.0)
lostfluxfrac = 0.0;
dhsum = 0.5 * dsum / (1.0-lostfluxfrac);
dsum = lostfluxfrac * dsum / (1.0-lostfluxfrac);
neff = 0;
spixt = spix;
for (i=npix; i--;)
if ((dsum += (double)*(spixt++)) >= dhsum)
{
neff = i;
break;
}
dhval = (double)*(spixt-1);
seff = neff;
dsumoff = 0.0;
if (spixt>=spix+2)
if (dhval > 0.0 && (frac = (dsum - dhsum) / dhval) < 1.0)
{
seff += frac;
dsumoff = frac*dhval;
dhval = dsumoff + (1.0 - frac)*(double)*(spixt-2);
}
obj2->fluxeff_prof = dhval;
if (FLAG(obj2.fluxmean_prof))
{
dsum = dsumoff;
for (i=neff; i--;)
dsum += (double)*(spixt++);
obj2->fluxmean_prof = seff > 0.0? dsum / seff : 0.0;
}
}
free(spix);
return;
}
/****** profit_addparam *******************************************************
PROTO void profit_addparam(profitstruct *profit, paramenum paramindex,
PURPOSE Add a profile parameter to the list of fitted items.
INPUT Pointer to the profit structure,
Parameter index,
Pointer to the parameter pointer.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 29/03/2007
***/
void profit_addparam(profitstruct *profit, paramenum paramindex,
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
{
/* Check whether the parameter has already be registered */
if (profit->paramlist[paramindex])
/*-- Yes */
*param = profit->paramlist[paramindex];
else
/*-- No */
{
*param = profit->paramlist[paramindex] = &profit->param[profit->nparam];
profit->paramindex[paramindex] = profit->nparam++;
}
return;
}
/****** profit_resetparam ****************************************************
PROTO void profit_resetparam(profitstruct *profit, paramenum paramtype)
PURPOSE Set the initial, lower and upper boundary values of a profile parameter.
INPUT Pointer to the profit structure,
Parameter index.
OUTPUT -.
NOTES -.
AUTHOR E. Bertin (IAP)
VERSION 25/09/2008
***/
void profit_resetparam(profitstruct *profit, paramenum paramtype)
{
objstruct *obj;
obj2struct *obj2;
float param, parammin,parammax;
obj = profit->obj;
obj2 = profit->obj2;
param = parammin = parammax = 0.0; /* Avoid gcc -Wall warnings*/
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
switch(paramtype)
{
case PARAM_BACK:
param = 0.0;
parammin = -6.0*obj->sigbkg;
parammax = 6.0*obj->sigbkg;
break;
case PARAM_X:
param = obj->mx - (int)(obj->mx+0.49999);
parammin = -obj2->hl_radius*4;
parammax = obj2->hl_radius*4;
break;
case PARAM_Y:
param = obj->my - (int)(obj->my+0.49999);
parammin = -obj2->hl_radius*4;
parammax = obj2->hl_radius*4;
break;
case PARAM_SPHEROID_FLUX:
param = obj2->flux_auto/2.0;
parammin = -obj2->flux_auto/1000.0;
parammax = 2*obj2->flux_auto;
break;
case PARAM_SPHEROID_REFF:
param = obj2->hl_radius;
parammin = 0.1;
parammax = param * 4.0;
break;
case PARAM_SPHEROID_ASPECT:
param = FLAG(obj2.prof_disk_flux)? 1.0 : obj->b/obj->a;
parammin = FLAG(obj2.prof_disk_flux)? 0.5 : 0.01;
parammax = 1.0;
break;
case PARAM_SPHEROID_POSANG:
param = obj->theta;
parammin = 0.0;
parammax = 0.0;
break;
case PARAM_SPHEROID_SERSICN:
param = 4.0;
parammin = 1.0;
parammax = 10.0;
break;
case PARAM_DISK_FLUX:
param = obj2->flux_auto/2.0;
parammin = -obj2->flux_auto/1000.0;
parammax = 2*obj2->flux_auto;
break;
case PARAM_DISK_SCALE: /* From scalelength to Re */
param = obj2->hl_radius/1.67835*sqrt(obj->a/obj->b);
Emmanuel Bertin
committed
parammin = param/4.0;
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
parammax = param * 4.0;
break;
case PARAM_DISK_ASPECT:
param = obj->b/obj->a;
parammin = 0.01;
parammax = 1.0;
break;
case PARAM_DISK_POSANG:
param = obj->theta;
parammin = 0.0;
parammax = 0.0;
break;
case PARAM_ARMS_FLUX:
param = obj2->flux_auto/2.0;
parammin = 0.0;
parammax = obj2->flux_auto*2.0;
break;
case PARAM_ARMS_QUADFRAC:
param = 0.5;
parammin = 0.0;
parammax = 1.0;
break;
case PARAM_ARMS_SCALE:
param = 1.0;
parammin = 0.5;
parammax = 10.0;
break;
case PARAM_ARMS_START:
param = 0.5;
parammin = 0.0;
parammax = 3.0;
break;
case PARAM_ARMS_PITCH:
param = 20.0;
parammin = 5.0;
parammax = 50.0;
break;
case PARAM_ARMS_PITCHVAR:
param = 0.0;
parammin = -1.0;
parammax = 1.0;
break;
// if ((profit->spirindex=profit_spiralindex(profit, obj, obj2)) > 0.0)
// {
// param = -param;
// parammin = -parammax;
// parammax = -parammin;
// }
// printf("spiral index: %g \n", profit->spirindex);
// break;
case PARAM_ARMS_POSANG:
param = 0.0;
parammin = 0.0;
parammax = 0.0;
break;
case PARAM_ARMS_WIDTH:
param = 3.0;
parammin = 1.5;
parammax = 11.0;
break;