Changeset 9775 for trunk/psModules/src/objects/models/pmModel_SGAUSS.c
- Timestamp:
- Oct 29, 2006, 5:02:59 PM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/objects/models/pmModel_SGAUSS.c
r9730 r9775 1 #ifdef HAVE_CONFIG_H2 #include <config.h>3 #endif4 5 6 1 /****************************************************************************** 7 one component, two slopes: 8 1 / (1 + z^Npow + St*z^Ntide) 2 * this file defines the SGAUSS source shape model (XXX need a better name!). Note that these 3 * model functions are loaded by pmModelGroup.c using 'include', and thus need no 'include' 4 * statements of their own. The models use a psVector to represent the set of parameters, with 5 * the sequence used to specify the meaning of the parameter. The meaning of the parameters 6 * may thus vary depending on the specifics of the model. All models which are used a PSF 7 * representations share a few parameters, for which # define names are listed in pmModel.h: 9 8 10 params->data.F32[0] = So; 11 params->data.F32[1] = Zo; 12 params->data.F32[2] = Xo; 13 params->data.F32[3] = Yo; 14 params->data.F32[4] = 1 / SigmaX; 15 params->data.F32[5] = 1 / SigmaY; 16 params->data.F32[6] = Sxy; 17 params->data.F32[7] = Npow 18 params->data.F32[8] = St 19 *****************************************************************************/ 20 21 # define SQ(A)((A)*(A)) 9 power-law with fitted slope and outer tidal radius 10 1 / (1 + z^N + kz^4) 11 12 * PM_PAR_SKY 0 - local sky : note that this is unused and may be dropped in the future 13 * PM_PAR_I0 1 - central intensity 14 * PM_PAR_XPOS 2 - X center of object 15 * PM_PAR_YPOS 3 - Y center of object 16 * PM_PAR_SXX 4 - X^2 term of elliptical contour (sqrt(2) / SigmaX) 17 * PM_PAR_SYY 5 - Y^2 term of elliptical contour (sqrt(2) / SigmaY) 18 * PM_PAR_SXY 6 - X*Y term of elliptical contour 19 * PM_PAR_7 7 - slope of power-law component (N) 20 * PM_PAR_8 8 - amplitude of the tidal cutoff (k) 21 *****************************************************************************/ 22 23 /*** 24 XXXX the model in this file needs to be tested more carefully. 25 the code for guessing the power-law slope based on the radial profile 26 is either too slow or does not work well. 27 fix up the code to follow conventions in the other model function files. 28 ***/ 29 30 XXX broken code 31 32 # define PM_MODEL_FUNC pmModelFunc_SGAUSS 33 # define PM_MODEL_FLUX pmModelFlux_SGAUSS 34 # define PM_MODEL_GUESS pmModelGuess_SGAUSS 35 # define PM_MODEL_LIMITS pmModelLimits_SGAUSS 36 # define PM_MODEL_RADIUS pmModelRadius_SGAUSS 37 # define PM_MODEL_FROM_PSF pmModelFromPSF_SGAUSS 38 # define PM_MODEL_FIT_STATUS pmModelFitStatus_SGAUSS 39 22 40 psF64 psImageEllipseContour (psEllipseAxes axes, double xc, double yc, psImage *image); 23 psF64 p_psImageGetElementF64(psImage *a, int i, int j); 24 25 psF32 pmModelFunc_SGAUSS(psVector *deriv, 26 const psVector *params, 27 const psVector *x) 41 42 psF32 PM_MODEL_FUNC (psVector *deriv, 43 const psVector *params, 44 const psVector *x) 28 45 { 29 46 psF32 *PAR = params->data.F32; … … 61 78 } 62 79 63 bool pmModelLimits_SGAUSS(psVector **beta_lim, psVector **params_min, psVector **params_max)80 bool PM_MODEL_LIMITS (psVector **beta_lim, psVector **params_min, psVector **params_max) 64 81 { 65 82 … … 99 116 100 117 return (TRUE); 118 } 119 120 bool PM_MODEL_GUESS (pmModel *model, pmSource *source) 121 { 122 123 pmMoments *sMoments = source->moments; 124 pmPeak *peak = source->peak; 125 psF32 *params = model->params->data.F32; 126 127 psEllipseAxes axes; 128 psEllipseShape shape; 129 psEllipseMoments moments; 130 131 moments.x2 = PS_SQR(sMoments->Sx); 132 moments.y2 = PS_SQR(sMoments->Sy); 133 moments.xy = sMoments->Sxy; 134 135 // solve the math to go from Moments To Shape 136 axes = psEllipseMomentsToAxes(moments); 137 shape = psEllipseAxesToShape(axes); 138 139 params[0] = sMoments->Sky; 140 params[1] = sMoments->Peak - sMoments->Sky; 141 params[2] = peak->x; 142 params[3] = peak->y; 143 params[4] = 1.0 / shape.sx; 144 params[5] = 1.0 / shape.sy; 145 params[6] = shape.sxy; 146 147 # if (0) 148 149 f1 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels); 150 axes.major *= 2.0; 151 axes.minor *= 2.0; 152 f2 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels); 153 154 if (f1 > f2) { 155 params[7] = PS_MIN (3.0, PS_MAX (0.5, log(2.0*(f1/f2) - 1.0) / log(2.0))); 156 } else { 157 params[7] = 0.5; 158 } 159 # endif 160 161 params[7] = 1.8; 162 params[8] = 0.1; 163 164 165 return(true); 166 } 167 168 psF64 PM_MODEL_FLUX (const psVector *params) 169 { 170 float f, norm, z; 171 172 psF32 *PAR = params->data.F32; 173 174 psF64 A1 = PS_SQR(PAR[4]); 175 psF64 A2 = PS_SQR(PAR[5]); 176 psF64 A3 = PS_SQR(PAR[6]); 177 psF64 Area = 2.0 * M_PI / sqrt(A1*A2 - A3); 178 // Area is equivalent to 2 pi sigma^2 179 180 // the area needs to be multiplied by the integral of f(z) 181 norm = 0.0; 182 for (z = 0.005; z < 50; z += 0.01) { 183 psF32 pr = PAR[8]*z; 184 f = 1.0 / (1 + pow(z, PAR[7]) + PS_SQR(PS_SQR(pr))); 185 norm += f; 186 } 187 norm *= 0.01; 188 189 psF64 Flux = PAR[1] * Area * norm; 190 191 return(Flux); 192 } 193 194 // XXX need to define the radius along the major axis 195 // define this function so it never returns Inf or NaN 196 // return the radius which yields the requested flux 197 psF64 PM_MODEL_RADIUS (const psVector *params, psF64 flux) 198 { 199 psF64 r, z = 0.0, pr, f; 200 psF32 *PAR = params->data.F32; 201 202 psEllipseAxes axes; 203 psEllipseShape shape; 204 205 if (flux <= 0) 206 return (1.0); 207 if (PAR[1] <= 0) 208 return (1.0); 209 if (flux >= PAR[1]) 210 return (1.0); 211 212 // convert Sx,Sy,Sxy to major/minor axes 213 shape.sx = 1.0 / PAR[4]; 214 shape.sy = 1.0 / PAR[5]; 215 shape.sxy = PAR[6]; 216 217 axes = psEllipseShapeToAxes (shape); 218 psF64 dr = 1.0 / axes.major; 219 psF64 limit = flux / PAR[1]; 220 221 // XXX : we can do this faster with an intelligent starting choice 222 for (r = 0.0; r < 20.0; r += dr) { 223 z = PS_SQR(r); 224 pr = PAR[8]*z; 225 f = 1.0 / (1 + pow(z, PAR[7]) + PS_SQR(PS_SQR(pr))); 226 if (f < limit) 227 break; 228 } 229 psF64 radius = 2.0 * axes.major * sqrt (z); 230 if (isnan(radius)) { 231 fprintf (stderr, "error in code\n"); 232 } 233 return (radius); 234 } 235 236 bool PM_MODEL_FROM_PSF (pmModel *modelPSF, pmModel *modelFLT, pmPSF *psf) 237 { 238 239 psF32 *out = modelPSF->params->data.F32; 240 psF32 *in = modelFLT->params->data.F32; 241 242 out[0] = in[0]; 243 out[1] = in[1]; 244 out[2] = in[2]; 245 out[3] = in[3]; 246 247 for (int i = 4; i < 9; i++) { 248 psPolynomial2D *poly = psf->params->data[i-4]; 249 // XXX: Verify this (from EAM change) 250 //out[i] = Polynomial2DEval_EAM(poly, out[2], out[3]); 251 out[i] = psPolynomial2DEval(poly, out[2], out[3]); 252 } 253 return(true); 254 } 255 256 bool PM_MODEL_FIT_STATUS (pmModel *model) 257 { 258 259 psF32 dP; 260 bool status; 261 psEllipseAxes axes; 262 psEllipseShape shape; 263 264 psF32 *PAR = model->params->data.F32; 265 psF32 *dPAR = model->dparams->data.F32; 266 267 shape.sx = 1.0 / PAR[4]; 268 shape.sy = 1.0 / PAR[5]; 269 shape.sxy = PAR[6]; 270 271 axes = psEllipseShapeToAxes (shape); 272 273 dP = 0; 274 dP += PS_SQR(dPAR[4] / PAR[4]); 275 dP += PS_SQR(dPAR[5] / PAR[5]); 276 dP += PS_SQR(dPAR[7] / PAR[7]); 277 dP = sqrt (dP); 278 279 status = true; 280 status &= (dP < 0.5); 281 status &= (PAR[1] > 0); 282 status &= ((dPAR[1]/PAR[1]) < 0.5); 283 status &= (fabs(PAR[8]) < 0.5); 284 status &= (dPAR[8] < 0.1); 285 status &= (axes.major > 1.41); 286 status &= (axes.minor > 1.41); 287 status &= ((axes.major / axes.minor) < 5.0); 288 status &= (PAR[7] > 0.5); 289 290 if (status) 291 return true; 292 return false; 101 293 } 102 294 … … 142 334 } 143 335 144 bool pmModelGuess_SGAUSS (pmModel *model, pmSource *source) 336 // XXX EAM : test version using flux contours to guess slope 337 bool PM_MODEL_GUESS_HARD (pmModel *model, pmSource *source) 145 338 { 146 339 … … 148 341 pmPeak *peak = source->peak; 149 342 psF32 *params = model->params->data.F32; 343 float f1, f2; 150 344 151 345 psEllipseAxes axes; … … 169 363 params[6] = shape.sxy; 170 364 171 # if (0) 172 173 f1 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels); 365 f1 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels); 174 366 axes.major *= 2.0; 175 367 axes.minor *= 2.0; … … 181 373 params[7] = 0.5; 182 374 } 183 # endif184 185 params[7] = 1.8;186 375 params[8] = 0.1; 187 376 188 189 377 return(true); 190 378 } 191 379 192 // XXX EAM : test version using flux contours to guess slope 193 bool pmModelGuess_SGAUSS_HARD (pmModel *model, pmSource *source) 194 { 195 196 pmMoments *sMoments = source->moments; 197 pmPeak *peak = source->peak; 198 psF32 *params = model->params->data.F32; 199 float f1, f2; 200 201 psEllipseAxes axes; 202 psEllipseShape shape; 203 psEllipseMoments moments; 204 205 moments.x2 = PS_SQR(sMoments->Sx); 206 moments.y2 = PS_SQR(sMoments->Sy); 207 moments.xy = sMoments->Sxy; 208 209 // solve the math to go from Moments To Shape 210 axes = psEllipseMomentsToAxes(moments); 211 shape = psEllipseAxesToShape(axes); 212 213 params[0] = sMoments->Sky; 214 params[1] = sMoments->Peak - sMoments->Sky; 215 params[2] = peak->x; 216 params[3] = peak->y; 217 params[4] = 1.0 / shape.sx; 218 params[5] = 1.0 / shape.sy; 219 params[6] = shape.sxy; 220 221 f1 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels); 222 axes.major *= 2.0; 223 axes.minor *= 2.0; 224 f2 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels); 225 226 if (f1 > f2) { 227 params[7] = PS_MIN (3.0, PS_MAX (0.5, log(2.0*(f1/f2) - 1.0) / log(2.0))); 228 } else { 229 params[7] = 0.5; 230 } 231 params[8] = 0.1; 232 233 return(true); 234 } 235 236 psF64 pmModelFlux_SGAUSS(const psVector *params) 237 { 238 float f, norm, z; 239 240 psF32 *PAR = params->data.F32; 241 242 psF64 A1 = PS_SQR(PAR[4]); 243 psF64 A2 = PS_SQR(PAR[5]); 244 psF64 A3 = PS_SQR(PAR[6]); 245 psF64 Area = 2.0 * M_PI / sqrt(A1*A2 - A3); 246 // Area is equivalent to 2 pi sigma^2 247 248 // the area needs to be multiplied by the integral of f(z) 249 norm = 0.0; 250 for (z = 0.005; z < 50; z += 0.01) { 251 psF32 pr = PAR[8]*z; 252 f = 1.0 / (1 + pow(z, PAR[7]) + SQ(SQ(pr))); 253 norm += f; 254 } 255 norm *= 0.01; 256 257 psF64 Flux = PAR[1] * Area * norm; 258 259 return(Flux); 260 } 261 262 // XXX need to define the radius along the major axis 263 // define this function so it never returns Inf or NaN 264 // return the radius which yields the requested flux 265 psF64 pmModelRadius_SGAUSS (const psVector *params, psF64 flux) 266 { 267 psF64 r, z = 0.0, pr, f; 268 psF32 *PAR = params->data.F32; 269 270 psEllipseAxes axes; 271 psEllipseShape shape; 272 273 if (flux <= 0) 274 return (1.0); 275 if (PAR[1] <= 0) 276 return (1.0); 277 if (flux >= PAR[1]) 278 return (1.0); 279 280 // convert Sx,Sy,Sxy to major/minor axes 281 shape.sx = 1.0 / PAR[4]; 282 shape.sy = 1.0 / PAR[5]; 283 shape.sxy = PAR[6]; 284 285 axes = psEllipseShapeToAxes (shape); 286 psF64 dr = 1.0 / axes.major; 287 psF64 limit = flux / PAR[1]; 288 289 // XXX : we can do this faster with an intelligent starting choice 290 for (r = 0.0; r < 20.0; r += dr) { 291 z = SQ(r); 292 pr = PAR[8]*z; 293 f = 1.0 / (1 + pow(z, PAR[7]) + SQ(SQ(pr))); 294 if (f < limit) 295 break; 296 } 297 psF64 radius = 2.0 * axes.major * sqrt (z); 298 if (isnan(radius)) { 299 fprintf (stderr, "error in code\n"); 300 } 301 return (radius); 302 } 303 304 bool pmModelFromPSF_SGAUSS (pmModel *modelPSF, pmModel *modelFLT, pmPSF *psf) 305 { 306 307 psF32 *out = modelPSF->params->data.F32; 308 psF32 *in = modelFLT->params->data.F32; 309 310 out[0] = in[0]; 311 out[1] = in[1]; 312 out[2] = in[2]; 313 out[3] = in[3]; 314 315 for (int i = 4; i < 9; i++) { 316 psPolynomial2D *poly = psf->params->data[i-4]; 317 // XXX: Verify this (from EAM change) 318 //out[i] = Polynomial2DEval_EAM(poly, out[2], out[3]); 319 out[i] = psPolynomial2DEval(poly, out[2], out[3]); 320 } 321 return(true); 322 } 323 324 bool pmModelFitStatus_SGAUSS (pmModel *model) 325 { 326 327 psF32 dP; 328 bool status; 329 psEllipseAxes axes; 330 psEllipseShape shape; 331 332 psF32 *PAR = model->params->data.F32; 333 psF32 *dPAR = model->dparams->data.F32; 334 335 shape.sx = 1.0 / PAR[4]; 336 shape.sy = 1.0 / PAR[5]; 337 shape.sxy = PAR[6]; 338 339 axes = psEllipseShapeToAxes (shape); 340 341 dP = 0; 342 dP += PS_SQR(dPAR[4] / PAR[4]); 343 dP += PS_SQR(dPAR[5] / PAR[5]); 344 dP += PS_SQR(dPAR[7] / PAR[7]); 345 dP = sqrt (dP); 346 347 status = true; 348 status &= (dP < 0.5); 349 status &= (PAR[1] > 0); 350 status &= ((dPAR[1]/PAR[1]) < 0.5); 351 status &= (fabs(PAR[8]) < 0.5); 352 status &= (dPAR[8] < 0.1); 353 status &= (axes.major > 1.41); 354 status &= (axes.minor > 1.41); 355 status &= ((axes.major / axes.minor) < 5.0); 356 status &= (PAR[7] > 0.5); 357 358 if (status) 359 return true; 360 return false; 361 } 380 # undef PM_MODEL_FUNC 381 # undef PM_MODEL_FLUX 382 # undef PM_MODEL_GUESS 383 # undef PM_MODEL_LIMITS 384 # undef PM_MODEL_RADIUS 385 # undef PM_MODEL_FROM_PSF 386 # undef PM_MODEL_FIT_STATUS
Note:
See TracChangeset
for help on using the changeset viewer.
