profit.c 147 KB
Newer Older
2001
2002
2003
2004
2005
2006
2007
		*kernelt, *pixin,*pixin0, *mask,*maskt, *pixinout,
		*dpixin,*dpixin0, *dpixout,*dpixout0, *dx,*dy,
		*dgeoxpix0,*dgeoypix0, *dgeoxpix,*dgeoypix,
		xcin,xcout,ycin,ycout, xsin,ysin, xin,yin, x,y, val,
		invpixstep;
   int		*start,*startt, *nmask,*nmaskt, *modnaxisn,
		i,j,k,n,t,w,
2008
		ixsout,iysout, ixout,iyout, dixout,diyout, nxout,nyout,
2009
		iysina, nyin, hmw,hmh, ix,iy, ixin,iyin, interpw, offout;
2010

2011
2012
2013
  modnaxisn = profit->modnaxisn;
  interptype = INTERP_LANCZOS4;
  interpw = interp_kernwidth[interptype];
2014
  invpixstep = profit->subsamp/profit->pixstep;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2015

2016
  xcin = (float)(modnaxisn[0]/2);
2017
2018
2019
  xcout = ((int)(profit->subsamp*profit->objnaxisn[0])/2 + 0.5)
		/ profit->subsamp - 0.5;
  if ((dx=profit->paramlist[PARAM_X]))
2020
    xcout += *dx/profit->subsamp;
2021
2022

  xsin = xcin - xcout*invpixstep;			/* Input start x-coord*/
2023

2024
  if ((int)xsin >= modnaxisn[0]
2025
2026
2027
2028
#if defined(HAVE_ISNAN) && defined(HAVE_ISINF)
	|| isnan(xsin) || isinf(xsin)
#endif
	)
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
    return RETURN_ERROR;
  ixsout = 0;				/* Int. part of output start x-coord */
  if (xsin<0.0)
    {
    dixout = (int)(1.0-xsin/invpixstep);
/*-- Simply leave here if the images do not overlap in x */
    if (dixout >= profit->objnaxisn[0])
      return RETURN_ERROR;
    ixsout += dixout;
    xsin += dixout*invpixstep;
    }
2040
  nxout = (int)((modnaxisn[0]-xsin)/invpixstep);	/* nb of interpolated
2041
2042
2043
2044
2045
2046
							input pixels along x */
  if (nxout>(ixout=profit->objnaxisn[0]-ixsout))
    nxout = ixout;
  if (!nxout)
    return RETURN_ERROR;

2047
  ycin = (float)(modnaxisn[1]/2);
2048
2049
2050
  ycout = ((int)(profit->subsamp*profit->objnaxisn[1])/2 + 0.5)
		/ profit->subsamp - 0.5;
  if ((dy=profit->paramlist[PARAM_Y]))
2051
    ycout += *dy/profit->subsamp;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2052

2053
  ysin = ycin - ycout*invpixstep;		/* Input start y-coord*/
2054
  if ((int)ysin >= modnaxisn[1]
2055
2056
2057
2058
#if defined(HAVE_ISNAN) && defined(HAVE_ISINF)
	|| isnan(ysin) || isinf(ysin)
#endif
	)
2059
2060
2061
    return RETURN_ERROR;
  iysout = 0;				/* Int. part of output start y-coord */
  if (ysin<0.0)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2062
    {
2063
2064
2065
2066
2067
2068
    diyout = (int)(1.0-ysin/invpixstep);
/*-- Simply leave here if the images do not overlap in y */
    if (diyout >= profit->objnaxisn[1])
      return RETURN_ERROR;
    iysout += diyout;
    ysin += diyout*invpixstep;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2069
    }
2070
  nyout = (int)((modnaxisn[1]-ysin)/invpixstep);/* nb of interpolated
2071
2072
2073
2074
2075
							input pixels along y */
  if (nyout>(iyout=profit->objnaxisn[1]-iysout))
    nyout = iyout;
  if (!nyout)
    return RETURN_ERROR;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2076

2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
  w = profit->objnaxisn[0];

/* Initialize destination buffer to zero */
  memset(outpix, 0, (size_t)profit->nobjpix*sizeof(PIXTYPE));

  if (profit->dgeoflag) {
/*-- Resample taking into account differential geometry maps */
    offout = iysout*w + ixsout;
    pixout0 = outpix + offout;
    dgeoxpix0 = profit->dgeopix[0] + offout;
    dgeoypix0 = profit->dgeopix[1] + offout;
    yin = ysin + 1.0;    
    for (j = nyout; j--; yin += invpixstep) {
      pixout = pixout0;
      dgeoxpix = dgeoxpix0;
      dgeoypix = dgeoypix0;
      dgeoxpix0 += w;
      dgeoypix0 += w;
      pixout0 += w;
      xin = xsin + 1.0;
      for (i=nxout; i--; xin += invpixstep) {
        pos[0] = xin - *(dgeoxpix++)*invpixstep;
        pos[1] = yin - *(dgeoypix++)*invpixstep;
        *(pixout++) = (PIXTYPE)(factor*interpolate_pix(pos, inpix, modnaxisn,
			interptype));
      }
    }
  return RETURN_OK;
  }

2107
2108
/* Set the yrange for the x-resampling with some margin for interpolation */
  iysina = (int)ysin;	/* Int. part of Input start y-coord with margin */
2109
  hmh = interpw/2 - 1;	/* Interpolant start */
