public software.sextractor

[/] [trunk/] [src/] [winpos.c] - Blame information for rev 235

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 233 bertin
/*
2
*                               winpos.c
3 2 bertin
*
4 233 bertin
* Compute iteratively windowed parameters.
5 2 bertin
*
6 233 bertin
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7 2 bertin
*
8 233 bertin
*       This file part of:      SExtractor
9 2 bertin
*
10 235 bertin
*       Copyright:              (C) 2005-2010 Emmanuel Bertin -- IAP/CNRS/UPMC
11 2 bertin
*
12 233 bertin
*       License:                GNU General Public License
13
*
14
*       SExtractor is free software: you can redistribute it and/or modify
15
*       it under the terms of the GNU General Public License as published by
16
*       the Free Software Foundation, either version 3 of the License, or
17
*       (at your option) any later version.
18
*       SExtractor is distributed in the hope that it will be useful,
19
*       but WITHOUT ANY WARRANTY; without even the implied warranty of
20
*       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
*       GNU General Public License for more details.
22
*       You should have received a copy of the GNU General Public License
23
*       along with SExtractor. If not, see <http://www.gnu.org/licenses/>.
24
*
25
*       Last modified:          11/10/2010
26
*
27
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
28 2 bertin
 
29
#ifdef HAVE_CONFIG_H
30
#include        "config.h"
31
#endif
32
 
33
#include        <math.h>
34
#include        <stdlib.h>
35
 
36
#include        "define.h"
37
#include        "globals.h"
38
#include        "prefs.h"
39
#include        "winpos.h"
40
 
41
static  obj2struct      *obj2 = &outobj2;
42
 
43
/****** compute_winpos ********************************************************
44
PROTO   void compute_winpos(picstruct *field, picstruct *wfield,
45
                        objstruct *obj)
46
PURPOSE Compute windowed source barycenter.
47
INPUT   Picture structure pointer,
48
        Weight-map structure pointer,
49
        object structure.
50
OUTPUT  -.
51
NOTES   obj->posx and obj->posy are taken as initial centroid guesses.
52
AUTHOR  E. Bertin (IAP)
53 224 bertin
VERSION 16/07/2010
54 2 bertin
 ***/
55
void    compute_winpos(picstruct *field, picstruct *wfield, objstruct *obj)
56
 
