profit.c 143 KB
Newer Older
3001
3002
3003
3004
      for (i=neff; i--;)
        dsum += (double)*(spixt++);
      obj2->fluxmean_prof = seff > 0.0? dsum / seff : 0.0;
      }
3005
3006
3007
    free(spix);
    }

3008
/* Compute model peak */
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
  if (FLAG(obj2.peak_prof))
    {
/*-- Find position of maximum pixel in current hi-def raster */
    imax = 0;
    vmax = -BIG;
    spixt = hdprofit.modpix;
    for (i=npix; i--;)
      if ((val=*(spixt++))>vmax)
        {
        vmax = val;
        imax = i;
        }
    imax = npix-1 - imax;
    obj2->peak_prof = hdprofit.modpix[imax];
3023
3024
    }

3025
3026
/* Free hi-def model raster */
  free(hdprofit.modpix);
3027
3028
3029
3030
3031

  return;
  }


Emmanuel Bertin's avatar
Emmanuel Bertin committed
3032
3033
/****** profit_addparam *******************************************************
PROTO	void profit_addparam(profitstruct *profit, paramenum paramindex,
3034
		float **param)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3035
3036
3037
3038
3039
3040
3041
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)
3042
VERSION	29/03/2010
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3043
3044
 ***/
void	profit_addparam(profitstruct *profit, paramenum paramindex,
3045
		float **param)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3046
