profit.c 140 KB
Newer Older
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3001
3002
3003
3004
 ***/
void	profit_resetparam(profitstruct *profit, paramenum paramtype)
  {
   obj2struct	*obj2;
3005
   float	param, parammin,parammax, range;
3006
   parfitenum	fittype;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3007
3008
3009

  obj2 = profit->obj2;
  param = parammin = parammax = 0.0;	/* Avoid gcc -Wall warnings*/
3010

Emmanuel Bertin's avatar
Emmanuel Bertin committed
3011
3012
3013
  switch(paramtype)
    {
    case PARAM_BACK:
3014
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3015
      param = 0.0;
3016
3017
      parammin = -6.0*profit->guesssigbkg;
      parammax =  6.0*profit->guesssigbkg;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3018
3019
      break;
    case PARAM_X:
3020
      fittype = PARFIT_LINBOUND;
3021
      param = profit->guessdx;
3022
      range = profit->guessradius*4.0;
3023
3024
3025
3026
      if (range>profit->objnaxisn[0]*2.0)
        range = profit->objnaxisn[0]*2.0;
      parammin = -range;
      parammax =  range;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3027
3028
      break;
    case PARAM_Y:
3029
      fittype = PARFIT_LINBOUND;
3030
      param = profit->guessdy;
3031
      range = profit->guessradius*4.0;
3032
3033
3034
3035
      if (range>profit->objnaxisn[1]*2)
        range = profit->objnaxisn[1]*2;
      parammin = -range;
      parammax =  range;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3036
      break;
3037
    case PARAM_DIRAC_FLUX:
3038
3039
3040
3041
      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
3042
      break;
3043
    case PARAM_SPHEROID_FLUX:
3044
3045
3046
3047
      fittype = PARFIT_LOGBOUND;
      param = profit->guessflux/profit->nprof;
      parammin = 0.00001*profit->guessfluxmax;
      parammax = 10.0*profit->guessfluxmax;
3048
      break;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3049
    case PARAM_SPHEROID_REFF:
3050
3051
      fittype = PARFIT_LOGBOUND;
      param = FLAG(obj2.prof_disk_flux)? profit->guessradius
3052
			: profit->guessradius/sqrtf(profit->guessaspect);
3053
      parammin = 0.01;
3054
      parammax = param * 10.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3055
3056
      break;
    case PARAM_SPHEROID_ASPECT:
3057
      fittype = PARFIT_LOGBOUND;
3058
      param = FLAG(obj2.prof_disk_flux)? 1.0 : profit->guessaspect;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3059
      parammin = FLAG(obj2.prof_disk_flux)? 0.5 : 0.01;
3060
      parammax = FLAG(obj2.prof_disk_flux)? 2.0 : 100.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3061
3062
      break;
    case PARAM_SPHEROID_POSANG:
3063
      fittype = PARFIT_UNBOUND;
3064
      param = profit->guessposang;
3065
3066
      parammin = 90.0;
      parammax =  90.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3067
3068
      break;
    case PARAM_SPHEROID_SERSICN:
3069
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3070
      param = 4.0;
3071
      parammin = FLAG(obj2.prof_disk_flux)? 1.0 : 0.3;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3072
3073
3074
      parammax = 10.0;
      break;
    case PARAM_DISK_FLUX:
3075
3076
3077
3078
      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
3079
3080
      break;
    case PARAM_DISK_SCALE:	/* From scalelength to Re */
3081
      fittype = PARFIT_LOGBOUND;
3082
      param = profit->guessradius/(1.67835*sqrtf(profit->guessaspect));
3083
3084
      parammin = 0.01/1.67835;
      parammax = param * 10.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3085
3086
      break;
    case PARAM_DISK_ASPECT:
3087
      fittype = PARFIT_LOGBOUND;
3088
      param = profit->guessaspect;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3089
      parammin = 0.01;
3090
      parammax = 100.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3091
3092
      break;
    case PARAM_DISK_POSANG:
3093
      fittype = PARFIT_UNBOUND;
3094
      param = profit->guessposang;
3095
3096
      parammin = 90.0;
      parammax =  90.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3097
3098
      break;
    case PARAM_ARMS_FLUX:
3099
3100
3101
3102
      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
3103
3104
      break;
    case PARAM_ARMS_QUADFRAC:
3105
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3106
3107
3108
3109
3110
      param = 0.5;
      parammin = 0.0;
      parammax = 1.0;
      break;
    case PARAM_ARMS_SCALE:
3111
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3112
3113
3114
3115
3116
      param = 1.0;
      parammin = 0.5;
      parammax = 10.0;
      break;
    case PARAM_ARMS_START:
3117
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3118
3119
3120
3121
3122
      param = 0.5;
      parammin = 0.0;
      parammax = 3.0;
      break;
    case PARAM_ARMS_PITCH:
3123
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3124
3125
3126
3127
3128
      param = 20.0;
      parammin = 5.0;
      parammax = 50.0;
      break;
    case PARAM_ARMS_PITCHVAR:
3129
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
      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:
3143
      fittype = PARFIT_UNBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3144
3145
3146
3147
3148
      param = 0.0;
      parammin = 0.0;
      parammax = 0.0;
      break;
    case PARAM_ARMS_WIDTH:
3149
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3150
3151
3152
3153
3154
      param = 3.0;
      parammin = 1.5;
      parammax = 11.0;
      break;
    case PARAM_BAR_FLUX:
3155
3156
3157
3158
      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
3159
3160
      break;
    case PARAM_BAR_ASPECT:
3161
      fittype = PARFIT_LOGBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3162
3163
3164
3165
3166
      param = 0.3;
      parammin = 0.2;
      parammax = 0.5;
      break;
    case PARAM_BAR_POSANG:
3167
      fittype = PARFIT_UNBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3168
      param = 0.0;
3169
3170
      parammin = 90.0;
      parammax = 90.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3171
3172
      break;
    case PARAM_INRING_FLUX:
3173
3174
3175
3176
      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
3177
3178
      break;
    case PARAM_INRING_WIDTH:
3179
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3180
3181
3182
3183
3184
      param = 0.3;
      parammin = 0.0;
      parammax = 0.5;
      break;
    case PARAM_INRING_ASPECT:
3185
      fittype = PARFIT_LOGBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3186
3187
3188
3189
3190
      param = 0.8;
      parammin = 0.4;
      parammax = 1.0;
      break;
    case PARAM_OUTRING_FLUX:
3191
3192
3193
3194
      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
3195
3196
      break;
    case PARAM_OUTRING_START:
3197
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3198
3199
3200
3201
3202
      param = 4.0;
      parammin = 3.5;
      parammax = 6.0;
      break;
    case PARAM_OUTRING_WIDTH:
3203
      fittype = PARFIT_LINBOUND;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
      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;
3216
3217
  else if (parammin==0.0 && parammax==0.0)
    parammax = 1.0;
3218
  profit_setparam(profit, paramtype, param, parammin, parammax, fittype);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246

  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,
3247
3248
		float param, float parammin, float parammax,
		parfitenum parfittype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3249
3250
PURPOSE	Set the actual, lower and upper boundary values of a profile parameter.
INPUT	Pointer to the profit structure,
3251
3252
3253
3254
3255
	parameter index,
	actual value,
	lower boundary to the parameter,
	upper boundary to the parameter,
	parameter fitting type.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3256
3257
OUTPUT	RETURN_OK if the parameter is registered, RETURN_ERROR otherwise.
AUTHOR	E. Bertin (IAP)
3258
VERSION	20/05/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3259
3260
 ***/
int	profit_setparam(profitstruct *profit, paramenum paramtype,
3261
3262
		float param, float parammin,float parammax,
		parfitenum parfittype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3263
  {
3264
   float	*paramptr;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3265
3266
3267
3268
3269
   int		index;

/* Check whether the parameter has already be registered */
  if ((paramptr=profit->paramlist[(int)paramtype]))
    {
3270
    index = profit->paramindex[(int)paramtype];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3271
3272
3273
    profit->paraminit[index] = param;
    profit->parammin[index] = parammin;
    profit->parammax[index] = parammax;
3274
    profit->parfittype[index] = parfittype;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3275
3276
3277
3278
3279
3280
3281
3282
    return RETURN_OK;
    }
  else
    return RETURN_ERROR;
  }

  
/****** profit_boundtounbound *************************************************
3283
PROTO	int profit_boundtounbound(profitstruct *profit,
3284
				float *param, double *dparam, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3285
PURPOSE	Convert parameters from bounded to unbounded space.
3286
3287
3288
3289
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)
3290
OUTPUT	Number of free parameters.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3291
3292
NOTES	-.
AUTHOR	E. Bertin (IAP)
3293
VERSION	20/05/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3294
 ***/
3295
int	profit_boundtounbound(profitstruct *profit,
3296
				float *param, double *dparam, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3297
  {
3298
   double	num,den, tparam;
3299
   int		f,p, pstart,np;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3300

3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

  f = 0;
  for (p=pstart ; p<np; p++)
3314
    switch(profit->parfittype[p])
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3315
      {
3316
3317
3318
3319
3320
3321
3322
3323
3324
      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];
3325
3326
3327
        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;
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
        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
3341
3342
      }

3343
  return f;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3344
3345
3346
3347
  }


/****** profit_unboundtobound *************************************************
3348
PROTO	int profit_unboundtobound(profitstruct *profit,
3349
				double *dparam, float *param, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3350
PURPOSE	Convert parameters from unbounded to bounded space.
3351
3352
3353
3354
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)
3355
OUTPUT	Number of free parameters.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3356
3357
NOTES	-.
AUTHOR	E. Bertin (IAP)
3358
VERSION	20/05/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3359
 ***/
3360
int	profit_unboundtobound(profitstruct *profit,
3361
				double *dparam, float *param, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3362
  {
3363
   int		f,p, pstart,np;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3364

3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

  f = 0;
  for (p=pstart; p<np; p++)
3378
    switch(profit->parfittype[p])
3379
      {
3380
3381
3382
3383
3384
3385
3386
3387
3388
      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])
3389
3390
		/ (1.0 + exp(-(dparam[f]>50.0? 50.0
				: (dparam[f]<-50.0? -50.0: dparam[f]))))
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
		+ 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()");
3405
      }
3406
3407
 
  return f;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3408
3409
3410
3411
  }


/****** profit_covarunboundtobound ********************************************
3412
PROTO	int profit_covarunboundtobound(profitstruct *profit,
3413
				double *dcovar, float *covar)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3414
PURPOSE	Convert covariance matrix from unbounded to bounded space.
3415
3416
3417
INPUT	Pointer to the profit structure,
	input (incomplete) matrix of double precision covariances,
	output matrix of single precision covariances.
3418
OUTPUT	Number of parameters that hit a boundary.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3419
3420
NOTES	-.
AUTHOR	E. Bertin (IAP)
3421
VERSION	20/05/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3422
 ***/
3423
int	profit_covarunboundtobound(profitstruct *profit,
3424
				double *dcovar, float *covar)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3425
  {
3426
3427
   double	*dxdy,
		xmmin,maxmx, maxmmin;
3428
   float	*x,*xmin,*xmax;
3429
   parfitenum	*fittype;
3430
   int		*fflag,
3431
		f,f1,f2, p,p1,p2, nfree, nparam, nmin,nmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3432
3433

  nparam = profit->nparam;
3434
3435
  fittype = profit->parfittype;
  QMALLOC16(dxdy, double, PARAM_NPARAM);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3436
3437
3438
  x = profit->paraminit;
  xmin = profit->parammin;
  xmax = profit->parammax;
3439
  nmin = nmax = 0;
3440
  f = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3441
  for (p=0; p<profit->nparam; p++)
3442
    switch(fittype[p])
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3443
      {
3444
3445
3446
      case PARFIT_FIXED:
        break;
      case PARFIT_UNBOUND:
3447
        dxdy[f++] = xmax[p];
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
        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
3473
3474
      }

3475
3476
  nfree = f;

3477
3478
  memset(profit->covar, 0, nparam*nparam*sizeof(float));
  f2 = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3479
  for (p2=0; p2<nparam; p2++)
3480
    {
3481
    if (fittype[p2]!=PARFIT_FIXED)
3482
3483
3484
      {
      f1 = 0;
      for (p1=0; p1<nparam; p1++)
3485
        if (fittype[p1]!=PARFIT_FIXED)
3486
3487
3488
3489
3490
3491
3492
          {
          covar[p2*nparam+p1] = (float)(dcovar[f2*nfree+f1]*dxdy[f1]*dxdy[f2]);
          f1++;
          }
      f2++;
      }
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3493
3494
3495

  free(dxdy);

3496
3497
3498
3499
  profit->nlimmin = nmin;
  profit->nlimmax = nmax;

  return nmin+nmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3500
3501
3502
3503
  }


/****** prof_init *************************************************************
3504
PROTO	profstruct prof_init(profitstruct *profit, unsigned int modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3505
3506
PURPOSE	Allocate and initialize a new profile structure.
INPUT	Pointer to the profile-fitting structure,
3507
	model type.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3508
3509
3510
OUTPUT	A pointer to an allocated prof structure.
NOTES	-.
AUTHOR	E. Bertin (IAP)
3511
VERSION	08/12/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3512
 ***/
3513
profstruct	*prof_init(profitstruct *profit, unsigned int modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3514
3515
  {
   profstruct	*prof;
3516
   float	*pix,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3517
3518
3519
3520
3521
		rmax2, re2, dy2,r2, scale, zero, k,n, hinvn;
   int		width,height, ixc,iyc, ix,iy, nsub,
		d,s;

  QCALLOC(prof, profstruct, 1);
3522
3523
  prof->code = modeltype;
  switch(modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3524
    {
3525
3526
    case MODEL_BACK:
      prof->name = "background offset";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3527
3528
3529
3530
3531
      prof->naxis = 2;
      prof->pix = NULL;
      profit_addparam(profit, PARAM_BACK, &prof->flux);
      prof->typscale = 1.0;
      break;
3532
3533
    case MODEL_DIRAC:
      prof->name = "point source";
3534
3535
3536
3537
3538
      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];
3539
      QMALLOC(prof->pix, float, prof->npix);
3540
3541
3542
3543
3544
      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;
3545
3546
    case MODEL_SERSIC:
      prof->name = "Sersic spheroid";
3547
3548
3549
3550
3551
3552
      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
3553
3554
3555
3556
3557
3558
3559
3560
3561
      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;
3562
3563
    case MODEL_DEVAUCOULEURS:
      prof->name = "de Vaucouleurs spheroid";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3564
      prof->naxis = 2;
3565
3566
3567
3568
      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];
3569
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3570
3571
3572
3573
3574
3575
3576
3577
      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;
3578
3579
    case MODEL_EXPONENTIAL:
      prof->name = "exponential disk";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3580
      prof->naxis = 2;
3581
3582
3583
3584
      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];
3585
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3586
3587
3588
3589
3590
3591
3592
3593
      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;
3594
3595
    case MODEL_ARMS:
      prof->name = "spiral arms";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3596
      prof->naxis = 2;
3597
3598
3599
3600
      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];
3601
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
      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;
3617
3618
    case MODEL_BAR:
      prof->name = "bar";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3619
      prof->naxis = 2;
3620
3621
3622
3623
      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];
3624
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
      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;
3636
3637
    case MODEL_INRING:
      prof->name = "inner ring";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3638
      prof->naxis = 2;
3639
3640
3641
3642
      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];
3643
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
      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;
3655
3656
    case MODEL_OUTRING:
      prof->name = "outer ring";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3657
      prof->naxis = 2;
3658
3659
3660
3661
      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];
