IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 3, 2010, 8:50:52 AM (16 years ago)
Author:
eugene
Message:

updates from trunk

Location:
branches/simtest_nebulous_branches
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/simtest_nebulous_branches

  • branches/simtest_nebulous_branches/psModules

  • branches/simtest_nebulous_branches/psModules/src/objects/models/pmModel_QGAUSS.c

    r20001 r27840  
    11/******************************************************************************
    22 * 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'
     3 * model functions are loaded by pmModelClass.c using 'include', and thus need no 'include'
    44 * statements of their own.  The models use a psVector to represent the set of parameters, with
    55 * the sequence used to specify the meaning of the parameter.  The meaning of the parameters
     
    2020   *****************************************************************************/
    2121
     22#include <stdio.h>
     23#include <pslib.h>
     24
     25#include "pmMoments.h"
     26#include "pmPeaks.h"
     27#include "pmSource.h"
     28#include "pmModel.h"
     29#include "pmModel_QGAUSS.h"
     30
    2231# define PM_MODEL_FUNC            pmModelFunc_QGAUSS
    2332# define PM_MODEL_FLUX            pmModelFlux_QGAUSS
     
    2837# define PM_MODEL_PARAMS_FROM_PSF pmModelParamsFromPSF_QGAUSS
    2938# define PM_MODEL_FIT_STATUS      pmModelFitStatus_QGAUSS
     39# define PM_MODEL_SET_LIMITS      pmModelSetLimits_QGAUSS
     40
     41# define ALPHA   2.250
     42# define ALPHA_M 1.250
     43
     44// the model is a function of the pixel coordinate (pixcoord[0,1] = x,y)
     45// 0.5 PIX: the parameters are defined in terms of pixel coords, so the incoming pixcoords
     46// values need to be pixel coords
     47
     48// Lax parameter limits
     49static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, -1.0 };
     50static float paramsMaxLax[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 20.0 };
     51
     52// Moderate parameter limits
     53// Tolerate a small divot (k < 0)
     54static float paramsMinModerate[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, -0.05 };
     55static float paramsMaxModerate[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 20.0 };
     56
     57// Strict parameter limits
     58// k = PAR_7 < 0 is very undesirable (big divot in the middle)
     59static float paramsMinStrict[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, 0.0 };
     60static float paramsMaxStrict[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 20.0 };
     61
     62// Parameter limits to use
     63static float *paramsMinUse = paramsMinLax;
     64static float *paramsMaxUse = paramsMaxLax;
     65static float betaUse[] = { 1000, 3e6, 5, 5, 1.0, 1.0, 0.5, 2.0 };
     66
     67static bool limitsApply = true;         // Apply limits?
    3068
    3169psF32 PM_MODEL_FUNC (psVector *deriv,
     
    4886    assert (z >= 0);
    4987
    50     psF32 zp = pow(z,1.25);
     88    psF32 zp = pow(z,ALPHA_M);
    5189    psF32 r  = 1.0 / (1 + PAR[PM_PAR_7]*z + z*zp);
    5290
     
    5997        // note difference from a pure gaussian: q = params->data.F32[PM_PAR_I0]*r
    6098        psF32 t = r1*r;
    61         psF32 q = t*(PAR[PM_PAR_7] + 2.25*zp);
     99        psF32 q = t*(PAR[PM_PAR_7] + ALPHA*zp);
    62100
    63101        dPAR[PM_PAR_SKY]  = +1.0;
     
    79117# define AR_MAX 20.0
    80118# define AR_RATIO 0.99
     119
    81120bool PM_MODEL_LIMITS (psMinConstraintMode mode, int nParam, float *params, float *beta)
    82121{
    83     float beta_lim = 0, params_min = 0, params_max = 0;
    84     float f1 = 0, f2 = 0, q1 = 0, q2 = 0;
     122    if (!limitsApply) {
     123        return true;
     124    }
     125    psAssert(nParam >= 0 && nParam <= PM_PAR_7, "Parameter index is out of bounds");
    85126
    86127    // we need to calculate the limits for SXY specially
     128    float q2 = NAN;
    87129    if (nParam == PM_PAR_SXY) {
    88         f1 = 1.0 / PS_SQR(params[PM_PAR_SYY]) + 1.0 / PS_SQR(params[PM_PAR_SXX]);
    89         f2 = 1.0 / PS_SQR(params[PM_PAR_SYY]) - 1.0 / PS_SQR(params[PM_PAR_SXX]);
    90         q1 = PS_SQR(f1)*AR_RATIO - PS_SQR(f2);
     130        float f1 = 1.0 / PS_SQR(params[PM_PAR_SYY]) + 1.0 / PS_SQR(params[PM_PAR_SXX]);
     131        float f2 = 1.0 / PS_SQR(params[PM_PAR_SYY]) - 1.0 / PS_SQR(params[PM_PAR_SXX]);
     132        float q1 = PS_SQR(f1)*AR_RATIO - PS_SQR(f2);
    91133        q1 = (q1 < 0.0) ? 0.0 : q1;
    92134        // if q1 < 0.0, f2 ~ f1, we have a very large axis ratio near 45deg..  Saturate at that
    93135        // angle and let f2,f1 fight it out
    94         q2  = 0.5*sqrt (q1);
     136        q2 = 0.5*sqrtf(q1);
    95137    }
    96138
    97139    switch (mode) {
    98     case PS_MINIMIZE_BETA_LIMIT:
    99         switch (nParam) {
    100         case PM_PAR_SKY:
    101             beta_lim = 1000;
    102             break;
    103         case PM_PAR_I0:
    104             beta_lim = 3e6;
    105             break;
    106         case PM_PAR_XPOS:
    107             beta_lim = 5;
    108             break;
    109         case PM_PAR_YPOS:
    110             beta_lim = 5;
    111             break;
    112         case PM_PAR_SXX:
    113             beta_lim = 1.0;
    114             break;
    115         case PM_PAR_SYY:
    116             beta_lim = 1.0;
    117             break;
    118         case PM_PAR_SXY:
    119             beta_lim =  0.5*q2;
    120             break;
    121         case PM_PAR_7:
    122             beta_lim = 2.0;
    123             break;
    124         default:
    125             psAbort("invalid parameter %d for beta test", nParam);
    126         }
    127         if (fabs(beta[nParam]) > fabs(beta_lim)) {
    128             beta[nParam] = (beta[nParam] > 0) ? fabs(beta_lim) : -fabs(beta_lim);
    129             psTrace ("psModules.objects", 5, "|beta[nParam==%d]| > |beta_lim|; %g v. %g",
    130                      nParam, beta[nParam], beta_lim);
    131             return false;
    132         }
    133         return true;
    134     case PS_MINIMIZE_PARAM_MIN:
    135         switch (nParam) {
    136         case PM_PAR_SKY:
    137             params_min = -1000;
    138             break;
    139         case PM_PAR_I0:
    140             params_min =   0.01;
    141             break;
    142         case PM_PAR_XPOS:
    143             params_min =  -100;
    144             break;
    145         case PM_PAR_YPOS:
    146             params_min =  -100;
    147             break;
    148         case PM_PAR_SXX:
    149             params_min =   0.5;
    150             break;
    151         case PM_PAR_SYY:
    152             params_min =   0.5;
    153             break;
    154         case PM_PAR_SXY:
    155             params_min =  -q2;
    156             break;
    157         case PM_PAR_7:
    158             params_min =   0.1;
    159             break;
    160         default:
    161             psAbort("invalid parameter %d for param min test", nParam);
    162         }
    163         if (params[nParam] < params_min) {
    164             params[nParam] = params_min;
    165             psTrace ("psModules.objects", 5, "params[nParam==%d] < params_min; %g v. %g",
    166                      nParam, params[nParam], params_min);
    167             return false;
    168         }
    169         return true;
    170     case PS_MINIMIZE_PARAM_MAX:
    171         switch (nParam) {
    172         case PM_PAR_SKY:
    173             params_max =   1e5;
    174             break;
    175         case PM_PAR_I0:
    176             params_max =   1e8;
    177             break;
    178         case PM_PAR_XPOS:
    179             params_max =   1e4;
    180             break;
    181         case PM_PAR_YPOS:
    182             params_max =   1e4;
    183             break;
    184         case PM_PAR_SXX:
    185             params_max =   100;
    186             break;
    187         case PM_PAR_SYY:
    188             params_max =   100;
    189             break;
    190         case PM_PAR_SXY:
    191             params_max =  +q2;
    192             break;
    193         case PM_PAR_7:
    194             params_max =  20.0;
    195             break;
    196         default:
    197             psAbort("invalid parameter %d for param max test", nParam);
    198         }
    199         if (params[nParam] > params_max) {
    200             params[nParam] = params_max;
    201             psTrace ("psModules.objects", 5, "params[nParam==%d] > params_max; %g v. %g",
    202                      nParam, params[nParam], params_max);
    203             return false;
    204         }
    205         return true;
     140      case PS_MINIMIZE_BETA_LIMIT: {
     141          psAssert(beta, "Require beta to limit beta");
     142          float limit = betaUse[nParam];
     143          if (nParam == PM_PAR_SXY) {
     144              limit *= q2;
     145          }
     146          if (fabs(beta[nParam]) > fabs(limit)) {
     147              beta[nParam] = (beta[nParam] > 0) ? fabs(limit) : -fabs(limit);
     148              psTrace("psModules.objects", 5, "|beta[nParam==%d]| > |beta_lim|; %g v. %g",
     149                      nParam, beta[nParam], limit);
     150              return false;
     151          }
     152          return true;
     153      }
     154      case PS_MINIMIZE_PARAM_MIN: {
     155          psAssert(params, "Require parameters to limit parameters");
     156          psAssert(paramsMinUse, "Require parameter limits to limit parameters");
     157          float limit = paramsMinUse[nParam];
     158          if (nParam == PM_PAR_SXY) {
     159              limit *= q2;
     160          }
     161          if (params[nParam] < limit) {
     162              params[nParam] = limit;
     163              psTrace("psModules.objects", 5, "params[nParam==%d] < params_min; %g v. %g",
     164                      nParam, params[nParam], limit);
     165              return false;
     166          }
     167          return true;
     168      }
     169      case PS_MINIMIZE_PARAM_MAX: {
     170          psAssert(params, "Require parameters to limit parameters");
     171          psAssert(paramsMaxUse, "Require parameter limits to limit parameters");
     172          float limit = paramsMaxUse[nParam];
     173          if (nParam == PM_PAR_SXY) {
     174              limit *= q2;
     175          }
     176          if (params[nParam] > limit) {
     177              params[nParam] = limit;
     178              psTrace("psModules.objects", 5, "params[nParam==%d] > params_max; %g v. %g",
     179                      nParam, params[nParam], limit);
     180              return false;
     181          }
     182          return true;
     183      }
    206184    default:
    207185        psAbort("invalid choice for limits");
     
    213191
    214192// make an initial guess for parameters
     193// 0.5 PIX: moments and peaks are in pixel coords, thus so are model parameters
    215194bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
    216195{
     
    237216    if (!isfinite(shape.sxy)) return false;
    238217
    239     // XXX turn this off here for now PAR[PM_PAR_SKY]  = moments->Sky;
    240218    PAR[PM_PAR_SKY]  = 0.0;
    241219    PAR[PM_PAR_I0]   = peak->flux;
     
    273251    float f1, f2;
    274252    for (z = DZ; z < 50; z += DZ) {
    275         f1 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
     253        f1 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
    276254        z += DZ;
    277         f2 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
     255        f2 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
    278256        norm += f0 + 4*f1 + f2;
    279257        f0 = f2;
     
    290268psF64 PM_MODEL_RADIUS (const psVector *params, psF64 flux)
    291269{
    292     psF64 z, f;
     270    psF64 z;
    293271    int Nstep = 0;
    294272    psEllipseShape shape;
     
    296274    psF32 *PAR = params->data.F32;
    297275
    298     if (flux <= 0)
    299         return (1.0);
    300     if (PAR[PM_PAR_I0] <= 0)
    301         return (1.0);
    302     if (flux >= PAR[PM_PAR_I0])
    303         return (1.0);
     276    if (flux <= 0) return 1.0;
     277    if (PAR[PM_PAR_I0] <= 0) return 1.0;
     278    if (flux >= PAR[PM_PAR_I0]) return 1.0;
     279    if (PAR[PM_PAR_7] == 0.0) return powf(PAR[PM_PAR_I0] / flux - 1.0, 1.0 / ALPHA);
    304280
    305281    shape.sx  = PAR[PM_PAR_SXX] / M_SQRT2;
     
    317293
    318294    // choose a z value guaranteed to be beyond our limit
    319     float z0 = pow((1.0 / limit), (1.0 / 2.25));
    320     float z1 = (1.0 / limit) / PAR[PM_PAR_7];
    321     z1 = PS_MAX (z0, z1);
    322     z0 = 0.0;
    323 
    324     // perform a type of bisection to find the value
    325     float f0 = 1.0 / (1 + PAR[PM_PAR_7]*z0 + pow(z0, 2.25));
    326     float f1 = 1.0 / (1 + PAR[PM_PAR_7]*z1 + pow(z1, 2.25));
    327     while ((Nstep < 10) && (fabs(z1 - z0) > 0.5)) {
    328         z = 0.5*(z0 + z1);
    329         f = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
    330         if (f > limit) {
    331             z0 = z;
    332             f0 = f;
    333         } else {
    334             z1 = z;
    335             f1 = f;
    336         }
    337         Nstep ++;
     295    float z0 = 0.0;
     296    float z1 = pow((1.0 / limit), (1.0 / ALPHA));
     297    psAssert (isfinite(z1), "fix this code: z1 should not be nan for %f", PAR[PM_PAR_7]);
     298    if (PAR[PM_PAR_7] < 0.0) z1 *= 2.0;
     299
     300    // starting guess:
     301    z = 0.5*(z0 + z1);
     302    float dz = 1.0;
     303
     304    // use Newton-Raphson to minimize f(z) - limit = 0
     305    for (int i = 0; (i < 10) && (fabs(dz) > 0.0001); i++) {
     306        float q = (1.0 + PAR[PM_PAR_7]*z + pow(z, ALPHA));
     307        float dqdz = (PAR[PM_PAR_7] + ALPHA*pow(z, ALPHA - 1.0));
     308
     309        float f = 1.0 / q;
     310        float dfdz = -dqdz * f / q;
     311
     312        dz = (f - limit) / dfdz;
     313
     314        // fprintf (stderr, "%f %f %f : %f %f\n", f, z, dz, dfdz, q);
     315        z -= dz;
     316        z = PS_MAX(z, 0.0);
    338317    }
    339318    psF64 radius = sigma * sqrt (2.0 * z);
     
    444423bool PM_MODEL_FIT_STATUS (pmModel *model)
    445424{
    446 
    447     psF32 dP;
    448425    bool  status;
    449426
     
    451428    psF32 *dPAR = model->dparams->data.F32;
    452429
    453     dP = 0;
    454     dP += PS_SQR(dPAR[PM_PAR_SXX] / PAR[PM_PAR_SXX]);
    455     dP += PS_SQR(dPAR[PM_PAR_SYY] / PAR[PM_PAR_SYY]);
    456     dP = sqrt (dP);
    457 
    458430    status = true;
    459 //    status &= (dP < 0.5);
    460431    status &= (PAR[PM_PAR_I0] > 0);
    461432    status &= ((dPAR[PM_PAR_I0]/PAR[PM_PAR_I0]) < 0.5);
    462433
    463434    return status;
     435}
     436
     437
     438void PM_MODEL_SET_LIMITS(pmModelLimitsType type)
     439{
     440    switch (type) {
     441      case PM_MODEL_LIMITS_NONE:
     442        paramsMinUse = NULL;
     443        paramsMaxUse = NULL;
     444        limitsApply = true;
     445        break;
     446      case PM_MODEL_LIMITS_IGNORE:
     447        paramsMinUse = NULL;
     448        paramsMaxUse = NULL;
     449        limitsApply = false;
     450        break;
     451      case PM_MODEL_LIMITS_LAX:
     452        paramsMinUse = paramsMinLax;
     453        paramsMaxUse = paramsMaxLax;
     454        limitsApply = true;
     455        break;
     456      case PM_MODEL_LIMITS_MODERATE:
     457        paramsMinUse = paramsMinModerate;
     458        paramsMaxUse = paramsMaxModerate;
     459        limitsApply = true;
     460        break;
     461      case PM_MODEL_LIMITS_STRICT:
     462        paramsMinUse = paramsMinStrict;
     463        paramsMaxUse = paramsMaxStrict;
     464        limitsApply = true;
     465        break;
     466      default:
     467        psAbort("Unrecognised model limits type: %x", type);
     468    }
     469    return;
    464470}
    465471
     
    472478# undef PM_MODEL_PARAMS_FROM_PSF
    473479# undef PM_MODEL_FIT_STATUS
     480# undef PM_MODEL_SET_LIMITS
     481# undef ALPHA
     482# undef ALPHA_M
Note: See TracChangeset for help on using the changeset viewer.