profit.c 140 KB
Newer Older
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3001
3002
3003

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

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

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

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

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

3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

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

3337
  return f;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3338
3339
3340
3341
  }


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

3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

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


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

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

3469
3470
  nfree = f;

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

  free(dxdy);

3490
3491
3492
3493
  profit->nlimmin = nmin;
  profit->nlimmax = nmax;

  return nmin+nmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3494
3495
3496
3497
  }


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

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

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

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

3786
  npix = profit->nmodpix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3787

3788
  if (prof->code==MODEL_BACK)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3789
3790
3791
3792
3793
    {
    amp = fabs(*prof->flux);
    pixout = profit->modpix;
    for (i=npix; i--;)
      *(pixout++) += amp;
3794
3795
    prof->lostfluxfrac = 0.0;
    return 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3796
3797
3798
3799
    }

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

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

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

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

/*---- 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
3945
        {
3946
#ifdef HAVE_SINCOSF
3947
3948
3949
3950
3951
3952
3953
        sincosf(ang, &dsa, &dca);
#else
        dsa = sinf(ang);
        dca = cosf(ang);
#endif
        ddx1[a] = a11*dsa+a12*dca;
        ddx2[a] = a21*dsa+a22*dca;
3954
        ang += angstep;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3955
        }
3956
3957
3958
3959
3960
3961
3962
      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
3963
        {
3964
3965
3966
        r2 = r*r;
        val = (expf(krpinvn) - (a0 + r2*(a2+a3*r)))*r2*selem;
        for (a=0; a<nang; a++)
3967
          {
3968
3969
3970
3971
3972
3973
3974
3975
          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;
3976
          }
3977
        krpinvn *= dkrpinvn;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3978
        }
3979

3980
      prof->lostfluxfrac = prof->code==MODEL_EXPONENTIAL?
3981
3982
		(1.0 + rmax)*exp(-rmax)
		:1.0 - prof_gammainc(2.0*n, bn*pow(r2max, hinvn));
3983
      threshflag = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3984
      break;
3985
    case MODEL_ARMS:
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3986
3987
3988
3989
3990
3991
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;
      armamp = 1.0 - arm2amp;
      armrdphidr = 1.0/tan(*prof->featpitch*DEG);
      armrdphidrvar = 0.0 /**prof->featpitchvar*/;
      posang = *prof->featposang*DEG;
      width = fabs(*prof->featwidth);
width = 3.0;
For faster browsing, not all history is shown. View entire blame