File indexing completed on 2024-04-28 03:43:52

0001 /*
0002     This file is part of SEP
0003 
0004     SPDX-FileCopyrightText: 1993-2011 Emmanuel Bertin -- IAP /CNRS/UPMC
0005     SPDX-FileCopyrightText: 2014 SEP developers
0006 
0007     SPDX-License-Identifier: LGPL-3.0-or-later
0008 */
0009 
0010 #include <math.h>
0011 #include <stdlib.h>
0012 #include <stdio.h>
0013 #include <string.h>
0014 #include "sep.h"
0015 #include "sepcore.h"
0016 #include "extract.h"
0017 
0018 /********************************** cleanprep ********************************/
0019 /*
0020  * Prepare object for cleaning, by calculating mthresh.
0021  * This used to be in analyse() / examineiso().
0022  */
0023 
0024 int analysemthresh(int objnb, objliststruct *objlist, int minarea,
0025            PIXTYPE thresh)
0026 {
0027   objstruct *obj = objlist->obj+objnb;
0028   pliststruct *pixel = objlist->plist;
0029   pliststruct *pixt;
0030   PIXTYPE tpix;
0031   float     *heap,*heapt,*heapj,*heapk, swap;
0032   int       j, k, h, status;
0033 
0034   status = RETURN_OK;
0035   heap = heapt = heapj = heapk = NULL;
0036   h = minarea;
0037 
0038   if (obj->fdnpix < minarea)
0039     {
0040       obj->mthresh = 0.0;
0041       return status;
0042     }
0043 
0044   QMALLOC(heap, float, minarea, status);
0045   heapt = heap;
0046 
0047   /*-- Find the minareath pixel in decreasing intensity for CLEANing */
0048   for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
0049     {
0050       /* amount pixel is above threshold */
0051       tpix = PLISTPIX(pixt, cdvalue) - (PLISTEXIST(thresh)?
0052                     PLISTPIX(pixt, thresh):thresh);
0053       if (h>0)
0054         *(heapt++) = (float)tpix;
0055       else if (h)
0056         {
0057       if ((float)tpix>*heap)
0058         {
0059           *heap = (float)tpix;
0060           for (j=0; (k=(j+1)<<1)<=minarea; j=k)
0061         {
0062           heapk = heap+k;
0063           heapj = heap+j;
0064           if (k != minarea && *(heapk-1) > *heapk)
0065             {
0066               heapk++;
0067               k++;
0068             }
0069           if (*heapj <= *(--heapk))
0070             break;
0071           swap = *heapk;
0072           *heapk = *heapj;
0073           *heapj = swap;
0074         }
0075         }
0076         }
0077       else
0078         fqmedian(heap, minarea);
0079       h--;
0080     }
0081 
0082   obj->mthresh = *heap;
0083 
0084  exit:
0085   free(heap);
0086   return status;
0087 }
0088 
0089 /************************* preanalyse **************************************/
0090 
0091 void  preanalyse(int no, objliststruct *objlist)
0092 {
0093   objstruct *obj = &objlist->obj[no];
0094   pliststruct   *pixel = objlist->plist, *pixt;
0095   PIXTYPE   peak, cpeak, val, cval;
0096   double    rv;
0097   int       x, y, xmin,xmax, ymin,ymax, fdnpix;
0098   int           xpeak, ypeak, xcpeak, ycpeak;
0099   
0100   /*-----  initialize stacks and bounds */
0101   fdnpix = 0;
0102   rv = 0.0;
0103   peak = cpeak = -BIG;
0104   ymin = xmin = 2*MAXPICSIZE;    /* to be really sure!! */
0105   ymax = xmax = 0;
0106   xpeak = ypeak = xcpeak = ycpeak = 0; /* avoid -Wall warnings */
0107 
0108   /*-----  integrate results */
0109   for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
0110     {
0111       x = PLIST(pixt, x);
0112       y = PLIST(pixt, y);
0113       val = PLISTPIX(pixt, value);
0114       cval = PLISTPIX(pixt, cdvalue);
0115       if (peak < val)
0116     {
0117       peak = val;
0118       xpeak = x;
0119       ypeak = y;
0120     }
0121       if (cpeak < cval)
0122     {
0123       cpeak = cval;
0124       xcpeak = x;
0125       ycpeak = y;
0126     }
0127       rv += cval;
0128       if (xmin > x)
0129     xmin = x;
0130       if (xmax < x)
0131     xmax = x;
0132       if (ymin > y)
0133     ymin = y;
0134       if (ymax < y)
0135     ymax = y;
0136       fdnpix++;
0137     }    
0138   
0139   obj->fdnpix = (LONG)fdnpix;
0140   obj->fdflux = (float)rv;
0141   obj->fdpeak = cpeak;
0142   obj->dpeak = peak;
0143   obj->xpeak = xpeak;
0144   obj->ypeak = ypeak;
0145   obj->xcpeak = xcpeak;
0146   obj->ycpeak = ycpeak;
0147   obj->xmin = xmin;
0148   obj->xmax = xmax;
0149   obj->ymin = ymin;
0150   obj->ymax = ymax;
0151 
0152   return;
0153 }
0154 
0155 /******************************** analyse *********************************/
0156 /*
0157   If robust = 1, you must have run previously with robust=0
0158 */
0159 
0160 void  analyse(int no, objliststruct *objlist, int robust, double gain)
0161 {
0162   objstruct *obj = &objlist->obj[no];
0163   pliststruct   *pixel = objlist->plist, *pixt;
0164   PIXTYPE   peak, val, cval;
0165   double    thresh,thresh2, t1t2,darea,
0166                 mx,my, mx2,my2,mxy, rv, rv2, tv,
0167         xm,ym, xm2,ym2,xym,
0168                 temp,temp2, theta,pmx2,pmy2,
0169                 errx2, erry2, errxy, cvar, cvarsum;
0170   int       x, y, xmin, ymin, area2, dnpix;
0171 
0172   preanalyse(no, objlist);
0173   
0174   dnpix = 0;
0175   mx = my = tv = 0.0;
0176   mx2 = my2 = mxy = 0.0;
0177   cvarsum = errx2 = erry2 = errxy = 0.0;
0178   thresh = obj->thresh;
0179   peak = obj->dpeak;
0180   rv = obj->fdflux;
0181   rv2 = rv * rv;
0182   thresh2 = (thresh + peak)/2.0;
0183   area2 = 0;
0184   
0185   xmin = obj->xmin;
0186   ymin = obj->ymin;
0187 
0188   for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
0189     {
0190       x = PLIST(pixt,x)-xmin;  /* avoid roundoff errors on big images */
0191       y = PLIST(pixt,y)-ymin;  /* avoid roundoff errors on big images */
0192       cval = PLISTPIX(pixt, cdvalue);
0193       tv += (val = PLISTPIX(pixt, value));
0194       if (val>thresh)
0195     dnpix++;
0196       if (val > thresh2)
0197     area2++;
0198       mx += cval * x;
0199       my += cval * y;
0200       mx2 += cval * x*x;
0201       my2 += cval * y*y;
0202       mxy += cval * x*y;
0203 
0204     }
0205 
0206   /* compute object's properties */
0207   xm = mx / rv;    /* mean x */
0208   ym = my / rv;    /* mean y */
0209 
0210 
0211   /* In case of blending, use previous barycenters */
0212   if ((robust) && (obj->flag & SEP_OBJ_MERGED))
0213     {
0214       double xn, yn;
0215       
0216       xn = obj->mx-xmin;
0217       yn = obj->my-ymin;
0218       xm2 = mx2 / rv + xn*xn - 2*xm*xn;
0219       ym2 = my2 / rv + yn*yn - 2*ym*yn;
0220       xym = mxy / rv + xn*yn - xm*yn - xn*ym;
0221       xm = xn;
0222       ym = yn;
0223     }
0224   else
0225     {
0226       xm2 = mx2 / rv - xm * xm;  /* variance of x */
0227       ym2 = my2 / rv - ym * ym;  /* variance of y */
0228       xym = mxy / rv - xm * ym;  /* covariance */
0229 
0230     }
0231 
0232   /* Calculate the errors on the variances */
0233   for (pixt=pixel+obj->firstpix; pixt>=pixel; pixt=pixel+PLIST(pixt,nextpix))
0234     {
0235       x = PLIST(pixt,x)-xmin;  /* avoid roundoff errors on big images */
0236       y = PLIST(pixt,y)-ymin;  /* avoid roundoff errors on big images */
0237 
0238       cvar = PLISTEXIST(var)? PLISTPIX(pixt, var): 0.0;
0239       if (gain > 0.0) {  /* add poisson noise if given */
0240         cval = PLISTPIX(pixt, cdvalue);
0241         if (cval > 0.0) cvar += cval / gain;
0242       }
0243 
0244       /* Note that this works for both blended and non-blended cases
0245        * because xm is set to xn above for the blended case. */
0246       cvarsum += cvar;
0247       errx2 += cvar * (x - xm) * (x - xm);
0248       erry2 += cvar * (y - ym) * (y - ym);
0249       errxy += cvar * (x - xm) * (y - ym);
0250     }
0251   errx2 /= rv2;
0252   erry2 /= rv2;
0253   errxy /= rv2;
0254 
0255   /* Handle fully correlated x/y (which cause a singularity...) */
0256   if ((temp2=xm2*ym2-xym*xym)<0.00694)
0257     {
0258       xm2 += 0.0833333;
0259       ym2 += 0.0833333;
0260       temp2 = xm2*ym2-xym*xym;
0261       obj->flag |= SEP_OBJ_SINGU;
0262 
0263       /* handle it for the error parameters */
0264       cvarsum *= 0.08333/rv2;
0265       if (errx2*erry2 - errxy * errxy < cvarsum * cvarsum) {
0266         errx2 += cvarsum;
0267         erry2 += cvarsum;
0268       }
0269     }
0270 
0271   if ((fabs(temp=xm2-ym2)) > 0.0)
0272     theta = atan2(2.0 * xym, temp) / 2.0;
0273   else
0274     theta = PI/4.0;
0275 
0276   temp = sqrt(0.25*temp*temp+xym*xym);
0277   pmy2 = pmx2 = 0.5*(xm2+ym2);
0278   pmx2+=temp;
0279   pmy2-=temp;
0280   
0281   obj->dnpix = (LONG)dnpix;
0282   obj->dflux = tv;
0283   obj->mx = xm+xmin;    /* add back xmin */
0284   obj->my = ym+ymin;    /* add back ymin */
0285   obj->mx2 = xm2;
0286   obj->errx2 = errx2;
0287   obj->my2 = ym2;
0288   obj->erry2 = erry2;
0289   obj->mxy = xym;
0290   obj->errxy = errxy;
0291   obj->a = (float)sqrt(pmx2);
0292   obj->b = (float)sqrt(pmy2);
0293   obj->theta = theta;
0294   
0295   obj->cxx = (float)(ym2/temp2);
0296   obj->cyy = (float)(xm2/temp2);
0297   obj->cxy = (float)(-2*xym/temp2);
0298   
0299   darea = (double)area2 - dnpix;
0300   t1t2 = thresh/thresh2;
0301 
0302   /* debugging */
0303   /*if (t1t2>0.0 && !PLISTEXIST(thresh)) */  /* was: prefs.dweight_flag */
0304   if (t1t2 > 0.0)
0305     {
0306       obj->abcor = (darea<0.0?darea:-1.0)/(2*PI*log(t1t2<1.0?t1t2:0.99)
0307                        *obj->a*obj->b);
0308       if (obj->abcor>1.0)
0309     obj->abcor = 1.0;
0310     }
0311   else
0312     {
0313       obj->abcor = 1.0;
0314     }
0315 
0316   return;
0317 
0318 }