Changeset 9775 for trunk/psModules/src/objects/models/pmModel_QGAUSS.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_QGAUSS.c
r9730 r9775 1 #ifdef HAVE_CONFIG_H2 #include <config.h>3 #endif4 5 1 /****************************************************************************** 6 one component, two slopes: 7 1 / (1 + z^M + z^N) 2 * this file defines the QGAUSS 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: 8 8 9 params->data.F32[PM_PAR_SKY] = So; 10 params->data.F32[PM_PAR_I0] = Zo; 11 params->data.F32[PM_PAR_XPOS] = Xo; 12 params->data.F32[PM_PAR_YPOS] = Yo; 13 params->data.F32[PM_PAR_SXX] = sqrt(2.0) / SigmaX; 14 params->data.F32[PM_PAR_SYY] = sqrt(2.0) / SigmaY; 15 params->data.F32[PM_PAR_SXY] = Sxy; 16 params->data.F32[PM_PAR_7] = 17 params->data.F32[PM_PAR_8] = 18 *****************************************************************************/ 19 20 psF32 pmModelFunc_QGAUSS(psVector *deriv, 21 const psVector *params, 22 const psVector *x) 9 power-law with fitted linear term 10 1 / (1 + kz + z^2.25) 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 - amplitude of the linear component (k) 20 *****************************************************************************/ 21 22 # define PM_MODEL_FUNC pmModelFunc_QGAUSS 23 # define PM_MODEL_FLUX pmModelFlux_QGAUSS 24 # define PM_MODEL_GUESS pmModelGuess_QGAUSS 25 # define PM_MODEL_LIMITS pmModelLimits_QGAUSS 26 # define PM_MODEL_RADIUS pmModelRadius_QGAUSS 27 # define PM_MODEL_FROM_PSF pmModelFromPSF_QGAUSS 28 # define PM_MODEL_FIT_STATUS pmModelFitStatus_QGAUSS 29 30 psF32 PM_MODEL_FUNC (psVector *deriv, 31 const psVector *params, 32 const psVector *pixcoord) 23 33 { 24 34 psF32 *PAR = params->data.F32; 25 35 26 psF32 X = x->data.F32[0] - PAR[PM_PAR_XPOS]; 27 psF32 Y = x->data.F32[1] - PAR[PM_PAR_YPOS]; 28 psF32 px = PAR[PM_PAR_SXX]*X; 29 psF32 py = PAR[PM_PAR_SYY]*Y; 30 psF32 z = 0.5*PS_SQR(px) + 0.5*PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y; 36 psF32 X = pixcoord->data.F32[0] - PAR[PM_PAR_XPOS]; 37 psF32 Y = pixcoord->data.F32[1] - PAR[PM_PAR_YPOS]; 38 psF32 px = X / PAR[PM_PAR_SXX]; 39 psF32 py = Y / PAR[PM_PAR_SYY]; 40 psF32 z = PS_SQR(px) + PS_SQR(py) + PAR[PM_PAR_SXY]*X*Y; 41 42 // XXX if the elliptical contour is defined in valid way, this step should not be required. 43 // other models (like PGAUSS) don't use fractional powers, and thus do not have NaN values 44 // for negative values of z 31 45 if (z < 0) 32 46 z = 0; … … 45 59 psF32 q = t*(PAR[PM_PAR_7] + 2.25*zp); 46 60 47 dPAR[PM_PAR_SKY] = +1.0;48 dPAR[PM_PAR_I0] = +r;49 dPAR[PM_PAR_XPOS] = q*(2.0*px *PAR[PM_PAR_SXX] + PAR[PM_PAR_SXY]*Y);50 dPAR[PM_PAR_YPOS] = q*(2.0*py *PAR[PM_PAR_SYY] + PAR[PM_PAR_SXY]*X);51 dPAR[PM_PAR_SXX] = -2.0*q*px*X;52 dPAR[PM_PAR_SYY] = -2.0*q*py*Y;53 dPAR[PM_PAR_SXY] = -q*X*Y;54 dPAR[PM_PAR_7] = -t*z;61 dPAR[PM_PAR_SKY] = +1.0; 62 dPAR[PM_PAR_I0] = +r; 63 dPAR[PM_PAR_XPOS] = q*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]); 64 dPAR[PM_PAR_YPOS] = q*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]); 65 dPAR[PM_PAR_SXX] = +2.0*q*px*px/PAR[PM_PAR_SXX]; 66 dPAR[PM_PAR_SYY] = +2.0*q*py*py/PAR[PM_PAR_SYY]; 67 dPAR[PM_PAR_SXY] = -q*X*Y; 68 dPAR[PM_PAR_7] = -t*z; 55 69 } 56 70 return(f); 57 71 } 58 72 59 bool pmModelLimits_QGAUSS(psVector **beta_lim, psVector **params_min, psVector **params_max)73 bool PM_MODEL_LIMITS (psVector **beta_lim, psVector **params_min, psVector **params_max) 60 74 { 61 75 … … 77 91 params_min[0][0].data.F32[PM_PAR_XPOS] = -100; 78 92 params_min[0][0].data.F32[PM_PAR_YPOS] = -100; 79 params_min[0][0].data.F32[PM_PAR_SXX] = 0. 01;80 params_min[0][0].data.F32[PM_PAR_SYY] = 0. 01;93 params_min[0][0].data.F32[PM_PAR_SXX] = 0.5; 94 params_min[0][0].data.F32[PM_PAR_SYY] = 0.5; 81 95 params_min[0][0].data.F32[PM_PAR_SXY] = -5.0; 82 96 params_min[0][0].data.F32[PM_PAR_7] = 0.1; … … 86 100 params_max[0][0].data.F32[PM_PAR_XPOS] = 1e4; // this should be set by image dimensions! 87 101 params_max[0][0].data.F32[PM_PAR_YPOS] = 1e4; // this should be set by image dimensions! 88 params_max[0][0].data.F32[PM_PAR_SXX] = 2.0;89 params_max[0][0].data.F32[PM_PAR_SYY] = 2.0;102 params_max[0][0].data.F32[PM_PAR_SXX] = 100.0; 103 params_max[0][0].data.F32[PM_PAR_SYY] = 100.0; 90 104 params_max[0][0].data.F32[PM_PAR_SXY] = +5.0; 91 105 params_max[0][0].data.F32[PM_PAR_7] = 10.0; … … 95 109 96 110 // make an initial guess for parameters 97 bool pmModelGuess_QGAUSS (pmModel *model, pmSource *source)111 bool PM_MODEL_GUESS (pmModel *model, pmSource *source) 98 112 { 99 113 100 114 pmMoments *moments = source->moments; 101 115 pmPeak *peak = source->peak; 102 psF32 * params= model->params->data.F32;103 104 params[PM_PAR_SKY]= moments->Sky;105 params[PM_PAR_I0]= moments->Peak - moments->Sky;106 params[PM_PAR_XPOS] = peak->x;107 params[PM_PAR_YPOS] = peak->y;108 params[PM_PAR_SXX] = (moments->Sx < (1.2 / 2.0)) ? 2.0 : (1.2 /moments->Sx);109 params[PM_PAR_SYY] = (moments->Sy < (1.2 / 2.0)) ? 2.0 : (1.2 /moments->Sy);110 params[PM_PAR_SXY]= 0.0;111 params[PM_PAR_7]= 1.0;116 psF32 *PAR = model->params->data.F32; 117 118 PAR[PM_PAR_SKY] = moments->Sky; 119 PAR[PM_PAR_I0] = moments->Peak - moments->Sky; 120 PAR[PM_PAR_XPOS] = peak->x; 121 PAR[PM_PAR_YPOS] = peak->y; 122 PAR[PM_PAR_SXX] = PS_MAX(0.5, moments->Sx); 123 PAR[PM_PAR_SYY] = PS_MAX(0.5, moments->Sy); 124 PAR[PM_PAR_SXY] = 0.0; 125 PAR[PM_PAR_7] = 1.0; 112 126 113 127 return(true); 114 128 } 115 129 116 psF64 pmModelFlux_QGAUSS(const psVector *params)117 { 118 float z ;119 float norm;130 psF64 PM_MODEL_FLUX (const psVector *params) 131 { 132 float z, norm; 133 psEllipseShape shape; 120 134 121 135 psF32 *PAR = params->data.F32; 122 136 123 psF64 A1 = PS_SQR(PAR[PM_PAR_SXX]);124 psF64 A2 = PS_SQR(PAR[PM_PAR_SYY]);125 psF64 A3 = PS_SQR(PAR[PM_PAR_SXY]);126 psF64 Area = 2.0 * M_PI / sqrt(A1*A2 - A3); 137 shape.sx = PAR[PM_PAR_SXX] / sqrt(2.0); 138 shape.sy = PAR[PM_PAR_SYY] / sqrt(2.0); 139 shape.sxy = PAR[PM_PAR_SXY]; 140 127 141 // Area is equivalent to 2 pi sigma^2 142 psEllipseAxes axes = psEllipseShapeToAxes (shape); 143 psF64 Area = 2.0 * M_PI * axes.major * axes.minor; 128 144 129 145 // the area needs to be multiplied by the integral of f(z) … … 150 166 // define this function so it never returns Inf or NaN 151 167 // return the radius which yields the requested flux 152 psF64 pmModelRadius_QGAUSS(const psVector *params, psF64 flux)168 psF64 PM_MODEL_RADIUS (const psVector *params, psF64 flux) 153 169 { 154 170 psF64 z, f; 171 int Nstep = 0; 172 psEllipseShape shape; 173 155 174 psF32 *PAR = params->data.F32; 156 int Nstep = 0;157 175 158 176 if (flux <= 0) … … 163 181 return (1.0); 164 182 165 // if Sx == Sy, sigma = Sx == Sy 166 psF64 sigma = hypot (1.0 / PAR[PM_PAR_SXX], 1.0 / PAR[PM_PAR_SYY]) / sqrt(2.0); 183 shape.sx = PAR[PM_PAR_SXX] / sqrt(2.0); 184 shape.sy = PAR[PM_PAR_SYY] / sqrt(2.0); 185 shape.sxy = PAR[PM_PAR_SXY]; 186 187 psEllipseAxes axes = psEllipseShapeToAxes (shape); 188 psF64 sigma = axes.major; 189 167 190 psF64 limit = flux / PAR[PM_PAR_I0]; 168 191 169 # if 0 170 /* test example will just use both, printing both */ 171 psF64 dz = 1.0 / (2.0 * sigma*sigma); 172 173 // we can do this much better with intelligent choices here 174 for (z = 0.0; z < 30.0; z += dz) { 175 Nstep ++; 176 f = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25)); 177 // test: f = 1.0 / (1 + PAR[PM_PAR_7]*z + PS_SQR(z)); 178 if (f < limit) 179 break; 180 } 181 // fprintf (stderr, "rad 1: %f, want: %f, got: %f (%d steps)\n", z, limit, f, Nstep); 182 183 # else 184 185 /* use the fact that f is monotonically decreasing */ 186 z = 0; 192 // use the fact that f is monotonically decreasing 193 z = 0; 187 194 Nstep = 0; 188 195 … … 193 200 z0 = 0.0; 194 201 202 // perform a type of bisection to find the value 195 203 float f0 = 1.0 / (1 + PAR[PM_PAR_7]*z0 + pow(z0, 2.25)); 196 204 float f1 = 1.0 / (1 + PAR[PM_PAR_7]*z1 + pow(z1, 2.25)); … … 198 206 z = 0.5*(z0 + z1); 199 207 f = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25)); 200 // fprintf (stderr, "%f %f %f : %f %f %f\n", f0, f, f1, z0, z, z1);201 208 if (f > limit) { 202 209 z0 = z; … … 208 215 Nstep ++; 209 216 } 210 // fprintf (stderr, "rad 2: %f, want: %f, got: %f (%d steps)\n", z, limit, f, Nstep);211 # endif212 213 217 psF64 radius = sigma * sqrt (2.0 * z); 214 if (isnan(radius)) { 215 fprintf (stderr, "error in code\n"); 216 } 218 219 if (isnan(radius)) 220 psAbort ("psphot.model", "error in code: radius is NaN"); 221 217 222 return (radius); 218 223 } 219 224 220 bool pmModelFromPSF_QGAUSS(pmModel *modelPSF, pmModel *modelFLT, pmPSF *psf)225 bool PM_MODEL_FROM_PSF (pmModel *modelPSF, pmModel *modelFLT, pmPSF *psf) 221 226 { 222 227 … … 224 229 psF32 *in = modelFLT->params->data.F32; 225 230 226 out[PM_PAR_SKY] = in[PM_PAR_SKY]; 227 out[PM_PAR_I0] = in[PM_PAR_I0]; 228 out[PM_PAR_XPOS] = in[PM_PAR_XPOS]; 229 out[PM_PAR_YPOS] = in[PM_PAR_YPOS]; 230 231 assert (PM_PAR_YPOS + 1 == 4); // so starting at 4 is correct 232 for (int i = 4; i < 8; i++) { 233 psPolynomial2D *poly = psf->params->data[i-4]; 234 // XXX: Verify this (from EAM change) 235 //out[i] = Polynomial2DEval_EAM(poly, out[PM_PAR_XPOS], out[PM_PAR_YPOS]); 236 out[i] = psPolynomial2DEval(poly, out[PM_PAR_XPOS], out[PM_PAR_YPOS]); 237 } 231 // we require these two parameters to exist 232 assert (psf->params_NEW->n > PM_PAR_YPOS); 233 assert (psf->params_NEW->n > PM_PAR_XPOS); 234 235 for (int i = 0; i < psf->params_NEW->n; i++) { 236 if (psf->params_NEW->data[i] == NULL) { 237 out[i] = in[i]; 238 } else { 239 psPolynomial2D *poly = psf->params_NEW->data[i]; 240 out[i] = psPolynomial2DEval(poly, in[PM_PAR_XPOS], in[PM_PAR_YPOS]); 241 } 242 } 243 244 // the 2D model for SXY actually fits SXY / (SXX^-2 + SYY^-2); correct here 245 out[PM_PAR_SXY] = pmPSF_SXYtoModel (out); 246 238 247 return(true); 239 248 } 240 249 241 bool pmModelFitStatus_QGAUSS (pmModel *model)250 bool PM_MODEL_FIT_STATUS (pmModel *model) 242 251 { 243 252 … … 258 267 status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5); 259 268 260 if (!status) 261 return false; 262 return true; 263 } 269 return status; 270 } 271 272 # undef PM_MODEL_FUNC 273 # undef PM_MODEL_FLUX 274 # undef PM_MODEL_GUESS 275 # undef PM_MODEL_LIMITS 276 # undef PM_MODEL_RADIUS 277 # undef PM_MODEL_FROM_PSF 278 # undef PM_MODEL_FIT_STATUS
Note:
See TracChangeset
for help on using the changeset viewer.
