profit.c 131 KB
Newer Older
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
      break;
    case PARAM_OUTRING_START:
      param = 4.0;
      parammin = 3.5;
      parammax = 6.0;
      break;
    case PARAM_OUTRING_WIDTH:
      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;
3020
3021
  else if (parammin==0.0 && parammax==0.0)
    parammax = 1.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
  profit_setparam(profit, paramtype, param, parammin, parammax);

  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,
3051
		float param, float parammin, float parammax)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3052
3053
3054
3055
3056
3057
3058
3059
PURPOSE	Set the actual, lower and upper boundary values of a profile parameter.
INPUT	Pointer to the profit structure,
	Parameter index,
	Actual value,
	Lower boundary to the parameter,
	Upper boundary to the parameter.
OUTPUT	RETURN_OK if the parameter is registered, RETURN_ERROR otherwise.
AUTHOR	E. Bertin (IAP)
3060
VERSION	15/03/2009
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3061
3062
 ***/
int	profit_setparam(profitstruct *profit, paramenum paramtype,
3063
		float param, float parammin, float parammax)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3064
  {
3065
   float	*paramptr;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3066
3067
3068
3069
3070
   int		index;

/* Check whether the parameter has already be registered */
  if ((paramptr=profit->paramlist[(int)paramtype]))
    {
3071
    index = profit->paramindex[(int)paramtype];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
    profit->paraminit[index] = param;
    profit->parammin[index] = parammin;
    profit->parammax[index] = parammax;
    return RETURN_OK;
    }
  else
    return RETURN_ERROR;
  }

  
/****** profit_boundtounbound *************************************************
3083
3084
PROTO	void profit_boundtounbound(profitstruct *profit,
				float *param, double *dparam, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3085
PURPOSE	Convert parameters from bounded to unbounded space.
3086
3087
3088
3089
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)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3090
3091
3092
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
3093
VERSION	29/03/2010
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3094
 ***/