3047
3048
3049
3050
3051
3052
3053
3054
  {
/* 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];
3055
3056
    profit->paramindex[paramindex] = profit->nparam;
    profit->paramrevindex[profit->nparam++] = paramindex;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
    }

  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.
3068
OUTPUT	.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3069
3070
NOTES	-.
AUTHOR	E. Bertin (IAP)
3071
VERSION	15/01/2013
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3072
3073
3074
3075
 ***/
void	profit_resetparam(profitstruct *profit, paramenum paramtype)
  {
   obj2struct	*obj2;
3076
   float	param, parammin,parammax, range, priorcen,priorsig;
3077
   parfitenum	fittype;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3078
3079

  obj2 = profit->obj2;
3080
  param = parammin = parammax = priorcen = priorsig = 0.0;
3081

Emmanuel Bertin's avatar
Emmanuel Bertin committed
3082
3083
3084
  switch(paramtype)
    {
    case PARAM_BACK:
3085
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3086
      param = 0.0;
3087
3088
      parammin = -6.0*profit->guesssigbkg;
      parammax =  6.0*profit->guesssigbkg;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3089
3090
      break;
    case PARAM_X:
3091
      fittype = PARFIT_LINBOUND;
3092
      param = profit->guessdx;
3093
      range = profit->guessradius*4.0;
3094
3095
      if (range>profit->objnaxisn[0]*profit->subsamp*2.0)
        range = profit->objnaxisn[0]*profit->subsamp*2.0;
3096
3097
      parammin = -range;
      parammax =  range;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3098
3099
      break;
    case PARAM_Y:
3100
      fittype = PARFIT_LINBOUND;
3101
      param = profit->guessdy;
3102
      range = profit->guessradius*4.0;
3103
3104
      if (range>profit->objnaxisn[1]*profit->subsamp*2)
        range = profit->objnaxisn[1]*profit->subsamp*2;
3105
3106
      parammin = -range;
      parammax =  range;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3107
      break;
3108
    case PARAM_DIRAC_FLUX:
3109
3110
3111
3112
      fittype = PARFIT_LOGBOUND;
      param = profit->guessflux/profit->nprof;
      parammin = 0.00001*profit->guessfluxmax;
      parammax = 10.0*profit->guessfluxmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3113
      break;
3114
    case PARAM_SPHEROID_FLUX:
3115
3116
3117
3118
      fittype = PARFIT_LOGBOUND;
      param = profit->guessflux/profit->nprof;
      parammin = 0.00001*profit->guessfluxmax;
      parammax = 10.0*profit->guessfluxmax;
3119
      break;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3120
    case PARAM_SPHEROID_REFF:
3121
3122
      fittype = PARFIT_LOGBOUND;
      param = FLAG(obj2.prof_disk_flux)? profit->guessradius
3123
			: profit->guessradius/sqrtf(profit->guessaspect);
3124
      parammin = 0.01;
3125
      parammax = param * 10.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3126
3127
      break;
    case PARAM_SPHEROID_ASPECT:
3128
      fittype = PARFIT_LOGBOUND;
3129
      param = FLAG(obj2.prof_disk_flux)? 1.0 : profit->guessaspect;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3130
      parammin = FLAG(obj2.prof_disk_flux)? 0.5 : 0.01;
3131
      parammax = FLAG(obj2.prof_disk_flux)? 2.0 : 100.0;
3132
3133
      priorcen = 0.3;
      priorsig = 0.0 /*0.4*/;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3134
3135
      break;
    case PARAM_SPHEROID_POSANG:
3136
      fittype = PARFIT_UNBOUND;
3137
      param = profit->guessposang;
3138
3139
      parammin = 90.0;
      parammax =  90.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3140
3141
      break;
    case PARAM_SPHEROID_SERSICN:
3142
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3143
      param = 4.0;
3144
      parammin = FLAG(obj2.prof_disk_flux)? 1.0 : 0.3;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3145
      parammax = 10.0;
3146
3147
      priorcen = 1.0;
      priorsig = 0.0 /*2.0*/;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3148
3149
      break;
    case PARAM_DISK_FLUX:
3150
3151
3152
3153
      fittype = PARFIT_LOGBOUND;
      param = profit->guessflux/profit->nprof;
      parammin = 0.00001*profit->guessfluxmax;
      parammax = 10.0*profit->guessfluxmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3154
3155
      break;
    case PARAM_DISK_SCALE:	/* From scalelength to Re */
3156
      fittype = PARFIT_LOGBOUND;
3157
      param = profit->guessradius/(1.67835*sqrtf(profit->guessaspect));
3158
3159
      parammin = 0.01/1.67835;
      parammax = param * 10.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3160
3161
      break;
    case PARAM_DISK_ASPECT:
3162
      fittype = PARFIT_LOGBOUND;
3163
      param = profit->guessaspect;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3164
      parammin = 0.01;
3165
      parammax = 100.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3166
3167
      break;
    case PARAM_DISK_POSANG:
3168
      fittype = PARFIT_UNBOUND;
3169
      param = profit->guessposang;
3170
3171
      parammin = 90.0;
      parammax =  90.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3172
3173
      break;
    case PARAM_ARMS_FLUX:
3174
3175
3176
3177
      fittype = PARFIT_LOGBOUND;
      param = profit->guessflux/profit->nprof;
      parammin = 0.00001*profit->guessfluxmax;
      parammax = 10.0*profit->guessfluxmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3178
3179
      break;
    case PARAM_ARMS_QUADFRAC:
3180
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3181
3182
3183
3184
3185
      param = 0.5;
      parammin = 0.0;
      parammax = 1.0;
      break;
    case PARAM_ARMS_SCALE:
3186
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3187
3188
3189
3190
3191
      param = 1.0;
      parammin = 0.5;
      parammax = 10.0;
      break;
    case PARAM_ARMS_START:
3192
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3193
3194
3195
3196
3197
      param = 0.5;
      parammin = 0.0;
      parammax = 3.0;
      break;
    case PARAM_ARMS_PITCH:
3198
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3199
3200
3201
3202
3203
      param = 20.0;
      parammin = 5.0;
      parammax = 50.0;
      break;
    case PARAM_ARMS_PITCHVAR:
3204
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
      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:
3218
      fittype = PARFIT_UNBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3219
3220
3221
3222
3223
      param = 0.0;
      parammin = 0.0;
      parammax = 0.0;
      break;
    case PARAM_ARMS_WIDTH:
3224
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3225
3226
3227
3228
3229
      param = 3.0;
      parammin = 1.5;
      parammax = 11.0;
      break;
    case PARAM_BAR_FLUX:
3230
3231
3232
3233
      fittype = PARFIT_LOGBOUND;
      param = profit->guessflux/profit->nprof;
      parammin = 0.00001*profit->guessfluxmax;
      parammax = 4.0*profit->guessfluxmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3234
3235
      break;
    case PARAM_BAR_ASPECT:
3236
      fittype = PARFIT_LOGBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3237
3238
3239
3240
3241
      param = 0.3;
      parammin = 0.2;
      parammax = 0.5;
      break;
    case PARAM_BAR_POSANG:
3242
      fittype = PARFIT_UNBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3243
      param = 0.0;
3244
3245
      parammin = 90.0;
      parammax = 90.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3246
3247
      break;
    case PARAM_INRING_FLUX:
3248
3249
3250
3251
      fittype = PARFIT_LOGBOUND;
      param = profit->guessflux/profit->nprof;
      parammin = 0.00001*profit->guessfluxmax;
      parammax = 4.0*profit->guessfluxmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3252
3253
      break;
    case PARAM_INRING_WIDTH:
3254
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3255
3256
3257
3258
3259
      param = 0.3;
      parammin = 0.0;
      parammax = 0.5;
      break;
    case PARAM_INRING_ASPECT:
3260
      fittype = PARFIT_LOGBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3261
3262
3263
3264
3265
      param = 0.8;
      parammin = 0.4;
      parammax = 1.0;
      break;
    case PARAM_OUTRING_FLUX:
3266
3267
3268
3269
      fittype = PARFIT_LOGBOUND;
      param = profit->guessflux/profit->nprof;
      parammin = 0.00001*profit->guessfluxmax;
      parammax = 4.0*profit->guessfluxmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3270
3271
      break;
    case PARAM_OUTRING_START:
3272
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3273
3274
3275
3276
3277
      param = 4.0;
      parammin = 3.5;
      parammax = 6.0;
      break;
    case PARAM_OUTRING_WIDTH:
3278
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
      param = 0.3;
      parammin = 0.0;
      parammax = 0.5;
      break;
    default:
      error(EXIT_FAILURE, "*Internal Error*: Unknown profile parameter in ",
		"profit_resetparam()");
      break;
   }

  if (parammin!=parammax && (param<=parammin || param>=parammax))
    param = (parammin+parammax)/2.0;
3291
3292
  else if (parammin==0.0 && parammax==0.0)
    parammax = 1.0;
3293
3294
  profit_setparam(profit, paramtype, param, parammin, parammax, fittype,
	priorcen, priorsig);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322

  return;
  }


/****** profit_resetparams ****************************************************
PROTO	void profit_resetparams(profitstruct *profit)
PURPOSE	Set the initial, lower and upper boundary values of profile parameters.
INPUT	Pointer to the profit structure.
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
VERSION	18/09/2008
 ***/
void	profit_resetparams(profitstruct *profit)
  {
   int		p;


  for (p=0; p<PARAM_NPARAM; p++)
    profit_resetparam(profit, (paramenum)p);

  return;
  }


/****** profit_setparam ****************************************************
PROTO	void profit_setparam(profitstruct *profit, paramenum paramtype,
3323
		float param, float parammin, float parammax,
3324
3325
		parfitenum parfittype,
		float priorcen, float priorsig)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3326
3327
PURPOSE	Set the actual, lower and upper boundary values of a profile parameter.
INPUT	Pointer to the profit structure,
3328
3329
3330
3331
3332
	parameter index,
	actual value,
	lower boundary to the parameter,
	upper boundary to the parameter,
	parameter fitting type.
3333
3334
	prior central value,
	prior standard deviation.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3335
3336
OUTPUT	RETURN_OK if the parameter is registered, RETURN_ERROR otherwise.
AUTHOR	E. Bertin (IAP)
3337
VERSION	16/01/2013
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3338
3339
 ***/
int	profit_setparam(profitstruct *profit, paramenum paramtype,
3340
		float param, float parammin,float parammax,
3341
3342
		parfitenum parfittype,
		float priorcen, float priorsig)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3343
  {
3344
   double	dtemp;
3345
   float	*paramptr;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3346
3347
3348
3349
3350
   int		index;

/* Check whether the parameter has already be registered */
  if ((paramptr=profit->paramlist[(int)paramtype]))
    {
3351
    index = profit->paramindex[(int)paramtype];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3352
3353
3354
    profit->paraminit[index] = param;
    profit->parammin[index] = parammin;
    profit->parammax[index] = parammax;
3355
    profit->parfittype[index] = parfittype;
3356
3357
    profit_boundtounbound(profit, &priorcen, &profit->dparampcen[index], index);
    profit->dparampsig[index] = priorsig;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3358
3359
3360
3361
3362
3363
3364
3365
    return RETURN_OK;
    }
  else
    return RETURN_ERROR;
  }

  
/****** profit_boundtounbound *************************************************
3366
PROTO	int profit_boundtounbound(profitstruct *profit,
3367
				float *param, double *dparam, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3368
PURPOSE	Convert parameters from bounded to unbounded space.
3369
3370
3371
3372
INPUT	Pointer to the profit structure,
	input array of single precision parameters,
	output (incomplete) array of double precision parameters,
	parameter selection index (<0 = all parameters)
3373
OUTPUT	Number of free parameters.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3374
3375
NOTES	-.
AUTHOR	E. Bertin (IAP)
3376
VERSION	20/05/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3377
 ***/
3378
int	profit_boundtounbound(profitstruct *profit,
3379
				float *param, double *dparam, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3380
  {
3381
   double	num,den, tparam;
3382
   int		f,p, pstart,np;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3383

3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

  f = 0;
  for (p=pstart ; p<np; p++)
3397
    switch(profit->parfittype[p])
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3398
      {
3399
3400
3401
3402
3403
3404
3405
3406
3407
      case PARFIT_FIXED:
        break;
      case PARFIT_UNBOUND:
        if (profit->parammax[p] > 0.0 || profit->parammax[p] < 0.0)
          dparam[f] = param[p-pstart] / profit->parammax[p];
        f++;
        break;
      case PARFIT_LINBOUND:
        tparam = param[p-pstart];
3408
3409
3410
        num = tparam - profit->parammin[p];
        den = profit->parammax[p] - tparam;
        dparam[f] = num>1e-50? (den>1e-50? log(num/den): 50.0) : -50.0;
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
        f++;
        break;
      case PARFIT_LOGBOUND:
        tparam = log(param[p-pstart]);
        num = tparam - log(profit->parammin[p]);
        den = log(profit->parammax[p]) - tparam;
        dparam[f] = num>1e-50? (den>1e-50? log(num/den): 50.0) : -50.0;
        f++;
        break;
      default:
        error(EXIT_FAILURE,
		"*Internal Error*: Unknown parameter fitting type in ",
		"profit_boundtounbound()");
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3424
3425
      }

3426
  return f;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3427
3428
3429
3430
  }


/****** profit_unboundtobound *************************************************
3431
PROTO	int profit_unboundtobound(profitstruct *profit,
3432
				double *dparam, float *param, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3433
PURPOSE	Convert parameters from unbounded to bounded space.
3434
3435
3436
3437
INPUT	Pointer to the profit structure,
	input (incomplete) array of double precision parameters,
	output array of single precision parameters.
	parameter selection index (<0 = all parameters)
3438
OUTPUT	Number of free parameters.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3439
3440
NOTES	-.
AUTHOR	E. Bertin (IAP)
3441
VERSION	20/05/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3442
 ***/
3443
int	profit_unboundtobound(profitstruct *profit,
3444
				double *dparam, float *param, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3445
  {
3446
   int		f,p, pstart,np;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3447

3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

  f = 0;
  for (p=pstart; p<np; p++)
3461
    switch(profit->parfittype[p])
3462
      {
3463
3464
3465
3466
3467
3468
3469
3470
3471
      case PARFIT_FIXED:
        param[p-pstart] = profit->paraminit[p];
        break;
      case PARFIT_UNBOUND:
        param[p-pstart] = dparam[f]*profit->parammax[p];
        f++;
        break;
      case PARFIT_LINBOUND:
        param[p-pstart] = (profit->parammax[p] - profit->parammin[p])
3472
3473
		/ (1.0 + exp(-(dparam[f]>50.0? 50.0
				: (dparam[f]<-50.0? -50.0: dparam[f]))))
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
		+ profit->parammin[p];
        f++;
        break;
      case PARFIT_LOGBOUND:
        param[p-pstart] = exp(log(profit->parammax[p]/profit->parammin[p])
		/ (1.0 + exp(-(dparam[f]>50.0? 50.0
				: (dparam[f]<-50.0? -50.0: dparam[f])))))
		*profit->parammin[p];
        f++;
        break;
      default:
        error(EXIT_FAILURE,
		"*Internal Error*: Unknown parameter fitting type in ",
		"profit_unboundtobound()");
3488
      }
3489
3490
 
  return f;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3491
3492
3493
3494
  }


/****** profit_covarunboundtobound ********************************************
3495
PROTO	int profit_covarunboundtobound(profitstruct *profit,
3496
				double *dcovar, float *covar)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3497
PURPOSE	Convert covariance matrix from unbounded to bounded space.
3498
3499
3500
INPUT	Pointer to the profit structure,
	input (incomplete) matrix of double precision covariances,
	output matrix of single precision covariances.
3501
OUTPUT	Number of parameters that hit a boundary.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3502
3503
NOTES	-.
AUTHOR	E. Bertin (IAP)
3504
VERSION	20/05/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3505
 ***/
3506
int	profit_covarunboundtobound(profitstruct *profit,
3507
				double *dcovar, float *covar)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3508
  {
3509
3510
   double	*dxdy,
		xmmin,maxmx, maxmmin;
3511
   float	*x,*xmin,*xmax;
3512
   parfitenum	*fittype;
3513
   int		*fflag,
3514
		f,f1,f2, p,p1,p2, nfree, nparam, nmin,nmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3515
3516

  nparam = profit->nparam;
3517
3518
  fittype = profit->parfittype;
  QMALLOC16(dxdy, double, PARAM_NPARAM);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3519
3520
3521
  x = profit->paraminit;
  xmin = profit->parammin;
  xmax = profit->parammax;
3522
  nmin = nmax = 0;
3523
  f = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3524
  for (p=0; p<profit->nparam; p++)
3525
    switch(fittype[p])
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3526
      {
3527
3528
3529
      case PARFIT_FIXED:
        break;
      case PARFIT_UNBOUND:
3530
        dxdy[f++] = xmax[p];
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
        break;
      case PARFIT_LINBOUND:
        xmmin   = x[p] - xmin[p];
        maxmx   = xmax[p] - x[p];
        maxmmin = xmax[p] - xmin[p];
        dxdy[f++] = xmmin * maxmx / maxmmin;
        if (xmmin<0.001*maxmmin)
          nmin++;
        else if (maxmx<0.001*maxmmin)
          nmax++;
        break;
      case PARFIT_LOGBOUND:
        xmmin   = log(x[p]/xmin[p]);
        maxmx   = log(xmax[p]/x[p]);
        maxmmin = log(xmax[p]/xmin[p]);
        dxdy[f++] = x[p] * xmmin * maxmx / maxmmin;
        if (xmmin<0.001*maxmmin)
          nmin++;
        else if (maxmx<0.001*maxmmin)
          nmax++;
        break;
      default:
        error(EXIT_FAILURE,
		"*Internal Error*: Unknown parameter fitting type in ",
		"profit_boundtounbound()");
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3556
3557
      }

3558
3559
  nfree = f;

3560
3561
  memset(profit->covar, 0, nparam*nparam*sizeof(float));
  f2 = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3562
  for (p2=0; p2<nparam; p2++)
3563
    {
3564
    if (fittype[p2]!=PARFIT_FIXED)
3565
3566
3567
      {
      f1 = 0;
      for (p1=0; p1<nparam; p1++)
3568
        if (fittype[p1]!=PARFIT_FIXED)
3569
3570
3571
3572
3573
3574
3575
          {
          covar[p2*nparam+p1] = (float)(dcovar[f2*nfree+f1]*dxdy[f1]*dxdy[f2]);
          f1++;
          }
      f2++;
      }
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3576
3577
3578

  free(dxdy);

3579
3580
3581
3582
  profit->nlimmin = nmin;
  profit->nlimmax = nmax;

  return nmin+nmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3583
3584
3585
3586
  }


/****** prof_init *************************************************************
3587
PROTO	profstruct prof_init(profitstruct *profit, unsigned int modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3588
3589
PURPOSE	Allocate and initialize a new profile structure.
INPUT	Pointer to the profile-fitting structure,
3590
	model type.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3591
3592
3593
OUTPUT	A pointer to an allocated prof structure.
NOTES	-.
AUTHOR	E. Bertin (IAP)
3594
VERSION	08/12/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3595
 ***/
3596
profstruct	*prof_init(profitstruct *profit, unsigned int modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3597
3598
  {
   profstruct	*prof;
3599
   float	*pix,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3600
3601
3602
3603
3604
		rmax2, re2, dy2,r2, scale, zero, k,n, hinvn;
   int		width,height, ixc,iyc, ix,iy, nsub,
		d,s;

  QCALLOC(prof, profstruct, 1);
3605
3606
  prof->code = modeltype;
  switch(modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3607
    {
3608
3609
    case MODEL_BACK:
      prof->name = "background offset";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3610
3611
3612
3613
3614
      prof->naxis = 2;
      prof->pix = NULL;
      profit_addparam(profit, PARAM_BACK, &prof->flux);
      prof->typscale = 1.0;
      break;
3615
3616
    case MODEL_DIRAC:
      prof->name = "point source";
3617
3618
3619
3620
3621
      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];
3622
      QMALLOC(prof->pix, float, prof->npix);
3623
3624
3625
3626
3627
      prof->typscale = 1.0;
      profit_addparam(profit, PARAM_X, &prof->x[0]);
      profit_addparam(profit, PARAM_Y, &prof->x[1]);
      profit_addparam(profit, PARAM_DIRAC_FLUX, &prof->flux);
      break;
3628
3629
    case MODEL_SERSIC:
      prof->name = "Sersic spheroid";
3630
3631
3632
3633
3634
3635
      prof->naxis = 2;
      prof->naxisn[0] = PROFIT_MAXMODSIZE;
      prof->naxisn[1] = PROFIT_MAXMODSIZE;
      prof->naxisn[2] = 1;
      prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3636
3637
3638
3639
3640
3641
3642
3643
3644
      prof->typscale = 1.0;
      profit_addparam(profit, PARAM_X, &prof->x[0]);
      profit_addparam(profit, PARAM_Y, &prof->x[1]);
      profit_addparam(profit, PARAM_SPHEROID_FLUX, &prof->flux);
      profit_addparam(profit, PARAM_SPHEROID_REFF, &prof->scale);
      profit_addparam(profit, PARAM_SPHEROID_ASPECT, &prof->aspect);
      profit_addparam(profit, PARAM_SPHEROID_POSANG, &prof->posangle);
      profit_addparam(profit, PARAM_SPHEROID_SERSICN, &prof->extra[0]);
      break;
3645
3646
    case MODEL_DEVAUCOULEURS:
      prof->name = "de Vaucouleurs spheroid";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3647
      prof->naxis = 2;
3648
3649
3650
3651
      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];
3652
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3653
3654
3655
3656
3657
3658
3659
3660
      prof->typscale = 1.0;
      profit_addparam(profit, PARAM_X, &prof->x[0]);
      profit_addparam(profit, PARAM_Y, &prof->x[1]);
      profit_addparam(profit, PARAM_SPHEROID_FLUX, &prof->flux);
      profit_addparam(profit, PARAM_SPHEROID_REFF, &prof->scale);
      profit_addparam(profit, PARAM_SPHEROID_ASPECT, &prof->aspect);
      profit_addparam(profit, PARAM_SPHEROID_POSANG, &prof->posangle);
      break;
3661
3662
    case MODEL_EXPONENTIAL:
      prof->name = "exponential disk";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3663
      prof->naxis = 2;
3664
3665
3666
3667
      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];
3668
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3669
3670
3671
3672
3673
3674
3675
3676
      prof->typscale = 1.0;
      profit_addparam(profit, PARAM_X, &prof->x[0]);
      profit_addparam(profit, PARAM_Y, &prof->x[1]);
      profit_addparam(profit, PARAM_DISK_FLUX, &prof->flux);
      profit_addparam(profit, PARAM_DISK_SCALE, &prof->scale);
      profit_addparam(profit, PARAM_DISK_ASPECT, &prof->aspect);
      profit_addparam(profit, PARAM_DISK_POSANG, &prof->posangle);
      break;
3677
3678
    case MODEL_ARMS:
      prof->name = "spiral arms";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3679
      prof->naxis = 2;
3680
3681
3682
3683
      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];
3684
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
      prof->typscale = 1.0;
      profit_addparam(profit, PARAM_X, &prof->x[0]);
      profit_addparam(profit, PARAM_Y, &prof->x[1]);
      profit_addparam(profit, PARAM_DISK_SCALE, &prof->scale);
      profit_addparam(profit, PARAM_DISK_ASPECT, &prof->aspect);
      profit_addparam(profit, PARAM_DISK_POSANG, &prof->posangle);
      profit_addparam(profit, PARAM_ARMS_FLUX, &prof->flux);
      profit_addparam(profit, PARAM_ARMS_QUADFRAC, &prof->featfrac);
//      profit_addparam(profit, PARAM_ARMS_SCALE, &prof->featscale);
      profit_addparam(profit, PARAM_ARMS_START, &prof->featstart);
      profit_addparam(profit, PARAM_ARMS_PITCH, &prof->featpitch);
//      profit_addparam(profit, PARAM_ARMS_PITCHVAR, &prof->featpitchvar);
      profit_addparam(profit, PARAM_ARMS_POSANG, &prof->featposang);
//      profit_addparam(profit, PARAM_ARMS_WIDTH, &prof->featwidth);
      break;
3700
3701
    case MODEL_BAR:
      prof->name = "bar";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3702
      prof->naxis = 2;
3703
3704
3705
3706
      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];
3707
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
      prof->typscale = 1.0;
      profit_addparam(profit, PARAM_X, &prof->x[0]);
      profit_addparam(profit, PARAM_Y, &prof->x[1]);
      profit_addparam(profit, PARAM_DISK_SCALE, &prof->scale);
      profit_addparam(profit, PARAM_DISK_ASPECT, &prof->aspect);
      profit_addparam(profit, PARAM_DISK_POSANG, &prof->posangle);
      profit_addparam(profit, PARAM_ARMS_START, &prof->featstart);
      profit_addparam(profit, PARAM_BAR_FLUX, &prof->flux);
      profit_addparam(profit, PARAM_BAR_ASPECT, &prof->feataspect);
      profit_addparam(profit, PARAM_ARMS_POSANG, &prof->featposang);
      break;
3719
3720
    case MODEL_INRING:
      prof->name = "inner ring";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3721
      prof->naxis = 2;
3722
3723
3724
3725
      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];
3726
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
      prof->typscale = 1.0;
      profit_addparam(profit, PARAM_X, &prof->x[0]);
      profit_addparam(profit, PARAM_Y, &prof->x[1]);
      profit_addparam(profit, PARAM_DISK_SCALE, &prof->scale);
      profit_addparam(profit, PARAM_DISK_ASPECT, &prof->aspect);
      profit_addparam(profit, PARAM_DISK_POSANG, &prof->posangle);
      profit_addparam(profit, PARAM_ARMS_START, &prof->featstart);
      profit_addparam(profit, PARAM_INRING_FLUX, &prof->flux);
      profit_addparam(profit, PARAM_INRING_WIDTH, &prof->featwidth);
      profit_addparam(profit, PARAM_INRING_ASPECT, &prof->feataspect);
      break;
3738
3739
    case MODEL_OUTRING:
      prof->name = "outer ring";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3740
      prof->naxis = 2;
3741
3742
3743
3744
      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];
3745
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
      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;
3756
3757
    case MODEL_TABULATED:	/* An example of tabulated profile */
      prof->name = "tabulated model";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3758
      prof->naxis = 3;
3759
3760
3761
3762
3763
      width =  prof->naxisn[0] = PROFIT_MAXMODSIZE;
      height = prof->naxisn[1] = PROFIT_MAXMODSIZE;
      nsub = prof->naxisn[2] = PROFIT_MAXSMODSIZE;
      prof->npix = prof->naxisn[0]*prof->naxisn[1]*prof->naxisn[2];
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3764
3765
3766
3767
3768
3769
3770
      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;
3771
      scale = prof->extrascale[0]= 8.0/PROFIT_MAXSMODSIZE;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
      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;
    }

