profit.c 146 KB
Newer Older
1
2
/*
*				profit.c
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3
*
4
* Fit a range of galaxy models to an image.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
5
*
6
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Emmanuel Bertin's avatar
Emmanuel Bertin committed
7
*
8
*	This file part of:	SExtractor
Emmanuel Bertin's avatar
Emmanuel Bertin committed
9
*
10
*	Copyright:		(C) 2006-2013 Emmanuel Bertin -- IAP/CNRS/UPMC
11
12
13
14
15
16
17
18
19
20
21
22
23
24
*
*	License:		GNU General Public License
*
*	SExtractor is free software: you can redistribute it and/or modify
*	it under the terms of the GNU General Public License as published by
*	the Free Software Foundation, either version 3 of the License, or
*	(at your option) any later version.
*	SExtractor is distributed in the hope that it will be useful,
*	but WITHOUT ANY WARRANTY; without even the implied warranty of
*	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*	GNU General Public License for more details.
*	You should have received a copy of the GNU General Public License
*	along with SExtractor. If not, see <http://www.gnu.org/licenses/>.
*
25
*	Last modified:		23/09/2013
26
27
*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
Emmanuel Bertin's avatar
Emmanuel Bertin committed
28
29
30
31
32

#ifdef HAVE_CONFIG_H
#include        "config.h"
#endif

33
34
35
36
#ifndef HAVE_MATHIMF_H
#define _GNU_SOURCE
#endif

37
#include	<math.h>
Emmanuel Bertin's avatar
Emmanuel Bertin committed
38
39
40
41
42
43
44
45
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>

#include	"define.h"
#include	"globals.h"
#include	"prefs.h"
#include	"fits/fitscat.h"
46
#include	"levmar/levmar.h"
Emmanuel Bertin's avatar
Emmanuel Bertin committed
47
48
49
#include	"fft.h"
#include	"fitswcs.h"
#include	"check.h"
50
#include	"image.h"
Emmanuel Bertin's avatar
Emmanuel Bertin committed
51
52
53
54
#include	"pattern.h"
#include	"psf.h"
#include	"profit.h"

55
56
static double	prof_gammainc(double x, double a),
		prof_gamma(double x);
57
58
static float	prof_interpolate(profstruct *prof, float *posin);
static float	interpolate_pix(float *posin, float *pix, int *naxisn,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
59
60
		interpenum interptype);

61
static void	make_kernel(float pos, float *kernel, interpenum interptype);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
62
63
64

/*------------------------------- variables ---------------------------------*/

Emmanuel Bertin's avatar
Emmanuel Bertin committed
65
66
const int	interp_kernwidth[5]={1,2,4,6,8};

67
68
const int	flux_flag[PARAM_NPARAM] = {0,
					1,0,0,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
69
70
71
72
73
74
75
76
					1,0,0,0,0,
					1,0,0,0,
					1,0,0,0,0,0,0,0,
					1,0,0,
					1,0,0,
					1,0,0
					};

Emmanuel Bertin's avatar
Emmanuel Bertin committed
77
/* "Local" global variables for debugging purposes */
Emmanuel Bertin's avatar
Emmanuel Bertin committed
78
79
int theniter, the_gal;
static picstruct	*the_field, *the_wfield;
80
profitstruct		*theprofit,*thedprofit, *thepprofit, *theqprofit;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
81
82

/****** profit_init ***********************************************************
83
PROTO	profitstruct profit_init(psfstruct *psf, unsigned int modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
84
PURPOSE	Allocate and initialize a new profile-fitting structure.
85
86
INPUT	Pointer to PSF structure,
	Model type.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
87
88
89
OUTPUT	A pointer to an allocated profit structure.
NOTES	-.
AUTHOR	E. Bertin (IAP)
90
VERSION	22/04/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
91
 ***/
