Changeset 36085 for trunk/psModules/src/objects/models/pmModel_SERSIC.c
- Timestamp:
- Aug 31, 2013, 5:55:16 AM (13 years ago)
- Location:
- trunk/psModules
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
src/objects/models/pmModel_SERSIC.c (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules
- Property svn:mergeinfo changed
/branches/eam_branches/ipp-20130711/psModules (added) merged: 35843,35876,35947-35948,35961-35963,35966-35967,36021,36024,36027,36066-36069,36075
- Property svn:mergeinfo changed
-
trunk/psModules/src/objects/models/pmModel_SERSIC.c
r35768 r36085 20 20 * note that a Sersic model is usually defined in terms of R_e, the half-light radius. This 21 21 construction does not include a factor of 2 in the X^2 term, etc, like for a Gaussian. 22 Conversion from SXX, SYY, SXY to R_major, R_minor, theta can be done by using setting:22 Conversion from SXX, SYY, SXY to R_major, R_minor, theta can be done by using: 23 23 shape.sx = SXX / sqrt(2), shape.sy = SYY / sqrt(2), shape.sxy = SXY, then calling 24 24 psEllipseShapeToAxes, and multiplying the values of axes.major, axes.minor by sqrt(2) … … 55 55 #include "pmPSFtry.h" 56 56 #include "pmDetections.h" 57 #include "pmModel_CentralPixel.h" 57 58 58 59 #include "pmModel_SERSIC.h" … … 74 75 75 76 // Lax parameter limits 76 static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.001, 0.001, -1.0, 0. 05};77 static float paramsMaxLax[] = { 1.0e5, 1.0e 8, 1.0e4, 1.0e4, 100, 100, 1.0, 4.0 };77 static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.001, 0.001, -1.0, 0.1 }; 78 static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 1.0 }; 78 79 79 80 // Moderate parameter limits … … 88 89 static float *paramsMinUse = paramsMinLax; 89 90 static float *paramsMaxUse = paramsMaxLax; 90 static float betaUse[] = { 1000, 3e6, 5, 5, 1.0, 1.0, 0.5, 2.0};91 static float betaUse[] = { 2, 3e6, 5, 5, 10.0, 10.0, 0.5, 1.0}; 91 92 92 93 static bool limitsApply = true; // Apply limits? 93 94 94 # include "pmModel_SERSIC.CP.h"95 // # include "pmModel_SERSIC.CP.h" 95 96 96 97 psF32 PM_MODEL_FUNC (psVector *deriv, … … 111 112 psAssert (z >= 0, "do not allow negative z values in model"); 112 113 113 float index = 0.5 / PAR[PM_PAR_7];114 float par7 = PAR[PM_PAR_7];115 float bn = 1.9992*index - 0.3271; 116 float Io = exp(bn);117 118 psF32 f2 = bn*pow(z,par7); 119 psF32 f1 = Io*exp(-f2);114 float Sindex = 0.5 / PAR[PM_PAR_7]; 115 float kappa = pmSersicKappa (Sindex); 116 117 float q = kappa*pow(z,PAR[PM_PAR_7]); 118 psF32 f0 = exp(-q); 119 120 assert (isfinite(q)); 120 121 121 122 psF32 radius = hypot(X, Y); 122 if (radius < 1.0) { 123 124 // ** use bilinear interpolation to the given location from the 4 surrounding pixels centered on the object center 125 126 // first, use Rmajor and index to find the central pixel flux (fraction of total flux) 127 psEllipseAxes axes; 128 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 129 130 // get the central pixel flux from the lookup table 131 float xPix = (axes.major - centralPixelXo) / centralPixeldX; 132 xPix = PS_MIN (PS_MAX(xPix, 0), centralPixelNX - 1); 133 float yPix = (index - centralPixelYo) / centralPixeldY; 134 yPix = PS_MIN (PS_MAX(yPix, 0), centralPixelNY - 1); 135 136 // the integral of a Sersic has an analytical form as follows: 137 float logGamma = lgamma(2.0*index); 138 float bnFactor = pow(bn, 2.0*index); 139 float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor; 140 141 // XXX interpolate to get the value 142 // XXX for the moment, just integerize 143 // XXX I need to multiply by the integrated flux to get the flux in the central pixel 144 float Vcenter = centralPixel[(int)yPix][(int)xPix] * norm; 145 146 float px1 = 1.0 / PAR[PM_PAR_SXX]; 147 float py1 = 1.0 / PAR[PM_PAR_SYY]; 148 float z10 = PS_SQR(px1); 149 float z01 = PS_SQR(py1); 150 151 // which pixels do we need for this interpolation? 152 // (I do not keep state information, so I don't know anything about other evaluations of nearby pixels...) 153 if ((X >= 0) && (Y >= 0)) { 154 float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive 155 float V00 = Vcenter; 156 float V10 = Io*exp(-bn*pow(z10,par7)); 157 float V01 = Io*exp(-bn*pow(z01,par7)); 158 float V11 = Io*exp(-bn*pow(z11,par7)); 159 f1 = interpolatePixels(V00, V10, V01, V11, X, Y); 160 } 161 if ((X < 0) && (Y >= 0)) { 162 float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative 163 float V00 = Io*exp(-bn*pow(z10,par7)); 164 float V10 = Vcenter; 165 float V01 = Io*exp(-bn*pow(z11,par7)); 166 float V11 = Io*exp(-bn*pow(z01,par7)); 167 f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), Y); 168 } 169 if ((X >= 0) && (Y < 0)) { 170 float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative 171 float V00 = Io*exp(-bn*pow(z01,par7)); 172 float V10 = Io*exp(-bn*pow(z11,par7)); 173 float V01 = Vcenter; 174 float V11 = Io*exp(-bn*pow(z10,par7)); 175 f1 = interpolatePixels(V00, V10, V01, V11, X, (1.0 + Y)); 176 } 177 if ((X < 0) && (Y < 0)) { 178 float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive 179 float V00 = Io*exp(-bn*pow(z11,par7)); 180 float V10 = Io*exp(-bn*pow(z10,par7)); 181 float V01 = Io*exp(-bn*pow(z01,par7)); 182 float V11 = Vcenter; 183 f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), (1.0 + Y)); 184 } 185 } 186 187 psF32 z0 = PAR[PM_PAR_I0]*f1; 188 psF32 f0 = PAR[PM_PAR_SKY] + z0; 189 190 if (!isfinite(z0)) { 191 fprintf(stderr, "z0 is not finite for %f %f %f %f %f. Parameters: \n", X, Y, radius, z, f1); 123 if (radius <= 1.5) { 124 // Nsub ~ 10*index^2 + 1 125 psEllipseAxes axes = pmPSF_ModelToAxes(PAR, pmModelClassGetType ("PS_MODEL_SERSIC")); 126 int Nsub = 2 * ((int)(6.0*Sindex / axes.minor)) + 1; 127 Nsub = PS_MIN (Nsub, 121); 128 Nsub = PS_MAX (Nsub, 11); 129 f0 = pmModelCP_SersicSubpix (X, Y, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], Sindex, Nsub); 130 } 131 if (!isfinite(f0)) { 132 fprintf(stderr, "f0 is not finite for %f %f %f %f %f. Parameters: \n", X, Y, radius, z, q); 192 133 fprintf(stderr, "%f %f %f %f %f %f %f %f\n", PAR[0], PAR[1], PAR[2], PAR[3], PAR[4], 193 134 PAR[5], PAR[6], PAR[7]); 194 135 } 195 196 assert (isfinite(f2)); 136 assert (isfinite(f0)); 137 138 psF32 f1 = PAR[PM_PAR_I0]*f0; 139 psF32 f = PAR[PM_PAR_SKY] + f1; 140 197 141 assert (isfinite(f1)); 198 assert (isfinite(z0)); 199 assert (isfinite(f0)); 142 assert (isfinite(f)); 200 143 201 144 if (deriv != NULL) { … … 203 146 204 147 dPAR[PM_PAR_SKY] = +1.0; 205 dPAR[PM_PAR_I0] = +f1; 206 207 // gradient is infinite for z = 0; saturate at z = 0.01 208 psF32 z1 = (z < 0.01) ? z0*bn*par7*pow(0.01,par7 - 1.0) : z0*bn*par7*pow(z,par7 - 1.0); 209 210 dPAR[PM_PAR_7] = (z < 0.01) ? -z0*pow(0.01,par7)*log(0.01) : -z0*f2*log(z); 211 dPAR[PM_PAR_7] *= 3.0; 212 213 assert (isfinite(z1)); 148 dPAR[PM_PAR_I0] = +f0; 149 150 if (z > 0.01) { 151 float z1 = f1*kappa*PAR[PM_PAR_7]*pow(z,PAR[PM_PAR_7]-1.0); 152 dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px + Y*PAR[PM_PAR_SXY]); 153 dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py + X*PAR[PM_PAR_SXY]); 154 dPAR[PM_PAR_SXX] = +2.0*z1*px*px/PAR[PM_PAR_SXX]; 155 dPAR[PM_PAR_SYY] = +2.0*z1*py*py/PAR[PM_PAR_SYY]; 156 dPAR[PM_PAR_SXY] = -1.0*z1*X*Y; 157 dPAR[PM_PAR_7] = -1.0*f1*q*log(z); 158 } else { 159 // gradient -> 0 for z -> 0, but has undef form 160 float z1 = f1*kappa*PAR[PM_PAR_7]*pow(z,PAR[PM_PAR_7]); 161 dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SXX] + PAR[PM_PAR_SXY]); 162 dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SYY] + PAR[PM_PAR_SXY]); 163 dPAR[PM_PAR_SXX] = +2.0*z1*px/PAR[PM_PAR_SXX]/PAR[PM_PAR_SXX]; 164 dPAR[PM_PAR_SYY] = +2.0*z1*py/PAR[PM_PAR_SYY]/PAR[PM_PAR_SYY]; 165 dPAR[PM_PAR_SXY] = -1.0*z1; 166 // dPAR[PM_PAR_7] = -1.0*f1*q*log(z + 0.0001); 167 dPAR[PM_PAR_7] = -1.0*f1*q*log(z + 0.0001); // factor of 16 to reduce the gain 168 } 214 169 assert (isfinite(dPAR[PM_PAR_7])); 215 216 dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]); 217 dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]); 218 dPAR[PM_PAR_SXX] = +2.0*z1*px*px/PAR[PM_PAR_SXX]; // XXX : increase drag? 219 dPAR[PM_PAR_SYY] = +2.0*z1*py*py/PAR[PM_PAR_SYY]; 220 dPAR[PM_PAR_SXY] = -1.0*z1*X*Y; 221 } 222 return (f0); 170 } 171 return (f); 223 172 } 224 173 … … 370 319 psEllipseAxes axes; 371 320 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 372 float AspectRatio = axes.minor / axes.major; 373 374 float index = 0.5 / PAR[PM_PAR_7]; 375 float bn = 1.9992*index - 0.3271; 376 377 // the integral of a Sersic has an analytical form as follows: 378 float logGamma = lgamma(2.0*index); 379 float bnFactor = pow(bn, 2.0*index); 380 float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor; 381 382 psF64 Flux = PAR[PM_PAR_I0] * norm * AspectRatio; 383 384 return(Flux); 321 322 float Sindex = 0.5 / PAR[PM_PAR_7]; 323 float norm = pmSersicNorm (Sindex); 324 325 float flux = PAR[PM_PAR_I0] * 2.0 * M_PI * axes.major * axes.minor * norm; 326 327 return(flux); 385 328 } 386 329 … … 401 344 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 402 345 346 float Sindex = 0.5 / PAR[PM_PAR_7]; 347 float kappa = pmSersicKappa (Sindex); 348 403 349 // f = Io exp(-z^n) -> z^n = ln(Io/f) 404 psF64 zn = log(PAR[PM_PAR_I0] / flux) ;405 psF64 radius = axes.major * sqrt (2.0) * pow(zn, 0.5 / PAR[PM_PAR_7]);350 psF64 zn = log(PAR[PM_PAR_I0] / flux) / kappa; 351 psF64 radius = axes.major * pow(zn, Sindex); 406 352 407 353 psAssert (isfinite(radius), "fix this code: radius should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f), par 7 = %f",
Note:
See TracChangeset
for help on using the changeset viewer.