3662
      QMALLOC(prof->pix, float, prof->npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
      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;
3673
3674
    case MODEL_TABULATED:	/* An example of tabulated profile */
      prof->name = "tabulated model";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3675
      prof->naxis = 3;
3676
3677
3678
3679
3680
      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
3681
3682
3683
3684
3685
3686
3687
      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;
3688
      scale = prof->extrascale[0]= 8.0/PROFIT_MAXSMODSIZE;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
      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;
    }

3720
  if (prof->naxis>2)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3721
3722
3723
3724
3725
3726
3727
3728
3729
    {
    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];
3730
    QMALLOC16(prof->kernelbuf, float, prof->kernelnlines);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
    }

  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 **************************************************************
3760
3761
PROTO	float prof_add(profitstruct *profit, profstruct *prof,
		int extfluxfac_flag)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3762
PURPOSE	Add a model profile to an image.
3763
3764
3765
3766
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
3767
3768
NOTES	-.
AUTHOR	E. Bertin (IAP)
3769
VERSION	25/07/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3770
 ***/
3771
float	prof_add(profitstruct *profit, profstruct *prof, int extfluxfac_flag)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3772
  {
3773
3774
   double	xscale, yscale, saspect, ctheta,stheta, flux, scaling, bn, n,
		dx1cout,dx2cout, ddx1[36],ddx2[36];
3775
   float	posin[PROFIT_MAXEXTRA], posout[2], dnaxisn[2],
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3776
		*pixin, *pixin2, *pixout,
3777
3778
		fluxfac, amp,cd11,cd12,cd21,cd22, dx1,dx2,
		x1,x10,x2, x1cin,x2cin, x1cout,x2cout, x1max,x2max, x1in,x2in,
3779
		k, hinvn, x1t,x2t, ca,sa, u,umin,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3780
3781
		armamp,arm2amp, armrdphidr, armrdphidrvar, posang,
		width, invwidth2,
3782
3783
		r,r2,rmin, r2minxin,r2minxout, rmax, r2max,
		r2max1, r2max2, r2min, invr2xdif,
3784
3785
		val, theta, thresh, ra,rb, num,num2,den, ang,angstep,
		invn, dr, krpinvn,dkrpinvn, rs,rs2,
3786
3787
3788
		a11,a12,a21,a22, invdet, dca,dsa, a0,a2,a3, p1,p2,
		krspinvn, ekrspinvn, selem;
   int		npix, threshflag,
3789
		a,d,e,i, ix1,ix2, ix1max,ix2max, nang, nx2,
3790
		npix2;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3791

3792
  npix = profit->nmodpix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3793

3794
  if (prof->code==MODEL_BACK)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3795
3796
3797
3798
3799
    {
    amp = fabs(*prof->flux);
    pixout = profit->modpix;
    for (i=npix; i--;)
      *(pixout++) += amp;
3800
3801
    prof->lostfluxfrac = 0.0;
    return 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3802
3803
3804
3805
    }

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

3806
  if (prof->code!=MODEL_DIRAC)
3807
3808
3809
3810
3811
3812
    {
/*-- 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
3813
		0.0 : fabs(scaling / (*prof->scale*prof->typscale));
3814
    yscale = (*prof->scale*saspect == 0.0)?
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3815
		0.0 : fabs(scaling / (*prof->scale*prof->typscale*saspect));
3816
3817
3818
3819
    cd11 = (float)(xscale*ctheta);
    cd12 = (float)(xscale*stheta);
    cd21 = (float)(-yscale*stheta);
    cd22 = (float)(yscale*ctheta);
3820
3821
3822
3823
3824
    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
3825
    nx2 = profit->modnaxisn[1]/2 + 1;
3826
3827
3828

/*-- Compute the largest r^2 that fits in the frame */
    num = cd11*cd22-cd12*cd21;
3829
    num *= num;
3830
3831
    x1max = x1cout - 1.0;
    x2max = x2cout - 1.0;
3832
3833
3834
3835
3836
3837
3838
    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);
3839
    rmax = sqrtf(r2max);
3840
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3841
3842
3843

  switch(prof->code)
    {
3844
    case MODEL_DIRAC:
3845
      memset(prof->pix, 0, profit->nmodpix);
3846
3847
3848
3849
3850
      prof->pix[profit->modnaxisn[0]/2
		+ (profit->modnaxisn[1]/2)*profit->modnaxisn[0]] = 1.0;
      prof->lostfluxfrac = 0.0;
      threshflag = 0;
      break;
3851
3852
3853
    case MODEL_SERSIC:
    case MODEL_DEVAUCOULEURS:
    case MODEL_EXPONENTIAL:
3854
3855
3856
3857
3858
3859
/*---- 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*/
3860
      if (prof->code==MODEL_EXPONENTIAL)
3861
        bn = n = 1.0;
3862
      else if (prof->code==MODEL_DEVAUCOULEURS)
3863
3864
3865
3866
3867
3868
3869
3870
        {
        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)
3871
		+ 131.0/(1148175*n*n*n);	/* Ciotti & Bertin 1999 */
3872
3873
        }
      invn = 1.0/n;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3874
      hinvn = 0.5/n;
3875
3876
      k = -bn;
/*---- Compute central polynomial terms */
3877
      krspinvn = prof->code==MODEL_EXPONENTIAL? -rs : k*expf(logf(rs)*invn);
3878
3879
3880
3881
3882
3883
3884
      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
3885
3886
      x10 = -x1cout - dx1;
      x2 = -x2cout - dx2;
3887
      pixin = prof->pix;
3888
      if (prof->code==MODEL_EXPONENTIAL)
3889
        for (ix2=nx2; ix2--; x2+=1.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3890
          {
3891
3892
          x1 = x10;
          for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3893
            {
3894
3895
3896
3897
            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
3898
              {
3899
3900
              *(pixin++) = 0.0;
              continue;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3901
              }
3902
3903
            val = ra<rs2? a0+ra*(a2+a3*sqrtf(ra)) : expf(-sqrtf(ra));
            *(pixin++) = val;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3904
3905
            }
          }
3906
3907
      else
        for (ix2=nx2; ix2--; x2+=1.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3908
          {
3909
3910
          x1 = x10;
          for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
3911
            {
3912
3913
3914
3915
            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
3916
              {
3917
3918
              *(pixin++) = 0.0;
              continue;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3919
              }
3920
3921
            val = ra<rs2? a0+ra*(a2+a3*sqrtf(ra)) : expf(k*expf(logf(ra)*hinvn));
            *(pixin++) = val;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3922
3923
            }
          }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3924
3925
3926
/*---- Copy the symmetric part */
      if ((npix2=(profit->modnaxisn[1]-nx2)*profit->modnaxisn[0]) > 0)
        {
3927
3928
3929
3930
3931
3932
        pixin2 = pixin - profit->modnaxisn[0] - 1;
        if (!(profit->modnaxisn[0]&1))
          {
          *(pixin++) = 0.0;
          npix2--;
          }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3933
3934
3935
        for (i=npix2; i--;)
          *(pixin++) = *(pixin2--);
        }
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950

/*---- Compute the sharp part of the profile */
      ix1max = profit->modnaxisn[0];
      ix2max = profit->modnaxisn[1];
      dx1cout = x1cout + 0.4999999;
      dx2cout = x2cout + 0.4999999;
      invdet = 1.0/fabsf(cd11*cd22 - cd12*cd21);
      a11 = cd22*invdet;
      a12 = -cd12*invdet;
      a21 = -cd21*invdet;
      a22 = cd11*invdet;
      nang = 72 / 2;		/* 36 angles; only half of them are computed*/
      angstep = PI/nang;
      ang = 0.0;
      for (a=0; a<nang; a++)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3951
        {
3952
#ifdef HAVE_SINCOSF
3953
3954
3955
3956
3957
3958
3959
        sincosf(ang, &dsa, &dca);
#else
        dsa = sinf(ang);
        dca = cosf(ang);
#endif
        ddx1[a] = a11*dsa+a12*dca;
        ddx2[a] = a21*dsa+a22*dca;
3960
        ang += angstep;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3961
        }
3962
3963
3964
3965
3966
3967
3968
      r = DEXPF(-4.0);
      dr = DEXPF(0.05);
      selem = 0.5*angstep*(dr - 1.0/dr)/(xscale*yscale);
      krpinvn = k*DEXPF(-4.0*invn);
      dkrpinvn = DEXPF(0.05*invn);
      pixin = prof->pix;
      for (; r<rs; r *= dr)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3969
        {
3970
3971
3972
        r2 = r*r;
        val = (expf(krpinvn) - (a0 + r2*(a2+a3*r)))*r2*selem;
        for (a=0; a<nang; a++)
3973
          {
3974
3975
3976
3977
3978
3979
3980
3981
          ix1 = (int)(dx1cout + r*ddx1[a]);
          ix2 = (int)(dx2cout + r*ddx2[a]);
          if (ix1>=0 && ix1<ix1max && ix2>=0 && ix2<ix2max)
            pixin[ix2*ix1max+ix1] += val;
          ix1 = (int)(dx1cout - r*ddx1[a]);
          ix2 = (int)(dx2cout - r*ddx2[a]);
          if (ix1>=0 && ix1<ix1max && ix2>=0 && ix2<ix2max)
            pixin[ix2*ix1max+ix1] += val;
3982
          }
3983
        krpinvn *= dkrpinvn;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3984
        }
3985

3986
      prof->lostfluxfrac = prof->code==MODEL_EXPONENTIAL?
3987
3988
		(1.0 + rmax)*exp(-rmax)
		:1.0 - prof_gammainc(2.0*n, bn*pow(r2max, hinvn));
3989
      threshflag = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3990
      break;
3991
    case MODEL_ARMS:
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3992
3993
3994
3995
3996
3997
3998
3999
4000
      r2min = *prof->featstart**prof->featstart;
      r2minxin = r2min * (1.0 - PROFIT_BARXFADE) * (1.0 - PROFIT_BARXFADE);
      r2minxout = r2min * (1.0 + PROFIT_BARXFADE) * (1.0 + PROFIT_BARXFADE);
      if ((invr2xdif = (r2minxout - r2minxin)) > 0.0)
        invr2xdif = 1.0 / invr2xdif;
      else
        invr2xdif = 1.0;
      umin = 0.5*logf(r2minxin + 0.00001);
      arm2amp = *prof->featfrac;
For faster browsing, not all history is shown. View entire blame