92
profitstruct	*profit_init(psfstruct *psf, unsigned int modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
93
94
  {
   profitstruct		*profit;
95
   int			t, nmodels;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
96
97
98

  QCALLOC(profit, profitstruct, 1);
  profit->psf = psf;
99
100
101
102
103
  QMALLOC(profit->prof, profstruct *, MODEL_NMAX);
  nmodels = 0;
  for (t=1; t<(1<<MODEL_NMAX); t<<=1)
    if (modeltype&t)
      profit->prof[nmodels++] = prof_init(profit, t);
104
105
106
107
108
109
110
111
112
113
/* Allocate memory for the complete model */
  QMALLOC16(profit->modpix, float, PROFIT_MAXMODSIZE*PROFIT_MAXMODSIZE);
  QMALLOC16(profit->modpix2, float, PROFIT_MAXMODSIZE*PROFIT_MAXMODSIZE);
  QMALLOC16(profit->cmodpix, float, PROFIT_MAXMODSIZE*PROFIT_MAXMODSIZE);
  QMALLOC16(profit->psfpix, float, PROFIT_MAXMODSIZE*PROFIT_MAXMODSIZE);
  QMALLOC16(profit->objpix, PIXTYPE, PROFIT_MAXOBJSIZE*PROFIT_MAXOBJSIZE);
  QMALLOC16(profit->objweight, PIXTYPE, PROFIT_MAXOBJSIZE*PROFIT_MAXOBJSIZE);
  QMALLOC16(profit->lmodpix, PIXTYPE, PROFIT_MAXOBJSIZE*PROFIT_MAXOBJSIZE);
  QMALLOC16(profit->lmodpix2, PIXTYPE, PROFIT_MAXOBJSIZE*PROFIT_MAXOBJSIZE);
  QMALLOC16(profit->resi, float, PROFIT_MAXOBJSIZE*PROFIT_MAXOBJSIZE);
114
  QMALLOC16(profit->presi, float, profit->nparam);
115
  QMALLOC16(profit->covar, float, profit->nparam*profit->nparam);
116
  profit->nprof = nmodels;
117
  profit->fluxfac = 1.0;	/* Default */
Emmanuel Bertin's avatar
Emmanuel Bertin committed
118
119
120
121
122
123
124
125
126
127
128
129

  return profit;
  }  


/****** profit_end ************************************************************
PROTO	void prof_end(profstruct *prof)
PURPOSE	End (deallocate) a profile-fitting structure.
INPUT	Prof structure.
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
130
VERSION	12/07/2012
Emmanuel Bertin's avatar
Emmanuel Bertin committed
131
132
133
134
135
136
137
 ***/
void	profit_end(profitstruct *profit)
  {
   int	p;

  for (p=0; p<profit->nprof; p++)
    prof_end(profit->prof[p]);
138
139
140
141
142
143
144
145
146
  free(profit->modpix);
  free(profit->modpix2);
  free(profit->cmodpix);
  free(profit->psfpix);
  free(profit->lmodpix);
  free(profit->lmodpix2);
  free(profit->objpix);
  free(profit->objweight);
  free(profit->resi);
147
  free(profit->presi);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
148
149
  free(profit->prof);
  free(profit->covar);
150
  QFFTWF_FREE(profit->psfdft);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  free(profit);

  return;
  }


/****** profit_fit ************************************************************
PROTO	void profit_fit(profitstruct *profit, picstruct *field,
		picstruct *wfield, objstruct *obj, obj2struct *obj2)
PURPOSE	Fit profile(s) convolved with the PSF to a detected object.
INPUT	Array of profile structures,
	Number of profiles,
	Pointer to the profile-fitting structure,
	Pointer to the field,
	Pointer to the field weight,
	Pointer to the obj.
OUTPUT	Pointer to an allocated fit structure (containing details about the
	fit).
NOTES	It is a modified version of the lm_minimize() of lmfit.
AUTHOR	E. Bertin (IAP)
171
VERSION	23/09/2013
Emmanuel Bertin's avatar
Emmanuel Bertin committed
172
173
174
175
176
 ***/
void	profit_fit(profitstruct *profit,
		picstruct *field, picstruct *wfield,
		objstruct *obj, obj2struct *obj2)
  {
177
    profitstruct	*pprofit, *qprofit;
178
    patternstruct	*pattern;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
179
180
    psfstruct		*psf;
    checkstruct		*check;
181
182
183
    double		emx2,emy2,emxy, a , cp,sp, cn, bn, n, rho,
			sum, sump,sumq, sumpw2,sumqw2,sumpqw, sump0,sumq0,
			fluxerr, err;
184
    PIXTYPE		valp,valq,sig2;
185
186
187
    float		param0[PARAM_NPARAM], param1[PARAM_NPARAM],
			param[PARAM_NPARAM],
			**list,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
188
			*cov,
189
			psf_fwhm, dchi2, aspect, chi2;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
190
    int			*index,
191
			c,i,j,p, nparam, nparam2, ncomp, nprof;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
192
193

  nparam = profit->nparam;
194
  nparam2 = nparam*nparam;
195
  nprof = profit->nprof;
196

Emmanuel Bertin's avatar
Emmanuel Bertin committed
197
  if (profit->psfdft)
198
199
    QFFTWF_FREE(profit->psfdft);

Emmanuel Bertin's avatar
Emmanuel Bertin committed
200
201
202

  psf = profit->psf;
  profit->pixstep = psf->pixstep;
203
  obj2->prof_flag = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
204
205

/* Create pixmaps at image resolution */
206
207
  profit->ix = (int)(obj->mx + 0.49999);/* internal convention: 1st pix = 0 */
  profit->iy = (int)(obj->my + 0.49999);/* internal convention: 1st pix = 0 */
Emmanuel Bertin's avatar
Emmanuel Bertin committed
208
  psf_fwhm = psf->masksize[0]*psf->pixstep;
209
  profit->objnaxisn[0] = (((int)((obj->xmax-obj->xmin+1) + psf_fwhm + 0.499)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
210
		*1.2)/2)*2 + 1;
211
  profit->objnaxisn[1] = (((int)((obj->ymax-obj->ymin+1) + psf_fwhm + 0.499)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
212
213
214
215
216
		*1.2)/2)*2 + 1;
  if (profit->objnaxisn[1]<profit->objnaxisn[0])
    profit->objnaxisn[1] = profit->objnaxisn[0];
  else
    profit->objnaxisn[0] = profit->objnaxisn[1];
217
218
  if (profit->objnaxisn[0]>PROFIT_MAXOBJSIZE)
    {
219
220
    profit->subsamp = ceil((float)profit->objnaxisn[0]/PROFIT_MAXOBJSIZE);
    profit->objnaxisn[1] = (profit->objnaxisn[0] /= (int)profit->subsamp);
221
222
223
    obj2->prof_flag |= PROFLAG_OBJSUB;
    }
  else
224
    profit->subsamp = 1.0;
225
  profit->nobjpix = profit->objnaxisn[0]*profit->objnaxisn[1];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
226

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/* Create pixmap at model resolution */
  profit->modnaxisn[0] =
	((int)(profit->objnaxisn[0]*profit->subsamp/profit->pixstep
		+0.4999)/2+1)*2; 
  profit->modnaxisn[1] =
	((int)(profit->objnaxisn[1]*profit->subsamp/profit->pixstep
		+0.4999)/2+1)*2; 
  if (profit->modnaxisn[1] < profit->modnaxisn[0])
    profit->modnaxisn[1] = profit->modnaxisn[0];
  else
    profit->modnaxisn[0] = profit->modnaxisn[1];
  if (profit->modnaxisn[0]>PROFIT_MAXMODSIZE)
    {
    profit->pixstep = (double)profit->modnaxisn[0] / PROFIT_MAXMODSIZE;
    profit->modnaxisn[0] = profit->modnaxisn[1] = PROFIT_MAXMODSIZE;
    obj2->prof_flag |= PROFLAG_MODSUB;
    }
  profit->nmodpix = profit->modnaxisn[0]*profit->modnaxisn[1];

Emmanuel Bertin's avatar
Emmanuel Bertin committed
246
247
248
249
250
251
252
/* Use (dirty) global variables to interface with lmfit */
  the_field = field;
  the_wfield = wfield;
  theprofit = profit;
  profit->obj = obj;
  profit->obj2 = obj2;

253
254
255
/* Compute the local PSF */
  profit_psf(profit);

Emmanuel Bertin's avatar
Emmanuel Bertin committed
256
  profit->nresi = profit_copyobjpix(profit, field, wfield);
257
  profit->npresi = 0;
258
/* Check if the number of constraints exceeds the number of free parameters */
Emmanuel Bertin's avatar
Emmanuel Bertin committed
259
260
  if (profit->nresi < nparam)
    {
261
262
263
    if (FLAG(obj2.prof_vector))
      for (p=0; p<nparam; p++)
        obj2->prof_vector[p] = 0.0;
264
265
266
267
268
269
    if (FLAG(obj2.prof_errvector))
      for (p=0; p<nparam; p++)
        obj2->prof_errvector[p] = 0.0;
    if (FLAG(obj2.prof_errmatrix))
      for (p=0; p<nparam2; p++)
        obj2->prof_errmatrix[p] = 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
270
    obj2->prof_niter = 0;
271
    obj2->prof_flag |= PROFLAG_NOTCONST;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
272
273
274
275
    return;
    }

/* Set initial guesses and boundaries */
276
277
278
  profit->guesssigbkg = profit->sigma = obj->sigbkg;
  profit->guessdx = obj->mx - (int)(obj->mx+0.49999);
  profit->guessdy = obj->my - (int)(obj->my+0.49999);
279
280
281
282
283
284
  if ((profit->guessflux = obj2->flux_auto) <= 0.0)
    profit->guessflux = 0.0;
  if ((profit->guessfluxmax = 10.0*obj2->fluxerr_auto) <= profit->guessflux)
    profit->guessfluxmax = profit->guessflux;
  if (profit->guessfluxmax <= 0.0)
    profit->guessfluxmax = 1.0;
285
286
287
288
  if ((profit->guessradius = 0.5*psf->fwhm) < obj2->hl_radius)
    profit->guessradius = obj2->hl_radius;
  profit->guessaspect = obj->b/obj->a;
  profit->guessposang = obj->theta;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
289
290
291
292

  profit_resetparams(profit);

/* Actual minimisation */
Emmanuel Bertin's avatar
Emmanuel Bertin committed
293
  fft_reset();
294
the_gal++;
295

Emmanuel Bertin's avatar
Emmanuel Bertin committed
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*
char str[1024];
sprintf(str, "obj_%04d.fits", the_gal);
catstruct *bcat;
float *bpix, *opix,*lmodpix,*objpix;
bcat=read_cat("base.fits");
QMALLOC(bpix, float, field->npix);
QFSEEK(bcat->file, bcat->tab->bodypos, SEEK_SET, bcat->filename);
read_body(bcat->tab, bpix, field->npix); 
free_cat(&bcat,1);
bcat=read_cat(str);
QMALLOC(opix, float, profit->nobjpix);
QFSEEK(bcat->file, bcat->tab->bodypos, SEEK_SET, bcat->filename);
read_body(bcat->tab, opix, profit->nobjpix); 
free_cat(&bcat,1);
addfrombig(bpix, field->width, field->height,
		profit->objpix, profit->objnaxisn[0],profit->objnaxisn[1],
		profit->ix,profit->iy, -1.0);
objpix = profit->objpix;
lmodpix = opix;
for (i=profit->nobjpix; i--;)
*(objpix++) += *(lmodpix++);
free(bpix);
free(opix);
*/
Emmanuel Bertin's avatar
Emmanuel Bertin committed
321
  profit->niter = profit_minimize(profit, PROFIT_MAXITER);
322
/*
Emmanuel Bertin's avatar
Emmanuel Bertin committed
323
324
325
326
327
328
329
330
331
profit_residuals(profit,field,wfield, 0.0, profit->paraminit, NULL);
check=initcheck(str, CHECK_OTHER,1);
check->width = profit->objnaxisn[0];
check->height = profit->objnaxisn[1];
reinitcheck(field,check);
memcpy(check->pix, profit->lmodpix, profit->nobjpix*sizeof(float));
reendcheck(field,check);
endcheck(check);

332
333
334
335
336
337
338
  chi2 = profit->chi2;
  for (p=0; p<nparam; p++)
    param1[p] = profit->paraminit[p];
  profit_resetparams(profit);
  for (p=0; p<nparam; p++)
    profit->paraminit[p] = param1[p] + (profit->paraminit[p]<param1[p]?1.0:-1.0)
			* sqrt(profit->covar[p*(nparam+1)]);
339

340
341
342
343
344
345
346
347
348
349
350
351
  profit->niter = profit_minimize(profit, PROFIT_MAXITER);
  if (chi2<profit->chi2)
    for (p=0; p<nparam; p++)
      profit->paraminit[p] = param1[p];

list = profit->paramlist;
index = profit->paramindex;
for (i=0; i<PARAM_NPARAM; i++)
if (list[i] && i!= PARAM_SPHEROID_ASPECT && i!=PARAM_SPHEROID_POSANG)
profit->freeparam_flag[index[i]] = 0;
profit->niter = profit_minimize(profit, PROFIT_MAXITER);
*/
352

353
354
355
356
357
  if (profit->nlimmin)
    obj2->prof_flag |= PROFLAG_MINLIM;
  if (profit->nlimmax)
    obj2->prof_flag |= PROFLAG_MAXLIM;

Emmanuel Bertin's avatar
Emmanuel Bertin committed
358
359
360
361
  for (p=0; p<nparam; p++)
    profit->paramerr[p]= sqrt(profit->covar[p*(nparam+1)]);

/* CHECK-Images */
362
363
364
  if ((check = prefs.check[CHECK_PROFILES]))
    {
    profit_residuals(profit,field,wfield, 0.0, profit->paraminit, NULL);
365
366
367
    if (profit->subsamp>1.0)
      addcheck_resample(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
368
		profit->ix,profit->iy, profit->subsamp,
369
370
371
372
		1.0/(profit->subsamp*profit->subsamp));
    else
      addcheck(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
373
374
		profit->ix,profit->iy, 1.0);
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
375

Emmanuel Bertin's avatar
Emmanuel Bertin committed
376
377
  if ((check = prefs.check[CHECK_SUBPROFILES]))
    {
378
    profit_residuals(profit,field,wfield, 0.0, profit->paraminit, NULL);
379
380
381
    if (profit->subsamp>1.0)
      addcheck_resample(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
382
		profit->ix,profit->iy, profit->subsamp,
383
384
385
386
		-1.0/(profit->subsamp*profit->subsamp));
    else
      addcheck(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
Emmanuel Bertin's avatar
Emmanuel Bertin committed
387
388
		profit->ix,profit->iy, -1.0);
    }
389
390
391
392
393
394
395
396
397
398
399
  if ((check = prefs.check[CHECK_SPHEROIDS]))
    {
/*-- Set to 0 flux components that do not belong to spheroids */
    for (p=0; p<profit->nparam; p++)
      param[p] = profit->paraminit[p];
    list = profit->paramlist;
    index = profit->paramindex;
    for (i=0; i<PARAM_NPARAM; i++)
      if (list[i] && flux_flag[i] && i!= PARAM_SPHEROID_FLUX)
        param[index[i]] = 0.0;
    profit_residuals(profit,field,wfield, 0.0, param, NULL);
400
401
402
    if (profit->subsamp>1.0)
      addcheck_resample(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
403
		profit->ix,profit->iy, profit->subsamp,
404
405
406
407
		1.0/(profit->subsamp*profit->subsamp));
    else
      addcheck(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
408
409
410
411
412
413
414
415
416
417
418
419
420
		profit->ix,profit->iy, 1.0);
    }
  if ((check = prefs.check[CHECK_SUBSPHEROIDS]))
    {
/*-- Set to 0 flux components that do not belong to spheroids */
    for (p=0; p<profit->nparam; p++)
      param[p] = profit->paraminit[p];
    list = profit->paramlist;
    index = profit->paramindex;
    for (i=0; i<PARAM_NPARAM; i++)
      if (list[i] && flux_flag[i] && i!= PARAM_SPHEROID_FLUX)
        param[index[i]] = 0.0;
    profit_residuals(profit,field,wfield, 0.0, param, NULL);
421
422
423
    if (profit->subsamp>1.0)
      addcheck_resample(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
424
		profit->ix,profit->iy, profit->subsamp,
425
426
427
428
		-1.0/(profit->subsamp*profit->subsamp));
    else
      addcheck(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
429
430
431
		profit->ix,profit->iy, -1.0);
    }
  if ((check = prefs.check[CHECK_DISKS]))
Emmanuel Bertin's avatar
Emmanuel Bertin committed
432
    {
433
434
435
436
437
438
439
440
441
/*-- Set to 0 flux components that do not belong to disks */
    for (p=0; p<profit->nparam; p++)
      param[p] = profit->paraminit[p];
    list = profit->paramlist;
    index = profit->paramindex;
    for (i=0; i<PARAM_NPARAM; i++)
      if (list[i] && flux_flag[i] && i!= PARAM_DISK_FLUX)
        param[index[i]] = 0.0;
    profit_residuals(profit,field,wfield, 0.0, param, NULL);
442
443
444
    if (profit->subsamp>1.0)
      addcheck_resample(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
445
		profit->ix,profit->iy, profit->subsamp,
446
447
448
449
		1.0/(profit->subsamp*profit->subsamp));
    else
      addcheck(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
Emmanuel Bertin's avatar
Emmanuel Bertin committed
450
451
		profit->ix,profit->iy, 1.0);
    }
452
453
454
455
456
457
458
459
460
461
462
  if ((check = prefs.check[CHECK_SUBDISKS]))
    {
/*-- Set to 0 flux components that do not belong to disks */
    for (p=0; p<profit->nparam; p++)
      param[p] = profit->paraminit[p];
    list = profit->paramlist;
    index = profit->paramindex;
    for (i=0; i<PARAM_NPARAM; i++)
      if (list[i] && flux_flag[i] && i!= PARAM_DISK_FLUX)
        param[index[i]] = 0.0;
    profit_residuals(profit,field,wfield, 0.0, param, NULL);
463
464
465
    if (profit->subsamp>1.0)
      addcheck_resample(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
466
		profit->ix,profit->iy, profit->subsamp,
467
468
469
470
		-1.0/(profit->subsamp*profit->subsamp));
    else
      addcheck(check, profit->lmodpix,
		profit->objnaxisn[0],profit->objnaxisn[1],
471
472
		profit->ix,profit->iy, -1.0);
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
473
 
474
475
/* Compute compressed residuals */
  profit_residuals(profit,field,wfield, 10.0, profit->paraminit,profit->resi);
476

Emmanuel Bertin's avatar
Emmanuel Bertin committed
477
478
479
480
/* Fill measurement parameters */
  if (FLAG(obj2.prof_vector))
    {
    for (p=0; p<nparam; p++)
481
      obj2->prof_vector[p]= profit->paraminit[p];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
482
483
484
485
486
487
    }
  if (FLAG(obj2.prof_errvector))
    {
    for (p=0; p<nparam; p++)
      obj2->prof_errvector[p]= profit->paramerr[p];
    }
488
489
490
491
492
  if (FLAG(obj2.prof_errmatrix))
    {
    for (p=0; p<nparam2; p++)
      obj2->prof_errmatrix[p]= profit->covar[p];
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
493
494
495

  obj2->prof_niter = profit->niter;
  obj2->flux_prof = profit->flux;
496
497
  if (FLAG(obj2.fluxerr_prof))
    {
498
    fluxerr = 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
499
500
501
502
503
504
505
506
507
    cov = profit->covar;
    index = profit->paramindex;
    list = profit->paramlist;
    for (i=0; i<PARAM_NPARAM; i++)
      if (flux_flag[i] && list[i])
        {
        cov = profit->covar + nparam*index[i];
        for (j=0; j<PARAM_NPARAM; j++)
          if (flux_flag[j] && list[j])
508
            fluxerr += cov[index[j]];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
509
        }
510
    obj2->fluxerr_prof = fluxerr>0.0? sqrt(fluxerr): 0.0;
511
512
    }

513
514
515
  obj2->prof_chi2 = (profit->nresi > profit->nparam)?
		profit->chi2 / (profit->nresi - profit->nparam) : 0.0;

516
/* Position */
Emmanuel Bertin's avatar
Emmanuel Bertin committed
517
518
519
520
521
  if (FLAG(obj2.x_prof))
    {
    i = profit->paramindex[PARAM_X];
    j = profit->paramindex[PARAM_Y];
/*-- Model coordinates follow the FITS convention (first pixel at 1,1) */
522
523
    if (profit->paramlist[PARAM_X])
      {
524
      obj2->x_prof = (double)profit->ix + *profit->paramlist[PARAM_X] + 1.0;
525
526
527
528
529
530
      obj2->poserrmx2_prof = emx2 = profit->covar[i*(nparam+1)];
      }
    else
      emx2 = 0.0;
    if (profit->paramlist[PARAM_Y])
      {
531
      obj2->y_prof = (double)profit->iy + *profit->paramlist[PARAM_Y] + 1.0;
532
533
534
535
536
537
538
539
      obj2->poserrmy2_prof = emy2 = profit->covar[j*(nparam+1)];
      }
    else
      emy2 = 0.0;
    if (profit->paramlist[PARAM_X] && profit->paramlist[PARAM_Y])
      obj2->poserrmxy_prof = emxy = profit->covar[i+j*nparam];
    else
      emxy = 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555

/*-- Error ellipse parameters */
    if (FLAG(obj2.poserra_prof))
      {
       double	pmx2,pmy2,temp,theta;

      if (fabs(temp=emx2-emy2) > 0.0)
        theta = atan2(2.0 * emxy,temp) / 2.0;
      else
        theta = PI/4.0;

      temp = sqrt(0.25*temp*temp+ emxy*emxy);
      pmy2 = pmx2 = 0.5*(emx2+emy2);
      pmx2+=temp;
      pmy2-=temp;

556
557
      obj2->poserra_prof = (float)sqrt(pmx2>0.0? pmx2 : 0.0);
      obj2->poserrb_prof = (float)sqrt(pmy2>0.0? pmy2 : 0.0);
558
      obj2->poserrtheta_prof = (float)(theta/DEG);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
559
560
561
562
563
564
565
566
567
568
569
570
      }

    if (FLAG(obj2.poserrcxx_prof))
      {
       double	temp;

      obj2->poserrcxx_prof = (float)(emy2/(temp=emx2*emy2-emxy*emxy));
      obj2->poserrcyy_prof = (float)(emx2/temp);
      obj2->poserrcxy_prof = (float)(-2*emxy/temp);
      }
    }

571
572
573
574
575
576
577
578
579
580
581
582
583
/* Equivalent noise area */
  if (FLAG(obj2.prof_noisearea))
    obj2->prof_noisearea = profit_noisearea(profit);

/* Second order moments and ellipticities */
  if (FLAG(obj2.prof_mx2))
    profit_moments(profit, obj2);

/* Second order moments of the convolved model (used by other parameters) */
  if (FLAG(obj2.prof_convmx2))
    profit_convmoments(profit, obj2);

/* "Hybrid" magnitudes */
Emmanuel Bertin's avatar
Emmanuel Bertin committed
584
585
586
587
588
589
  if (FLAG(obj2.fluxcor_prof))
    {
    profit_residuals(profit,field,wfield, 0.0, profit->paraminit, NULL);
    profit_fluxcor(profit, obj, obj2);
    }

590
/* Do measurements on the rasterised model (surface brightnesses) */
591
  if (FLAG(obj2.fluxeff_prof))
592
    profit_surface(profit, obj2); 
Emmanuel Bertin's avatar
Emmanuel Bertin committed
593

594
595
596
597
598
599
600
601
602
603
604
605
606
/* Background offset */
  if (FLAG(obj2.prof_offset_flux))
    {
    obj2->prof_offset_flux = *profit->paramlist[PARAM_BACK];
    obj2->prof_offset_fluxerr=profit->paramerr[profit->paramindex[PARAM_BACK]];
    }

/* Point source */
  if (FLAG(obj2.prof_dirac_flux))
    {
    obj2->prof_dirac_flux = *profit->paramlist[PARAM_DIRAC_FLUX];
    obj2->prof_dirac_fluxerr =
		profit->paramerr[profit->paramindex[PARAM_DIRAC_FLUX]];
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
    if (FLAG(obj2.prof_dirac_fluxratio))
      {
      obj2->prof_dirac_fluxratio = (rho = obj2->flux_prof>(1.0/BIG)?
				obj2->prof_dirac_flux / obj2->flux_prof
				: 0.0);
      index = profit->paramindex;
      c = index[PARAM_DIRAC_FLUX];
      list = profit->paramlist;
      cov = profit->covar + c*nparam;
      err = 0.0;
      for (i=0; i<PARAM_NPARAM; i++)
        if (flux_flag[i] && list[i])
          err += cov[index[i]];
      err = cov[c] + rho*rho*fluxerr - 2.0*rho*err;
      obj2->prof_dirac_fluxratioerr = (err>(1.0/BIG) && profit->flux>(1.0/BIG))?
					sqrt(err)/profit->flux : 0.0;
      }
624
625
    }

626
/* Spheroid */
Emmanuel Bertin's avatar
Emmanuel Bertin committed
627
628
  if (FLAG(obj2.prof_spheroid_flux))
    {
629
630
631
632
633
634
635
636
637
    if ((aspect = *profit->paramlist[PARAM_SPHEROID_ASPECT]) > 1.0)
      {
      *profit->paramlist[PARAM_SPHEROID_REFF] *= aspect;
      profit->paramerr[profit->paramindex[PARAM_SPHEROID_REFF]] *= aspect;
      profit->paramerr[profit->paramindex[PARAM_SPHEROID_ASPECT]]
			/= (aspect*aspect);
      *profit->paramlist[PARAM_SPHEROID_ASPECT] = 1.0 / aspect;
      *profit->paramlist[PARAM_SPHEROID_POSANG] += 90.0;
      }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
    obj2->prof_spheroid_flux = *profit->paramlist[PARAM_SPHEROID_FLUX];
    obj2->prof_spheroid_fluxerr =
		profit->paramerr[profit->paramindex[PARAM_SPHEROID_FLUX]];
    obj2->prof_spheroid_reff = *profit->paramlist[PARAM_SPHEROID_REFF];
    obj2->prof_spheroid_refferr = 
		profit->paramerr[profit->paramindex[PARAM_SPHEROID_REFF]];
    obj2->prof_spheroid_aspect = *profit->paramlist[PARAM_SPHEROID_ASPECT];
    obj2->prof_spheroid_aspecterr = 
		profit->paramerr[profit->paramindex[PARAM_SPHEROID_ASPECT]];
    obj2->prof_spheroid_theta =
			fmod_m90_p90(*profit->paramlist[PARAM_SPHEROID_POSANG]);
    obj2->prof_spheroid_thetaerr = 
		profit->paramerr[profit->paramindex[PARAM_SPHEROID_POSANG]];
    if (FLAG(obj2.prof_spheroid_sersicn))
      {
      obj2->prof_spheroid_sersicn = *profit->paramlist[PARAM_SPHEROID_SERSICN];
      obj2->prof_spheroid_sersicnerr = 
		profit->paramerr[profit->paramindex[PARAM_SPHEROID_SERSICN]];
      }
657
658
659
660
661
    else
      obj2->prof_spheroid_sersicn = 4.0;
    if (FLAG(obj2.prof_spheroid_peak))
      {
      n = obj2->prof_spheroid_sersicn;
662
      bn = 2.0*n - 1.0/3.0 + 4.0/(405.0*n) + 46.0/(25515.0*n*n)
663
		+ 131.0/(1148175*n*n*n);	/* Ciotti & Bertin 1999 */
664
      cn = n * prof_gamma(2.0*n) * pow(bn, -2.0*n);
665
      obj2->prof_spheroid_peak = obj2->prof_spheroid_reff>0.0?
666
	obj2->prof_spheroid_flux
667
		/ (2.0 * PI * cn
668
		* obj2->prof_spheroid_reff*obj2->prof_spheroid_reff
669
		* obj2->prof_spheroid_aspect)
670
671
	: 0.0;
      if (FLAG(obj2.prof_spheroid_fluxeff))
672
673
674
        obj2->prof_spheroid_fluxeff = obj2->prof_spheroid_peak * exp(-bn);
      if (FLAG(obj2.prof_spheroid_fluxmean))
        obj2->prof_spheroid_fluxmean = obj2->prof_spheroid_peak * cn;
675
      }
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
    if (FLAG(obj2.prof_spheroid_fluxratio))
      {
      obj2->prof_spheroid_fluxratio = (rho = obj2->flux_prof>(1.0/BIG)?
				obj2->prof_spheroid_flux / obj2->flux_prof
				: 0.0);
      index = profit->paramindex;
      c = index[PARAM_SPHEROID_FLUX];
      list = profit->paramlist;
      cov = profit->covar + c*nparam;
      err = 0.0;
      for (i=0; i<PARAM_NPARAM; i++)
        if (flux_flag[i] && list[i])
          err += cov[index[i]];
      err = cov[c] + rho*rho*fluxerr - 2.0*rho*err;
      obj2->prof_spheroid_fluxratioerr
				= (err>(1.0/BIG) && profit->flux>(1.0/BIG))?
					sqrt(err)/profit->flux : 0.0;
      }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
694
695
696
697
698
    }

/* Disk */
  if (FLAG(obj2.prof_disk_flux))
    {
699
700
701
702
703
704
705
706
707
    if ((aspect = *profit->paramlist[PARAM_DISK_ASPECT]) > 1.0)
      {
      *profit->paramlist[PARAM_DISK_SCALE] *= aspect;
      profit->paramerr[profit->paramindex[PARAM_DISK_SCALE]] *= aspect;
      profit->paramerr[profit->paramindex[PARAM_DISK_ASPECT]]
			/= (aspect*aspect);
      *profit->paramlist[PARAM_DISK_ASPECT] = 1.0 / aspect;
      *profit->paramlist[PARAM_DISK_POSANG] += 90.0;
      }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
    obj2->prof_disk_flux = *profit->paramlist[PARAM_DISK_FLUX];
    obj2->prof_disk_fluxerr =
		profit->paramerr[profit->paramindex[PARAM_DISK_FLUX]];
    obj2->prof_disk_scale = *profit->paramlist[PARAM_DISK_SCALE];
    obj2->prof_disk_scaleerr =
		profit->paramerr[profit->paramindex[PARAM_DISK_SCALE]];
    obj2->prof_disk_aspect = *profit->paramlist[PARAM_DISK_ASPECT];
    obj2->prof_disk_aspecterr =
		profit->paramerr[profit->paramindex[PARAM_DISK_ASPECT]];
    obj2->prof_disk_theta = fmod_m90_p90(*profit->paramlist[PARAM_DISK_POSANG]);
    obj2->prof_disk_thetaerr =
		profit->paramerr[profit->paramindex[PARAM_DISK_POSANG]];
    if (FLAG(obj2.prof_disk_inclination))
      {
      obj2->prof_disk_inclination = acos(obj2->prof_disk_aspect) / DEG;
      if (FLAG(obj2.prof_disk_inclinationerr))
        {
        a = sqrt(1.0-obj2->prof_disk_aspect*obj2->prof_disk_aspect);
        obj2->prof_disk_inclinationerr = obj2->prof_disk_aspecterr
					/(a>0.1? a : 0.1)/DEG;
        }
      }

731
732
733
    if (FLAG(obj2.prof_disk_peak))
      {
      obj2->prof_disk_peak = obj2->prof_disk_scale>0.0?
734
	obj2->prof_disk_flux
735
736
737
738
	/ (2.0 * PI * obj2->prof_disk_scale*obj2->prof_disk_scale
		* obj2->prof_disk_aspect)
	: 0.0;
      if (FLAG(obj2.prof_disk_fluxeff))
739
740
741
        obj2->prof_disk_fluxeff = obj2->prof_disk_peak * 0.186682; /* e^-(b_n)*/
      if (FLAG(obj2.prof_disk_fluxmean))
        obj2->prof_disk_fluxmean = obj2->prof_disk_peak * 0.355007;/* b_n^(-2)*/
742
743
      }

744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
    if (FLAG(obj2.prof_disk_fluxratio))
      {
      obj2->prof_disk_fluxratio = (rho = obj2->flux_prof>(1.0/BIG)?
					obj2->prof_disk_flux / obj2->flux_prof
					: 0.0);
      index = profit->paramindex;
      c = index[PARAM_DISK_FLUX];
      list = profit->paramlist;
      cov = profit->covar + c*nparam;
      err = 0.0;
      for (i=0; i<PARAM_NPARAM; i++)
        if (flux_flag[i] && list[i])
          err += cov[index[i]];
      err = cov[c] + rho*rho*fluxerr - 2.0*rho*err;
      obj2->prof_disk_fluxratioerr = (err>(1.0/BIG) && profit->flux>(1.0/BIG))?
					sqrt(err)/profit->flux : 0.0;
      }

Emmanuel Bertin's avatar
Emmanuel Bertin committed
762
763
764
/* Disk pattern */
    if (prefs.pattern_flag)
      {
765
      profit_residuals(profit,field,wfield, PROFIT_DYNPARAM,
766
			profit->paraminit,profit->resi);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
      pattern = pattern_init(profit, prefs.pattern_type,
		prefs.prof_disk_patternncomp);
      pattern_fit(pattern, profit);
      if (FLAG(obj2.prof_disk_patternspiral))
        obj2->prof_disk_patternspiral = pattern_spiral(pattern);
      if (FLAG(obj2.prof_disk_patternvector))
        {
        ncomp = pattern->size[2];
        for (p=0; p<ncomp; p++)
          obj2->prof_disk_patternvector[p] = (float)pattern->coeff[p];
        }
      if (FLAG(obj2.prof_disk_patternmodvector))
        {
        ncomp = pattern->ncomp*pattern->nfreq;
        for (p=0; p<ncomp; p++)
          obj2->prof_disk_patternmodvector[p] = (float)pattern->mcoeff[p];
        }
      if (FLAG(obj2.prof_disk_patternargvector))
        {
        ncomp = pattern->ncomp*pattern->nfreq;
        for (p=0; p<ncomp; p++)
          obj2->prof_disk_patternargvector[p] = (float)pattern->acoeff[p];
        }
      pattern_end(pattern);
      }

/* Bar */
    if (FLAG(obj2.prof_bar_flux))
      {
      obj2->prof_bar_flux = *profit->paramlist[PARAM_BAR_FLUX];
      obj2->prof_bar_fluxerr =
		profit->paramerr[profit->paramindex[PARAM_BAR_FLUX]];
      obj2->prof_bar_length = *profit->paramlist[PARAM_ARMS_START]
				**profit->paramlist[PARAM_DISK_SCALE];
      obj2->prof_bar_lengtherr = *profit->paramlist[PARAM_ARMS_START]
		  * profit->paramerr[profit->paramindex[PARAM_DISK_SCALE]]
		+ *profit->paramlist[PARAM_DISK_SCALE]
		  * profit->paramerr[profit->paramindex[PARAM_ARMS_START]];
      obj2->prof_bar_aspect = *profit->paramlist[PARAM_BAR_ASPECT];
      obj2->prof_bar_aspecterr =
		profit->paramerr[profit->paramindex[PARAM_BAR_ASPECT]];
      obj2->prof_bar_posang = 
			fmod_m90_p90(*profit->paramlist[PARAM_ARMS_POSANG]);
      obj2->prof_bar_posangerr =
		profit->paramerr[profit->paramindex[PARAM_ARMS_POSANG]];
      if (FLAG(obj2.prof_bar_theta))
        {
        cp = cos(obj2->prof_bar_posang*DEG);
        sp = sin(obj2->prof_bar_posang*DEG);
        a = obj2->prof_disk_aspect;
        obj2->prof_bar_theta = fmod_m90_p90(atan2(a*sp,cp)/DEG
				+ obj2->prof_disk_theta);
        obj2->prof_bar_thetaerr = obj2->prof_bar_posangerr*a/(cp*cp+a*a*sp*sp);
        }
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
      if (FLAG(obj2.prof_bar_fluxratio))
        {
        obj2->prof_bar_fluxratio = (rho = obj2->flux_prof>(1.0/BIG)?
					obj2->prof_bar_flux / obj2->flux_prof
					: 0.0);
        index = profit->paramindex;
        c = index[PARAM_BAR_FLUX];
        list = profit->paramlist;
        cov = profit->covar + c*nparam;
        err = 0.0;
        for (i=0; i<PARAM_NPARAM; i++)
          if (flux_flag[i] && list[i])
            err += cov[index[i]];
        err = cov[c] + rho*rho*fluxerr - 2.0*rho*err;
        obj2->prof_bar_fluxratioerr = (err>(1.0/BIG) && profit->flux>(1.0/BIG))?
					sqrt(err)/profit->flux : 0.0;
        }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861

/* Arms */
      if (FLAG(obj2.prof_arms_flux))
        {
        obj2->prof_arms_flux = *profit->paramlist[PARAM_ARMS_FLUX];
        obj2->prof_arms_fluxerr =
		profit->paramerr[profit->paramindex[PARAM_ARMS_FLUX]];
        obj2->prof_arms_pitch =
		fmod_m90_p90(*profit->paramlist[PARAM_ARMS_PITCH]);
        obj2->prof_arms_pitcherr =
		profit->paramerr[profit->paramindex[PARAM_ARMS_PITCH]];
        obj2->prof_arms_start = *profit->paramlist[PARAM_ARMS_START]
				**profit->paramlist[PARAM_DISK_SCALE];
        obj2->prof_arms_starterr = *profit->paramlist[PARAM_ARMS_START]
		  * profit->paramerr[profit->paramindex[PARAM_DISK_SCALE]]
		+ *profit->paramlist[PARAM_DISK_SCALE]
		  * profit->paramerr[profit->paramindex[PARAM_ARMS_START]];
        obj2->prof_arms_quadfrac = *profit->paramlist[PARAM_ARMS_QUADFRAC];
        obj2->prof_arms_quadfracerr =
		profit->paramerr[profit->paramindex[PARAM_ARMS_QUADFRAC]];
        obj2->prof_arms_posang =
			fmod_m90_p90(*profit->paramlist[PARAM_ARMS_POSANG]);
        obj2->prof_arms_posangerr =
		profit->paramerr[profit->paramindex[PARAM_ARMS_POSANG]];
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
        if (FLAG(obj2.prof_arms_fluxratio))
          {
          obj2->prof_arms_fluxratio = (rho = obj2->flux_prof>(1.0/BIG)?
					obj2->prof_arms_flux / obj2->flux_prof
					: 0.0);
          index = profit->paramindex;
          c = index[PARAM_ARMS_FLUX];
          list = profit->paramlist;
          cov = profit->covar + c*nparam;
          err = 0.0;
          for (i=0; i<PARAM_NPARAM; i++)
            if (flux_flag[i] && list[i])
              err += cov[index[i]];
          err = cov[c] + rho*rho*fluxerr - 2.0*rho*err;
          obj2->prof_arms_fluxratioerr
				= (err>(1.0/BIG) && profit->flux>(1.0/BIG))?
					sqrt(err)/profit->flux : 0.0;
          }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
880
881
882
883
        }
      }
    }

884
/* Star/galaxy classification */
885
  if (FLAG(obj2.prof_class_star) || FLAG(obj2.prof_concentration))
886
    {
887
888
    profit_residuals(profit,field,wfield, PROFIT_DYNPARAM, profit->paraminit,
	FLAG(obj2.prof_class_star) ? profit->resi : NULL);
889
890
891
    pprofit = thepprofit;
    nparam = pprofit->nparam;
    if (pprofit->psfdft)
892
      QFFTWF_FREE(pprofit->psfdft);
893
894
    psf = pprofit->psf;
    pprofit->pixstep = profit->pixstep;
895
896
897
    pprofit->guesssigbkg = profit->guesssigbkg;
    pprofit->guessdx = profit->guessdx;
    pprofit->guessdy = profit->guessdy;
898
899
    pprofit->guessflux = profit->guessflux;
    pprofit->guessfluxmax = profit->guessfluxmax;
900
901
902
    pprofit->guessradius = profit->guessradius;
    pprofit->guessaspect = profit->guessaspect;
    pprofit->guessposang = profit->guessposang;
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
    pprofit->ix = profit->ix;
    pprofit->iy = profit->iy;
    pprofit->objnaxisn[0] = profit->objnaxisn[0];
    pprofit->objnaxisn[1] = profit->objnaxisn[1];
    pprofit->subsamp = profit->subsamp;
    pprofit->nobjpix = profit->nobjpix;
    pprofit->obj = obj;
    pprofit->obj2 = obj2;
    pprofit->nresi = profit_copyobjpix(pprofit, field, wfield);
    pprofit->modnaxisn[0] = profit->modnaxisn[0];
    pprofit->modnaxisn[1] = profit->modnaxisn[1];
    pprofit->nmodpix = profit->nmodpix;
    profit_psf(pprofit);
    pprofit->sigma = obj->sigbkg;
    profit_resetparams(pprofit);
918
919
    if (profit->paramlist[PARAM_X] && profit->paramlist[PARAM_Y])
      {
920
921
922
923
924
925
926
      pprofit->paraminit[pprofit->paramindex[PARAM_X]] = *profit->paramlist[PARAM_X];
      pprofit->paraminit[pprofit->paramindex[PARAM_Y]] = *profit->paramlist[PARAM_Y];
      }
    fft_reset();
    pprofit->paraminit[pprofit->paramindex[PARAM_DIRAC_FLUX]] = profit->flux;
    pprofit->niter = profit_minimize(pprofit, PROFIT_MAXITER);
    profit_residuals(pprofit,field,wfield, PROFIT_DYNPARAM, pprofit->paraminit,
927
			FLAG(obj2.prof_class_star)? pprofit->resi : NULL);
928
929
930
    qprofit = theqprofit;
    nparam = qprofit->nparam;
    if (qprofit->psfdft)
931
      QFFTWF_FREE(qprofit->psfdft);
932
    qprofit->pixstep = profit->pixstep;
933
934
935
    qprofit->guesssigbkg = profit->guesssigbkg;
    qprofit->guessdx = profit->guessdx;
    qprofit->guessdy = profit->guessdy;
936
937
    qprofit->guessflux = profit->guessflux;
    qprofit->guessfluxmax = profit->guessfluxmax;
938
939
940
    qprofit->guessradius = profit->guessradius;
    qprofit->guessaspect = profit->guessaspect;
    qprofit->guessposang = profit->guessposang;
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
    qprofit->ix = profit->ix;
    qprofit->iy = profit->iy;
    qprofit->objnaxisn[0] = profit->objnaxisn[0];
    qprofit->objnaxisn[1] = profit->objnaxisn[1];
    qprofit->subsamp = profit->subsamp;
    qprofit->nobjpix = profit->nobjpix;
    qprofit->obj = obj;
    qprofit->obj2 = obj2;
    qprofit->nresi = profit_copyobjpix(qprofit, field, wfield);
    qprofit->modnaxisn[0] = profit->modnaxisn[0];
    qprofit->modnaxisn[1] = profit->modnaxisn[1];
    qprofit->nmodpix = profit->nmodpix;
    profit_psf(qprofit);
    qprofit->sigma = obj->sigbkg;
    profit_resetparams(qprofit);
    fft_reset();
957
958
959
960
961
962
    qprofit->paraminit[qprofit->paramindex[PARAM_X]]
		= pprofit->paraminit[pprofit->paramindex[PARAM_X]];
    qprofit->paraminit[qprofit->paramindex[PARAM_Y]]
		= pprofit->paraminit[pprofit->paramindex[PARAM_Y]];
    qprofit->paraminit[qprofit->paramindex[PARAM_DISK_FLUX]]
		= pprofit->paraminit[pprofit->paramindex[PARAM_DIRAC_FLUX]];
963
964
965
966
    qprofit->paraminit[qprofit->paramindex[PARAM_DISK_SCALE]] = psf->fwhm/16.0;
    qprofit->paraminit[qprofit->paramindex[PARAM_DISK_ASPECT]] = 1.0;
    qprofit->paraminit[qprofit->paramindex[PARAM_DISK_POSANG]] = 0.0;
    profit_residuals(qprofit,field,wfield, PROFIT_DYNPARAM, qprofit->paraminit,
967
			FLAG(obj2.prof_class_star)? qprofit->resi : NULL);
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
    sump = sumq = sumpw2 = sumqw2 = sumpqw = sump0 = sumq0 = 0.0;
    for (p=0; p<pprofit->nobjpix; p++)
      if (pprofit->objweight[p]>0 && pprofit->objpix[p]>-BIG)
        {
        valp = pprofit->lmodpix[p];
        sump += (double)(valp*pprofit->objpix[p]);
	valq = qprofit->lmodpix[p];
        sumq += (double)(valq*pprofit->objpix[p]);
	sump0 += (double)(valp*valp);
	sumq0 += (double)(valp*valq);
        sig2 = 1.0f/(pprofit->objweight[p]*pprofit->objweight[p]);
        sumpw2 += valp*valp*sig2;
        sumqw2 += valq*valq*sig2;
        sumpqw += valp*valq*sig2;
        }

984
985
    if (FLAG(obj2.prof_class_star))
      {
986
      dchi2 = 0.5*(pprofit->chi2 - profit->chi2);
987
      obj2->prof_class_star = dchi2 < 50.0?
988
	(dchi2 > -50.0? 2.0/(1.0+expf(dchi2)) : 2.0) : 0.0;
989
990
991
      }
    if (FLAG(obj2.prof_concentration))
      {
992
      obj2->prof_concentration = sump>0.0? (sumq/sump - sumq0/sump0) : 1.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
993
      if (FLAG(obj2.prof_concentrationerr))
994
995
996
        obj2->prof_concentrationerr = (sump>0.0 && (err = sumqw2*sump*sump
		+sumpw2*sumq*sumq-2.0*sumpqw*sump*sumq)>0.0)?
			sqrt(err) / (sump*sump) : 1.0;
997
      }
998
999
    }

Emmanuel Bertin's avatar
Emmanuel Bertin committed
1000
/* clean up. */
For faster browsing, not all history is shown. View entire blame