- Timestamp:
- Aug 15, 2013, 5:56:56 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20130711/psModules/src/objects/models/pmModel_EXP.c
r35876 r35961 82 82 static bool limitsApply = true; // Apply limits? 83 83 84 # include "pmModel_SERSIC.CP.h" 84 // # include "pmModel_SERSIC.CP.h" 85 86 // the problems I'm having with the SERSIC-like functions are: 87 // 1) making sure I have the right functional form so that PAR[SXX,etc] represent R_eff (half-light radius) 88 // 2) getting the central pixel right 89 // 3) getting the derivaties right. 85 90 86 91 psF32 PM_MODEL_FUNC (psVector *deriv, … … 101 106 psAssert (z >= 0, "do not allow negative z values in model"); 102 107 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 108 // for EXP, we can hard-wire kappa(1): 109 // float index = 1.0; 110 float kappa = 1.70056; 111 112 // sqrt(z) is r 113 float q = kappa*sqrt(z); 114 psF32 f0 = exp(-q); 115 116 psF32 f1 = PAR[PM_PAR_I0]*f0; 117 psF32 f = PAR[PM_PAR_SKY] + f1; 118 119 assert (isfinite(q)); 120 assert (isfinite(f0)); 121 assert (isfinite(f1)); 122 assert (isfinite(f)); 123 124 // only worry about the central 4 pixels at most 111 125 psF32 radius = hypot(X, Y); 112 126 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); 127 // subdivide the central 2,3,4 pixels by Nx,Ny 128 float Npix = 0.0; 129 float Fpix = 0.0; 130 float Xpix = floor(pixcoord->data.F32[0]) - PAR[PM_PAR_XPOS]; 131 float Ypix = floor(pixcoord->data.F32[1]) - PAR[PM_PAR_YPOS]; 132 for (float ix = 0.1; ix < 1.0; ix += 0.2) { 133 for (float iy = 0.1; iy < 1.0; iy += 0.2) { 134 psF32 X = Xpix + ix; 135 psF32 Y = Ypix + iy; 136 psF32 px = X / PAR[PM_PAR_SXX]; 137 psF32 py = Y / PAR[PM_PAR_SYY]; 138 psF32 z = PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y; 139 140 // sqrt(z) is r 141 float q = kappa*sqrt(z); 142 psF32 f0 = exp(-q); 143 144 psF32 f1 = PAR[PM_PAR_I0]*f0; 145 psF32 fx = PAR[PM_PAR_SKY] + f1; 146 Fpix += fx; 147 Npix += 1.0; 150 148 } 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)); 181 assert (isfinite(f1)); 182 assert (isfinite(z0)); 183 assert (isfinite(f0)); 149 } 150 f = Fpix / Npix; 151 } 184 152 185 153 if (deriv != NULL) { … … 187 155 188 156 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); 157 dPAR[PM_PAR_I0] = +f0; 158 159 if (z > 0.01) { 160 float z1 = 0.5*f1*kappa/sqrt(z); 161 dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px + Y*PAR[PM_PAR_SXY]); 162 dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py + X*PAR[PM_PAR_SXY]); 163 dPAR[PM_PAR_SXX] = +2.0*z1*px*px/PAR[PM_PAR_SXX]; 164 dPAR[PM_PAR_SYY] = +2.0*z1*py*py/PAR[PM_PAR_SYY]; 165 dPAR[PM_PAR_SXY] = -1.0*z1*X*Y; 166 } else { 167 // gradient -> 0 for z -> 0, but has undef form 168 float z1 = 0.5*f1*kappa; 169 dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SXX] + PAR[PM_PAR_SXY]); 170 dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SYY] + PAR[PM_PAR_SXY]); 171 dPAR[PM_PAR_SXX] = +2.0*z1*px/PAR[PM_PAR_SXX]/PAR[PM_PAR_SXX]; 172 dPAR[PM_PAR_SYY] = +2.0*z1*py/PAR[PM_PAR_SYY]/PAR[PM_PAR_SYY]; 173 dPAR[PM_PAR_SXY] = -1.0*z1; 174 } 175 } 176 return (f); 203 177 } 204 178 … … 314 288 psEllipseAxes axes; 315 289 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); 290 291 // static value for EXP: 292 float norm = 0.34578; // \int exp(-kappa*sqrt(z)) r dr 293 294 float flux = PAR[PM_PAR_I0] * 2.0 * M_PI * axes.major * axes.minor * norm; 295 296 return(flux); 329 297 } 330 298 … … 345 313 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 346 314 347 // f = Io exp(-sqrt(z)) -> sqrt(z) = ln(Io/f) 348 psF64 zn = log(PAR[PM_PAR_I0] / flux); 315 // static value for EXP: 316 float kappa = 1.70056; 317 318 // f = Io exp(-kappa*sqrt(z)) -> sqrt(z) = ln(Io/f) / kappa 319 psF64 zn = log(PAR[PM_PAR_I0] / flux) / kappa; 349 320 psF64 radius = axes.major * sqrt (2.0) * zn; 350 321 … … 501 472 return; 502 473 } 474 475 # if (0) 476 void bilin_inter_function () { 477 // first, use Rmajor and index to find the central pixel flux (fraction of total flux) 478 psEllipseAxes axes; 479 pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true); 480 481 // get the central pixel flux from the lookup table 482 float xPix = (axes.major - centralPixelXo) / centralPixeldX; 483 xPix = PS_MIN (PS_MAX(xPix, 0), centralPixelNX - 1); 484 float yPix = (index - centralPixelYo) / centralPixeldY; 485 yPix = PS_MIN (PS_MAX(yPix, 0), centralPixelNY - 1); 486 487 // the integral of a Sersic has an analytical form as follows: 488 float logGamma = lgamma(2.0*index); 489 float bnFactor = pow(bn, 2.0*index); 490 float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor; 491 492 // XXX interpolate to get the value 493 // XXX for the moment, just integerize 494 // XXX I need to multiply by the integrated flux to get the flux in the central pixel 495 float Vcenter = centralPixel[(int)yPix][(int)xPix] * norm; 496 497 float px1 = 1.0 / PAR[PM_PAR_SXX]; 498 float py1 = 1.0 / PAR[PM_PAR_SYY]; 499 float z10 = PS_SQR(px1); 500 float z01 = PS_SQR(py1); 501 502 // which pixels do we need for this interpolation? 503 // (I do not keep state information, so I don't know anything about other evaluations of nearby pixels...) 504 if ((X >= 0) && (Y >= 0)) { 505 float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive 506 float V00 = Vcenter; 507 float V10 = Io*exp(-bn*pow(z10,par7)); 508 float V01 = Io*exp(-bn*pow(z01,par7)); 509 float V11 = Io*exp(-bn*pow(z11,par7)); 510 f1 = interpolatePixels(V00, V10, V01, V11, X, Y); 511 } 512 if ((X < 0) && (Y >= 0)) { 513 float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative 514 float V00 = Io*exp(-bn*pow(z10,par7)); 515 float V10 = Vcenter; 516 float V01 = Io*exp(-bn*pow(z11,par7)); 517 float V11 = Io*exp(-bn*pow(z01,par7)); 518 f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), Y); 519 } 520 if ((X >= 0) && (Y < 0)) { 521 float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative 522 float V00 = Io*exp(-bn*pow(z01,par7)); 523 float V10 = Io*exp(-bn*pow(z11,par7)); 524 float V01 = Vcenter; 525 float V11 = Io*exp(-bn*pow(z10,par7)); 526 f1 = interpolatePixels(V00, V10, V01, V11, X, (1.0 + Y)); 527 } 528 if ((X < 0) && (Y < 0)) { 529 float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive 530 float V00 = Io*exp(-bn*pow(z11,par7)); 531 float V10 = Io*exp(-bn*pow(z10,par7)); 532 float V01 = Io*exp(-bn*pow(z01,par7)); 533 float V11 = Vcenter; 534 f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), (1.0 + Y)); 535 } 536 } 537 # endif
Note:
See TracChangeset
for help on using the changeset viewer.
