Changeset 36680 for branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_EXP.c
- Timestamp:
- Apr 21, 2014, 5:42:34 AM (12 years ago)
- Location:
- branches/eam_branches/ps2-tc3-20130727
- Files:
-
- 4 edited
-
. (modified) (1 prop)
-
psModules (modified) (1 prop)
-
psModules/src/objects (modified) (1 prop)
-
psModules/src/objects/models/pmModel_EXP.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ps2-tc3-20130727
- Property svn:mergeinfo changed
-
branches/eam_branches/ps2-tc3-20130727/psModules
- Property svn:mergeinfo deleted
-
branches/eam_branches/ps2-tc3-20130727/psModules/src/objects
- Property svn:ignore
-
old new 12 12 pmSourceIO_CMF_PS1_V1.v1.c 13 13 pmSourceIO_CMF_PS1_V4.c 14 pmSourceIO_CMF_PS1_V5.c 14 15 pmSourceIO_CMF_PS1_SV1.c 15 16 pmSourceIO_CMF_PS1_SV2.c
-
- Property svn:ignore
-
branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_EXP.c
r35768 r36680 40 40 #include "pmSourceDiffStats.h" 41 41 #include "pmSourceSatstar.h" 42 #include "pmSourceLensing.h" 42 43 #include "pmSource.h" 43 44 #include "pmSourceFitModel.h" … … 45 46 #include "pmPSFtry.h" 46 47 #include "pmDetections.h" 48 #include "pmModel_CentralPixel.h" 47 49 48 50 #include "pmModel_EXP.h" … … 62 64 // 0.5 PIX: the parameters are defined in terms of pixel coords, so the incoming pixcoords 63 65 // values need to be pixel coords 66 // 67 68 // Notes on changing kappa value from 1.70056 to 1.678 69 // I'm using a functional form f(x,y) = Io exp(-kappa (r / r_e)). 70 // The article by Graham & Driver (2005) uses a form Ie exp(-bn [(r / r_e) -1]) 71 // which is equal to Ie exp(-bn (r / r_e)) exp(bn). 72 // Thus, my Io = Ie exp(bn) and my kappa is their bn. 73 // My value of kappa is 1.700, their value for bn is 1.678., so I am off by a small amount there (1.5%). 74 75 76 #define KAPPA_EXP 1.678 77 #define OLD_KAPP_EXP 1.70056 78 64 79 65 80 // Lax parameter limits 66 81 static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.05, 0.05, -1.0 }; 67 static float paramsMaxLax[] = { 1.0e5, 1.0e 8, 1.0e4, 1.0e4, 100, 100, 1.0 };82 static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0 }; 68 83 69 84 // Moderate parameter limits … … 78 93 static float *paramsMinUse = paramsMinLax; 79 94 static float *paramsMaxUse = paramsMaxLax; 80 static float betaUse[] = { 1000, 3e6, 5, 5, 1.0, 1.0, 0.5};95 static float betaUse[] = { 2, 3e6, 5, 5, 10.0, 10.0, 0.5}; 81 96 82 97 static bool limitsApply = true; // Apply limits? 83 98 84 # include "pmModel_SERSIC.CP.h" 99 // # include "pmModel_SERSIC.CP.h" 100 101 // the problems I'm having with the SERSIC-like functions are: 102 // 1) making sure I have the right functional form so that PAR[SXX,etc] represent R_eff (half-light radius) 103 // 2) getting the central pixel right 104 // 3) getting the derivaties right. 85 105 86 106 psF32 PM_MODEL_FUNC (psVector *deriv, … … 101 121 psAssert (z >= 0, "do not allow negative z values in model"); 102 122 103 float index = 1.0; 104 float par7 = 0.5; 105 float bn = 1.9992*index - 0.3271; 106 float Io = exp(bn); 107 108 psF32 f2 = bn*sqrt(z); 109 psF32 f1 = Io*exp(-f2); 110 123 // for EXP, we can hard-wire kappa(1): 124 // float index = 1.0; 125 float kappa = KAPPA_EXP; 126 127 // sqrt(z) is r 128 float q = kappa*sqrt(z); 129 psF32 f0 = exp(-q); 130 131 assert (isfinite(q)); 132 133 // only worry about the central 4 pixels at most 111 134 psF32 radius = hypot(X, Y); 112 if (radius < 1.0) { 113 114 // ** use bilinear interpolation to the given location from the 4 surrounding pixels centered on the object center 115 116 // first, use Rmajor and index to find the central pixel flux (fraction of total flux) 117 psEllipseAxes axes; 118 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 119 120 // get the central pixel flux from the lookup table 121 float xPix = (axes.major - centralPixelXo) / centralPixeldX; 122 xPix = PS_MIN (PS_MAX(xPix, 0), centralPixelNX - 1); 123 float yPix = (index - centralPixelYo) / centralPixeldY; 124 yPix = PS_MIN (PS_MAX(yPix, 0), centralPixelNY - 1); 125 126 // the integral of a Sersic has an analytical form as follows: 127 float logGamma = lgamma(2.0*index); 128 float bnFactor = pow(bn, 2.0*index); 129 float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor; 130 131 // XXX interpolate to get the value 132 // XXX for the moment, just integerize 133 // XXX I need to multiply by the integrated flux to get the flux in the central pixel 134 float Vcenter = centralPixel[(int)yPix][(int)xPix] * norm; 135 136 float px1 = 1.0 / PAR[PM_PAR_SXX]; 137 float py1 = 1.0 / PAR[PM_PAR_SYY]; 138 float z10 = PS_SQR(px1); 139 float z01 = PS_SQR(py1); 140 141 // which pixels do we need for this interpolation? 142 // (I do not keep state information, so I don't know anything about other evaluations of nearby pixels...) 143 if ((X >= 0) && (Y >= 0)) { 144 float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive 145 float V00 = Vcenter; 146 float V10 = Io*exp(-bn*pow(z10,par7)); 147 float V01 = Io*exp(-bn*pow(z01,par7)); 148 float V11 = Io*exp(-bn*pow(z11,par7)); 149 f1 = interpolatePixels(V00, V10, V01, V11, X, Y); 150 } 151 if ((X < 0) && (Y >= 0)) { 152 float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative 153 float V00 = Io*exp(-bn*pow(z10,par7)); 154 float V10 = Vcenter; 155 float V01 = Io*exp(-bn*pow(z11,par7)); 156 float V11 = Io*exp(-bn*pow(z01,par7)); 157 f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), Y); 158 } 159 if ((X >= 0) && (Y < 0)) { 160 float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative 161 float V00 = Io*exp(-bn*pow(z01,par7)); 162 float V10 = Io*exp(-bn*pow(z11,par7)); 163 float V01 = Vcenter; 164 float V11 = Io*exp(-bn*pow(z10,par7)); 165 f1 = interpolatePixels(V00, V10, V01, V11, X, (1.0 + Y)); 166 } 167 if ((X < 0) && (Y < 0)) { 168 float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive 169 float V00 = Io*exp(-bn*pow(z11,par7)); 170 float V10 = Io*exp(-bn*pow(z10,par7)); 171 float V01 = Io*exp(-bn*pow(z01,par7)); 172 float V11 = Vcenter; 173 f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), (1.0 + Y)); 174 } 175 } 176 177 psF32 z0 = PAR[PM_PAR_I0]*f1; 178 psF32 f0 = PAR[PM_PAR_SKY] + z0; 179 180 assert (isfinite(f2)); 135 if (radius <= 1.5) { 136 f0 = pmModelCP_SersicSubpix (X, Y, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], 1.0, 51); 137 } 138 assert (isfinite(f0)); 139 140 psF32 f1 = PAR[PM_PAR_I0]*f0; 141 psF32 f = PAR[PM_PAR_SKY] + f1; 142 181 143 assert (isfinite(f1)); 182 assert (isfinite(z0)); 183 assert (isfinite(f0)); 144 assert (isfinite(f)); 184 145 185 146 if (deriv != NULL) { … … 187 148 188 149 dPAR[PM_PAR_SKY] = +1.0; 189 dPAR[PM_PAR_I0] = +f1; 190 191 // gradient is infinite for z = 0; saturate at z = 0.01 192 // z1 is -df/dz (the negative sign is canceled by most of dz/dPAR[i] 193 psF32 z1 = (z < 0.01) ? 0.5*bn*z0/sqrt(0.01) : 0.5*bn*z0/sqrt(z); 194 195 // XXX dampen SXX and SYY as in GAUSS? 196 dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]); 197 dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]); 198 dPAR[PM_PAR_SXX] = +2.0*z1*px*px/PAR[PM_PAR_SXX]; 199 dPAR[PM_PAR_SYY] = +2.0*z1*py*py/PAR[PM_PAR_SYY]; 200 dPAR[PM_PAR_SXY] = -1.0*z1*X*Y; 201 } 202 return (f0); 150 dPAR[PM_PAR_I0] = +f0; 151 152 if (z > 0.01) { 153 float z1 = 0.5*f1*kappa/sqrt(z); 154 dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px + Y*PAR[PM_PAR_SXY]); 155 dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py + X*PAR[PM_PAR_SXY]); 156 dPAR[PM_PAR_SXX] = +2.0*z1*px*px/PAR[PM_PAR_SXX]; 157 dPAR[PM_PAR_SYY] = +2.0*z1*py*py/PAR[PM_PAR_SYY]; 158 dPAR[PM_PAR_SXY] = -1.0*z1*X*Y; 159 } else { 160 // gradient -> 0 for z -> 0, but has undef form 161 float z1 = 0.5*f1*kappa; 162 dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SXX] + PAR[PM_PAR_SXY]); 163 dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SYY] + PAR[PM_PAR_SXY]); 164 dPAR[PM_PAR_SXX] = +2.0*z1*px/PAR[PM_PAR_SXX]/PAR[PM_PAR_SXX]; 165 dPAR[PM_PAR_SYY] = +2.0*z1*py/PAR[PM_PAR_SYY]/PAR[PM_PAR_SYY]; 166 dPAR[PM_PAR_SXY] = -1.0*z1; 167 } 168 } 169 return (f); 203 170 } 204 171 … … 284 251 bool PM_MODEL_GUESS (pmModel *model, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal) 285 252 { 253 // for the moment, we are going to require moments and KronFlux 254 if (!source->moments) return false; 255 pmMoments *moments = source->moments; 256 257 if (!isfinite(moments->KronFlux)) return false; 258 if (!isfinite(moments->Mrf)) return false; 259 if (moments->Mrf < 0.0) return false; 260 286 261 psF32 *PAR = model->params->data.F32; 287 262 … … 289 264 PAR[PM_PAR_SKY] = 0.0; 290 265 291 // set the shape parameters 292 if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments, true)) { 293 return false; 294 } 295 296 // set the model normalization 297 if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) { 298 return false; 299 } 266 psEllipseMoments emoments; 267 emoments.x2 = moments->Mxx; 268 emoments.xy = moments->Mxy; 269 emoments.y2 = moments->Myy; 270 271 // force the axis ratio to be < 20.0 272 psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0); 273 274 if (!isfinite(axes.major)) return false; 275 if (!isfinite(axes.minor)) return false; 276 if (!isfinite(axes.theta)) return false; 277 278 // Mxx, Mxy, Myy define the elliptical shape, but Mrf defines the width 279 float scale = moments->Mrf / axes.major; 280 axes.major *= scale; 281 axes.minor *= scale; 282 283 pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], axes, true); 284 285 // psEllipseAxes axes; 286 // use the code in SetShape here to avoid doing this 2x 287 // pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 288 289 // float norm = pmSersicNorm (4); // hardwire 290 float norm = 0.34578; 291 float normFlux = 2.0 * M_PI * axes.major * axes.minor * norm; 292 PAR[PM_PAR_I0] = moments->KronFlux / normFlux; 300 293 301 294 // set the model position … … 306 299 return(true); 307 300 } 308 309 301 // An exponential model is equivalent to a Sersic with index = 1.0 310 302 psF64 PM_MODEL_FLUX (const psVector *params) … … 314 306 psEllipseAxes axes; 315 307 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 316 float AspectRatio = axes.minor / axes.major; 317 318 float index = 1.0; 319 float bn = 1.9992*index - 0.3271; 320 321 // the integral of a Sersic has an analytical form as follows: 322 float logGamma = lgamma(2.0*index); 323 float bnFactor = pow(bn, 2.0*index); 324 float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor; 325 326 psF64 Flux = PAR[PM_PAR_I0] * norm * AspectRatio; 327 328 return(Flux); 308 309 // static value for EXP: 310 float norm = 0.34578; // \int exp(-kappa*sqrt(z)) r dr 311 312 float flux = PAR[PM_PAR_I0] * 2.0 * M_PI * axes.major * axes.minor * norm; 313 314 return(flux); 329 315 } 330 316 … … 345 331 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 346 332 347 // f = Io exp(-sqrt(z)) -> sqrt(z) = ln(Io/f) 348 psF64 zn = log(PAR[PM_PAR_I0] / flux); 349 psF64 radius = axes.major * sqrt (2.0) * zn; 333 // static value for EXP: 334 float kappa = KAPPA_EXP; 335 336 // f = Io exp(-kappa*sqrt(z)) -> sqrt(z) = ln(Io/f) / kappa 337 psF64 zn = log(PAR[PM_PAR_I0] / flux) / kappa; 338 psF64 radius = axes.major * zn; 350 339 351 340 psAssert (isfinite(radius), "fix this code: radius should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)", … … 501 490 return; 502 491 } 492 493 # if (0) 494 void bilin_inter_function () { 495 // first, use Rmajor and index to find the central pixel flux (fraction of total flux) 496 psEllipseAxes axes; 497 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 498 499 // get the central pixel flux from the lookup table 500 float xPix = (axes.major - centralPixelXo) / centralPixeldX; 501 xPix = PS_MIN (PS_MAX(xPix, 0), centralPixelNX - 1); 502 float yPix = (index - centralPixelYo) / centralPixeldY; 503 yPix = PS_MIN (PS_MAX(yPix, 0), centralPixelNY - 1); 504 505 // the integral of a Sersic has an analytical form as follows: 506 float logGamma = lgamma(2.0*index); 507 float bnFactor = pow(bn, 2.0*index); 508 float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor; 509 510 // XXX interpolate to get the value 511 // XXX for the moment, just integerize 512 // XXX I need to multiply by the integrated flux to get the flux in the central pixel 513 float Vcenter = centralPixel[(int)yPix][(int)xPix] * norm; 514 515 float px1 = 1.0 / PAR[PM_PAR_SXX]; 516 float py1 = 1.0 / PAR[PM_PAR_SYY]; 517 float z10 = PS_SQR(px1); 518 float z01 = PS_SQR(py1); 519 520 // which pixels do we need for this interpolation? 521 // (I do not keep state information, so I don't know anything about other evaluations of nearby pixels...) 522 if ((X >= 0) && (Y >= 0)) { 523 float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive 524 float V00 = Vcenter; 525 float V10 = Io*exp(-bn*pow(z10,par7)); 526 float V01 = Io*exp(-bn*pow(z01,par7)); 527 float V11 = Io*exp(-bn*pow(z11,par7)); 528 f1 = interpolatePixels(V00, V10, V01, V11, X, Y); 529 } 530 if ((X < 0) && (Y >= 0)) { 531 float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative 532 float V00 = Io*exp(-bn*pow(z10,par7)); 533 float V10 = Vcenter; 534 float V01 = Io*exp(-bn*pow(z11,par7)); 535 float V11 = Io*exp(-bn*pow(z01,par7)); 536 f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), Y); 537 } 538 if ((X >= 0) && (Y < 0)) { 539 float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative 540 float V00 = Io*exp(-bn*pow(z01,par7)); 541 float V10 = Io*exp(-bn*pow(z11,par7)); 542 float V01 = Vcenter; 543 float V11 = Io*exp(-bn*pow(z10,par7)); 544 f1 = interpolatePixels(V00, V10, V01, V11, X, (1.0 + Y)); 545 } 546 if ((X < 0) && (Y < 0)) { 547 float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive 548 float V00 = Io*exp(-bn*pow(z11,par7)); 549 float V10 = Io*exp(-bn*pow(z10,par7)); 550 float V01 = Io*exp(-bn*pow(z01,par7)); 551 float V11 = Vcenter; 552 f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), (1.0 + Y)); 553 } 554 } 555 # endif
Note:
See TracChangeset
for help on using the changeset viewer.
