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 }