57
  {
58 224 bertin
   float                r2,invtwosig2, raper,raper2, rintlim,rintlim2,rextlim2,
59
                        dx,dx1,dy,dy2, sig, invngamma, pdbkg,
60
                        offsetx,offsety,scalex,scaley,scale2, locarea;
61
   double               tv, norm, pix, var, backnoise2, invgain, locpix,
62
                        dxpos,dypos, err,err2, emx2,emy2,emxy,
63 2 bertin
                        esum, temp,temp2, mx2, my2,mxy,pmx2, theta, mx,my,
64
                        mx2ph, my2ph;
65
   int                  i,x,y, x2,y2, xmin,xmax,ymin,ymax, sx,sy, w,h,
66
                        fymin,fymax, pflag,corrflag, gainflag, errflag,
67
                        momentflag;
68
   long                 pos;
69
   PIXTYPE              *strip,*stript, *wstrip,*wstript,
70
                        wthresh = 0.0;
71
 
72
  if (wfield)
73
    wthresh = wfield->weight_thresh;
74
  wstrip = wstript = NULL;
75
  w = field->width;
76
  h = field->stripheight;
77
  fymin = field->ymin;
78
  fymax = field->ymax;
79
  pflag = (prefs.detect_type==PHOTO)? 1:0;
80
  corrflag = (prefs.mask_type==MASK_CORRECT);
81
  gainflag = wfield && prefs.weightgain_flag;
82
  errflag = FLAG(obj2.winposerr_mx2);
83
  momentflag = FLAG(obj2.win_mx2) | FLAG(obj2.winposerr_mx2);
84
  var = backnoise2 = field->backsig*field->backsig;
85 224 bertin
  invgain = field->gain>0.0? 1.0/field->gain : 0.0;
86 2 bertin
  sig = obj2->hl_radius*2.0/2.35; /* From half-FWHM to sigma */
87 224 bertin
  invtwosig2 = 1.0/(2.0*sig*sig);
88 2 bertin
 
89
/* Integration radius */
90
  raper = WINPOS_NSIG*sig;
91
 
92
/* For photographic data */
93
  if (pflag)
94
    {
95 224 bertin
    invngamma = 1.0/field->ngamma;
96
    pdbkg = expf(obj->dbkg*invngamma);
97 2 bertin
    }
98
  else
99
    {
100 224 bertin
    invngamma = 0.0;
101 2 bertin
    pdbkg = 0.0;
102
    }
103
  raper2 = raper*raper;
104
/* Internal radius of the oversampled annulus (<r-sqrt(2)/2) */
105
  rintlim = raper - 0.75;
106
  rintlim2 = (rintlim>0.0)? rintlim*rintlim: 0.0;
107
/* External radius of the oversampled annulus (>r+sqrt(2)/2) */
108
  rextlim2 = (raper + 0.75)*(raper + 0.75);
109
  scaley = scalex = 1.0/WINPOS_OVERSAMP;
110
  scale2 = scalex*scaley;
111
  offsetx = 0.5*(scalex-1.0);
112
  offsety = 0.5*(scaley-1.0);
113
/* Use isophotal centroid as a first guess */
114
  mx = obj2->posx - 1.0;
115
  my = obj2->posy - 1.0;
116
 
117
  for (i=0; i<WINPOS_NITERMAX; i++)
118
    {
119
    xmin = (int)(mx-raper+0.499999);
120
    xmax = (int)(mx+raper+1.499999);
121
    ymin = (int)(my-raper+0.499999);
122
    ymax = (int)(my+raper+1.499999);
123
    mx2ph = mx*2.0 + 0.49999;
124
    my2ph = my*2.0 + 0.49999;
125
 
126
    if (xmin < 0)
127
      {
128
      xmin = 0;
129
      obj->flag |= OBJ_APERT_PB;
130
      }
131
    if (xmax > w)
132
      {
133
      xmax = w;
134
      obj->flag |= OBJ_APERT_PB;
135
      }
136
    if (ymin < fymin)
137
      {
138
      ymin = fymin;
139
      obj->flag |= OBJ_APERT_PB;
140
      }
141
    if (ymax > fymax)
142
      {
143
      ymax = fymax;
144
      obj->flag |= OBJ_APERT_PB;
145
      }
146
 
147
    tv = esum = emxy = emx2 = emy2 = mx2 = my2 = mxy = 0.0;
148
    dxpos = dypos = 0.0;
149
    strip = field->strip;
150
    wstrip = wstript = NULL;            /* To avoid gcc -Wall warnings */
151
    if (wfield)
152
      wstrip = wfield->strip;
153
    for (y=ymin; y<ymax; y++)
154
      {
155
      stript = strip + (pos = (y%h)*w + xmin);
156
      if (wfield)
157
        wstript = wstrip + pos;
158
      for (x=xmin; x<xmax; x++, stript++, wstript++)
159
        {
160
        dx = x - mx;
161
        dy = y - my;
162
        if ((r2=dx*dx+dy*dy)<rextlim2)
163
          {
164
          if (WINPOS_OVERSAMP>1 && r2> rintlim2)
165
            {
166
            dx += offsetx;
167
            dy += offsety;
168
            locarea = 0.0;
169
            for (sy=WINPOS_OVERSAMP; sy--; dy+=scaley)
170
              {
171
              dx1 = dx;
172
              dy2 = dy*dy;
173
              for (sx=WINPOS_OVERSAMP; sx--; dx1+=scalex)
174
                if (dx1*dx1+dy2<raper2)
175
                  locarea += scale2;
176
              }
177
            }
178
          else
179
            locarea = 1.0;
180 224 bertin
          locarea *= expf(-r2*invtwosig2);
181 2 bertin
/*-------- Here begin tests for pixel and/or weight overflows. Things are a */
182
/*-------- bit intricated to have it running as fast as possible in the most */
183
/*-------- common cases */
184
          if ((pix=*stript)<=-BIG || (wfield && (var=*wstript)>=wthresh))
185
            {
186
            if (corrflag
187
                && (x2=(int)(mx2ph-x))>=0 && x2<w
188
                && (y2=(int)(my2ph-y))>=fymin && y2<fymax
189
                && (pix=*(strip + (pos = (y2%h)*w + x2)))>-BIG)
190
              {
191
              if (wfield)
192
                {
193
                var = *(wstrip + pos);
194
                if (var>=wthresh)
195
                  pix = var = 0.0;
196
                }
197
              }
198
            else
199
              {
200
              pix = 0.0;
201
              if (wfield)
202
                var = 0.0;
203
              }
204
            }
205
          if (pflag)
206 224 bertin
            pix = expf(pix*invngamma);
207 2 bertin
          dx = x - mx;
208
          dy = y - my;
209
          locpix = locarea*pix;
210
          tv += locpix;
211
          dxpos += locpix*dx;
212
          dypos += locpix*dy;
213
          if (errflag)
214
            {
215
            err = var;
216
            if (pflag)
217 224 bertin
              err *= locpix*pix*invngamma*invngamma;
218
            else if (invgain>0.0 && pix>0.0)
219 2 bertin
              {
220
              if (gainflag)
221 224 bertin
                err += pix*invgain*var/backnoise2;
222 2 bertin
              else
223 224 bertin
                err += pix*invgain;
224 2 bertin
              }
225
            err2 = locarea*locarea*err;
226
            esum += err2;
227
            emx2 += err2*(dx*dx+0.0833);        /* Finite pixel size */
228
            emy2 += err2*(dy*dy+0.0833);        /* Finite pixel size */
229
            emxy += err2*dx*dy;
230
            }
231
          if (momentflag)
232
            {
233
            mx2 += locpix*dx*dx;
234
            my2 += locpix*dy*dy;
235
            mxy += locpix*dx*dy;
236
            }
237
          }
238
        }
239
      }
240
 
241
    if (tv>0.0)
242
      {
243 224 bertin
      mx += (dxpos /= tv)*WINPOS_FAC;
244
      my += (dypos /= tv)*WINPOS_FAC;
245 2 bertin
      }
246
    else
247
      break;
248
 
249
/*-- Stop here if position does not change */
250
    if (dxpos*dxpos+dypos*dypos < WINPOS_STEPMIN*WINPOS_STEPMIN)
251
      break;
252
    }
253
  mx2 = mx2/tv - dxpos*dxpos;
254
  my2 = my2/tv - dypos*dypos;
255
  mxy = mxy/tv - dxpos*dypos;
256
  obj2->winpos_x = mx + 1.0;    /* The dreaded 1.0 FITS offset */
257
  obj2->winpos_y = my + 1.0;    /* The dreaded 1.0 FITS offset */
258
  obj2->winpos_niter = i+1;
259
 
260
/* WINdowed flux */
261
  if (FLAG(obj2.flux_win))
262
    {
263
    obj2->flux_win = tv;
264
    obj2->fluxerr_win = sqrt(esum);
265
    }
266
  temp2=mx2*my2-mxy*mxy;
267 224 bertin
  obj2->win_flag = (tv <= 0.0)*4 + (mx2 < 0.0 || my2 < 0.0)*2 + (temp2<0.0);
268 2 bertin
  if (obj2->win_flag)
269
    {
270
/*--- Negative values: revert to isophotal estimates */
271
    if (errflag)
272
      {
273
      obj2->winposerr_mx2 = obj->poserr_mx2;
274
      obj2->winposerr_my2 = obj->poserr_my2;
275
      obj2->winposerr_mxy = obj->poserr_mxy;
276
      if (FLAG(obj2.winposerr_a))
277
        {
278
        obj2->winposerr_a = obj2->poserr_a;
279
        obj2->winposerr_b = obj2->poserr_b;
280
        obj2->winposerr_theta = obj2->poserr_theta;
281
        }
282
      if (FLAG(obj2.winposerr_cxx))
283
        {
284
        obj2->winposerr_cxx = obj2->poserr_cxx;
285
        obj2->winposerr_cyy = obj2->poserr_cyy;
286
        obj2->winposerr_cxy = obj2->poserr_cxy;
287
        }
288
      }
289
    if (momentflag)
290
      {
291
      obj2->win_mx2 = obj->mx2;
292
      obj2->win_my2 = obj->my2;
293
      obj2->win_mxy = obj->mxy;
294
      if (FLAG(obj2.win_cxx))
295
        {
296
        obj2->win_cxx = obj->cxx;
297
        obj2->win_cyy = obj->cyy;
298
        obj2->win_cxy = obj->cxy;
299
        }
300
      if (FLAG(obj2.win_a))
301
        {
302
        obj2->win_a = obj->a;
303
        obj2->win_b = obj->b;
304
        obj2->win_polar = obj2->polar;
305
        obj2->win_theta = obj->theta;
306
        }
307
      }
308
    }
309
  else
310
    {
311
    if (errflag)
312
      {
313 224 bertin
      norm = WINPOS_FAC*WINPOS_FAC/(tv*tv);
314
      emx2 *= norm;
315
      emy2 *= norm;
316
      emxy *= norm;
317 2 bertin
/*-- Handle fully correlated profiles (which cause a singularity...) */
318 224 bertin
      esum *= 0.08333*norm;
319 2 bertin
      if (obj->singuflag && (emx2*emy2-emxy*emxy) < esum*esum)
320
        {
321
        emx2 += esum;
322
        emy2 += esum;
323
        }
324
 
325
      obj2->winposerr_mx2 = emx2;
326
      obj2->winposerr_my2 = emy2;
327
      obj2->winposerr_mxy = emxy;
328
/*---- Error ellipse parameters */
329
      if (FLAG(obj2.winposerr_a))
330
        {
331
         double pmx2,pmy2,temp,theta;
332
 
333
        if (fabs(temp=emx2-emy2) > 0.0)
334
          theta = atan2(2.0 * emxy,temp) / 2.0;
335
        else
336
          theta = PI/4.0;
337
 
338
        temp = sqrt(0.25*temp*temp+ emxy*emxy);
339
        pmy2 = pmx2 = 0.5*(emx2+emy2);
340
        pmx2+=temp;
341
        pmy2-=temp;
342
 
343
        obj2->winposerr_a = (float)sqrt(pmx2);
344
        obj2->winposerr_b = (float)sqrt(pmy2);
345
        obj2->winposerr_theta = theta*180.0/PI;
346
        }
347
 
348
      if (FLAG(obj2.winposerr_cxx))
349
        {
350
         double temp;
351
 
352
        obj2->winposerr_cxx = (float)(emy2/(temp=emx2*emy2-emxy*emxy));
353
        obj2->winposerr_cyy = (float)(emx2/temp);
354
        obj2->winposerr_cxy = (float)(-2*emxy/temp);
355
        }
356
      }
357 3 bertin
 
358 2 bertin
    if (momentflag)
359
      {
360
/*-- Handle fully correlated profiles (which cause a singularity...) */
361
      if ((temp2=mx2*my2-mxy*mxy)<0.00694)
362
        {
363
        mx2 += 0.0833333;
364
        my2 += 0.0833333;
365
        temp2 = mx2*my2-mxy*mxy;
366
        }
367
      obj2->win_mx2 = mx2;
368
      obj2->win_my2 = my2;
369
      obj2->win_mxy = mxy;
370
 
371
      if (FLAG(obj2.win_cxx))
372
        {
373
        obj2->win_cxx = (float)(my2/temp2);
374
        obj2->win_cyy = (float)(mx2/temp2);
375
        obj2->win_cxy = (float)(-2*mxy/temp2);
376
        }
377
 
378
      if (FLAG(obj2.win_a))
379
        {
380
        if ((fabs(temp=mx2-my2)) > 0.0)
381
          theta = atan2(2.0 * mxy,temp) / 2.0;
382
        else
383
          theta = PI/4.0;
384
 
385
        temp = sqrt(0.25*temp*temp+mxy*mxy);
386
        pmx2 = 0.5*(mx2+my2);
387
        obj2->win_a = (float)sqrt(pmx2 + temp);
388
        obj2->win_b = (float)sqrt(pmx2 - temp);
389
        if (FLAG(obj2.win_polar))
390
          obj2->win_polar = temp / pmx2;
391
        obj2->win_theta = theta*180.0/PI;
392
        }
393
      }
394
    }
395
 
396
  return;
397
  }
398
 
399