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

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

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

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

3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

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

3331
  return f;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3332
3333
3334
3335
  }


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

3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

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


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

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

3463
3464
  nfree = f;

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

  free(dxdy);

3484
3485
3486
3487
  profit->nlimmin = nmin;
  profit->nlimmax = nmax;

  return nmin+nmax;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3488
3489
3490
3491
  }


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

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

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

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

3780
  npix = profit->nmodpix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3781

3782
  if (prof->code==MODEL_BACK)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3783
3784
3785
3786
3787
    {
    amp = fabs(*prof->flux);
    pixout = profit->modpix;
    for (i=npix; i--;)
      *(pixout++) += amp;
3788
3789
    prof->lostfluxfrac = 0.0;
    return 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3790
3791
3792
3793
    }

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

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

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

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

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

3974
      prof->lostfluxfrac = prof->code==MODEL_EXPONENTIAL?
3975
3976
		(1.0 + rmax)*exp(-rmax)
		:1.0 - prof_gammainc(2.0*n, bn*pow(r2max, hinvn));
3977
      threshflag = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3978
      break;
3979
    case MODEL_ARMS:
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
      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;
      x1 = -x1cout - dx1;
      x2 = -x2cout - dx2;
3997
      pixin = prof->pix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3998
3999
4000
      for (ix2=profit->modnaxisn[1]; ix2--; x2+=1.0)
        {
        x1t = cd12*x2 + cd11*x1;
For faster browsing, not all history is shown. View entire blame