3803
  if (prof->naxis>2)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3804
3805
3806
3807
3808
3809
3810
3811
3812
    {
    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];
3813
    QMALLOC16(prof->kernelbuf, float, prof->kernelnlines);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
    }

  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 **************************************************************
3843
3844
PROTO	float prof_add(profitstruct *profit, profstruct *prof,
		int extfluxfac_flag)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3845
PURPOSE	Add a model profile to an image.
3846
3847
3848
3849
INPUT	Profile-fitting structure,
	profile structure,
	flag (0 if flux correction factor is to be computed internally) 
OUTPUT	Total (asymptotic) flux contribution.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3850
3851
NOTES	-.
AUTHOR	E. Bertin (IAP)
3852
VERSION	13/02/2013
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3853
 ***/
3854
float	prof_add(profitstruct *profit, profstruct *prof, int extfluxfac_flag)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3855
  {
3856
3857
   double	xscale, yscale, saspect, ctheta,stheta, flux, scaling, bn, n,
		dx1cout,dx2cout, ddx1[36],ddx2[36];
3858
   float	posin[PROFIT_MAXEXTRA], posout[2], dnaxisn[2],
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3859
		*pixin, *pixin2, *pixout,
3860
3861
		fluxfac, amp,cd11,cd12,cd21,cd22, dx1,dx2,
		x1,x10,x2, x1cin,x2cin, x1cout,x2cout, x1max,x2max, x1in,x2in,
3862
		k, hinvn, x1t,x2t, ca,sa, u,umin,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3863
3864
		armamp,arm2amp, armrdphidr, armrdphidrvar, posang,
		width, invwidth2,
3865
3866
		r,r2,rmin, r2minxin,r2minxout, rmax, r2max,
		r2max1, r2max2, r2min, invr2xdif,
3867
3868
		val, theta, thresh, ra,rb, num,num2,den, ang,angstep,
		invn, dr, krpinvn,dkrpinvn, rs,rs2,
3869
3870
3871
		a11,a12,a21,a22, invdet, dca,dsa, a0,a2,a3, p1,p2,
		krspinvn, ekrspinvn, selem;
   int		npix, threshflag,
3872
		a,d,e,i, ix1,ix2, ix1max,ix2max, nang, nx2,
3873
		npix2;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3874

3875
  npix = profit->nmodpix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3876

3877
  if (prof->code==MODEL_BACK)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3878
3879
3880
3881
3882
    {
    amp = fabs(*prof->flux);
    pixout = profit->modpix;
    for (i=npix; i--;)
      *(pixout++) += amp;
3883
3884
    prof->lostfluxfrac = 0.0;
    return 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3885
3886
3887
3888
    }

  scaling = profit->pixstep / prof->typscale;

3889
  if (prof->code!=MODEL_DIRAC)
3890
3891
3892
3893
3894
3895
    {
/*-- Compute Profile CD matrix */
    ctheta = cos(*prof->posangle*DEG);
    stheta = sin(*prof->posangle*DEG);
    saspect = fabs(*prof->aspect);
    xscale = (*prof->scale==0.0)?
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3896
		0.0 : fabs(scaling / (*prof->scale*prof->typscale));
3897
    yscale = (*prof->scale*saspect == 0.0)?
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3898
		0.0 : fabs(scaling / (*prof->scale*prof->typscale*saspect));
3899
3900
3901
3902
    cd11 = (float)(xscale*ctheta);
    cd12 = (float)(xscale*stheta);
    cd21 = (float)(-yscale*stheta);
    cd22 = (float)(yscale*ctheta);
3903
3904
3905
3906
3907
    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);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3908
    nx2 = profit->modnaxisn[1]/2 + 1;
3909
3910
3911

/*-- Compute the largest r^2 that fits in the frame */
    num = cd11*cd22-cd12*cd21;
3912
    num *= num;
3913
3914
    x1max = x1cout - 1.0;
    x2max = x2cout - 1.0;
3915
3916
3917
3918
3919
3920
3921
    den = fabs(cd12*cd12+cd22*cd22);
    num2 = x1max*x1max*num;
    r2max1 = num2<PROFIT_MAXR2MAX*den? num2 / den : PROFIT_MAXR2MAX;
    den = fabs(cd11*cd11+cd21*cd21);
    num2 = x2max*x2max*num;
    r2max2 = num2<PROFIT_MAXR2MAX*den? num2 / den : PROFIT_MAXR2MAX;
    r2max = (r2max1 < r2max2? r2max1 : r2max2);
3922
    rmax = sqrtf(r2max);
3923
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3924
3925
3926

  switch(prof->code)
    {
3927
    case MODEL_DIRAC:
3928
      memset(prof->pix, 0, profit->nmodpix);
3929
3930
3931
3932
3933
      prof->pix[profit->modnaxisn[0]/2
		+ (profit->modnaxisn[1]/2)*profit->modnaxisn[0]] = 1.0;
      prof->lostfluxfrac = 0.0;
      threshflag = 0;
      break;
3934
3935
3936
    case MODEL_SERSIC:
    case MODEL_DEVAUCOULEURS:
    case MODEL_EXPONENTIAL:
3937
3938
3939
3940
3941
3942
/*---- Compute sharp/smooth transition radius */
      rs = PROFIT_SMOOTHR*(xscale>yscale?xscale:yscale);
      if (rs<=0)
        rs = 1.0;
      rs2 = rs*rs;
/*---- The consequence of sampling on flux is compensated by PSF normalisation*/
3943
      if (prof->code==MODEL_EXPONENTIAL)
3944
        bn = n = 1.0;
3945
      else if (prof->code==MODEL_DEVAUCOULEURS)
3946
3947
3948
3949
3950
3951
3952
3953
        {
        n = 4.0;
        bn = 7.66924944;
        }
      else
        {
        n = fabs(*prof->extra[0]);
        bn = 2.0*n - 1.0/3.0 + 4.0/(405.0*n) + 46.0/(25515.0*n*n)
3954
		+ 131.0/(1148175*n*n*n);	/* Ciotti & Bertin 1999 */
3955
3956
        }
      invn = 1.0/n;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3957
      hinvn = 0.5/n;
3958
3959
      k = -bn;
/*---- Compute central polynomial terms */
3960
      krspinvn = prof->code==MODEL_EXPONENTIAL? -rs : k*expf(logf(rs)*invn);
3961
3962
3963
3964
3965
3966
3967
      ekrspinvn = expf(krspinvn);
      p2 = krspinvn*invn*invn;
      p1 = krspinvn*p2;
      a0 = (1+(1.0/6.0)*(p1+(1.0-5.0*n)*p2))*ekrspinvn;
      a2 = (-1.0/2.0)*(p1+(1.0-3.0*n)*p2)/rs2*ekrspinvn;
      a3 = (1.0/3.0)*(p1+(1.0-2.0*n)*p2)/(rs2*rs)*ekrspinvn;
/*---- Compute the smooth part of the profile */
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3968
3969
      x10 = -x1cout - dx1;
      x2 = -x2cout - dx2;
3970
      pixin = prof->pix;
3971
      if (prof->code==MODEL_EXPONENTIAL)
3972
        for (ix2=nx2; ix2--; x2+=1.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3973
          {
3974
3975
          x1 = x10;
          for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3976
            {
3977
3978
3979
3980
            x1in = cd12*x2 + cd11*x1;
            x2in = cd22*x2 + cd21*x1;
            ra = x1in*x1in+x2in*x2in;
            if (ra>r2max)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3981
              {
3982
3983
              *(pixin++) = 0.0;
              continue;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3984
              }
3985
3986
            val = ra<rs2? a0+ra*(a2+a3*sqrtf(ra)) : expf(-sqrtf(ra));
            *(pixin++) = val;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3987
3988
            }
          }
3989
3990
      else
        for (ix2=nx2; ix2--; x2+=1.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3991
          {
3992
3993
          x1 = x10;
          for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
3994
            {
3995
3996
3997
3998
            x1in = cd12*x2 + cd11*x1;
            x2in = cd22*x2 + cd21*x1;
            ra = x1in*x1in+x2in*x2in;
            if (ra>r2max)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3999
              {
4000
              *(pixin++) = 0.0;
For faster browsing, not all history is shown. View entire blame