2110
2111
  if (iysina<0 || ((iysina -= hmh)< 0))
    iysina = 0;
2112
2113
2114
  nyin = (int)(ysin+nyout*invpixstep)+interpw-hmh;/* Interpolated Input y size*/
  if (nyin > modnaxisn[1])			/* with margin */
    nyin = modnaxisn[1];
2115
2116
2117
2118
2119
/* Express everything relative to the effective Input start (with margin) */
  nyin -= iysina;
  ysin -= (float)iysina;

/* Allocate interpolant stuff for the x direction */
2120
  QMALLOC(mask, float, nxout*interpw);	/* Interpolation masks */
2121
2122
  QMALLOC(nmask, int, nxout);		/* Interpolation mask sizes */
  QMALLOC(start, int, nxout);		/* Int. part of Input conv starts */
2123

2124
/* Compute the local interpolant and data starting points in x */
2125
  hmw = interpw/2 - 1;
2126
2127
2128
2129
2130
2131
2132
  xin = xsin;
  maskt = mask;
  nmaskt = nmask;
  startt = start;
  for (j=nxout; j--; xin+=invpixstep)
    {
    ix = (ixin=(int)xin) - hmw;
2133
2134
    make_kernel(xin - ixin, kernel, interptype);
    kernelt = kernel;
2135
    if (ix < 0)
2136
      {
2137
      n = interpw + ix;
2138
      ix = 0;
2139
      kernelt -= ix;
2140
      }
2141
    else
2142
2143
      n = interpw;
    if (n>(t=modnaxisn[0]-ix))
2144
2145
2146
      n=t;
    *(startt++) = ix;
    *(nmaskt++) = n;
2147
    for (i=n; i--;)
2148
      *(maskt++) = *(kernelt++);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2149
    }
2150
2151
2152
2153

  QCALLOC(pixinout, float, nxout*nyin);	/* Intermediary frame-buffer */

/* Make the interpolation in x (this includes transposition) */
2154
  pixin0 = inpix + iysina*modnaxisn[0];
2155
  dpixout0 = pixinout;
2156
  for (k=nyin; k--; pixin0+=modnaxisn[0], dpixout0++)
2157
2158
2159
2160
2161
2162
    {
    maskt = mask;
    nmaskt = nmask;
    startt = start;
    dpixout = dpixout0;
    for (j=nxout; j--; dpixout+=nyin)
2163
      {
2164
2165
2166
2167
2168
      pixin = pixin0+*(startt++);
      val = 0.0; 
      for (i=*(nmaskt++); i--;)
        val += *(maskt++)**(pixin++);
      *dpixout = val;
2169
      }
2170
    }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2171

2172
/* Reallocate interpolant stuff for the y direction */
2173
  QREALLOC(mask, float, nyout*interpw);	/* Interpolation masks */
2174
2175
2176
2177
  QREALLOC(nmask, int, nyout);			/* Interpolation mask sizes */
  QREALLOC(start, int, nyout);		/* Int. part of Input conv starts */

/* Compute the local interpolant and data starting points in y */
2178
  hmh = interpw/2 - 1;
2179
2180
2181
2182
2183
2184
2185
  yin = ysin;
  maskt = mask;
  nmaskt = nmask;
  startt = start;
  for (j=nyout; j--; yin+=invpixstep)
    {
    iy = (iyin=(int)yin) - hmh;
2186
2187
    make_kernel(yin - iyin, kernel, interptype);
    kernelt = kernel;
2188
2189
    if (iy < 0)
      {
2190
2191
      n = interpw + iy;
      kernelt -= iy;
2192
2193
2194
      iy = 0;
      }
    else
2195
      n = interpw;
2196
2197
2198
2199
    if (n>(t=nyin-iy))
      n=t;
    *(startt++) = iy;
    *(nmaskt++) = n;
2200
    for (i=n; i--;)
2201
      *(maskt++) = *(kernelt++);
2202
2203
2204
2205
    }

/* Make the interpolation in y and transpose once again */
  dpixin0 = pixinout;
2206
  pixout0 = outpix+ixsout+iysout*w;
2207
2208
2209
2210
2211
2212
  for (k=nxout; k--; dpixin0+=nyin, pixout0++)
    {
    maskt = mask;
    nmaskt = nmask;
    startt = start;
    pixout = pixout0;
2213
    for (j=nyout; j--; pixout+=w)
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
      {
      dpixin = dpixin0+*(startt++);
      val = 0.0; 
      for (i=*(nmaskt++); i--;)
        val += *(maskt++)**(dpixin++);
       *pixout = (PIXTYPE)(factor*val);
      }
    }

/* Free memory */
  free(pixinout);
  free(mask);
  free(nmask);
  free(start);

  return RETURN_OK;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2230
2231
2232
2233
  }


/****** profit_convolve *******************************************************
2234
PROTO	void profit_convolve(profitstruct *profit, float *modpix)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2235
2236
2237
2238
2239
2240
2241
2242
PURPOSE	Convolve a model image with the local PSF.
INPUT	Pointer to the profit structure,
	Pointer to the image raster.
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
VERSION	15/09/2008
 ***/
2243
void	profit_convolve(profitstruct *profit, float *modpix)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
  {
  if (!profit->psfdft)
    profit_makedft(profit);

  fft_conv(modpix, profit->psfdft, profit->modnaxisn);

  return;
  }