3095
3096
void	profit_boundtounbound(profitstruct *profit,
				float *param, double *dparam, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3097
3098
  {
   double	num,den;
3099
3100
   float	tparam;
   int		f,p, pstart,np;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3101

3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

  f = 0;
  for (p=pstart ; p<np; p++)
    if (profit->freeparam_flag[p])
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3116
      {
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
      tparam = param[p-pstart];
      if (profit->parammin[p]!=profit->parammax[p])
        {
        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;
        }
      else if (profit->parammax[p] > 0.0 || profit->parammax[p] < 0.0)
        dparam[f] = param[p-pstart] / profit->parammax[p];

      f++;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3128
3129
3130
3131
3132
3133
3134
      }

  return;
  }


/****** profit_unboundtobound *************************************************
3135
3136
PROTO	void profit_unboundtobound(profitstruct *profit,
				double *dparam, float *param, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3137
PURPOSE	Convert parameters from unbounded to bounded space.
3138
3139
3140
3141
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)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3142
3143
3144
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
3145
VERSION	08/07/2010
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3146
 ***/
3147
3148
void	profit_unboundtobound(profitstruct *profit,
				double *dparam, float *param, int index)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3149
  {
3150
   int		f,p, pstart,np;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3151

3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
  if (index<0)
    {
    pstart = 0;
    np = profit->nparam;
    }
  else
    {
    pstart = index;
    np = pstart+1;
    }

  f = 0;
  for (p=pstart; p<np; p++)
    {
    if (profit->freeparam_flag[p])
      {
      param[p-pstart] = (profit->parammin[p]!=profit->parammax[p])?
		((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])
		:  dparam[f]*profit->parammax[p];
      f++;
      }
    else
      param[p-pstart] = profit->paraminit[p];
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3179
3180
3181
3182
3183
3184

  return;
  }


/****** profit_covarunboundtobound ********************************************
3185
3186
PROTO	void profit_covarunboundtobound(profitstruct *profit,
				double *dcovar, float *covar)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3187
PURPOSE	Convert covariance matrix from unbounded to bounded space.
3188
3189
3190
INPUT	Pointer to the profit structure,
	input (incomplete) matrix of double precision covariances,
	output matrix of single precision covariances.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3191
3192
3193
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
3194
VERSION	27/07/2010
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3195
 ***/
3196
3197
void	profit_covarunboundtobound(profitstruct *profit,
				double *dcovar, float *covar)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3198
  {
3199
   double	*dxdy;
3200
3201
3202
   float	*x,*xmin,*xmax;
   int		*fflag,
		f,f1,f2, nfree, p,p1,p2, nparam;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3203
3204

  nparam = profit->nparam;
3205
3206
3207
  fflag = profit->freeparam_flag;
  nfree = profit->nfreeparam;
  QMALLOC16(dxdy, double, nfree);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3208
3209
3210
  x = profit->paraminit;
  xmin = profit->parammin;
  xmax = profit->parammax;
3211
  f = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3212
  for (p=0; p<profit->nparam; p++)
3213
    if (fflag[p])
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3214
      {
3215
      if (xmin[p]!=xmax[p])
3216
        dxdy[f++] = (x[p] - xmin[p]) * (xmax[p] - x[p]) / (xmax[p] - xmin[p]);
3217
3218
      else
        dxdy[f++] = xmax[p];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3219
3220
      }

3221
3222
  memset(profit->covar, 0, nparam*nparam*sizeof(float));
  f2 = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3223
  for (p2=0; p2<nparam; p2++)
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
    {
    if (fflag[p2])
      {
      f1 = 0;
      for (p1=0; p1<nparam; p1++)
        if (fflag[p1])
          {
          covar[p2*nparam+p1] = (float)(dcovar[f2*nfree+f1]*dxdy[f1]*dxdy[f2]);
          f1++;
          }
      f2++;
      }
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3237
3238
3239
3240
3241
3242
3243
3244

  free(dxdy);

  return;
  }


/****** prof_init *************************************************************
3245
PROTO	profstruct prof_init(profitstruct *profit, unsigned int modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3246
3247
PURPOSE	Allocate and initialize a new profile structure.
INPUT	Pointer to the profile-fitting structure,
3248
	model type.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3249
3250
3251
OUTPUT	A pointer to an allocated prof structure.
NOTES	-.
AUTHOR	E. Bertin (IAP)
3252
VERSION	22/04/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3253
 ***/
3254
profstruct	*prof_init(profitstruct *profit, unsigned int modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3255
3256
  {
   profstruct	*prof;
3257
   float	*pix,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3258
3259
3260
3261
3262
		rmax2, re2, dy2,r2, scale, zero, k,n, hinvn;
   int		width,height, ixc,iyc, ix,iy, nsub,
		d,s;

  QCALLOC(prof, profstruct, 1);
3263
3264
  prof->code = modeltype;
  switch(modeltype)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3265
    {
3266
3267
    case MODEL_BACK:
      prof->name = "background offset";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3268
3269
3270
3271
3272
      prof->naxis = 2;
      prof->pix = NULL;
      profit_addparam(profit, PARAM_BACK, &prof->flux);
      prof->typscale = 1.0;
      break;
3273
3274
    case MODEL_DIRAC:
      prof->name = "point source";
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
      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];
      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;
3285
3286
    case MODEL_SERSIC:
      prof->name = "Sersic spheroid";
3287
3288
3289
3290
3291
3292
      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
3293
3294
3295
3296
3297
3298
3299
3300
3301
      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;
3302
3303
    case MODEL_DEVAUCOULEURS:
      prof->name = "de Vaucouleurs spheroid";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3304
      prof->naxis = 2;
3305
3306
3307
3308
3309
      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, profit->nmodpix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3310
3311
3312
3313
3314
3315
3316
3317
      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;
3318
3319
    case MODEL_EXPONENTIAL:
      prof->name = "exponential disk";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3320
      prof->naxis = 2;
3321
3322
3323
3324
3325
      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, profit->nmodpix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3326
3327
3328
3329
3330
3331
3332
3333
      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;
3334
3335
    case MODEL_ARMS:
      prof->name = "spiral arms";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3336
      prof->naxis = 2;
3337
3338
3339
3340
3341
      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, profit->nmodpix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
      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;
3357
3358
    case MODEL_BAR:
      prof->name = "bar";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3359
      prof->naxis = 2;
3360
3361
3362
3363
3364
      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, profit->nmodpix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
      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;
3376
3377
    case MODEL_INRING:
      prof->name = "inner ring";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3378
      prof->naxis = 2;
3379
3380
3381
3382
3383
      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, profit->nmodpix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
      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;
3395
3396
    case MODEL_OUTRING:
      prof->name = "outer ring";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3397
      prof->naxis = 2;
3398
3399
3400
3401
3402
      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, profit->nmodpix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
      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;
3413
3414
    case MODEL_TABULATED:	/* An example of tabulated profile */
      prof->name = "tabulated model";
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3415
3416
3417
3418
      prof->naxis = 3;
      width =  prof->naxisn[0] = PROFIT_PROFRES;
      height = prof->naxisn[1] = PROFIT_PROFRES;
      nsub = prof->naxisn[2] = PROFIT_PROFSRES;
3419
      QCALLOC(prof->pix, float, width*height*nsub);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
      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;
      scale = prof->extrascale[0]= 8.0/PROFIT_PROFSRES;
      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;
    }

3459
3460
3461
  QMALLOC(prof->pix, float, prof->npix);

  if (prof->naxis>2)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3462
3463
3464
3465
3466
3467
3468
3469
3470
    {
    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];
3471
    QMALLOC16(prof->kernelbuf, float, prof->kernelnlines);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
    }

  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 **************************************************************
3501
3502
PROTO	float prof_add(profitstruct *profit, profstruct *prof,
		int extfluxfac_flag)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3503
PURPOSE	Add a model profile to an image.
3504
3505
3506
3507
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
3508
3509
NOTES	-.
AUTHOR	E. Bertin (IAP)
3510
VERSION	11/03/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3511
 ***/
3512
float	prof_add(profitstruct *profit, profstruct *prof, int extfluxfac_flag)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3513
  {
3514
3515
   double	xscale, yscale, saspect, ctheta,stheta, flux, scaling, bn, n,
		dx1cout,dx2cout, ddx1[36],ddx2[36];
3516
   float	posin[PROFIT_MAXEXTRA], posout[2], dnaxisn[2],
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3517
		*pixin, *pixin2, *pixout,
3518
3519
		fluxfac, amp,cd11,cd12,cd21,cd22, dx1,dx2,
		x1,x10,x2, x1cin,x2cin, x1cout,x2cout, x1max,x2max, x1in,x2in,
3520
		k, hinvn, x1t,x2t, ca,sa, u,umin,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3521
3522
		armamp,arm2amp, armrdphidr, armrdphidrvar, posang,
		width, invwidth2,
3523
3524
		r,r2,rmin, r2minxin,r2minxout, rmax, r2max,
		r2max1, r2max2, r2min, invr2xdif,
3525
3526
		val, theta, thresh, ra,rb, num,num2,den, ang,angstep,
		invn, dr, krpinvn,dkrpinvn, rs,rs2,
3527
3528
3529
		a11,a12,a21,a22, invdet, dca,dsa, a0,a2,a3, p1,p2,
		krspinvn, ekrspinvn, selem;
   int		npix, threshflag,
3530
		a,d,e,i, ix1,ix2, ix1max,ix2max, nang, nx2,
3531
		npix2;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3532

3533
  npix = profit->nmodpix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3534

3535
  if (prof->code==MODEL_BACK)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3536
3537
3538
3539
3540
    {
    amp = fabs(*prof->flux);
    pixout = profit->modpix;
    for (i=npix; i--;)
      *(pixout++) += amp;
3541
3542
    prof->lostfluxfrac = 0.0;
    return 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3543
3544
3545
3546
    }

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

3547
  if (prof->code!=MODEL_DIRAC)
3548
3549
3550
3551
3552
3553
    {
/*-- 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
3554
		0.0 : fabs(scaling / (*prof->scale*prof->typscale));
3555
    yscale = (*prof->scale*saspect == 0.0)?
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3556
		0.0 : fabs(scaling / (*prof->scale*prof->typscale*saspect));
3557
3558
3559
3560
    cd11 = (float)(xscale*ctheta);
    cd12 = (float)(xscale*stheta);
    cd21 = (float)(-yscale*stheta);
    cd22 = (float)(yscale*ctheta);
3561
3562
3563
3564
3565
    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
3566
    nx2 = profit->modnaxisn[1]/2 + 1;
3567
3568
3569

/*-- Compute the largest r^2 that fits in the frame */
    num = cd11*cd22-cd12*cd21;
3570
    num *= num;
3571
3572
    x1max = x1cout - 1.0;
    x2max = x2cout - 1.0;
3573
3574
3575
3576
3577
3578
3579
    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);
3580
    rmax = sqrtf(r2max);
3581
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3582
3583
3584

  switch(prof->code)
    {
3585
    case MODEL_DIRAC:
3586
3587
3588
3589
3590
      prof->pix[profit->modnaxisn[0]/2
		+ (profit->modnaxisn[1]/2)*profit->modnaxisn[0]] = 1.0;
      prof->lostfluxfrac = 0.0;
      threshflag = 0;
      break;
3591
3592
3593
    case MODEL_SERSIC:
    case MODEL_DEVAUCOULEURS:
    case MODEL_EXPONENTIAL:
3594
3595
3596
3597
3598
3599
/*---- 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*/
3600
      if (prof->code==MODEL_EXPONENTIAL)
3601
        bn = n = 1.0;
3602
      else if (prof->code==MODEL_DEVAUCOULEURS)
3603
3604
3605
3606
3607
3608
3609
3610
        {
        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)
3611
		+ 131.0/(1148175*n*n*n);	/* Ciotti & Bertin 1999 */
3612
3613
        }
      invn = 1.0/n;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3614
      hinvn = 0.5/n;
3615
3616
      k = -bn;
/*---- Compute central polynomial terms */
3617
      krspinvn = prof->code==MODEL_EXPONENTIAL? -rs : k*expf(logf(rs)*invn);
3618
3619
3620
3621
3622
3623
3624
      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
3625
3626
      x10 = -x1cout - dx1;
      x2 = -x2cout - dx2;
3627
      pixin = prof->pix;
3628
      if (prof->code==MODEL_EXPONENTIAL)
3629
        for (ix2=nx2; ix2--; x2+=1.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3630
          {
3631
3632
          x1 = x10;
          for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3633
            {
3634
3635
3636
3637
            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
3638
              {
3639
3640
              *(pixin++) = 0.0;
              continue;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3641
              }
3642
3643
            val = ra<rs2? a0+ra*(a2+a3*sqrtf(ra)) : expf(-sqrtf(ra));
            *(pixin++) = val;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3644
3645
            }
          }
3646
3647
      else
        for (ix2=nx2; ix2--; x2+=1.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3648
          {
3649
3650
          x1 = x10;
          for (ix1=profit->modnaxisn[0]; ix1--; x1+=1.0)
3651
            {
3652
3653
3654
3655
            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
3656
              {
3657
3658
              *(pixin++) = 0.0;
              continue;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3659
              }
3660
3661
            val = ra<rs2? a0+ra*(a2+a3*sqrtf(ra)) : expf(k*expf(logf(ra)*hinvn));
            *(pixin++) = val;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3662
3663
            }
          }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3664
3665
3666
/*---- Copy the symmetric part */
      if ((npix2=(profit->modnaxisn[1]-nx2)*profit->modnaxisn[0]) > 0)
        {
3667
3668
3669
3670
3671
3672
        pixin2 = pixin - profit->modnaxisn[0] - 1;
        if (!(profit->modnaxisn[0]&1))
          {
          *(pixin++) = 0.0;
          npix2--;
          }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3673
3674
3675
        for (i=npix2; i--;)
          *(pixin++) = *(pixin2--);
        }
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690

/*---- 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
3691
        {
3692
3693
3694
3695
        sincosf(ang, &dca, &dsa);
        ddx1[a] = a11*dca+a12*dsa;
        ddx2[a] = a21*dca+a22*dsa;
        ang += angstep;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3696
        }
3697
3698
3699
3700
3701
3702
3703
      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
3704
        {
3705
3706
3707
        r2 = r*r;
        val = (expf(krpinvn) - (a0 + r2*(a2+a3*r)))*r2*selem;
        for (a=0; a<nang; a++)
3708
          {
3709
3710
3711
3712
3713
3714
3715
3716
          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;
3717
          }
3718
        krpinvn *= dkrpinvn;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3719
        }
3720

3721
      prof->lostfluxfrac = prof->code==MODEL_EXPONENTIAL?
3722
3723
		(1.0 + rmax)*exp(-rmax)
		:1.0 - prof_gammainc(2.0*n, bn*pow(r2max, hinvn));
3724
      threshflag = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3725
      break;
3726
    case MODEL_ARMS:
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
      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;
3744
      pixin = prof->pix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
      for (ix2=profit->modnaxisn[1]; ix2--; x2+=1.0)
        {
        x1t = cd12*x2 + cd11*x1;
        x2t = cd22*x2 + cd21*x1;
        for (ix1=profit->modnaxisn[0]; ix1--;)
          {
          r2 = x1t*x1t+x2t*x2t;
          if (r2>r2minxin)
            {
            u = 0.5*logf(r2 + 0.00001);
            theta = (armrdphidr+armrdphidrvar*(u-umin))*u+posang;
            ca = cosf(theta);
            sa = sinf(theta);
            x1in = (x1t*ca - x2t*sa);
            x2in = (x1t*sa + x2t*ca);
            amp = expf(-sqrtf(x1t*x1t+x2t*x2t));
            if (r2<r2minxout)
              amp *= (r2 - r2minxin)*invr2xdif;
            ra = x1in*x1in/r2;
            rb = x2in*x2in/r2;
            *(pixin++) = amp * (armamp*PROFIT_POWF(ra,width)
				+ arm2amp*PROFIT_POWF(rb,width));
            }
          else
            *(pixin++) = 0.0;
          x1t += cd11;
          x2t += cd21; 
         }
        }
3774
3775
      prof->lostfluxfrac = 0.0;
      threshflag = 1;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3776
      break;
3777
    case MODEL_BAR:
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
      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;
      invwidth2 = fabs(1.0 / (*prof->featstart**prof->feataspect));
      posang = *prof->featposang*DEG;
      ca = cosf(posang);
      sa = sinf(posang);
      x1 = -x1cout - dx1;
      x2 = -x2cout - dx2;
3791
      pixin = prof->pix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
      for (ix2=profit->modnaxisn[1]; ix2--; x2+=1.0)
        {
        x1t = cd12*x2 + cd11*x1;
        x2t = cd22*x2 + cd21*x1;
        for (ix1=profit->modnaxisn[0]; ix1--;)
          {
          r2 = x1t*x1t+x2t*x2t;
          if (r2<r2minxout)
            {
            x1in = x1t*ca - x2t*sa;
            x2in = invwidth2*(x1t*sa + x2t*ca);
            *(pixin++) = (r2>r2minxin) ?
				(r2minxout - r2)*invr2xdif*expf(-x2in*x2in)
				: expf(-x2in*x2in);
            }
          else
            *(pixin++) = 0.0;
          x1t += cd11;
          x2t += cd21;
          }
        }
3813
3814
      prof->lostfluxfrac = 0.0;
      threshflag = 1;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3815
      break;
3816
    case MODEL_INRING:
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
      rmin = *prof->featstart;
      r2minxin = *prof->featstart-4.0**prof->featwidth;
      if (r2minxin < 0.0)
        r2minxin = 0.0;
      r2minxin *= r2minxin;
      r2minxout = *prof->featstart+4.0**prof->featwidth;
      r2minxout *= r2minxout;
      invwidth2 = 0.5 / (*prof->featwidth**prof->featwidth);
      cd22 /= *prof->feataspect;
      cd21 /= *prof->feataspect;
      x1 = -x1cout - dx1;
      x2 = -x2cout - dx2;
3829
      pixin = prof->pix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
      for (ix2=profit->modnaxisn[1]; ix2--; x2+=1.0)
        {
        x1t = cd12*x2 + cd11*x1;
        x2t = cd22*x2 + cd21*x1;
        for (ix1=profit->modnaxisn[0]; ix1--;)
          {
          r2 = x1t*x1t+x2t*x2t;
          if (r2>r2minxin && r2<r2minxout)
            {
            r = sqrt(r2) - rmin;
            *(pixin++) = expf(-invwidth2*r*r);
            }
          else
            *(pixin++) = 0.0;
          x1t += cd11;
          x2t += cd21;
          }
        }
3848
3849
      prof->lostfluxfrac = 0.0;
      threshflag = 1;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3850
      break;
3851
    case MODEL_OUTRING:
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
      rmin = *prof->featstart;
      r2minxin = *prof->featstart-4.0**prof->featwidth;
      if (r2minxin < 0.0)
        r2minxin = 0.0;
      r2minxin *= r2minxin;
      r2minxout = *prof->featstart+4.0**prof->featwidth;
      r2minxout *= r2minxout;
      invwidth2 = 0.5 / (*prof->featwidth**prof->featwidth);
      x1 = -x1cout - dx1;
      x2 = -x2cout - dx2;
3862
      pixin = prof->pix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
      for (ix2=profit->modnaxisn[1]; ix2--; x2+=1.0)
        {
        x1t = cd12*x2 + cd11*x1;
        x2t = cd22*x2 + cd21*x1;
        for (ix1=profit->modnaxisn[0]; ix1--;)
          {
          r2 = x1t*x1t+x2t*x2t;
          if (r2>r2minxin && r2<r2minxout)
            {
            r = sqrt(r2) - rmin;
            *(pixin++) = expf(-invwidth2*r*r);
            }
          else
            *(pixin++) = 0.0;
          x1t += cd11;
          x2t += cd21;
          }
        }
3881
3882
      prof->lostfluxfrac = 0.0;
      threshflag = 1;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
      break;
    default:
/*---- Tabulated profile: remap each pixel */
/*---- Initialize multi-dimensional counters */
     for (d=0; d<2; d++)
        {
        posout[d] = 1.0;	/* FITS convention */
        dnaxisn[d] = profit->modnaxisn[d] + 0.99999;
        }

      for (e=0; e<prof->naxis - 2; e++)
        {
        d = 2+e;
/*------ Compute position along axis */
        posin[d] = (*prof->extra[e]-prof->extrazero[e])/prof->extrascale[e]+1.0;
/*------ Keep position within boundaries and let interpolation do the rest */
        if (posin[d] < 0.99999)
          {
          if (prof->extracycleflag[e])
3902
            posin[d] += (float)prof->naxisn[d];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3903
3904
3905
          else
            posin[d] = 1.0;
          }
3906
        else if (posin[d] > (float)prof->naxisn[d])
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3907
3908
3909
          {
          if (prof->extracycleflag[e])
          posin[d] = (prof->extracycleflag[e])?
3910
3911
		  fmod(posin[d], (float)prof->naxisn[d])
		: (float)prof->naxisn[d];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3912
3913
          }
        }
3914
3915
      x1cin = (float)(prof->naxisn[0]/2);
      x2cin = (float)(prof->naxisn[1]/2);
3916
      pixin = prof->pix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
      for (i=npix; i--;)
        {
        x1 = posout[0] - x1cout - 1.0 - dx1;
        x2 = posout[1] - x2cout - 1.0 - dx2;
        posin[0] = cd11*x1 + cd12*x2 + x1cin + 1.0;
        posin[1] = cd21*x1 + cd22*x2 + x2cin + 1.0;
        *(pixin++) = prof_interpolate(prof, posin);
        for (d=0; d<2; d++)
          if ((posout[d]+=1.0) < dnaxisn[d])
            break;
          else
            posout[d] = 1.0;
        }
3930
3931
      prof->lostfluxfrac = 0.0;
      threshflag = 1;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3932
3933
3934
    break;
    }

3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
/* For complex profiles, threshold to the brightest pixel value at border */
  if (threshflag)
    {
/*-- Now find truncation threshold */
/*-- Find the shortest distance to a vignet border */
    rmax = x1cout;
    if (rmax > (r = x2cout))
      rmax = r;
    rmax += 0.01;
    if (rmax<1.0)
      rmax = 1.0;
    r2max = rmax*rmax;
    rmin = rmax - 1.0;
    r2min = rmin*rmin;

/*-- Find best threshold (the max around the circle with radius rmax */
    dx2 = -x2cout;
3952
    pixin = prof->pix;
3953
3954
3955
3956
3957
3958
3959
3960
    thresh = -BIG;
    for (ix2=profit->modnaxisn[1]; ix2--; dx2 += 1.0)
      {
      dx1 = -x1cout;
      for (ix1=profit->modnaxisn[0]; ix1--; dx1 += 1.0)
        if ((val=*(pixin++))>thresh && (r2=dx1*dx1+dx2*dx2)>r2min && r2<r2max)
          thresh = val;
      }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3961

3962
3963
/*-- Threshold and measure the flux */
    flux = 0.0;
3964
    pixin = prof->pix;
3965
3966
3967
3968
3969
3970
3971
    for (i=npix; i--; pixin++)
      if (*pixin >= thresh)
        flux += (double)*pixin;
      else
        *pixin = 0.0;
    }
  else
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3972
    {
3973
    flux = 0.0;
3974
    pixin = prof->pix;
3975
3976
    for (i=npix; i--;)
      flux += (double)*(pixin++);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3977
3978
    }

3979
3980
3981
3982
3983
3984
3985
  if (extfluxfac_flag)
    fluxfac = prof->fluxfac;
  else
    {
    if (prof->lostfluxfrac < 1.0)
      flux /= (1.0 - prof->lostfluxfrac);

3986
    prof->fluxfac = fluxfac = fabs(flux)>0.0? profit->fluxfac/fabs(flux) : 0.0;
3987
3988
3989
3990
3991
    }

  pixin = prof->pix;
  for (i=npix; i--;)
    *(pixin++) *= fluxfac;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3992
3993

/* Correct final flux */
3994
3995
  fluxfac = *prof->flux;
  pixin = prof->pix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3996
  pixout = profit->modpix;
3997
  for (i=npix; i--;)
3998
    *(pixout++) += fluxfac**(pixin++);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
3999

4000
  return *prof->flux;
For faster browsing, not all history is shown. View entire blame