IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 29, 2006, 5:02:59 PM (20 years ago)
Author:
magnier
Message:

major cleanup of model code, fixes to use new param defs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/objects/models/pmModel_SGAUSS.c

    r9730 r9775  
    1 #ifdef HAVE_CONFIG_H
    2 #include <config.h>
    3 #endif
    4 
    5 
    61/******************************************************************************
    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:
    98 
    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
     30XXX 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
    2240psF64 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
     42psF32 PM_MODEL_FUNC (psVector *deriv,
     43                     const psVector *params,
     44                     const psVector *x)
    2845{
    2946    psF32 *PAR = params->data.F32;
     
    6178}
    6279
    63 bool pmModelLimits_SGAUSS (psVector **beta_lim, psVector **params_min, psVector **params_max)
     80bool PM_MODEL_LIMITS (psVector **beta_lim, psVector **params_min, psVector **params_max)
    6481{
    6582
     
    99116
    100117    return (TRUE);
     118}
     119
     120bool 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
     168psF64 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
     197psF64 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
     236bool 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
     256bool 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;
    101293}
    102294
     
    142334}
    143335
    144 bool pmModelGuess_SGAUSS (pmModel *model, pmSource *source)
     336// XXX EAM : test version using flux contours to guess slope
     337bool PM_MODEL_GUESS_HARD (pmModel *model, pmSource *source)
    145338{
    146339
     
    148341    pmPeak    *peak     = source->peak;
    149342    psF32     *params   = model->params->data.F32;
     343    float f1, f2;
    150344
    151345    psEllipseAxes axes;
     
    169363    params[6] = shape.sxy;
    170364
    171     # if (0)
    172 
    173         f1 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels);
     365    f1 = psImageEllipseContour (axes, peak->x, peak->y, source->pixels);
    174366    axes.major *= 2.0;
    175367    axes.minor *= 2.0;
     
    181373        params[7] = 0.5;
    182374    }
    183     # endif
    184 
    185     params[7] = 1.8;
    186375    params[8] = 0.1;
    187376
    188 
    189377    return(true);
    190378}
    191379
    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.