/****** profit_makedft *******************************************************
PROTO	void profit_makedft(profitstruct *profit)
PURPOSE	Create the Fourier transform of the descrambled PSF component.
INPUT	Pointer to the profit structure.
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
VERSION	22/04/2008
 ***/
void	profit_makedft(profitstruct *profit)
  {
   psfstruct	*psf;
2266
2267
   float      *mask,*maskt, *ppix;
   float       dx,dy, r,r2,rmin,rmin2,rmax,rmax2,rsig,invrsig2;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
   int          width,height,npix,offset, psfwidth,psfheight,psfnpix,
                cpwidth, cpheight,hcpwidth,hcpheight, i,j,x,y;

  if (!(psf=profit->psf))
    return;

  psfwidth = profit->modnaxisn[0];
  psfheight = profit->modnaxisn[1];
  psfnpix = psfwidth*psfheight;
  width = profit->modnaxisn[0];
  height = profit->modnaxisn[1];
  npix = width*height;
2280
  QCALLOC(mask, float, npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
  cpwidth = (width>psfwidth)?psfwidth:width;
  hcpwidth = cpwidth>>1;
  cpwidth = hcpwidth<<1;
  offset = width - cpwidth;
  cpheight = (height>psfheight)?psfheight:height;
  hcpheight = cpheight>>1;
  cpheight = hcpheight<<1;

/* Frame and descramble the PSF data */
  ppix = profit->psfpix + (psfheight/2)*psfwidth + psfwidth/2;
  maskt = mask;
  for (j=hcpheight; j--; ppix+=psfwidth)
    {
    for (i=hcpwidth; i--;)
      *(maskt++) = *(ppix++);      
    ppix -= cpwidth;
    maskt += offset;
    for (i=hcpwidth; i--;)
      *(maskt++) = *(ppix++);      
    }

  ppix = profit->psfpix + ((psfheight/2)-hcpheight)*psfwidth + psfwidth/2;
  maskt += width*(height-cpheight);
  for (j=hcpheight; j--; ppix+=psfwidth)
    {
    for (i=hcpwidth; i--;)
      *(maskt++) = *(ppix++);      
    ppix -= cpwidth;
    maskt += offset;
    for (i=hcpwidth; i--;)
      *(maskt++) = *(ppix++);      
    }

/* Truncate to a disk that has diameter = (box width) */
  rmax = cpwidth - 1.0 - hcpwidth;
  if (rmax > (r=hcpwidth))
    rmax = r;
  if (rmax > (r=cpheight-1.0-hcpheight))
    rmax = r;
  if (rmax > (r=hcpheight))
    rmax = r;
  if (rmax<1.0)
    rmax = 1.0;
  rmax2 = rmax*rmax;
  rsig = psf->fwhm/profit->pixstep;
  invrsig2 = 1/(2*rsig*rsig);
  rmin = rmax - (3*rsig);     /* 3 sigma annulus (almost no aliasing) */
  rmin2 = rmin*rmin;

  maskt = mask;
  dy = 0.0;
  for (y=hcpheight; y--; dy+=1.0)
    {
    dx = 0.0;
    for (x=hcpwidth; x--; dx+=1.0, maskt++)
      if ((r2=dx*dx+dy*dy)>rmin2)
2337
        *maskt *= (r2>rmax2)?0.0:expf((2*rmin*sqrtf(r2)-r2-rmin2)*invrsig2);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2338
2339
2340
2341
    dx = -hcpwidth;
    maskt += offset;
    for (x=hcpwidth; x--; dx+=1.0, maskt++)
      if ((r2=dx*dx+dy*dy)>rmin2)
2342
        *maskt *= (r2>rmax2)?0.0:expf((2*rmin*sqrtf(r2)-r2-rmin2)*invrsig2);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2343
2344
2345
2346
2347
2348
2349
2350
    }
  dy = -hcpheight;
  maskt += width*(height-cpheight);
  for (y=hcpheight; y--; dy+=1.0)
    {
    dx = 0.0;
    for (x=hcpwidth; x--; dx+=1.0, maskt++)
      if ((r2=dx*dx+dy*dy)>rmin2)
2351
        *maskt *= (r2>rmax2)?0.0:expf((2*rmin*sqrtf(r2)-r2-rmin2)*invrsig2);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2352
2353
2354
2355
    dx = -hcpwidth;
    maskt += offset;
    for (x=hcpwidth; x--; dx+=1.0, maskt++)
      if ((r2=dx*dx+dy*dy)>rmin2)
2356
        *maskt *= (r2>rmax2)?0.0:expf((2*rmin*sqrtf(r2)-r2-rmin2)*invrsig2);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
    }

/* Finally move to Fourier space */
  profit->psfdft = fft_rtf(mask, profit->modnaxisn);

  free(mask);

  return;
  }


/****** profit_copyobjpix *****************************************************
PROTO	int profit_copyobjpix(profitstruct *profit, picstruct *field,
2370
			picstruct *wfield, picstruct *dgeofield)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2371
2372
2373
PURPOSE	Copy a piece of the input field image to a profit structure.
INPUT	Pointer to the profit structure,
	Pointer to the field structure,
2374
2375
	Pointer to the field weight structure,
	Pointer to the differential geometry field structure
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2376
2377
2378
OUTPUT	The number of valid pixels copied.
NOTES	Global preferences are used.
AUTHOR	E. Bertin (IAP)
2379
VERSION	17/02/2015
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2380
2381
 ***/
int	profit_copyobjpix(profitstruct *profit, picstruct *field,
2382
			picstruct *wfield, picstruct *dgeofield)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2383
  {
2384
   float	dx, dy2, dr2, rad2;
2385
2386
2387
2388
   PIXTYPE	*pixin,*wpixin,*dgeoxpixin,*dgeoypixin, *pixout,*wpixout,
		*dgeoxpixout, *dgeoypixout,
		backnoise2, invgain, satlevel, wthresh, pix,spix, wpix,swpix,
		dgeoxpix,dgeoypix,sdgeoxpix,sdgeoypix;
2389
   int		i,x,y, xmin,xmax,ymin,ymax, w,h,dw, npix, off, gainflag,
2390
		badflag, sflag, sx,sy,sn,sw, ix,iy;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2391
2392
2393
2394

/* First put the image background to -BIG */
  pixout = profit->objpix;
  wpixout = profit->objweight;
2395
2396
  dgeoxpixout = profit->dgeopix[0];
  dgeoypixout = profit->dgeopix[1];
2397
  for (i=profit->objnaxisn[0]*profit->objnaxisn[1]; i--;)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2398
2399
    {
    *(pixout++) = -BIG;
2400
    *(wpixout++) = *(dgeoxpixout++) = *(dgeoypixout++) = 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2401
2402
2403
2404
2405
2406
2407
2408
2409
    }

/* Don't go further if out of frame!! */
  ix = profit->ix;
  iy = profit->iy;
  if (ix<0 || ix>=field->width || iy<field->ymin || iy>=field->ymax)
    return 0;

  backnoise2 = field->backsig*field->backsig;
2410
  sn = (int)profit->subsamp;
2411
2412
2413
  sflag = (sn>1);
  w = profit->objnaxisn[0]*sn;
  h = profit->objnaxisn[1]*sn;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
  invgain = (field->gain > 0.0) ? 1.0/field->gain : 0.0;
  satlevel = field->satur_level - profit->obj->bkg;
  rad2 = h/2.0;
  if (rad2 > w/2.0)
    rad2 = w/2.0;
  rad2 *= rad2;

/* Set the image boundaries */
  pixout = profit->objpix;
  wpixout = profit->objweight;
2424
2425
  dgeoxpixout = profit->dgeopix[0];
  dgeoypixout = profit->dgeopix[1];
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2426
2427
2428
2429
  ymin = iy-h/2;
  ymax = ymin + h;
  if (ymin<field->ymin)
    {
2430
2431
2432
    off = (field->ymin-ymin-1)/sn + 1;
    pixout += off*profit->objnaxisn[0];
    wpixout += off*profit->objnaxisn[0];
2433
2434
    dgeoxpixout += off*profit->objnaxisn[0];
    dgeoypixout += off*profit->objnaxisn[0];
2435
    ymin += off*sn;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2436
2437
    }
  if (ymax>field->ymax)
2438
    ymax -= ((ymax-field->ymax-1)/sn + 1)*sn;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2439
2440
2441

  xmin = ix-w/2;
  xmax = xmin + w;
2442
  dw = 0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2443
2444
  if (xmax>field->width)
    {
2445
2446
2447
    off = (xmax-field->width-1)/sn + 1;
    dw += off;
    xmax -= off*sn;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2448
2449
2450
    }
  if (xmin<0)
    {
2451
2452
2453
    off = (-xmin-1)/sn + 1;
    pixout += off;
    wpixout += off;
2454
2455
    dgeoxpixout += off;
    dgeoypixout += off;
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
    dw += off;
    xmin += off*sn;
    }
/* Make sure the input frame size is a multiple of the subsampling step */
  if (sflag)
    {
/*
    if (((rem=ymax-ymin)%sn))
      {
      ymin += rem/2;
      ymax -= (rem-rem/2);
      }
    if (((rem=xmax-xmin)%sn))
      {
      xmin += rem/2;
      pixout += rem/2;
      wpixout += rem/2;
      dw += rem;
      xmax -= (rem-rem/2);
      }
*/
    sw = field->width;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2478
2479
2480
2481
    }

/* Copy the right pixels to the destination */
  npix = 0;
2482
  if (wfield) {
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2483
    gainflag = prefs.weightgain_flag;
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
    wthresh = wfield->weight_thresh;
  } else {
    gainflag = 0;
    wthresh = BIG;
  }
  if (sflag)
    {
    swpix = backnoise2 / (double)(sn*sn);
    sdgeoxpix = sdgeoypix = 0.0;
/*-- Sub-sampling case */
    for (y=ymin; y<ymax; y+=sn)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2495
      {
2496
      for (x=xmin; x<xmax; x+=sn)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2497
        {
2498
2499
2500
        pix = wpix = 0.0;
        badflag = 0;
        for (sy=0; sy<sn; sy++)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2501
          {
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
          dy2 = (y+sy-iy);
          dy2 *= dy2;
          dx = (x-ix);
          pixin = &PIX(field, x, y+sy);
          if (wfield)
            wpixin = &PIX(wfield, x, y+sy);
          if (dgeofield) {
            dgeoxpixin = &DGEOPIXX(dgeofield, x, y+sy);
            dgeoypixin = &DGEOPIXY(dgeofield, x, y+sy);
          }
          for (sx=sn; sx--;)
2513
            {
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
            dr2 = dy2 + dx*dx;
            dx++;
            spix = *(pixin++);
            if (wfield)
              swpix = *(wpixin++);
            if (dgeofield) {
                sdgeoxpix = *(dgeoxpixin++);
                sdgeoypix = *(dgeoypixin++);
            }
            if (dr2<rad2 && spix>-BIG && spix<satlevel && swpix<wthresh)
2524
              {
2525
2526
2527
2528
              pix += spix;
              wpix += swpix;
              dgeoxpix += sdgeoxpix;
              dgeoypix += sdgeoypix;
2529
              }
2530
2531
            else
              badflag=1;
2532
            }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2533
          }
2534
2535
2536
2537
        *(pixout++) = pix;
        *(dgeoxpixout++) = dgeoxpix;
        *(dgeoypixout++) = dgeoypix;
        if (!badflag)	/* A single bad pixel ruins is all (saturation, etc.)*/
2538
          {
2539
          *(wpixout++) = 1.0 / sqrt(wpix+(pix>0.0?
2540
		(gainflag? pix*wpix/backnoise2:pix)*invgain : 0.0));
2541
          npix++;
2542
          }
2543
2544
        else
          *(wpixout++) = 0.0;
2545
        }
2546
2547
2548
2549
2550
      pixout += dw;
      wpixout += dw;
      dgeoxpixout += dw;
      dgeoypixout += dw;
      }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2551
2552
    }
  else
2553
    {
2554
2555
2556
    wpix = backnoise2;
    dgeoxpix = dgeoypix = 0.0;
    for (y=ymin; y<ymax; y++)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2557
      {
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
      dy2 = y-iy;
      dy2 *= dy2;
      pixin = &PIX(field, xmin, y);
      if (wfield)
        wpixin = &PIX(wfield, xmin, y);
      if (dgeofield) {
        dgeoxpixin = &DGEOPIXX(dgeofield, xmin, y);
        dgeoypixin = &DGEOPIXY(dgeofield, xmin, y);
      }
      for (x=xmin; x<xmax; x++)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2568
        {
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
        dx = x-ix;
        dr2 = dy2 + dx*dx;
        pix = *(pixin++);
        if (wfield)
          wpix = *(wpixin++);
        if (dgeofield) {
          dgeoxpix = *(dgeoxpixin++);
          dgeoypix = *(dgeoypixin++);
        }
        if (dr2<rad2 && pix>-BIG && pix<satlevel && wpix<wthresh)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2579
          {
2580
          *(pixout++) = pix;
2581
2582
2583
2584
2585
          *(wpixout++) = 1.0 / sqrt(wpix+(pix>0.0?
		(gainflag? pix*wpix/backnoise2:pix)*invgain : 0.0));
          npix++;
          *(dgeoxpixout++) = dgeoxpix;
          *(dgeoypixout++) = dgeoypix;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2586
          }
2587
2588
        else
          *(pixout++) = *(wpixout++) = *(dgeoxpixout++) = *(dgeoypixout++) = 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2589
        }
2590
2591
2592
2593
      pixout += dw;
      wpixout += dw;
      dgeoxpixout += dw;
      dgeoypixout += dw;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2594
      }
2595
    }
2596

Emmanuel Bertin's avatar
Emmanuel Bertin committed
2597
2598
2599
2600
2601
  return npix;
  }


/****** profit_spiralindex ****************************************************
2602
PROTO	float profit_spiralindex(profitstruct *profit)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2603
2604
2605
2606
2607
2608
2609
PURPOSE	Compute the spiral index of a galaxy image (positive for arms
	extending counter-clockwise and negative for arms extending CW, 0 for
	no spiral pattern).
INPUT	Profile-fitting structure.
OUTPUT	Vector of residuals.
NOTES	-.
AUTHOR	E. Bertin (IAP)
2610
VERSION	12/07/2012
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2611
 ***/
2612
float profit_spiralindex(profitstruct *profit)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2613
2614
2615
  {
   objstruct	*obj;
   obj2struct	*obj2;
2616
   float	*dx,*dy, *fdx,*fdy, *gdx,*gdy, *gdxt,*gdyt, *pix,
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
		fwhm, invtwosigma2, hw,hh, ohw,ohh, x,y,xstart, tx,ty,txstart,
		gx,gy, r2, spirindex, invsig, val, sep;
   PIXTYPE	*fpix;
   int		i,j, npix;

  npix = profit->objnaxisn[0]*profit->objnaxisn[1];

  obj = profit->obj;
  obj2 = profit->obj2;
/* Compute simple derivative vectors at a fraction of the object scale */
2627
  fwhm = profit->guessradius * 2.0 / 4.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2628
2629
2630
2631
2632
  if (fwhm < 2.0)
    fwhm = 2.0;
  sep = 2.0;

  invtwosigma2 = -(2.35*2.35/(2.0*fwhm*fwhm));
2633
  hw = (float)(profit->objnaxisn[0]/2);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2634
  ohw = profit->objnaxisn[0] - hw;
2635
  hh = (float)(profit->objnaxisn[1]/2);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2636
2637
2638
  ohh = profit->objnaxisn[1] - hh;
  txstart = -hw;
  ty = -hh;
2639
  QMALLOC(dx, float, npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
  pix = dx;
  for (j=profit->objnaxisn[1]; j--; ty+=1.0)
    {
    tx = txstart;
    y = ty < -0.5? ty + hh : ty - ohh;
    for (i=profit->objnaxisn[0]; i--; tx+=1.0)
      {
      x = tx < -0.5? tx + hw : tx - ohw;
      *(pix++) = exp(invtwosigma2*((x+sep)*(x+sep)+y*y))
		- exp(invtwosigma2*((x-sep)*(x-sep)+y*y));
      }
    }
2652
  QMALLOC(dy, float, npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
  pix = dy;
  ty = -hh;
  for (j=profit->objnaxisn[1]; j--; ty+=1.0)
    {
    tx = txstart;
    y = ty < -0.5? ty + hh : ty - ohh;
    for (i=profit->objnaxisn[0]; i--; tx+=1.0)
      {
      x = tx < -0.5? tx + hw : tx - ohw;
      *(pix++) = exp(invtwosigma2*(x*x+(y+sep)*(y+sep)))
		- exp(invtwosigma2*(x*x+(y-sep)*(y-sep)));
      }
    }

2667
  QMALLOC(gdx, float, npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2668
2669
2670
2671
2672
2673
2674
2675
2676
  gdxt = gdx;
  fpix = profit->objpix;
  invsig = npix/profit->sigma;
  for (i=npix; i--; fpix++)
    {
    val = *fpix > -1e29? *fpix*invsig : 0.0;
    *(gdxt++) = (val>0.0? log(1.0+val) : -log(1.0-val));
    }
  gdy = NULL;			/* to avoid gcc -Wall warnings */
2677
  QMEMCPY(gdx, gdy, float, npix);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2678
2679
2680
2681
2682
2683
  fdx = fft_rtf(dx, profit->objnaxisn);
  fft_conv(gdx, fdx, profit->objnaxisn);
  fdy = fft_rtf(dy, profit->objnaxisn);
  fft_conv(gdy, fdy, profit->objnaxisn);

/* Compute estimator */
2684
  invtwosigma2 = -1.18*1.18 / (2.0*profit->guessradius*profit->guessradius);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
  xstart = -hw - obj->mx + (int)(obj->mx+0.49999);
  y = -hh -  obj->my + (int)(obj->my+0.49999);;
  spirindex = 0.0;
  gdxt = gdx;
  gdyt = gdy;
  for (j=profit->objnaxisn[1]; j--; y+=1.0)
    {
    x = xstart;
    for (i=profit->objnaxisn[0]; i--; x+=1.0)
      {
      gx = *(gdxt++);
      gy = *(gdyt++);
      if ((r2=x*x+y*y)>0.0)
        spirindex += (x*y*(gx*gx-gy*gy)+gx*gy*(y*y-x*x))/r2
			* exp(invtwosigma2*r2);
      }
    }

  free(dx);
  free(dy);
2705
2706
  QFFTWF_FREE(fdx);
  QFFTWF_FREE(fdy);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2707
2708
2709
2710
2711
2712
2713
2714
  free(gdx);
  free(gdy);

  return spirindex;
  }


/****** profit_moments ****************************************************
2715
PROTO	void profit_moments(profitstruct *profit, obj2struct *obj2)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2716
PURPOSE	Compute the 2nd order moments from the unconvolved object model.
2717
2718
INPUT	Profile-fitting structure,
	Pointer to obj2 structure.
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2719
2720
2721
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
2722
VERSION	22/04/2011
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2723
 ***/
2724
void	 profit_moments(profitstruct *profit, obj2struct *obj2)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2725
  {
2726
   profstruct	*prof;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2727
2728
2729
2730
2731
2732
   double	dpdmx2[6], cov[4],
		*jac,*jact, *pjac,*pjact, *dcovar,*dcovart,
		*dmx2,*dmy2,*dmxy,
		m0,invm0, mx2,my2,mxy, den,invden,
		temp, temp2,invtemp2,invstemp2,
		pmx2,theta, flux, dval;
2733
   float	 *covart;
2734
   int		findex[MODEL_NMAX],
2735
		i,j,p, nparam;
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769

/*  hw = (float)(profit->modnaxisn[0]/2);*/
/*  hh = (float)(profit->modnaxisn[1]/2);*/
/*  r2max = hw<hh? hw*hw : hh*hh;*/
/*  xstart = -hw;*/
/*  y = -hh;*/
/*  pix = profit->modpix;*/
/*  mx2 = my2 = mxy = mx = my = sum = 0.0;*/
/*  for (iy=profit->modnaxisn[1]; iy--; y+=1.0)*/
/*    {*/
/*    x = xstart;*/
/*    for (ix=profit->modnaxisn[0]; ix--; x+=1.0)*/
/*      if (y*y+x*x <= r2max)*/
/*        {*/
/*        val = *(pix++);*/
/*        sum += val;*/
/*        mx  += val*x;*/
/*        my  += val*y;*/
/*        mx2 += val*x*x;*/
/*        mxy += val*x*y;*/
/*        my2 += val*y*y;*/
/*        }*/
/*      else*/
/*        pix++;*/
/*    }*/

/*  if (sum <= 1.0/BIG)*/
/*    sum = 1.0;*/
/*  mx /= sum;*/
/*  my /= sum;*/
/*  obj2->prof_mx2 = mx2 = mx2/sum - mx*mx;*/
/*  obj2->prof_my2 = my2 = my2/sum - my*my;*/
/*  obj2->prof_mxy = mxy = mxy/sum - mx*my;*/

2770
  nparam = profit->nparam;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2771
  if (FLAG(obj2.prof_e1err) || FLAG(obj2.prof_pol1err))
2772
2773
2774
    {
/*-- Set up Jacobian matrices */
    QCALLOC(jac, double, nparam*3);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2775
2776
2777
2778
2779
2780
    QMALLOC(pjac, double, (nparam<2? 6 : nparam*3));
    QMALLOC(dcovar, double, nparam*nparam);
    dcovart = dcovar;
    covart = profit->covar;
    for (i=nparam*nparam; i--;)
      *(dcovart++) = (double)(*(covart++));
2781
2782
2783
2784
2785
    dmx2 = jac;
    dmy2 = jac+nparam;
    dmxy = jac+2*nparam;
    }
  else
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2786
    jac = pjac = dcovar = dmx2 = dmy2 = dmxy = NULL;
2787

2788
2789
  m0 = mx2 = my2 = mxy = 0.0;
  for (p=0; p<profit->nprof; p++)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2790
    {
2791
    prof = profit->prof[p];
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
    findex[p] = prof_moments(profit, prof, pjac);
    flux = *prof->flux;
    m0 += flux;
    mx2 += prof->mx2*flux;
    my2 += prof->my2*flux;
    mxy += prof->mxy*flux;
    if (jac)
      {
      jact = jac;
      pjact = pjac;
      for (j=nparam*3; j--;)
        *(jact++) += flux * *(pjact++);
      }
    }
  invm0 = 1.0 / m0;
  obj2->prof_mx2 = (mx2 *= invm0);
  obj2->prof_my2 = (my2 *= invm0);
  obj2->prof_mxy = (mxy *= invm0);
/* Complete the flux derivative of moments */
  if (jac)
    {
    for (p=0; p<profit->nprof; p++)
      {
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2815
2816
2817
2818
      prof = profit->prof[p];
      dmx2[findex[p]] = prof->mx2 - mx2;
      dmy2[findex[p]] = prof->my2 - my2;
      dmxy[findex[p]] = prof->mxy - mxy;
2819
2820
2821
2822
      }
    jact = jac;
    for (j=nparam*3; j--;)
      *(jact++) *= invm0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2823
    }
2824
2825
2826

/* Handle fully correlated profiles (which cause a singularity...) */
  if ((temp2=mx2*my2-mxy*mxy)<0.00694)
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2827
    {
2828
2829
2830
2831
2832
    mx2 += 0.0833333;
    my2 += 0.0833333;
    temp2 = mx2*my2-mxy*mxy;
    }

Emmanuel Bertin's avatar
Emmanuel Bertin committed
2833
2834
2835
2836
2837
/* Use the Jacobians to compute the moment covariance matrix */
  if (jac)
    propagate_covar(dcovar, jac, obj2->prof_mx2cov, nparam, 3,
						pjac);	/* We re-use pjac */

2838
  if (FLAG(obj2.prof_pol1))
2839
    {
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2840
/*--- "Polarisation", i.e. module = (a^2-b^2)/(a^2+b^2) */
2841
2842
2843
2844
    if (mx2+my2 > 1.0/BIG)
      {
      obj2->prof_pol1 = (mx2 - my2) / (mx2+my2);
      obj2->prof_pol2 = 2.0*mxy / (mx2 + my2);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2845
      if (FLAG(obj2.prof_pol1err))
2846
        {
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
/*------ Compute the Jacobian of polarisation */
        invden = 1.0/(mx2+my2);
        dpdmx2[0] =  2.0*my2*invden*invden;
        dpdmx2[1] = -2.0*mx2*invden*invden;
        dpdmx2[2] =  0.0;
        dpdmx2[3] = -2.0*mxy*invden*invden;
        dpdmx2[4] = -2.0*mxy*invden*invden;
        dpdmx2[5] =  2.0*invden;

/*------ Use the Jacobian to compute the polarisation covariance matrix */
        propagate_covar(obj2->prof_mx2cov, dpdmx2, cov, 3, 2,
						pjac);	/* We re-use pjac */
        obj2->prof_pol1err = (float)sqrt(cov[0]<0.0? 0.0: cov[0]);
        obj2->prof_pol2err = (float)sqrt(cov[3]<0.0? 0.0: cov[3]);
        obj2->prof_pol12corr = (dval=cov[0]*cov[3]) > 0.0?
					(float)(cov[1]/sqrt(dval)) : 0.0;
2863
2864
2865
2866
        }
      }
    else
      obj2->prof_pol1 = obj2->prof_pol2
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2867
	= obj2->prof_pol1err = obj2->prof_pol2err = obj2->prof_pol12corr = 0.0;
2868
2869
2870
2871
    }

  if (FLAG(obj2.prof_e1))
    {
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2872
/*--- "Ellipticity", i.e. module = (a-b)/(a+b) */
2873
2874
    if (mx2+my2 > 1.0/BIG)
      {
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2875
2876
      den = (temp2>=0.0) ? mx2+my2+2.0*sqrt(temp2) : mx2+my2;
      invden = 1.0/den;
2877
2878
      obj2->prof_e1 = (float)(invden * (mx2 - my2));
      obj2->prof_e2 = (float)(2.0 * invden * mxy);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2879
      if (FLAG(obj2.prof_e1err))
2880
        {
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2881
/*------ Compute the Jacobian of ellipticity */
2882
        invstemp2 = (temp2>=0.0) ? 1.0/sqrt(temp2) : 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
        dpdmx2[0] = ( den - (1.0+my2*invstemp2)*(mx2-my2))*invden*invden;
        dpdmx2[1] = (-den - (1.0+mx2*invstemp2)*(mx2-my2))*invden*invden;
        dpdmx2[2] = 2.0*mxy*invstemp2*(mx2-my2)*invden*invden;
        dpdmx2[3] = -2.0*mxy*(1.0+my2*invstemp2)*invden*invden;
        dpdmx2[4] = -2.0*mxy*(1.0+mx2*invstemp2)*invden*invden;
        dpdmx2[5] =  (2.0*den+4.0*mxy*mxy*invstemp2)*invden*invden;

/*------ Use the Jacobian to compute the ellipticity covariance matrix */
        propagate_covar(obj2->prof_mx2cov, dpdmx2, cov, 3, 2,
					pjac);	/* We re-use pjac */
        obj2->prof_e1err = (float)sqrt(cov[0]<0.0? 0.0: cov[0]);
        obj2->prof_e2err = (float)sqrt(cov[3]<0.0? 0.0: cov[3]);
        obj2->prof_e12corr = (dval=cov[0]*cov[3]) > 0.0?
					(float)(cov[1]/sqrt(dval)) : 0.0;
2897
        }
2898
      }
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2899
    else
2900
      obj2->prof_e1 = obj2->prof_e2
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2901
	= obj2->prof_e1err = obj2->prof_e2err = obj2->prof_e12corr = 0.0;
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2902
    }
2903
2904
2905

  if (FLAG(obj2.prof_cxx))
    {
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2906
2907
2908
2909
    invtemp2 = (temp2>=0.0) ? 1.0/temp2 : 0.0;
    obj2->prof_cxx = (float)(my2*invtemp2);
    obj2->prof_cyy = (float)(mx2*invtemp2);
    obj2->prof_cxy = (float)(-2*mxy*invtemp2);
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
    }

  if (FLAG(obj2.prof_a))
    {
    if ((fabs(temp=mx2-my2)) > 0.0)
      theta = atan2(2.0 * mxy,temp) / 2.0;
    else
      theta = PI/4.0;

    temp = sqrt(0.25*temp*temp+mxy*mxy);
    pmx2 = 0.5*(mx2+my2);
    obj2->prof_a = (float)sqrt(pmx2 + temp);
    obj2->prof_b = (float)sqrt(pmx2 - temp);
    obj2->prof_theta = theta*180.0/PI;
    }

2926
2927
2928
/* Free memory used by Jacobians */
  free(jac);
  free(pjac);
Emmanuel Bertin's avatar
Emmanuel Bertin committed
2929
  free(dcovar);
2930

Emmanuel Bertin's avatar
Emmanuel Bertin committed
2931
2932
2933
2934
  return;
  }


2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
/****** profit_convmoments ****************************************************
PROTO	void profit_convmoments(profitstruct *profit, obj2struct *obj2)
PURPOSE	Compute the 2nd order moments of the convolved object model.
INPUT	Profile-fitting structure,
	Pointer to obj2 structure.
OUTPUT	-.
NOTES	-.
AUTHOR	E. Bertin (IAP)
VERSION	12/04/2011
 ***/
void	 profit_convmoments(profitstruct *profit, obj2struct *obj2)
  {
   double	hw,hh, r2max, x,xstart,y, mx2,my2,mxy,mx,my,sum, dval,
		temp,temp2,invtemp2, pmx2, theta;
   PIXTYPE	*pix;
   int		ix,iy, w,h;

  w = profit->modnaxisn[0];
  h = profit->modnaxisn[1];
  hw = (double)(w/2);
  hh = (double)(h/2);

  r2max = hw<hh? hw*hw : hh*hh;
  xstart = -hw;
  y = -hh;
  pix = profit->cmodpix;
  mx2 = my2 = mxy = mx = my = sum = 0.0;
  for (iy=h; iy--; y+=1.0)
    {
    x = xstart;
    for (ix=w; ix--; x+=1.0)
      if (y*y+x*x <= r2max)
        {
        dval = *(pix++);
        sum += dval;
        mx  += dval*x;
        my  += dval*y;
        mx2 += dval*x*x;
        mxy += dval*x*y;
        my2 += dval*y*y;
        }
      else
        pix++;
    }

  if (sum <= 1.0/BIG)
    sum = 1.0;
  mx /= sum;
  my /= sum;
  obj2->prof_convmx2 = (mx2 = mx2/sum - mx*mx)*profit->pixstep*profit->pixstep;
  obj2->prof_convmy2 = (my2 = my2/sum - my*my)*profit->pixstep*profit->pixstep;
  obj2->prof_convmxy = (mxy = mxy/sum - mx*my)*profit->pixstep*profit->pixstep;

/* Handle fully correlated profiles (which cause a singularity...) */
  if ((temp2=mx2*my2-mxy*mxy)<0.00694)
    {
    mx2 += 0.0833333;
    my2 += 0.0833333;
    temp2 = mx2*my2-mxy*mxy;
    }

  temp2 *= profit->pixstep*profit->pixstep;

  if (FLAG(obj2.prof_convcxx))
    {
    invtemp2 = (temp2>=0.0) ? 1.0/temp2 : 0.0;
For faster browsing, not all history is shown. View entire blame