IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Apr 21, 2014, 5:42:34 AM (12 years ago)
Author:
eugene
Message:

merge changes from trunk

Location:
branches/eam_branches/ps2-tc3-20130727
Files:
69 edited
5 copied

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ps2-tc3-20130727

  • branches/eam_branches/ps2-tc3-20130727/psModules

    • Property svn:mergeinfo deleted
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects

    • Property svn:ignore
      •  

        old new  
        1212pmSourceIO_CMF_PS1_V1.v1.c
        1313pmSourceIO_CMF_PS1_V4.c
         14pmSourceIO_CMF_PS1_V5.c
        1415pmSourceIO_CMF_PS1_SV1.c
        1516pmSourceIO_CMF_PS1_SV2.c
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/Makefile.am

    r34823 r36680  
    2020        pmModelClass.c \
    2121        pmModelUtils.c \
     22        pmModel_CentralPixel.c \
    2223        pmSource.c \
    2324        pmPhotObj.c \
     
    3940        pmSourceIO_SX.c \
    4041        pmSourceIO_CMP.c \
     42        pmSourceIO_CFF.c \
    4143        pmSourceIO_SMPDATA.c \
    4244        pmSourceIO_PS1_DEV_0.c \
     
    4749        pmSourceIO_CMF_PS1_V3.c \
    4850        pmSourceIO_CMF_PS1_V4.c \
     51        pmSourceIO_CMF_PS1_V5.c \
    4952        pmSourceIO_CMF_PS1_SV1.c \
    5053        pmSourceIO_CMF_PS1_SV2.c \
     
    7477        pmGrowthCurve.c \
    7578        pmSourceMatch.c \
     79        pmSourceLensing.c \
    7680        pmDetEff.c \
    7781        pmSourceGroups.c \
     
    97101        pmModelClass.h \
    98102        pmModelUtils.h \
     103        pmModel_CentralPixel.h \
    99104        pmSource.h \
    100105        pmPhotObj.h \
     
    110115        pmSourceOutputs.h \
    111116        pmSourceIO.h \
    112         pmSourceSatstar.h \ 
     117        pmSourceSatstar.h \
    113118        pmSourcePlots.h \
    114119        pmSourceVisual.h \
     
    122127        pmGrowthCurveGenerate.h \
    123128        pmSourceMatch.h \
     129        pmSourceLensing.h \
    124130        pmDetEff.h \
    125131        pmSourceGroups.h \
     
    142148pmSourceIO_CMF_PS1_V3.c \
    143149pmSourceIO_CMF_PS1_V4.c \
     150pmSourceIO_CMF_PS1_V5.c \
    144151pmSourceIO_CMF_PS1_DV1.c \
    145152pmSourceIO_CMF_PS1_DV2.c \
     
    160167        mksource.pl pmSourceIO_CMF.c.in PS1_V4 pmSourceIO_CMF_PS1_V4.c
    161168
     169pmSourceIO_CMF_PS1_V5.c : pmSourceIO_CMF.c.in mksource.pl
     170        mksource.pl pmSourceIO_CMF.c.in PS1_V5 pmSourceIO_CMF_PS1_V5.c
     171
    162172pmSourceIO_CMF_PS1_DV1.c : pmSourceIO_CMF.c.in mksource.pl
    163173        mksource.pl pmSourceIO_CMF.c.in PS1_DV1 pmSourceIO_CMF_PS1_DV1.c
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/mksource.pl

    r34403 r36680  
    1919               "PS1_V3", 3,
    2020               "PS1_V4", 4,
     21               "PS1_V5", 5,
    2122    );
    2223%cmfmodes_dv = ("PS1_DV1", 1,
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_DEV.c

    r35768 r36680  
    1616   * PM_PAR_SYY 5   - Y^2 term of elliptical contour (sqrt(2) / SigmaY)
    1717   * PM_PAR_SXY 6   - X*Y term of elliptical contour
    18    * PM_PAR_7   7   - normalized dev parameter
    1918
    2019   note that a standard dev model uses exp(-K*(z^(1/2n) - 1).  the additional elements (K,
     
    4443#include "pmSourceDiffStats.h"
    4544#include "pmSourceSatstar.h"
     45#include "pmSourceLensing.h"
    4646#include "pmSource.h"
    4747#include "pmSourceFitModel.h"
     
    4949#include "pmPSFtry.h"
    5050#include "pmDetections.h"
     51#include "pmModel_CentralPixel.h"
    5152
    5253#include "pmModel_DEV.h"
     
    6364# define PM_MODEL_SET_LIMITS      pmModelSetLimits_DEV
    6465
    65 // f = exp(-z^0.125)
     66// f = exp(-kappa*r^(1/index))
     67// f = exp(-kappa*z^(0.5/index))
     68// index = 4, 0.5/index = 0.125
    6669# define ALPHA 0.125
    67 // # define ALPHA 0.25
    6870
    6971// the model is a function of the pixel coordinate (pixcoord[0,1] = x,y)
     
    7375// Lax parameter limits
    7476static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.001, 0.001, -1.0 };
    75 static float paramsMaxLax[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0 };
     77static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0 };
    7678
    7779// Moderate parameter limits
     
    8688static float *paramsMinUse = paramsMinLax;
    8789static float *paramsMaxUse = paramsMaxLax;
    88 static float betaUse[] = { 1000, 3e6, 5, 5, 1.0, 1.0, 0.5 };
     90static float betaUse[] = { 2, 3e6, 5, 5, 10.0, 10.0, 0.5 };
    8991
    9092static bool limitsApply = true;         // Apply limits?
    91 
    92 # include "pmModel_SERSIC.CP.h"
    9393
    9494psF32 PM_MODEL_FUNC (psVector *deriv,
     
    109109    psAssert (z >= 0, "do not allow negative z values in model");
    110110
    111     float index = 0.5 / ALPHA;
    112     float par7 = ALPHA;
    113     float bn = 1.9992*index - 0.3271;
    114     float Io = exp(bn);
    115 
    116     psF32 f2 = bn*pow(z,ALPHA);
    117     psF32 f1 = Io*exp(-f2);
    118 
    119     psF32 radius = hypot(X, Y);
    120     if (radius < 1.0) {
    121 
    122         // ** use bilinear interpolation to the given location from the 4 surrounding pixels centered on the object center
    123 
    124         // first, use Rmajor and index to find the central pixel flux (fraction of total flux)
    125         psEllipseAxes axes;
    126         pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
    127 
    128         // get the central pixel flux from the lookup table
    129         float xPix = (axes.major - centralPixelXo) / centralPixeldX;
    130         xPix = PS_MIN (PS_MAX(xPix, 0), centralPixelNX - 1);
    131         float yPix = (index - centralPixelYo) / centralPixeldY;
    132         yPix = PS_MIN (PS_MAX(yPix, 0), centralPixelNY - 1);
    133 
    134         // the integral of a Sersic has an analytical form as follows:
    135         float logGamma = lgamma(2.0*index);
    136         float bnFactor = pow(bn, 2.0*index);
    137         float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor;
    138 
    139         // XXX interpolate to get the value
    140         // XXX for the moment, just integerize
    141         // XXX I need to multiply by the integrated flux to get the flux in the central pixel
    142         float Vcenter = centralPixel[(int)yPix][(int)xPix] * norm;
    143        
    144         float px1 = 1.0 / PAR[PM_PAR_SXX];
    145         float py1 = 1.0 / PAR[PM_PAR_SYY];
    146         float z10 = PS_SQR(px1);
    147         float z01 = PS_SQR(py1);
    148 
    149         // which pixels do we need for this interpolation?
    150         // (I do not keep state information, so I don't know anything about other evaluations of nearby pixels...)
    151         if ((X >= 0) && (Y >= 0)) {
    152             float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
    153             float V00 = Vcenter;
    154             float V10 = Io*exp(-bn*pow(z10,par7));
    155             float V01 = Io*exp(-bn*pow(z01,par7));
    156             float V11 = Io*exp(-bn*pow(z11,par7));
    157             f1 = interpolatePixels(V00, V10, V01, V11, 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(z10,par7));
    162             float V10 = Vcenter;
    163             float V01 = Io*exp(-bn*pow(z11,par7));
    164             float V11 = Io*exp(-bn*pow(z01,par7));
    165             f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), Y);
    166         }
    167         if ((X >= 0) && (Y < 0)) {
    168             float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative
    169             float V00 = Io*exp(-bn*pow(z01,par7));
    170             float V10 = Io*exp(-bn*pow(z11,par7));
    171             float V01 = Vcenter;
    172             float V11 = Io*exp(-bn*pow(z10,par7));
    173             f1 = interpolatePixels(V00, V10, V01, V11, X, (1.0 + Y));
    174         }
    175         if ((X < 0) && (Y < 0)) {
    176             float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
    177             float V00 = Io*exp(-bn*pow(z11,par7));
    178             float V10 = Io*exp(-bn*pow(z10,par7));
    179             float V01 = Io*exp(-bn*pow(z01,par7));
    180             float V11 = Vcenter;
    181             f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), (1.0 + Y));
    182         }
     111    // for DEV, we can hard-wire kappa(4):
     112    // float index = 4.0;
     113    float kappa = 7.670628;
     114
     115    // r = sqrt(z)
     116    float q = kappa*pow(z,ALPHA);
     117    float f0 = exp(-q);
     118
     119    assert (isfinite(q));
     120
     121    // only worry about the central pixels at most
     122    float radius = hypot(X, Y);
     123    if (radius <= 1.5) {
     124        // Nsub ~ 10*index^2 + 1
     125        psEllipseAxes axes = pmPSF_ModelToAxes(PAR, pmModelClassGetType ("PS_MODEL_DEV"));
     126        int Nsub = 2 * ((int)(25 / 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], 4.0, Nsub);
    183130    }   
    184 
    185     psF32 z0 = PAR[PM_PAR_I0]*f1;
    186     psF32 f0 = PAR[PM_PAR_SKY] + z0;
    187 
    188     assert (isfinite(f2));
     131    assert (isfinite(f0));
     132
     133    float f1 = PAR[PM_PAR_I0]*f0;
     134    float f = PAR[PM_PAR_SKY] + f1;
     135
    189136    assert (isfinite(f1));
    190     assert (isfinite(z0));
    191     assert (isfinite(f0));
     137    assert (isfinite(f));
    192138
    193139    if (deriv != NULL) {
     
    195141
    196142        dPAR[PM_PAR_SKY]  = +1.0;
    197         dPAR[PM_PAR_I0]   = +2.0*f1; // XXX extra damping..
    198 
    199         // gradient is infinite for z = 0; saturate at z = 0.01
    200         psF32 z1 = (z < 0.01) ? z0*bn*ALPHA*pow(0.01,ALPHA - 1.0) : z0*bn*ALPHA*pow(z,ALPHA - 1.0);
    201 
    202         assert (isfinite(z1));
    203 
    204         dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]);
    205         dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]);
    206         dPAR[PM_PAR_SXX]  = +2.0*z1*px*px/PAR[PM_PAR_SXX];
    207         dPAR[PM_PAR_SYY]  = +2.0*z1*py*py/PAR[PM_PAR_SYY];
    208         dPAR[PM_PAR_SXY]  = -1.0*z1*X*Y;
    209     }
    210     return (f0);
     143        dPAR[PM_PAR_I0]   = +f0;
     144
     145        if (z > 0.01) {
     146          float z1 = f1*kappa*ALPHA*pow(z,ALPHA-1.0);
     147          dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px + Y*PAR[PM_PAR_SXY]);
     148          dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py + X*PAR[PM_PAR_SXY]);
     149          dPAR[PM_PAR_SXX]  = +2.0*z1*px*px/PAR[PM_PAR_SXX];
     150          dPAR[PM_PAR_SYY]  = +2.0*z1*py*py/PAR[PM_PAR_SYY];
     151          dPAR[PM_PAR_SXY]  = -1.0*z1*X*Y;
     152        } else {
     153          // gradient -> 0 for z -> 0, but has undef form
     154          float z1 = f1*kappa*ALPHA*pow(z,ALPHA);
     155          dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SXX] + PAR[PM_PAR_SXY]);
     156          dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SYY] + PAR[PM_PAR_SXY]);
     157          dPAR[PM_PAR_SXX]  = +2.0*z1*px/PAR[PM_PAR_SXX]/PAR[PM_PAR_SXX];
     158          dPAR[PM_PAR_SYY]  = +2.0*z1*py/PAR[PM_PAR_SYY]/PAR[PM_PAR_SYY];
     159          dPAR[PM_PAR_SXY]  = -1.0*z1;
     160        }
     161    }
     162    return (f);
    211163}
    212164
     
    292244bool PM_MODEL_GUESS (pmModel *model, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal)
    293245{
     246    // for the moment, we are going to require moments and KronFlux
     247    if (!source->moments) return false;
     248    pmMoments *moments = source->moments;
     249
     250    if (!isfinite(moments->KronFlux)) return false;
     251    if (!isfinite(moments->Mrf)) return false;
     252    if (moments->Mrf < 0.0) return false;
     253
    294254    psF32 *PAR  = model->params->data.F32;
    295255
     
    297257    PAR[PM_PAR_SKY]  = 0.0;
    298258
    299     // set the shape parameters
    300     if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments, true)) {
    301       return false;
    302     }
    303 
    304     // the normalization is modified by the slope
    305     float index = 0.5 / ALPHA;
    306     float bn = 1.9992*index - 0.3271;
    307     float Io = exp(0.5*bn);
    308 
    309     // set the model normalization
    310     if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
    311       return false;
    312     }
    313     PAR[PM_PAR_I0] /= Io;
     259    psEllipseMoments emoments;
     260    emoments.x2 = moments->Mxx;
     261    emoments.xy = moments->Mxy;
     262    emoments.y2 = moments->Myy;
     263
     264    // force the axis ratio to be < 20.0
     265    psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
     266
     267    if (!isfinite(axes.major)) return false;
     268    if (!isfinite(axes.minor)) return false;
     269    if (!isfinite(axes.theta)) return false;
     270
     271    // Mxx, Mxy, Myy define the elliptical shape, but Mrf defines the width
     272    // the factor of 2.3 comes from Table 1 of Graham and Driver (2005)
     273    float scale = moments->Mrf / axes.major / 2.3;
     274    axes.major *= scale;
     275    axes.minor *= scale;
     276
     277    pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], axes, true);
     278
     279    // psEllipseAxes axes;
     280    // use the code in SetShape here to avoid doing this 2x
     281    // pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
     282
     283    // float norm = pmSersicNorm (4);  // hardwire
     284    float norm = 0.00168012;
     285    float normFlux = 2.0 * M_PI * axes.major * axes.minor * norm;
     286    PAR[PM_PAR_I0] = moments->KronFlux / normFlux;
    314287
    315288    // set the model position
     
    328301    psEllipseAxes axes;
    329302    pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
    330     float AspectRatio = axes.minor / axes.major;
    331 
    332     float index = 4.0;
    333     float bn = 1.9992*index - 0.3271;
    334 
    335     // the integral of a Sersic has an analytical form as follows:
    336     float logGamma = lgamma(2.0*index);
    337     float bnFactor = pow(bn, 2.0*index);
    338     float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor;
    339    
    340     psF64 Flux = PAR[PM_PAR_I0] * norm * AspectRatio;
    341 
    342     return(Flux);
     303
     304    float norm = 0.00168012;
     305    float flux = PAR[PM_PAR_I0] * 2.0 * M_PI * axes.major * axes.minor * norm;
     306
     307    return(flux);
    343308}
    344309
     
    359324    pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
    360325
    361     // f = Io exp(-z^n) -> z^n = ln(Io/f)
    362     psF64 zn = log(PAR[PM_PAR_I0] / flux);
    363     psF64 radius = axes.major * sqrt (2.0) * pow(zn, 0.5 / ALPHA);
     326    // static value for DEV:
     327    float kappa = 7.670628;
     328
     329    // f = Io exp(-kappa*z^n) -> z^n = ln(Io/f) / kappa
     330    psF64 zn = log(PAR[PM_PAR_I0] / flux) / kappa;
     331    psF64 radius = axes.major * pow(zn, 0.5 / ALPHA);
    364332
    365333    psAssert (isfinite(radius), "fix this code: radius should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)",
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_EXP.c

    r35768 r36680  
    4040#include "pmSourceDiffStats.h"
    4141#include "pmSourceSatstar.h"
     42#include "pmSourceLensing.h"
    4243#include "pmSource.h"
    4344#include "pmSourceFitModel.h"
     
    4546#include "pmPSFtry.h"
    4647#include "pmDetections.h"
     48#include "pmModel_CentralPixel.h"
    4749
    4850#include "pmModel_EXP.h"
     
    6264// 0.5 PIX: the parameters are defined in terms of pixel coords, so the incoming pixcoords
    6365// values need to be pixel coords
     66//
     67
     68// Notes on changing kappa value from 1.70056 to 1.678
     69// I'm using a functional form f(x,y) = Io exp(-kappa (r / r_e)). 
     70// The article by Graham & Driver (2005) uses a form Ie exp(-bn [(r / r_e) -1])
     71// which is equal to Ie exp(-bn (r / r_e)) exp(bn). 
     72// Thus, my Io = Ie exp(bn) and my kappa is their bn.
     73// My value of kappa is 1.700, their value for bn is 1.678., so I am off by a small amount there (1.5%). 
     74
     75
     76#define KAPPA_EXP 1.678
     77#define OLD_KAPP_EXP 1.70056
     78
    6479
    6580// Lax parameter limits
    6681static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.05, 0.05, -1.0 };
    67 static float paramsMaxLax[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0 };
     82static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0 };
    6883
    6984// Moderate parameter limits
     
    7893static float *paramsMinUse = paramsMinLax;
    7994static float *paramsMaxUse = paramsMaxLax;
    80 static float betaUse[] = { 1000, 3e6, 5, 5, 1.0, 1.0, 0.5};
     95static float betaUse[] = { 2, 3e6, 5, 5, 10.0, 10.0, 0.5};
    8196
    8297static bool limitsApply = true;         // Apply limits?
    8398
    84 # include "pmModel_SERSIC.CP.h"
     99// # include "pmModel_SERSIC.CP.h"
     100
     101// the problems I'm having with the SERSIC-like functions are:
     102// 1) making sure I have the right functional form so that PAR[SXX,etc] represent R_eff (half-light radius)
     103// 2) getting the central pixel right
     104// 3) getting the derivaties right.
    85105
    86106psF32 PM_MODEL_FUNC (psVector *deriv,
     
    101121    psAssert (z >= 0, "do not allow negative z values in model");
    102122
    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 
     123    // for EXP, we can hard-wire kappa(1):
     124    // float index = 1.0;
     125    float kappa = KAPPA_EXP;
     126
     127    // sqrt(z) is r
     128    float q = kappa*sqrt(z);
     129    psF32 f0 = exp(-q);
     130
     131    assert (isfinite(q));
     132
     133    // only worry about the central 4 pixels at most
    111134    psF32 radius = hypot(X, Y);
    112     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);
    150         }
    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));
     135    if (radius <= 1.5) {
     136        f0 = pmModelCP_SersicSubpix (X, Y, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], 1.0, 51);
     137    }
     138    assert (isfinite(f0));
     139
     140    psF32 f1 = PAR[PM_PAR_I0]*f0;
     141    psF32 f = PAR[PM_PAR_SKY] + f1;
     142
    181143    assert (isfinite(f1));
    182     assert (isfinite(z0));
    183     assert (isfinite(f0));
     144    assert (isfinite(f));
    184145
    185146    if (deriv != NULL) {
     
    187148
    188149        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);
     150        dPAR[PM_PAR_I0]   = +f0;
     151
     152        if (z > 0.01) {
     153          float z1 = 0.5*f1*kappa/sqrt(z);
     154          dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px + Y*PAR[PM_PAR_SXY]);
     155          dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py + X*PAR[PM_PAR_SXY]);
     156          dPAR[PM_PAR_SXX]  = +2.0*z1*px*px/PAR[PM_PAR_SXX];
     157          dPAR[PM_PAR_SYY]  = +2.0*z1*py*py/PAR[PM_PAR_SYY];
     158          dPAR[PM_PAR_SXY]  = -1.0*z1*X*Y;
     159        } else {
     160          // gradient -> 0 for z -> 0, but has undef form
     161          float z1 = 0.5*f1*kappa;
     162          dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SXX] + PAR[PM_PAR_SXY]);
     163          dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SYY] + PAR[PM_PAR_SXY]);
     164          dPAR[PM_PAR_SXX]  = +2.0*z1*px/PAR[PM_PAR_SXX]/PAR[PM_PAR_SXX];
     165          dPAR[PM_PAR_SYY]  = +2.0*z1*py/PAR[PM_PAR_SYY]/PAR[PM_PAR_SYY];
     166          dPAR[PM_PAR_SXY]  = -1.0*z1;
     167        }
     168    }
     169    return (f);
    203170}
    204171
     
    284251bool PM_MODEL_GUESS (pmModel *model, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal)
    285252{
     253    // for the moment, we are going to require moments and KronFlux
     254    if (!source->moments) return false;
     255    pmMoments *moments = source->moments;
     256
     257    if (!isfinite(moments->KronFlux)) return false;
     258    if (!isfinite(moments->Mrf)) return false;
     259    if (moments->Mrf < 0.0) return false;
     260
    286261    psF32 *PAR  = model->params->data.F32;
    287262
     
    289264    PAR[PM_PAR_SKY]  = 0.0;
    290265
    291     // set the shape parameters
    292     if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments, true)) {
    293       return false;
    294     }
    295 
    296     // set the model normalization
    297     if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
    298       return false;
    299     }
     266    psEllipseMoments emoments;
     267    emoments.x2 = moments->Mxx;
     268    emoments.xy = moments->Mxy;
     269    emoments.y2 = moments->Myy;
     270
     271    // force the axis ratio to be < 20.0
     272    psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
     273
     274    if (!isfinite(axes.major)) return false;
     275    if (!isfinite(axes.minor)) return false;
     276    if (!isfinite(axes.theta)) return false;
     277
     278    // Mxx, Mxy, Myy define the elliptical shape, but Mrf defines the width
     279    float scale = moments->Mrf / axes.major;
     280    axes.major *= scale;
     281    axes.minor *= scale;
     282
     283    pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], axes, true);
     284
     285    // psEllipseAxes axes;
     286    // use the code in SetShape here to avoid doing this 2x
     287    // pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
     288
     289    // float norm = pmSersicNorm (4);  // hardwire
     290    float norm = 0.34578;
     291    float normFlux = 2.0 * M_PI * axes.major * axes.minor * norm;
     292    PAR[PM_PAR_I0] = moments->KronFlux / normFlux;
    300293
    301294    // set the model position
     
    306299    return(true);
    307300}
    308 
    309301// An exponential model is equivalent to a Sersic with index = 1.0
    310302psF64 PM_MODEL_FLUX (const psVector *params)
     
    314306    psEllipseAxes axes;
    315307    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);
     308
     309    // static value for EXP:
     310    float norm = 0.34578; // \int exp(-kappa*sqrt(z)) r dr
     311
     312    float flux = PAR[PM_PAR_I0] * 2.0 * M_PI * axes.major * axes.minor * norm;
     313
     314    return(flux);
    329315}
    330316
     
    345331    pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
    346332
    347     // f = Io exp(-sqrt(z)) -> sqrt(z) = ln(Io/f)
    348     psF64 zn = log(PAR[PM_PAR_I0] / flux);
    349     psF64 radius = axes.major * sqrt (2.0) * zn;
     333    // static value for EXP:
     334    float kappa = KAPPA_EXP;
     335
     336    // f = Io exp(-kappa*sqrt(z)) -> sqrt(z) = ln(Io/f) / kappa
     337    psF64 zn = log(PAR[PM_PAR_I0] / flux) / kappa;
     338    psF64 radius = axes.major * zn;
    350339
    351340    psAssert (isfinite(radius), "fix this code: radius should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)",
     
    501490    return;
    502491}
     492
     493# if (0)
     494void bilin_inter_function () {
     495        // first, use Rmajor and index to find the central pixel flux (fraction of total flux)
     496        psEllipseAxes axes;
     497        pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
     498
     499        // get the central pixel flux from the lookup table
     500        float xPix = (axes.major - centralPixelXo) / centralPixeldX;
     501        xPix = PS_MIN (PS_MAX(xPix, 0), centralPixelNX - 1);
     502        float yPix = (index - centralPixelYo) / centralPixeldY;
     503        yPix = PS_MIN (PS_MAX(yPix, 0), centralPixelNY - 1);
     504
     505        // the integral of a Sersic has an analytical form as follows:
     506        float logGamma = lgamma(2.0*index);
     507        float bnFactor = pow(bn, 2.0*index);
     508        float norm = 2.0 * M_PI * PS_SQR(axes.major) * index * exp(bn) * exp(logGamma) / bnFactor;
     509
     510        // XXX interpolate to get the value
     511        // XXX for the moment, just integerize
     512        // XXX I need to multiply by the integrated flux to get the flux in the central pixel
     513        float Vcenter = centralPixel[(int)yPix][(int)xPix] * norm;
     514       
     515        float px1 = 1.0 / PAR[PM_PAR_SXX];
     516        float py1 = 1.0 / PAR[PM_PAR_SYY];
     517        float z10 = PS_SQR(px1);
     518        float z01 = PS_SQR(py1);
     519
     520        // which pixels do we need for this interpolation?
     521        // (I do not keep state information, so I don't know anything about other evaluations of nearby pixels...)
     522        if ((X >= 0) && (Y >= 0)) {
     523            float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
     524            float V00 = Vcenter;
     525            float V10 = Io*exp(-bn*pow(z10,par7));
     526            float V01 = Io*exp(-bn*pow(z01,par7));
     527            float V11 = Io*exp(-bn*pow(z11,par7));
     528            f1 = interpolatePixels(V00, V10, V01, V11, X, Y);
     529        }
     530        if ((X < 0) && (Y >= 0)) {
     531            float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative
     532            float V00 = Io*exp(-bn*pow(z10,par7));
     533            float V10 = Vcenter;
     534            float V01 = Io*exp(-bn*pow(z11,par7));
     535            float V11 = Io*exp(-bn*pow(z01,par7));
     536            f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), Y);
     537        }
     538        if ((X >= 0) && (Y < 0)) {
     539            float z11 = z10 + z01 - PAR[PM_PAR_SXY]; // X * Y negative
     540            float V00 = Io*exp(-bn*pow(z01,par7));
     541            float V10 = Io*exp(-bn*pow(z11,par7));
     542            float V01 = Vcenter;
     543            float V11 = Io*exp(-bn*pow(z10,par7));
     544            f1 = interpolatePixels(V00, V10, V01, V11, X, (1.0 + Y));
     545        }
     546        if ((X < 0) && (Y < 0)) {
     547            float z11 = z10 + z01 + PAR[PM_PAR_SXY]; // X * Y positive
     548            float V00 = Io*exp(-bn*pow(z11,par7));
     549            float V10 = Io*exp(-bn*pow(z10,par7));
     550            float V01 = Io*exp(-bn*pow(z01,par7));
     551            float V11 = Vcenter;
     552            f1 = interpolatePixels(V00, V10, V01, V11, (1.0 + X), (1.0 + Y));
     553        }
     554}
     555# endif
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_GAUSS.c

    r35768 r36680  
    4040#include "pmSourceDiffStats.h"
    4141#include "pmSourceSatstar.h"
     42#include "pmSourceLensing.h"
    4243#include "pmSource.h"
    4344#include "pmSourceFitModel.h"
     
    6162// Lax parameter limits
    6263static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0 };
    63 static float paramsMaxLax[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0 };
     64static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0 };
    6465
    6566// Moderate parameter limits
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_PGAUSS.c

    r35768 r36680  
    4040#include "pmSourceDiffStats.h"
    4141#include "pmSourceSatstar.h"
     42#include "pmSourceLensing.h"
    4243#include "pmSource.h"
    4344#include "pmSourceFitModel.h"
     
    6162// Lax parameter limits
    6263static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0 };
    63 static float paramsMaxLax[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0 };
     64static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0 };
    6465
    6566// Moderate parameter limits
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_PS1_V1.c

    r35768 r36680  
    4242#include "pmSourceDiffStats.h"
    4343#include "pmSourceSatstar.h"
     44#include "pmSourceLensing.h"
    4445#include "pmSource.h"
    4546#include "pmSourceFitModel.h"
     
    7071// Lax parameter limits
    7172static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, -1.0 };
    72 static float paramsMaxLax[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 20.0 };
     73static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 20.0 };
    7374
    7475// Moderate parameter limits
    7576// Tolerate a small divot (k < 0)
    7677static float paramsMinModerate[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, -0.05 };
    77 static float paramsMaxModerate[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 20.0 };
     78static float paramsMaxModerate[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 20.0 };
    7879
    7980// Strict parameter limits
    8081// k = PAR_7 < 0 is very undesirable (big divot in the middle)
    8182static float paramsMinStrict[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, 0.0 };
    82 static float paramsMaxStrict[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 20.0 };
     83static float paramsMaxStrict[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 20.0 };
    8384
    8485// Parameter limits to use
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_QGAUSS.c

    r35768 r36680  
    4242#include "pmSourceDiffStats.h"
    4343#include "pmSourceSatstar.h"
     44#include "pmSourceLensing.h"
    4445#include "pmSource.h"
    4546#include "pmSourceFitModel.h"
     
    7071// Lax parameter limits
    7172static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, -1.0 };
    72 static float paramsMaxLax[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 20.0 };
     73static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 20.0 };
    7374
    7475// Moderate parameter limits
    7576// Tolerate a small divot (k < 0)
    7677static float paramsMinModerate[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, -0.05 };
    77 static float paramsMaxModerate[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 20.0 };
     78static float paramsMaxModerate[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 20.0 };
    7879
    7980// Strict parameter limits
    8081// k = PAR_7 < 0 is very undesirable (big divot in the middle)
    8182static float paramsMinStrict[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, 0.0 };
    82 static float paramsMaxStrict[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 20.0 };
     83static float paramsMaxStrict[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 20.0 };
    8384
    8485// Parameter limits to use
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_RGAUSS.c

    r35768 r36680  
    4141#include "pmSourceDiffStats.h"
    4242#include "pmSourceSatstar.h"
     43#include "pmSourceLensing.h"
    4344#include "pmSource.h"
    4445#include "pmSourceFitModel.h"
     
    6667// Lax parameter limits
    6768static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.5, 0.5, -1.0, 1.25 };
    68 static float paramsMaxLax[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 4.0 };
     69static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 4.0 };
    6970
    7071// Moderate parameter limits
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_SERSIC.c

    r35768 r36680  
    2020   * note that a Sersic model is usually defined in terms of R_e, the half-light radius.  This
    2121     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:
    2323     shape.sx = SXX / sqrt(2), shape.sy = SYY / sqrt(2), shape.sxy = SXY, then calling
    2424     psEllipseShapeToAxes, and multiplying the values of axes.major, axes.minor by sqrt(2)
     
    5050#include "pmSourceDiffStats.h"
    5151#include "pmSourceSatstar.h"
     52#include "pmSourceLensing.h"
    5253#include "pmSource.h"
    5354#include "pmSourceFitModel.h"
     
    5556#include "pmPSFtry.h"
    5657#include "pmDetections.h"
     58#include "pmModel_CentralPixel.h"
    5759
    5860#include "pmModel_SERSIC.h"
     
    7476
    7577// 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.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 4.0 };
     78static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.001, 0.001, -1.0, 0.0625 };
     79static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 1.0 };
    7880
    7981// Moderate parameter limits
     
    8890static float *paramsMinUse = paramsMinLax;
    8991static float *paramsMaxUse = paramsMaxLax;
    90 static float betaUse[] = { 1000, 3e6, 5, 5, 1.0, 1.0, 0.5, 2.0 };
     92static float betaUse[] = { 2, 3e6, 5, 5, 10.0, 10.0, 0.5, 1.0};
    9193
    9294static bool limitsApply = true;         // Apply limits?
    9395
    94 # include "pmModel_SERSIC.CP.h"
     96// # include "pmModel_SERSIC.CP.h"
    9597
    9698psF32 PM_MODEL_FUNC (psVector *deriv,
     
    111113    psAssert (z >= 0, "do not allow negative z values in model");
    112114
    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);
     115    float Sindex = 0.5 / PAR[PM_PAR_7];
     116    float kappa = pmSersicKappa (Sindex);
     117
     118    float q = kappa*pow(z,PAR[PM_PAR_7]);
     119    psF32 f0 = exp(-q);
     120
     121    assert (isfinite(q));
    120122
    121123    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);
     124    if (radius <= 1.5) {
     125        // Nsub ~ 10*index^2 + 1
     126        psEllipseAxes axes = pmPSF_ModelToAxes(PAR, pmModelClassGetType ("PS_MODEL_SERSIC"));
     127        int Nsub = 2 * ((int)(6.0*Sindex / axes.minor)) + 1;
     128        Nsub = PS_MIN (Nsub, 121);
     129        Nsub = PS_MAX (Nsub, 11);
     130        f0 = pmModelCP_SersicSubpix (X, Y, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], Sindex, Nsub);
     131    }
     132    if (!isfinite(f0)) {
     133        fprintf(stderr, "f0 is not finite for %f %f %f %f %f.  Parameters: \n", X, Y, radius, z, q);
    192134        fprintf(stderr, "%f %f %f %f %f %f %f %f\n", PAR[0], PAR[1], PAR[2], PAR[3], PAR[4],
    193135            PAR[5], PAR[6], PAR[7]);
    194136    }
    195 
    196     assert (isfinite(f2));
     137    assert (isfinite(f0));
     138
     139    psF32 f1 = PAR[PM_PAR_I0]*f0;
     140    psF32 f = PAR[PM_PAR_SKY] + f1;
     141
    197142    assert (isfinite(f1));
    198     assert (isfinite(z0));
    199     assert (isfinite(f0));
     143    assert (isfinite(f));
    200144
    201145    if (deriv != NULL) {
     
    203147
    204148        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));
     149        dPAR[PM_PAR_I0]   = +f0;
     150
     151        if (z > 0.01) {
     152          float z1 = f1*kappa*PAR[PM_PAR_7]*pow(z,PAR[PM_PAR_7]-1.0);
     153          dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px + Y*PAR[PM_PAR_SXY]);
     154          dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py + X*PAR[PM_PAR_SXY]);
     155          dPAR[PM_PAR_SXX]  = +2.0*z1*px*px/PAR[PM_PAR_SXX];
     156          dPAR[PM_PAR_SYY]  = +2.0*z1*py*py/PAR[PM_PAR_SYY];
     157          dPAR[PM_PAR_SXY]  = -1.0*z1*X*Y;
     158          dPAR[PM_PAR_7]    = -1.0*f1*q*log(z);
     159        } else {
     160          // gradient -> 0 for z -> 0, but has undef form
     161          float z1 = f1*kappa*PAR[PM_PAR_7]*pow(z,PAR[PM_PAR_7]);
     162          dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SXX] + PAR[PM_PAR_SXY]);
     163          dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0/PAR[PM_PAR_SYY] + PAR[PM_PAR_SXY]);
     164          dPAR[PM_PAR_SXX]  = +2.0*z1*px/PAR[PM_PAR_SXX]/PAR[PM_PAR_SXX];
     165          dPAR[PM_PAR_SYY]  = +2.0*z1*py/PAR[PM_PAR_SYY]/PAR[PM_PAR_SYY];
     166          dPAR[PM_PAR_SXY]  = -1.0*z1;
     167          // dPAR[PM_PAR_7]    = -1.0*f1*q*log(z + 0.0001);
     168          dPAR[PM_PAR_7]    = -1.0*f1*q*log(z + 0.0001); // factor of 16 to reduce the gain
     169        }
    214170        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);
     171    }
     172    return (f);
    223173}
    224174
     
    370320    psEllipseAxes axes;
    371321    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);
     322
     323    float Sindex = 0.5 / PAR[PM_PAR_7];
     324    float norm = pmSersicNorm (Sindex);
     325
     326    float flux = PAR[PM_PAR_I0] * 2.0 * M_PI * axes.major * axes.minor * norm;
     327
     328    return(flux);
    385329}
    386330
     
    401345    pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
    402346
     347    float Sindex = 0.5 / PAR[PM_PAR_7];
     348    float kappa = pmSersicKappa (Sindex);
     349
    403350    // 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]);
     351    psF64 zn = log(PAR[PM_PAR_I0] / flux) / kappa;
     352    psF64 radius = axes.major * pow(zn, Sindex);
    406353
    407354    psAssert (isfinite(radius), "fix this code: radius should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f), par 7 = %f",
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/models/pmModel_TRAIL.c

    r35768 r36680  
    4040#include "pmSourceDiffStats.h"
    4141#include "pmSourceSatstar.h"
     42#include "pmSourceLensing.h"
    4243#include "pmSource.h"
    4344#include "pmSourceFitModel.h"
     
    6162// Lax parameter limits
    6263static float paramsMinLax[] = { -1.0e3, 1.0e-2, -1.0e2, -1.0e2,   0.5, -3.3, -0.5 };
    63 static float paramsMaxLax[] = {  1.0e5, 1.0e+8, +1.0e4, +1.0e4, 150.0, +3.3 , 5.0 };
     64static float paramsMaxLax[] = {  1.0e5, 1.00+9, +1.0e5, +1.0e5, 150.0, +3.3 , 5.0 };
    6465
    6566// Moderate parameter limits
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmDetEff.c

    r34403 r36680  
    2424#include "pmSourceDiffStats.h"
    2525#include "pmSourceSatstar.h"
     26#include "pmSourceLensing.h"
    2627#include "pmSource.h"
    2728#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmFootprintCullPeaks.c

    r34800 r36680  
    2525bool dumpfootprints (pmFootprint *fp, pmFootprintSpans *fpSp);
    2626
    27  /*
    28   * Examine the peaks in a pmFootprint, and throw away the ones that are not sufficiently
    29   * isolated.  More precisely, for each peak find the highest coll that you'd have to traverse
    30   * to reach a still higher peak --- and if that coll's more (less?) than nsigma DN below your
    31   * starting point, discard the peak.
    32   */
     27/*
     28 * Examine the peaks in a pmFootprint, and throw away the ones that are not sufficiently
     29 * isolated.  More precisely, for each peak find the highest coll that you'd have to traverse
     30 * to reach a still higher peak --- and if that coll's more (less?) than nsigma DN below your
     31 * starting point, discard the peak.
     32 */
    3333
    3434# define IN_PEAK 1
     
    4848
    4949    if (fp->peaks == NULL || fp->peaks->n < 2) { // nothing to do
    50         return PS_ERR_NONE;
     50        return PS_ERR_NONE;
    5151    }
    5252
     
    9191
    9292        // max flux is above threshold for brightest peak
    93       pmPeak *maxPeak = NULL;
    94       for (int i = 0; i < fp->peaks->n; i++) {
    95         pmPeak *testPeak = fp->peaks->data[i];
    96         float this_peak = useSmoothedImage ? testPeak->smoothFlux : testPeak->rawFlux;
     93        pmPeak *maxPeak = NULL;
     94        for (int i = 0; i < fp->peaks->n; i++) {
     95            pmPeak *testPeak = fp->peaks->data[i];
     96            float this_peak = useSmoothedImage ? testPeak->smoothFlux : testPeak->rawFlux;
    9797       
    98         if (isfinite(this_peak)) {
    99           maxPeak = fp->peaks->data[i];
    100           break;
    101         }
    102       }
    103       psAssert(maxPeak,"maxPeak was not set in these peaks");
    104       //      = fp->peaks->data[0];
     98            if (isfinite(this_peak)) {
     99                maxPeak = fp->peaks->data[i];
     100                break;
     101            }
     102        }
     103        psAssert(maxPeak,"maxPeak was not set in these peaks");
     104        //      = fp->peaks->data[0];
    105105        float maxFlux = useSmoothedImage ? maxPeak->smoothFlux : maxPeak->rawFlux;
    106106
     
    130130        }
    131131#if (0)
    132         if (threshbounds->data.F32[threshbounds->n-1] > maxFlux) {
    133             psWarning ("upper limit: %f does not include max flux: %f",
    134                     threshbounds->data.F32[threshbounds->n-1], maxFlux);
    135         }
     132        if (threshbounds->data.F32[threshbounds->n-1] > maxFlux) {
     133            psWarning ("upper limit: %f does not include max flux: %f",
     134                       threshbounds->data.F32[threshbounds->n-1], maxFlux);
     135        }
    136136#endif
    137137        psHistogram *threshist = psHistogramAllocGeneric(threshbounds);
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmGrowthCurve.c

    r34403 r36680  
    3737#include "pmSourceDiffStats.h"
    3838#include "pmSourceSatstar.h"
     39#include "pmSourceLensing.h"
    3940#include "pmSource.h"
    4041#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmGrowthCurveGenerate.c

    r34403 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmModel.c

    r34498 r36680  
    217217    // the options allow us to modify various aspects of the model
    218218    if (mode & PM_MODEL_OP_NORM) {
     219        // if we are including the sky, renormalizing should force use to normalized down the sky flux
     220        params->data.F32[PM_PAR_SKY] /= params->data.F32[PM_PAR_I0];
    219221        params->data.F32[PM_PAR_I0] = 1.0;
    220222    }
    221223    if (!(mode & PM_MODEL_OP_SKY)) {
    222224        params->data.F32[PM_PAR_SKY] = 0.0;
    223     }
     225    } 
    224226    if (mode & PM_MODEL_OP_CENTER) {
    225227        params->data.F32[PM_PAR_XPOS] = image->col0 + 0.5*image->numCols;
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmModelClass.c

    r34259 r36680  
    6666
    6767static pmModelClass *models = NULL;
     68static psVector *modelClassLookupTable = NULL;  // translation between model types in header and here
    6869static int Nmodels = 0;
    6970
     
    135136    models = NULL;
    136137    Nmodels = 0;
     138    psFree(modelClassLookupTable);
     139    modelClassLookupTable = NULL;
    137140    return;
    138141}
     
    193196}
    194197
     198
     199bool pmModelClassWriteHeader(psMetadata *header)
     200{
     201    psMetadataAddS32(header, PS_LIST_TAIL, "MTNUM", PS_META_REPLACE, "number of model types", Nmodels);
     202    for (int i = 0; i < Nmodels; i++) {
     203        char modelNameKey[16];
     204        char modelValKey[16];
     205        sprintf(modelNameKey, "MTNAM%02d", i);
     206        sprintf(modelValKey,  "MTVAL%02d", i);
     207        psMetadataAddStr(header, PS_LIST_TAIL, modelNameKey, PS_META_REPLACE, "", models[i].name);
     208        psMetadataAddS32(header, PS_LIST_TAIL, modelValKey, PS_META_REPLACE, "", i);
     209    }
     210
     211    return true;
     212}
     213
     214bool pmModelClassReadHeader(psMetadata *header) {
     215    psFree(modelClassLookupTable);
     216
     217    bool status;
     218    int numHeaderModels = psMetadataLookupS32(&status, header, "MTNUM");
     219    if (!status) {
     220        return false;
     221    }
     222
     223    psVector *inputTypes = psVectorAlloc(numHeaderModels, PS_TYPE_S32);
     224    psVector *localTypes = psVectorAlloc(numHeaderModels, PS_TYPE_S32);
     225    int max_val = -1;
     226    for (int i = 0; i < numHeaderModels; i++) {
     227        char modelNameKey[16];
     228        char modelValKey[16];
     229        sprintf(modelNameKey, "MTNAM%02d", i);
     230        sprintf(modelValKey,  "MTVAL%02d", i);
     231        psString thisName = psMetadataLookupStr(&status, header, modelNameKey);
     232        int thisVal = psMetadataLookupS32(&status, header, modelValKey);
     233        if (thisVal > max_val) {
     234            max_val = thisVal;
     235        }
     236        inputTypes->data.S32[i] = thisVal;
     237        localTypes->data.S32[i] = pmModelClassGetType(thisName);
     238    }
     239    if (max_val < 0) {
     240        psFree(inputTypes);
     241        psFree(localTypes);
     242        return false;
     243    }
     244
     245    modelClassLookupTable = psVectorAlloc(max_val + 1, PS_TYPE_S32);
     246    psVectorInit(modelClassLookupTable, -1);
     247
     248    for (int i = 0; i < numHeaderModels; i++) {
     249        int thisVal = inputTypes->data.S32[i];
     250        int localVal = localTypes->data.S32[i];
     251        modelClassLookupTable->data.S32[thisVal] = localVal;
     252    }
     253    psFree(inputTypes);
     254    psFree(localTypes);
     255
     256    return true;
     257}
     258
     259pmModelType pmModelClassGetLocalType(pmModelType inputType) {
     260    pmModelType localType = -1;
     261
     262    if (modelClassLookupTable) {
     263        if (inputType >= 0 && inputType < modelClassLookupTable->n) {
     264            localType = modelClassLookupTable->data.S32[inputType];
     265        }
     266    } else {
     267        // no lookup table defined
     268        // for backwards compatability if inputType refers to a defined model, return it
     269        if (inputType >= 0 && pmModelClassGetName(inputType)) {
     270            localType = inputType;
     271        }
     272    }
     273
     274    return localType;
     275}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmModelClass.h

    r29004 r36680  
    7676void pmModelClassSetLimits(pmModelLimitsType type);
    7777
     78// write keywords to header definining the model type values used by this program
     79bool pmModelClassWriteHeader(psMetadata *header);
     80// create a lookup table for translating input model type values to local model type values
     81bool pmModelClassReadHeader(psMetadata *header);
     82// translate input model type value to local value
     83pmModelType pmModelClassGetLocalType(pmModelType inputType);
    7884
    7985/// @}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmModelFuncs.h

    r35560 r36680  
    3636
    3737typedef enum {
    38     PM_MODEL_STATUS_NONE         = 0x00, ///< model fit not yet attempted, no other info
    39     PM_MODEL_STATUS_FITTED       = 0x01, ///< model fit completed
    40     PM_MODEL_STATUS_NONCONVERGE  = 0x02, ///< model fit did not converge
    41     PM_MODEL_STATUS_OFFIMAGE     = 0x04, ///< model fit drove out of range
    42     PM_MODEL_STATUS_BADARGS      = 0x08, ///< model fit called with invalid args
    43     PM_MODEL_STATUS_LIMITS       = 0x10, ///< model parameters hit limits
    44     PM_MODEL_STATUS_WEAK_FIT     = 0x20, ///< model fit met loose tolerance, but not tight tolerance
     38    PM_MODEL_STATUS_NONE           = 0x000, ///< model fit not yet attempted, no other info
     39    PM_MODEL_STATUS_FITTED         = 0x001, ///< model fit completed
     40    PM_MODEL_STATUS_NONCONVERGE    = 0x002, ///< model fit did not converge
     41    PM_MODEL_STATUS_OFFIMAGE       = 0x004, ///< model fit drove out of range
     42    PM_MODEL_STATUS_BADARGS        = 0x008, ///< model fit called with invalid args
     43    PM_MODEL_STATUS_LIMITS         = 0x010, ///< model parameters hit limits
     44    PM_MODEL_STATUS_WEAK_FIT       = 0x020, ///< model fit met loose tolerance, but not tight tolerance
     45    PM_MODEL_STATUS_NAN_CHISQ      = 0x040, ///< model fit failed with a NAN chisq
     46    PM_MODEL_SERSIC_PCM_FAIL_GUESS = 0x080, ///< sersic model fit failed on the initial moments-based guess
     47    PM_MODEL_SERSIC_PCM_FAIL_GRID  = 0x100, ///< sersic model fit failed on the grid search
     48    PM_MODEL_PCM_FAIL_GUESS        = 0x200, ///< non-sersic model fit failed on the initial moments-based guess
     49    PM_MODEL_BEST_FIT              = 0x400, ///< this model was the best fit and was subtracted
    4550} pmModelStatus;
    4651
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmModelUtils.c

    r35768 r36680  
    3939#include "pmSourceDiffStats.h"
    4040#include "pmSourceSatstar.h"
     41#include "pmSourceLensing.h"
    4142#include "pmSource.h"
    4243#include "pmSourceFitModel.h"
     
    129130bool pmModelAxesToParams (float *Sxx, float *Sxy, float *Syy, psEllipseAxes axes, bool useReff)  {
    130131
     132    // restrict axex to 0.5 here not below
     133    if (axes.minor < 0.2) axes.minor = 0.2;
     134    if (axes.major < 0.2) axes.major = 0.2;
     135
    131136    psEllipseShape shape = psEllipseAxesToShape (axes);
    132137
     
    137142    // set the shape parameters
    138143    if (useReff) {
    139         *Sxx  = PS_MAX(0.5, shape.sx);
    140         *Syy  = PS_MAX(0.5, shape.sy);
     144        // *Sxx  = PS_MAX(0.5, shape.sx);
     145        // *Syy  = PS_MAX(0.5, shape.sy);
     146        *Sxx  = shape.sx;
     147        *Syy  = shape.sy;
    141148        *Sxy  = shape.sxy * 2.0;
    142149    } else {
    143         *Sxx  = PS_MAX(0.5, M_SQRT2*shape.sx);
    144         *Syy  = PS_MAX(0.5, M_SQRT2*shape.sy);
     150        // *Sxx  = PS_MAX(0.5, M_SQRT2*shape.sx);
     151        // *Syy  = PS_MAX(0.5, M_SQRT2*shape.sy);
     152        *Sxx  = M_SQRT2*shape.sx;
     153        *Syy  = M_SQRT2*shape.sy;
    145154        *Sxy  = shape.sxy;
    146155    }
     
    190199
    191200    if (!isfinite(axes.major)) return false;
     201    if (axes.major == 0) return false;
    192202    if (!isfinite(axes.minor)) return false;
    193203    if (!isfinite(axes.theta)) return false;
     204    if (axes.major == 0) return false;
    194205
    195206    // Mxx, Mxy, Myy define the elliptical shape, but Mrf defines the width
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmMoments.h

    r32347 r36680  
    4444    float Myyyy;   ///< fourth moment
    4545
     46  // float wSum;    ///< window-weighted sum (NOT needed by lensing)
     47
    4648    float Sum;    ///< Pixel sum above sky (background).
    4749    float Peak;   ///< Peak counts above sky.
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPCM_MinimizeChisq.c

    r35768 r36680  
    3838#include "pmSourceDiffStats.h"
    3939#include "pmSourceSatstar.h"
     40#include "pmSourceLensing.h"
    4041#include "pmSource.h"
    4142#include "pmSourceFitModel.h"
    4243#include "pmPCMdata.h"
     44
     45# define SAVE_IMAGES 0
     46# if (SAVE_IMAGES)
     47int psphotSaveImage (psMetadata *header, psImage *image, char *filename);
     48# endif
    4349
    4450# define FACILITY "psModules.objects"
     
    9197    psF32 lambda = 0.001;
    9298    psF32 dLinear = 0.0;
    93     psF32 nu = 2.0;
     99    psF32 nu = 3.0;
    94100
    95101# if (USE_FFT && PRE_CONVOLVE)
     
    130136        }
    131137
     138        if (min->isInteractive) {
     139            fprintf (stderr, "%d : ", min->iter);
     140            for (int ti = 0; ti < params->n; ti++) {
     141                fprintf (stderr, "%f  ", params->data.F32[ti]);
     142            }
     143            fprintf (stderr, " : %f\n", min->value);
     144        }
     145
     146        char key[10]; // used for interactive responses
     147        bool testValue = false;
     148
    132149        // set a new guess for Alpha, Beta, Params
    133150        if (!psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda, &dLinear)) {
     151            if (false && min->isInteractive) {
     152                fprintf (stdout, "guess failed (singular matrix or NaN values), continue? [Y,n] ");
     153                if (!fgets(key, 8, stdin)) {
     154                    psWarning("Unable to read option");
     155                }
     156                switch (key[0]) {
     157                  case 'n':
     158                  case 'N':
     159                    done = true;
     160                    break;
     161                  case 'y':
     162                  case 'Y':
     163                  case '\n':
     164                    lambda *= 10.0;
     165                    continue;
     166                  default:
     167                    lambda *= 10.0;
     168                    continue;
     169                }
     170                if (done) break;
     171            }
    134172            min->iter ++;
    135173            if (min->iter >=  min->maxIter) break;
     
    138176        }
    139177
     178        if (false && min->isInteractive) {
     179            p_psVectorPrint(psTraceGetDestination(), Params, "current parameters: ");
     180            fprintf (stdout, "last chisq : %f\n", min->value);
     181            bool getOptions = true;
     182            while (getOptions) {
     183                fprintf (stdout, "options: (m)odify, (g)o, (q)uit: ");
     184                if (!fgets(key, 8, stdin)) {
     185                    psWarning("Unable to read option");
     186                }
     187                switch (key[0]) {
     188                  case 'm':
     189                  case 'M':
     190                    testValue = TRUE;
     191                    fprintf (stdout, "enter (Npar) (value): ");
     192                    int Npar = 0;
     193                    float value= 0;
     194                    int Nscan = fscanf (stdin, "%d %f", &Npar, &value);
     195                    if (Nscan != 2) {
     196                      fprintf (stderr, "scan failure\n");
     197                    }
     198                    Params->data.F32[Npar] = value;
     199                    break;
     200                  case 'g':
     201                  case 'G':
     202                  case '\n':
     203                    getOptions = false;
     204                    break;
     205                  default:
     206                    done = true;
     207                    break;
     208                }
     209                fprintf (stderr, "foo\n");
     210            }
     211            if (done) break;
     212        }
     213           
    140214        // dump some useful info if trace is defined
    141215        if (psTraceGetLevel(FACILITY) >= 6) {
     
    202276        // XXX : Madsen gives suggestion for better use of rho
    203277        // rho is positive if the new chisq is smaller
    204         if (rho >= -1e-6) {
     278        if (testValue || (rho >= -1e-6)) {
    205279            min->value = Chisq;
    206280            alpha  = psImageCopy(alpha, Alpha, PS_TYPE_F32);
     
    215289          case 0:
    216290            if (rho >= -1e-6) {
    217                 lambda *= 0.25;
     291                lambda *= 0.1;
    218292            } else {
    219293                lambda *= 10.0;
     
    234308            if (rho > 0.0) {
    235309                lambda *= PS_MAX(0.33, (1.0 - pow(2.0*rho - 1.0, 3.0)));
    236                 nu = 2.0;
     310                nu = 3.0;
    237311            } else {
    238312                lambda *= nu;
    239                 nu *= 2.0;
     313                nu *= 3.0;
    240314            }
    241315            break;
     
    408482# else
    409483    if (pcm->use1Dgauss) {
    410         // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
    411         // * the model flux is not masked
    412         // * threading takes place above this level
    413         pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type);
    414         psImageSmooth_PreAlloc_F32 (pcm->modelConvFlux, pcm->smdata);
    415         // psImageSmooth (pcm->modelConvFlux, pcm->sigma, pcm->nsigma);
     484
     485        if (USE_1D_CACHE) {
     486            // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     487            // * the model flux is not masked
     488            // * threading takes place above this level
     489            pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type);
     490            psImageSmoothCache_F32 (pcm->modelConvFlux, pcm->smdata);
     491        } else {
     492            pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type);
     493            psImageSmooth2dCache_F32 (pcm->modelConvFlux, pcm->smdata2d);
     494        }
    416495    } else {
    417496        psImageConvolveKernel (pcm->modelConvFlux, pcm->modelFlux, NULL, 0, pcm->psfFFT);
     
    428507# else
    429508        if (pcm->use1Dgauss) {
    430             // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
    431             // * the model flux is not masked
    432             // * threading takes place above this level
    433             dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
    434             psImageSmooth_PreAlloc_F32 (dmodelConv, pcm->smdata);
    435             // psImageSmooth (dmodelConv, pcm->sigma, pcm->nsigma);
     509            if (USE_1D_CACHE) {
     510                // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     511                // * the model flux is not masked
     512                // * threading takes place above this level
     513                dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     514                psImageSmoothCache_F32 (dmodelConv, pcm->smdata);
     515            } else {
     516                dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     517                psImageSmooth2dCache_F32 (dmodelConv, pcm->smdata2d);
     518            }
    436519        } else {
    437520            psImageConvolveKernel (dmodelConv, dmodel, NULL, 0, pcm->psfFFT);
     
    449532
    450533        if (pcm->use1Dgauss) {
    451             // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
    452             // * the model flux is not masked
    453             // * threading takes place above this level
    454             dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
    455             psImageSmooth_PreAlloc_F32 (dmodelConv, pcm->smdata);
    456             // psImageSmooth (dmodelConv, pcm->sigma, pcm->nsigma);
     534            if (USE_1D_CACHE) {
     535                // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     536                // * the model flux is not masked
     537                // * threading takes place above this level
     538                dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     539                psImageSmoothCache_F32 (dmodelConv, pcm->smdata);
     540            } else {
     541                dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     542                psImageSmooth2dCache_F32 (dmodelConv, pcm->smdata2d);
     543            }
    457544        } else {
    458545            psImageConvolveFFT (dmodelConv, dmodel, NULL, 0, pcm->psf);
     
    474561    // XXX TEST : SAVE IMAGES
    475562# if (SAVE_IMAGES)
    476     psphotSaveImage (NULL, pcm->psf->image, "psf.fits");
    477     psphotSaveImage (NULL, pcm->modelFlux, "model.fits");
    478     psphotSaveImage (NULL, pcm->modelConvFlux, "modelConv.fits");
    479     psphotSaveImage (NULL, source->pixels, "obj.fits");
    480     psphotSaveImage (NULL, source->maskObj, "mask.fits");
    481     psphotSaveImage (NULL, source->variance, "variance.fits");
     563    static int Npass = 0;
     564    char name[128];
     565    if (!pcm->use1Dgauss) {
     566      snprintf (name, 128, "psf.%03d.fits", Npass); psphotSaveImage (NULL, pcm->psf->image, name);
     567    }
     568    snprintf (name, 128, "mod.%03d.fits", Npass); psphotSaveImage (NULL, pcm->modelFlux, name);
     569    snprintf (name, 128, "cnv.%03d.fits", Npass); psphotSaveImage (NULL, pcm->modelConvFlux, name);
     570    snprintf (name, 128, "obj.%03d.fits", Npass); psphotSaveImage (NULL, source->pixels, name);
     571    snprintf (name, 128, "msk.%03d.fits", Npass); psphotSaveImage (NULL, source->maskObj, name);
     572    snprintf (name, 128, "var.%03d.fits", Npass); psphotSaveImage (NULL, source->variance, name);
     573    for (int n = 0; n < pcm->dmodelsFlux->n; n++) {
     574        psImage *dmodelConv = pcm->dmodelsConvFlux->data[n];
     575        if (!dmodelConv) continue;
     576        snprintf (name, 128, "dpar.%01d.%03d.fits", n, Npass); psphotSaveImage (NULL, dmodelConv, name);
     577    }
     578    Npass ++;
    482579# endif
    483580
     
    506603
    507604            float ymodel  = pcm->modelConvFlux->data.F32[i][j];
    508             float yweight = 1.0 / source->variance->data.F32[i][j];
     605
     606            // XXXX note this point here:::
     607            float yweight = pcm->poissonErrors ? 1.0 / source->variance->data.F32[i][j] : 1.0;
    509608            float delta = ymodel - source->pixels->data.F32[i][j];
    510609
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPCMdata.c

    r35768 r36680  
    3838#include "pmSourceDiffStats.h"
    3939#include "pmSourceSatstar.h"
     40#include "pmSourceLensing.h"
    4041#include "pmSource.h"
    4142#include "pmSourceFitModel.h"
     
    4344
    4445# define USE_DELTA_PSF 0
    45 # define USE_1D_GAUSS 1
    4646
    4747static void pmPCMdataFree (pmPCMdata *pcm) {
     
    5858    psFree (pcm->psfFFT);
    5959    psFree (pcm->constraint);
     60
    6061    psFree (pcm->smdata); // pre-allocated data for psImageSmooth_PreAlloc
     62    psFree (pcm->smdata2d); // pre-allocated data for psImageSmooth_PreAlloc
    6163    return;
    6264}
     
    8890    }
    8991
     92    pcm->smdata = NULL;
     93    pcm->smdata2d = NULL;
     94
    9095    pcm->modelConv = NULL;
    9196    pcm->psf = NULL;
     
    9499    pcm->nDOF = 0;
    95100
     101    pcm->poissonErrors = true;
     102
    96103    // full convolution with the PSF is expensive.  if we have to save time, we can do a 1D
    97104    // convolution with a Gaussian approximation to the kernel
    98105    pcm->use1Dgauss = false;
    99     pcm->nsigma = 3.0;
     106    pcm->nsigma = NAN; // this is set to something defined by the user
    100107    pcm->sigma = 1.0; // this should be set to something sensible when the psf is known
    101108
     
    173180}
    174181
     182int pmPCMsetParams (psMinConstraint *constraint, pmSourceFitMode mode) {
     183
     184    // set parameter mask based on fitting mode
     185    int nParams = 0;
     186    int nParAll = constraint->paramMask->n;
     187
     188    switch (mode) {
     189      case PM_SOURCE_FIT_NORM:
     190        // fits only source normalization (Io)
     191        nParams = 1;
     192        psVectorInit (constraint->paramMask, 1);
     193        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
     194        break;
     195
     196      case PM_SOURCE_FIT_PSF:
     197        // fits only x,y,Io
     198        nParams = 3;
     199        psVectorInit (constraint->paramMask, 1);
     200        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
     201        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_XPOS] = 0;
     202        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_YPOS] = 0;
     203        break;
     204
     205      case PM_SOURCE_FIT_EXT:
     206        // fits all params except sky
     207        nParams = nParAll - 1;
     208        psVectorInit (constraint->paramMask, 0);
     209        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
     210        break;
     211
     212      case PM_SOURCE_FIT_EXT_AND_SKY:
     213        // fits all params including sky
     214        nParams = nParAll;
     215        psVectorInit (constraint->paramMask, 0);
     216        break;
     217
     218      case PM_SOURCE_FIT_SHAPE:
     219        // fits shape (Sxx, Sxy, Syy) and Io
     220        nParams = 5;
     221        psVectorInit (constraint->paramMask, 1);
     222        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 0;
     223        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
     224        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SXX] = 0;
     225        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SXY] = 0;
     226        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SYY] = 0;
     227        break;
     228
     229      case PM_SOURCE_FIT_INDEX:
     230        // fits only Io, index (PAR7) -- only Io for models with < 8 params
     231        psVectorInit (constraint->paramMask, 1);
     232        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
     233        if (nParAll == 7) {
     234            nParams = 1;
     235        } else {
     236            nParams = 2;
     237            constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 0;
     238        }
     239        break;
     240
     241      case PM_SOURCE_FIT_NO_INDEX:
     242        // fits all but index (PAR7) including sky
     243        psVectorInit (constraint->paramMask, 0);
     244        if (nParAll == 7) {
     245            nParams = nParAll;
     246        } else {
     247            nParams = nParAll - 1;
     248            constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 1;
     249        }
     250        break;
     251      default:
     252        psAbort("invalid fitting mode");
     253    }
     254    return nParams;
     255}
     256
     257static int modelType_GAUSS = -1;
     258static int modelType_PS1_V1 = -1;
     259
     260// generate a Gaussian smoothing kernel for supplied sigma.  sigma here does not need to match
     261// that used to allocate the structure, but it is recommended
     262bool psImageSmoothCacheKernel_PS1_V1 (psImageSmoothCacheData *smdata, float sigma, float kappa) {
     263    // check for NULL structure elements?
     264
     265    int size = smdata->Nrange;
     266
     267    psFree (smdata->kernel);
     268    smdata->kernel = psVectorAlloc(2 * smdata->Nrange + 1, PS_TYPE_F32);
     269
     270    double sum = 0.0;                   // Sum of Gaussian, for normalization
     271    double factor = 1.0 / (sigma * M_SQRT2);    // Multiplier for i -> z
     272
     273    // PS1_V1 is a power-law with fitted linear term:
     274    // 1 / (1 + kappa z + z^1.666)  where z = (r/sigma)^2
     275
     276    // generate the kernel (not normalized)
     277    for (int i = -size, j = 0; i <= size; i++, j++) {
     278        float z = PS_SQR(i * factor);
     279        sum += smdata->kernel->data.F32[j] = 1.0 / (1 + kappa * z + pow(z,1.666));
     280    }
     281
     282    // renormalize kernel to integral of 1.0
     283    for (int i = 0; i < 2 * size + 1; i++) {
     284        smdata->kernel->data.F32[i] /= sum;
     285    }
     286
     287    return true;
     288}
     289
     290psImageSmoothCacheData *psImageSmoothCacheSetKernel (float *sigma, float *kappa, float nsigma, psImage *flux, pmModel *modelPSF) {
     291
     292    psAssert (modelPSF, "psf model must be defined");
     293   
     294    psEllipseAxes axes;
     295    bool useReff = pmModelUseReff (modelPSF->type);
     296    psF32 *PAR = modelPSF->params->data.F32;
     297    pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);
     298   
     299    *sigma = NAN;
     300    *kappa = NAN;
     301
     302    // XXX need to do this more carefully
     303    if (modelPSF->type == modelType_GAUSS) {
     304        float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);
     305        float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
     306        *sigma = 0.50 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
     307    }
     308    if (modelPSF->type == modelType_PS1_V1) {
     309        *sigma = 0.5 * (axes.major + axes.minor);
     310        *kappa = PAR[PM_PAR_7];
     311    }
     312    psAssert (isfinite(*sigma), "invalid model type");
     313
     314    // psImageSmoothCacheAlloc generates a structure but does not assign the smoothing vector
     315    psImageSmoothCacheData *smdata = psImageSmoothCacheAlloc (flux, *sigma, nsigma);
     316
     317    if (modelPSF->type == modelType_GAUSS) {
     318        psImageSmoothCacheKernel_Gauss (smdata, *sigma);
     319    }
     320    if (modelPSF->type == modelType_PS1_V1) {
     321        psImageSmoothCacheKernel_PS1_V1 (smdata, *sigma, *kappa);
     322    }
     323
     324    return smdata;
     325}
     326
     327psImageSmooth2dCacheData *psImageSmooth2dCacheSetKernel (float *sigma, float *kappa, float nsigma, psImage *flux, pmModel *modelPSF) {
     328
     329    psAssert (modelPSF, "psf model must be defined");
     330   
     331    psEllipseAxes axes;
     332    bool useReff = pmModelUseReff (modelPSF->type);
     333    psF32 *PAR = modelPSF->params->data.F32;
     334    pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);
     335   
     336    *sigma = NAN;
     337    *kappa = NAN;
     338
     339    // XXX need to do this more carefully
     340    if (modelPSF->type == modelType_GAUSS) {
     341        float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);
     342        float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
     343        *sigma = 0.50 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
     344    }
     345    if (modelPSF->type == modelType_PS1_V1) {
     346        *sigma = 0.5 * (axes.major + axes.minor);
     347        *kappa = PAR[PM_PAR_7];
     348    }
     349    psAssert (isfinite(*sigma), "invalid model type");
     350
     351    // psImageSmoothCacheAlloc generates a structure but does not assign the smoothing vector
     352    psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheAlloc (nsigma);
     353
     354    if (modelPSF->type == modelType_GAUSS) {
     355        psImageSmooth2dCacheKernel_Gauss (smdata, *sigma);
     356    }
     357    if (modelPSF->type == modelType_PS1_V1) {
     358        psImageSmooth2dCacheKernel_PS1_V1 (smdata, *sigma, *kappa);
     359    }
     360
     361    return smdata;
     362}
     363
    175364pmPCMdata *pmPCMinit(pmSource *source, pmSourceFitOptions *fitOptions, pmModel *model, psImageMaskType maskVal, float psfSize) {
    176365
    177     // make sure we save a cached copy of the psf flux
    178     pmSourceCachePSF (source, maskVal);
    179 
    180     // convert the cached cached psf model for this source to a psKernel
    181     psKernel *psf = pmPCMkernelFromPSF (source, psfSize);
    182     if (!psf) {
    183         // NOTE: this only happens if the source is too close to an edge
    184         model->flags |= PM_MODEL_STATUS_BADARGS;
    185         return NULL;
    186     }
    187 
    188 # if (USE_DELTA_PSF)
    189     psImageInit (psf->image, 0.0);
    190     psf->image->data.F32[(int)(0.5*psf->image->numRows)][(int)(0.5*psf->image->numCols)] = 1.0;
    191 # endif
     366    modelType_GAUSS = pmModelClassGetType ("PS_MODEL_GAUSS");
     367    modelType_PS1_V1 = pmModelClassGetType ("PS_MODEL_PS1_V1");
    192368
    193369    // count the number of unmasked pixels:
     
    219395    constraint->checkLimits = model->modelLimits;
    220396
    221     // set parameter mask based on fitting mode
    222     int nParams = 0;
    223     switch (fitOptions->mode) {
    224       case PM_SOURCE_FIT_NORM:
    225         // NORM-only model fits only source normalization (Io)
    226         nParams = 1;
    227         psVectorInit (constraint->paramMask, 1);
    228         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
    229         break;
    230       case PM_SOURCE_FIT_PSF:
    231         // PSF model only fits x,y,Io
    232         nParams = 3;
    233         psVectorInit (constraint->paramMask, 1);
    234         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
    235         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_XPOS] = 0;
    236         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_YPOS] = 0;
    237         break;
    238       case PM_SOURCE_FIT_EXT:
    239         // EXT model fits all params (except sky)
    240         nParams = params->n - 1;
    241         psVectorInit (constraint->paramMask, 0);
    242         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
    243         break;
    244       case PM_SOURCE_FIT_INDEX:
    245         // PSF model only fits Io, index (PAR7) -- only Io for models with < 8 params
    246         psVectorInit (constraint->paramMask, 1);
    247         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
    248         if (params->n == 7) {
    249             nParams = 1;
    250         } else {
    251             nParams = 2;
    252             constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 0;
    253         }
    254         break;
    255       case PM_SOURCE_FIT_NO_INDEX:
    256         // PSF model only fits Io, index (PAR7) -- only Io for models with < 8 params
    257         psVectorInit (constraint->paramMask, 0);
    258         constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
    259         if (params->n == 7) {
    260             nParams = params->n - 1;
    261         } else {
    262             nParams = params->n - 2;
    263             constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 1;
    264         }
    265         break;
    266       default:
    267         psAbort("invalid fitting mode");
    268     }
     397    int nParams = pmPCMsetParams (constraint, fitOptions->mode);
    269398
    270399    if (nPix <  nParams + 1) {
    271400        psTrace ("psModules.objects", 4, "insufficient valid pixels\n");
    272         psFree (psf);
    273401        psFree (constraint);
    274402        model->flags |= PM_MODEL_STATUS_BADARGS;
     
    278406    // generate PCM data storage structure
    279407    pmPCMdata *pcm = pmPCMdataAlloc (params, constraint->paramMask, source);
    280 
    281     pcm->psf = psf;
    282408    pcm->modelConv = psMemIncrRefCounter(model);
    283409    pcm->constraint = constraint;
     410
     411    pcm->poissonErrors = fitOptions->poissonErrors;
     412    pcm->nsigma = fitOptions->nsigma;
    284413
    285414    pcm->nPix = nPix;
     
    288417
    289418# if (USE_1D_GAUSS)
    290     pmModel *modelPSF = source->modelPSF;
    291     psAssert (modelPSF, "psf model must be defined");
    292    
    293     psEllipseAxes axes;
    294     bool useReff = pmModelUseReff (modelPSF->type);
    295     psF32 *PAR = modelPSF->params->data.F32;
    296     pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);
    297    
    298     float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);
    299     float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
    300419
    301420    pcm->use1Dgauss = true;
    302     pcm->sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
    303     pcm->nsigma = 2.0;
    304 
    305     pcm->smdata = psImageSmooth_PreAlloc_DataAlloc (source->pixels, pcm->sigma, pcm->nsigma);
     421    if (USE_1D_CACHE) {
     422        pcm->smdata = psImageSmoothCacheSetKernel (&pcm->sigma, &pcm->kappa, pcm->nsigma, source->pixels, source->modelPSF);
     423    } else {
     424        pcm->smdata2d = psImageSmooth2dCacheSetKernel (&pcm->sigma, &pcm->kappa, pcm->nsigma, source->pixels, source->modelPSF);
     425    }
     426
    306427# else
     428    // make sure we save a cached copy of the psf flux
     429    pmSourceCachePSF (source, maskVal);
     430
     431    // convert the cached cached psf model for this source to a psKernel
     432    psKernel *psf = pmPCMkernelFromPSF (source, psfSize);
     433    if (!psf) {
     434        // NOTE: this only happens if the source is too close to an edge
     435        model->flags |= PM_MODEL_STATUS_BADARGS;
     436        return NULL;
     437    }
     438
     439# if (USE_DELTA_PSF)
     440    psImageInit (psf->image, 0.0);
     441    psf->image->data.F32[(int)(0.5*psf->image->numRows)][(int)(0.5*psf->image->numCols)] = 1.0;
     442# endif
     443    pcm->psf = psf;
    307444    pcm->smdata = NULL;
    308445# endif
     
    341478    }
    342479
    343     // if we changed the fit mode, we need to update nDOF
    344     int nParams = 0;
    345     // set parameter mask based on fitting mode
    346     switch (fitOptions->mode) {
    347       case PM_SOURCE_FIT_NORM:
    348         // NORM-only model fits only source normalization (Io)
    349         nParams = 1;
    350         psVectorInit (pcm->constraint->paramMask, 1);
    351         pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
    352         break;
    353       case PM_SOURCE_FIT_PSF:
    354         // PSF model only fits x,y,Io
    355         nParams = 3;
    356         psVectorInit (pcm->constraint->paramMask, 1);
    357         pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
    358         pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_XPOS] = 0;
    359         pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_YPOS] = 0;
    360         break;
    361       case PM_SOURCE_FIT_EXT:
    362         // EXT model fits all params (except sky)
    363         nParams = model->params->n - 1;
    364         psVectorInit (pcm->constraint->paramMask, 0);
    365         pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
    366         break;
    367       case PM_SOURCE_FIT_INDEX:
    368         // PSF model only fits Io, index (PAR7) -- only Io for models with < 8 params
    369         psVectorInit (pcm->constraint->paramMask, 1);
    370         pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
    371         if (model->params->n == 7) {
    372             nParams = 1;
    373         } else {
    374             nParams = 2;
    375             pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 0;
    376         }
    377         break;
    378       case PM_SOURCE_FIT_NO_INDEX:
    379         // PSF model only fits Io, index (PAR7) -- only Io for models with < 8 params
    380         psVectorInit (pcm->constraint->paramMask, 0);
    381         pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
    382         if (model->params->n == 7) {
    383             nParams = model->params->n - 1;
    384         } else {
    385             nParams = model->params->n - 2;
    386             pcm->constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 1;
    387         }
    388         break;
    389       default:
    390         psAbort("invalid fitting mode");
    391     }
     480    int nParams = pmPCMsetParams (pcm->constraint, fitOptions->mode);
    392481
    393482    if (pcm->nPix <  nParams + 1) {
     
    415504            pcm->dmodelsConvFlux->data[n] = psImageCopy (pcm->dmodelsConvFlux->data[n], source->pixels, PS_TYPE_F32);
    416505        }
    417         psFree(pcm->smdata);
    418         pcm->smdata = psImageSmooth_PreAlloc_DataAlloc (source->pixels, pcm->sigma, pcm->nsigma);
     506
     507        // If we have changed the window, we need to redefine the smoothing target vectors (but pcm->sigma,kappa,nsigma remain)
     508        if (USE_1D_CACHE) {
     509            psFree(pcm->smdata);
     510            pcm->smdata = psImageSmoothCacheAlloc (source->pixels, pcm->sigma, pcm->nsigma);
     511
     512            pmModel *modelPSF = source->modelPSF;
     513            if (modelPSF->type == modelType_GAUSS) {
     514                psImageSmoothCacheKernel_Gauss (pcm->smdata, pcm->sigma);
     515            }
     516            if (modelPSF->type == modelType_PS1_V1) {
     517                psImageSmoothCacheKernel_PS1_V1 (pcm->smdata, pcm->sigma, pcm->kappa);
     518            }
     519        } else {
     520            psFree(pcm->smdata2d);
     521            pcm->smdata2d = psImageSmooth2dCacheAlloc (pcm->nsigma);
     522
     523            pmModel *modelPSF = source->modelPSF;
     524            if (modelPSF->type == modelType_GAUSS) {
     525                // psImageSmooth2dCacheKernel_Gauss (pcm->smdata2d, pcm->sigma);
     526            }
     527            if (modelPSF->type == modelType_PS1_V1) {
     528                psImageSmooth2dCacheKernel_PS1_V1 (pcm->smdata2d, pcm->sigma, pcm->kappa);
     529            }
     530        }
    419531    }
    420532
     
    423535
    424536// construct a realization of the source model
    425 bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize) {
     537bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize, float nsigma) {
    426538
    427539    PS_ASSERT_PTR_NON_NULL(source, false);
     
    440552    // convolve the model image with the PSF
    441553    if (USE_1D_GAUSS) {
    442         // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
    443         // * the model flux is not masked
    444         // * threading takes place above this level
    445554       
    446         // define the Gauss parameters from the psf
    447         pmModel *modelPSF = source->modelPSF;
    448         psAssert (modelPSF, "psf model must be defined");
    449    
    450         psEllipseAxes axes;
    451         bool useReff = pmModelUseReff (modelPSF->type);
    452         psF32 *PAR = modelPSF->params->data.F32;
    453         pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);
    454    
    455         float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);
    456         float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
    457 
    458         float sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
    459         float nsigma = 2.0;
    460 
    461         psImageSmooth (source->modelFlux, sigma, nsigma);
     555        float sigma = NAN;
     556        float kappa = NAN;
     557
     558        if (USE_1D_CACHE) {
     559            psImageSmoothCacheData *smdata = psImageSmoothCacheSetKernel (&sigma, &kappa, nsigma, source->modelFlux, source->modelPSF);
     560            psImageSmoothCache_F32 (source->modelFlux, smdata);
     561            psFree (smdata);
     562        } else {
     563            psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheSetKernel (&sigma, &kappa, nsigma, source->modelFlux, source->modelPSF);
     564            psImageSmooth2dCache_F32 (source->modelFlux, smdata);
     565            psFree (smdata);
     566        }
     567        // old call: psImageSmooth (source->modelFlux, sigma, nsigma);
    462568    } else {
    463569        // make sure we save a cached copy of the psf flux
     
    478584}
    479585
     586// construct a realization of the source model
     587bool pmPCMMakeModel (pmSource *source, pmModel *model, float Nsigma, psImageMaskType maskVal, int psfSize) {
     588
     589    PS_ASSERT_PTR_NON_NULL(source, false);
     590
     591    // if we already have a cached image, re-use that memory
     592    source->modelFlux = psImageCopy (source->modelFlux, source->pixels, PS_TYPE_F32);
     593    psImageInit (source->modelFlux, 0.0);
     594
     595    // modelFlux always has unity normalization (I0 = 1.0)
     596    // pmModelAdd (source->modelFlux, source->maskObj, model, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM, maskVal);
     597    pmModelAdd (source->modelFlux, NULL, model, PM_MODEL_OP_FULL | PM_MODEL_OP_SKY | PM_MODEL_OP_NORM, maskVal);
     598
     599    // convolve the model image with the PSF
     600    if (USE_1D_GAUSS) {
     601
     602        float sigma = NAN;
     603        float kappa = NAN;
     604
     605        if (USE_1D_CACHE) {
     606            psImageSmoothCacheData *smdata = psImageSmoothCacheSetKernel (&sigma, &kappa, Nsigma, source->modelFlux, source->modelPSF);
     607            psImageSmoothCache_F32 (source->modelFlux, smdata);
     608            psFree (smdata);
     609        } else {
     610            psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheSetKernel (&sigma, &kappa, Nsigma, source->modelFlux, source->modelPSF);
     611            psImageSmooth2dCache_F32 (source->modelFlux, smdata);
     612            psFree (smdata);
     613        }
     614        // old call: psImageSmooth (source->modelFlux, sigma, nsigma);
     615    } else {
     616        // make sure we save a cached copy of the psf flux
     617        pmSourceCachePSF (source, maskVal);
     618
     619        // convert the cached cached psf model for this source to a psKernel
     620        psKernel *psf = pmPCMkernelFromPSF (source, psfSize);
     621        if (!psf) {
     622            // NOTE: this only happens if the source is too close to an edge
     623            model->flags |= PM_MODEL_STATUS_BADARGS;
     624            return NULL;
     625        }
     626
     627        // XXX not sure if I can place the output on top of the input
     628        psImageConvolveFFT (source->modelFlux, source->modelFlux, NULL, 0, psf);
     629    }
     630    return true;
     631}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPCMdata.h

    r32725 r36680  
    1414/// @addtogroup Objects Object Detection / Analysis Functions
    1515/// @{
     16
     17// XXX this is basically for testing -- when I am happy with the convolution process, I'll strip this out
     18# define USE_1D_CACHE 0
     19# define USE_1D_GAUSS 1
    1620
    1721/** pmPCMdata : PSF Convolved Model data storage structure
     
    3640    int nDOF;
    3741
     42    bool poissonErrors;
     43
    3844    bool use1Dgauss;
     45    float kappa;
    3946    float sigma;
    4047    float nsigma;
    4148
    42     psImageSmooth_PreAlloc_Data *smdata;
     49    // psArray *smdata;
     50    psImageSmoothCacheData *smdata;
     51    psImageSmooth2dCacheData *smdata2d;
    4352} pmPCMdata;
    4453
     
    96105bool pmSourceFitPCM (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
    97106
    98 bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize);
     107bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize, float nsigma);
     108
     109bool pmPCMMakeModel (pmSource *source, pmModel *model, float Nsigma, psImageMaskType maskVal, int psfSize);
    99110
    100111/// @}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPSF.c

    r35768 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPSF_IO.c

    r34403 r36680  
    5454#include "pmSourceDiffStats.h"
    5555#include "pmSourceSatstar.h"
     56#include "pmSourceLensing.h"
    5657#include "pmSource.h"
    5758#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPSFtry.c

    r34403 r36680  
    3636#include "pmSourceDiffStats.h"
    3737#include "pmSourceSatstar.h"
     38#include "pmSourceLensing.h"
    3839#include "pmSource.h"
    3940#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPSFtryFitEXT.c

    r35768 r36680  
    3636#include "pmSourceDiffStats.h"
    3737#include "pmSourceSatstar.h"
     38#include "pmSourceLensing.h"
    3839#include "pmSource.h"
    3940#include "pmSourceUtils.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPSFtryFitPSF.c

    r35768 r36680  
    3434#include "pmSourceDiffStats.h"
    3535#include "pmSourceSatstar.h"
     36#include "pmSourceLensing.h"
    3637#include "pmSource.h"
    3738#include "pmSourceFitModel.h"
     
    7576            psfTry->mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = PSFTRY_MASK_BAD_MODEL;
    7677            psTrace ("psModules.objects", 4, "dropping %d (%d,%d) : bad PSF fit\n", i, source->peak->x, source->peak->y);
    77             return false;
     78            continue;
    7879        }
    7980
     
    118119    psfTry->psf->nPSFstars = Npsf;
    119120
    120     // DEBUG code: save the PSF model fit data in detail
    121 # ifdef DEBUG
    122 
    123     char filename[64];
    124     snprintf (filename, 64, "psffit.%dx%d.dat", psfTry->psf->trendNx, psfTry->psf->trendNy);
    125     FILE *f = fopen (filename, "w");
    126     psAssert (f, "failed open");
    127 
    128     for (int i = 0; i < psfTry->sources->n; i++) {
    129 
    130         // skip masked sources
    131         if (psfTry->mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PSFTRY_MASK_ALL) continue;
    132 
    133         pmSource *source = psfTry->sources->data[i];
    134 
    135         fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f\n",
    136                  source->peak->xf, source->peak->yf,
    137                  source->modelPSF->params->data.F32[PM_PAR_XPOS], source->modelPSF->params->data.F32[PM_PAR_YPOS],
    138                  source->psfMag, source->apMag, source->psfMagErr,
    139                  source->modelPSF->params->data.F32[PM_PAR_I0],
    140                  source->modelPSF->params->data.F32[PM_PAR_SXX], source->modelPSF->params->data.F32[PM_PAR_SXY],
    141                  source->modelPSF->params->data.F32[PM_PAR_SYY], source->modelPSF->params->data.F32[PM_PAR_7]);
    142     }
    143     fclose (f);
    144 # endif
    145 
    146121    pmSourceVisualShowModelFits (psfTry->psf, psfTry->sources, maskVal);
    147122
    148     psLogMsg ("psphot.psftry", PS_LOG_MINUTIA, "fit psf:   %f sec for %d of %ld sources\n", psTimerMark ("psf.fit"), Npsf, psfTry->sources->n);
     123    psLogMsg ("psphot.psftry", PS_LOG_MINUTIA, "fit psf:   %f sec for %d of %ld sources (%d x %d model)\n", psTimerMark ("psf.fit"), Npsf, psfTry->sources->n, psfTry->psf->trendNx, psfTry->psf->trendNy);
    149124    psTrace ("psModules.object", 3, "keeping %d of %ld PSF candidates (PSF)\n", Npsf, psfTry->sources->n);
    150125
    151126    if (Npsf == 0) {
    152         psError(PS_ERR_UNKNOWN, false, "No sources with good PSF fits after model is built.");
    153         return false;
     127#if 0
     128        // DEBUG code: save the PSF model fit data in detail
     129
     130        char hostname[256];
     131        gethostname (hostname, 256);
     132
     133        int pid = getpid();
     134
     135        char filename[64];
     136        snprintf (filename, 64, "psffit.%s.%d.%dx%d.dat", hostname, pid, psfTry->psf->trendNx, psfTry->psf->trendNy);
     137        FILE *f = fopen (filename, "w");
     138        psAssert (f, "failed open");
     139
     140        for (int i = 0; i < psfTry->sources->n; i++) {
     141
     142            // skip masked sources
     143          // if (psfTry->mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & PSFTRY_MASK_ALL) continue;
     144
     145            pmSource *source = psfTry->sources->data[i];
     146
     147            if (!source->modelPSF) continue;
     148
     149            float par7 = (source->modelPSF->params->n == 7) ? -100 : source->modelPSF->params->data.F32[PM_PAR_7];
     150            fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f %d\n",
     151                     source->peak->xf, source->peak->yf,
     152                     source->modelPSF->params->data.F32[PM_PAR_XPOS], source->modelPSF->params->data.F32[PM_PAR_YPOS],
     153                     source->psfMag, source->apMag, source->psfMagErr,
     154                     source->modelPSF->params->data.F32[PM_PAR_I0],
     155                     source->modelPSF->params->data.F32[PM_PAR_SXX], source->modelPSF->params->data.F32[PM_PAR_SXY],
     156                     source->modelPSF->params->data.F32[PM_PAR_SYY], par7,
     157                     psfTry->mask->data.PS_TYPE_VECTOR_MASK_DATA[i]);
     158        }
     159        fclose (f);
     160#endif
     161        psError(PS_ERR_UNKNOWN, false, "No sources with good PSF fits after model is built.");
     162        return false;
    154163    }
    155164
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPSFtryMakePSF.c

    r35768 r36680  
    3535#include "pmSourceDiffStats.h"
    3636#include "pmSourceSatstar.h"
     37#include "pmSourceLensing.h"
    3738#include "pmSource.h"
    3839#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPSFtryMetric.c

    r34403 r36680  
    3535#include "pmSourceDiffStats.h"
    3636#include "pmSourceSatstar.h"
     37#include "pmSourceLensing.h"
    3738#include "pmSource.h"
    3839#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPSFtryModel.c

    r34403 r36680  
    3636#include "pmSourceDiffStats.h"
    3737#include "pmSourceSatstar.h"
     38#include "pmSourceLensing.h"
    3839#include "pmSource.h"
    3940#include "pmSourceFitModel.h"
     
    111112
    112113    // set the max order (0 = constant) which the number of psf stars can support:
     114    int MaxOrderForStars = 0;
     115
     116    // we require only 3 stars for n = 0, increase stars / cell for higher order
     117    if (sources->n >=  16) MaxOrderForStars = 1; //  4 cells, 4 per cell
     118    if (sources->n >=  54) MaxOrderForStars = 2; //  9 cells, 6 per cell
     119    if (sources->n >= 128) MaxOrderForStars = 3; // 16 cells, 8 per cell
     120    if (sources->n >= 300) MaxOrderForStars = 4; // 25 cells, 12 per cell
     121    if (sources->n >  576) MaxOrderForStars = 5; // 36 cells, 16 per cell
     122
    113123    // rule of thumb: require 3 stars per 'cell' (order+1)^2
    114     int MaxOrderForStars = 0;
    115     if (sources->n >= 12) MaxOrderForStars = 1; // 4 cells
    116     if (sources->n >= 27) MaxOrderForStars = 2; // 9 cells
    117     if (sources->n >= 48) MaxOrderForStars = 3; // 16 cells
    118     if (sources->n >  75) MaxOrderForStars = 4; // 25 cells
     124    // if (sources->n >= 12) MaxOrderForStars = 1; // 4 cells
     125    // if (sources->n >= 27) MaxOrderForStars = 2; // 9 cells
     126    // if (sources->n >= 48) MaxOrderForStars = 3; // 16 cells
     127    // if (sources->n >= 75) MaxOrderForStars = 4; // 25 cells
     128    // if (sources->n > 108) MaxOrderForStars = 5; // 36 cells
    119129
    120130    int orderMax = PS_MAX (options->psfTrendNx, options->psfTrendNy);
     
    236246    // linear clipped fit of chisq trend vs flux
    237247    if (options->chiFluxTrend) {
     248
     249        if (0) {
     250            FILE *f = fopen ("test.psf.dat", "w");
     251            int fd = fileno (f);
     252            p_psVectorPrint (fd, flux, "flux");
     253            p_psVectorPrint (fd, chisq, "chisq");
     254            p_psVectorPrint (fd, mask, "mask");
     255            fclose (f);
     256        }
     257
    238258        bool result = psVectorClipFitPolynomial1D(psfTry->psf->ChiTrend, options->stats,
    239259                                                  mask, 0xff, chisq, NULL, flux);
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmPhotObj.c

    r34403 r36680  
    3636#include "pmSourceDiffStats.h"
    3737#include "pmSourceSatstar.h"
     38#include "pmSourceLensing.h"
    3839#include "pmSource.h"
    3940
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSource.c

    r35768 r36680  
    4141#include "pmSourcePhotometry.h"
    4242#include "pmSourceSatstar.h"
     43#include "pmSourceLensing.h"
    4344#include "pmSource.h"
    4445
     
    6667    psFree(tmp->extpars);
    6768    psFree(tmp->diffStats);
     69    psFree(tmp->galaxyFits);
    6870    psFree(tmp->radialAper);
     71    psFree(tmp->lensingOBJ);
     72    psFree(tmp->lensingPSF);
    6973    psTrace("psModules.objects", 10, "---- end ----\n");
    7074}
     
    164168    source->extpars = NULL;
    165169    source->diffStats = NULL;
     170    source->galaxyFits = NULL;
     171    source->lensingOBJ = NULL;
     172    source->lensingPSF = NULL;
    166173    source->radialAper = NULL;
    167174    source->parent = NULL;
     
    247254
    248255    source->region           = in->region;
     256
     257    // XXX I am not copying the pointers to things like the blends, satstar profile, galaxyFits, etc
    249258
    250259    return(source);
     
    690699            // why do we recalculate moments here?
    691700            // we already attempt to do this in psphotSourceStats
    692             // pmSourceMoments (source, INNER_RADIUS);
    693701            Nsatstar ++;
    694702            continue;
     
    804812    return true;
    805813}
    806 
    807 /******************************************************************************
    808 pmSourceMoments(source, radius): this function takes a subImage defined in the
    809 pmSource data structure, along with the peak location, and determines the
    810 various moments associated with that peak.
    811 
    812 Requires the following to have been created:
    813     pmSource
    814     pmSource->peak
    815     pmSource->pixels
    816     pmSource->variance
    817     pmSource->mask
    818 
    819 XXX: The peak calculations are done in image coords, not subImage coords.
    820 
    821 XXX EAM : this version clips input pixels on S/N
    822 XXX EAM : this version returns false for several reasons
    823 *****************************************************************************/
    824 # define VALID_RADIUS(X,Y,RAD2) (((RAD2) >= (PS_SQR(X) + PS_SQR(Y))) ? 1 : 0)
    825 
    826 /*** this been moved to pmSourceMoments.c ***/
    827 # if (0)
    828 bool pmSourceMoments(pmSource *source,
    829                      psF32 radius)
    830 {
    831     psTrace("psModules.objects", 10, "---- begin ----\n");
    832     PS_ASSERT_PTR_NON_NULL(source, false);
    833     PS_ASSERT_PTR_NON_NULL(source->peak, false);
    834     PS_ASSERT_PTR_NON_NULL(source->pixels, false);
    835     PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false);
    836 
    837     //
    838     // XXX: Verify the setting for sky if source->moments == NULL.
    839     //
    840     psF32 sky = 0.0;
    841     if (source->moments == NULL) {
    842         source->moments = pmMomentsAlloc();
    843     } else {
    844         sky = source->moments->Sky;
    845     }
    846 
    847     //
    848     // Sum = SUM (z - sky)
    849     // X1  = SUM (x - xc)*(z - sky)
    850     // X2  = SUM (x - xc)^2 * (z - sky)
    851     // XY  = SUM (x - xc)*(y - yc)*(z - sky)
    852     //
    853     psF32 peakPixel = -PS_MAX_F32;
    854     psS32 numPixels = 0;
    855     psF32 Sum = 0.0;
    856     psF32 Var = 0.0;
    857     psF32 X1 = 0.0;
    858     psF32 Y1 = 0.0;
    859     psF32 X2 = 0.0;
    860     psF32 Y2 = 0.0;
    861     psF32 XY = 0.0;
    862     psF32 x  = 0;
    863     psF32 y  = 0;
    864     psF32 R2 = PS_SQR(radius);
    865 
    866     psF32 xPeak = source->peak->x;
    867     psF32 yPeak = source->peak->y;
    868     psF32 xOff = source->pixels->col0 - source->peak->x;
    869     psF32 yOff = source->pixels->row0 - source->peak->y;
    870 
    871     // XXX why do I get different results for these two methods of finding Sx?
    872     // XXX Sx, Sy would be better measured if we clip pixels close to sky
    873     // XXX Sx, Sy can still be imaginary, so we probably need to keep Sx^2?
    874     // We loop through all pixels in this subimage (source->pixels), and for each
    875     // pixel that is not masked, AND within the radius of the peak pixel, we
    876     // proceed with the moments calculation.  need to do two loops for a
    877     // numerically stable result.  first loop: get the sums.
    878     // XXX EAM : mask == 0 is valid
    879 
    880     for (psS32 row = 0; row < source->pixels->numRows ; row++) {
    881 
    882         psF32 *vPix = source->pixels->data.F32[row];
    883         psF32 *vWgt = source->variance->data.F32[row];
    884         psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
    885 
    886         for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
    887             if (vMsk) {
    888                 if (*vMsk) {
    889                     vMsk++;
    890                     psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to mask: %d\n",
    891                             col, row, (int)*vMsk);
    892                     continue;
    893                 }
    894                 vMsk++;
    895             }
    896             if (isnan(*vPix)) continue;
    897 
    898             psF32 xDiff = col + xOff;
    899             psF32 yDiff = row + yOff;
    900 
    901             // radius is just a function of (xDiff, yDiff)
    902             if (!VALID_RADIUS(xDiff, yDiff, R2)) {
    903 #if 1
    904                 psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to position: %f %f\n",
    905                         col, row, xDiff, yDiff);
    906 #endif
    907                 continue;
    908             }
    909 
    910             psF32 pDiff = *vPix - sky;
    911             psF32 wDiff = *vWgt;
    912 
    913             // XXX EAM : check for valid S/N in pixel
    914             // XXX EAM : should this limit be user-defined?
    915 #if 1
    916             if (PS_SQR(pDiff) < wDiff) {
    917                 psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to insignificance: %f, %f\n",
    918                         col, row, pDiff, wDiff);
    919                 continue;
    920             }
    921 #endif
    922 
    923             Var += wDiff;
    924             Sum += pDiff;
    925 
    926             psF32 xWght = xDiff * pDiff;
    927             psF32 yWght = yDiff * pDiff;
    928 
    929             X1  += xWght;
    930             Y1  += yWght;
    931 
    932             XY  += xDiff * yWght;
    933             X2  += xDiff * xWght;
    934             Y2  += yDiff * yWght;
    935 
    936             peakPixel = PS_MAX (*vPix, peakPixel);
    937             numPixels++;
    938         }
    939     }
    940 
    941     // if we have less than (1/4) of the possible pixels, force a retry
    942     // XXX EAM - the limit is a bit arbitrary.  make it user defined?
    943     if ((numPixels < 0.75*R2) || (Sum <= 0)) {
    944         psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n",
    945                  numPixels, (int)(0.75*R2), Sum);
    946         psTrace("psModules.objects", 10, "---- end (false) ----\n");
    947         return (false);
    948     }
    949 
    950     psTrace ("psModules.objects", 4, "sky: %f  Sum: %f  X1: %f  Y1: %f  X2: %f  Y2: %f  XY: %f  Npix: %d\n",
    951              sky, Sum, X1, Y1, X2, Y2, XY, numPixels);
    952 
    953     //
    954     // first moment X  = X1/Sum + xc
    955     // second moment X = sqrt (X2/Sum - (X1/Sum)^2)
    956     // Sxy             = XY / Sum
    957     //
    958     x = X1/Sum;
    959     y = Y1/Sum;
    960     if ((fabs(x) > radius) || (fabs(y) > radius)) {
    961         psTrace ("psModules.objects", 3, "large centroid swing; invalid peak %d, %d\n",
    962                  source->peak->x, source->peak->y);
    963         psTrace("psModules.objects", 10, "---- end(false)  ----\n");
    964         return (false);
    965     }
    966 
    967     source->moments->Mx = x + xPeak;
    968     source->moments->My = y + yPeak;
    969 
    970     // XXX EAM : Sxy needs to have x*y subtracted
    971     source->moments->Mxy = XY/Sum - x*y;
    972     source->moments->Sum = Sum;
    973     source->moments->SN  = Sum / sqrt(Var);
    974     source->moments->Peak = peakPixel;
    975     source->moments->nPixels = numPixels;
    976 
    977     // XXX EAM : these values can be negative, so we need to limit the range
    978     // XXX EAM : make the use of this consistent: should this be the second moment or sqrt?
    979     // source->moments->Mxx = sqrt(PS_MAX(X2/Sum - PS_SQR(x), 0));
    980     // source->moments->Myy = sqrt(PS_MAX(Y2/Sum - PS_SQR(y), 0));
    981     source->moments->Mxx = PS_MAX(X2/Sum - PS_SQR(x), 0);
    982     source->moments->Myy = PS_MAX(Y2/Sum - PS_SQR(y), 0);
    983 
    984     psTrace ("psModules.objects", 4,
    985              "sky: %f  Sum: %f  Mx: %f  My: %f  Mxx: %f  Myy: %f  Mxy: %f\n",
    986              sky, Sum, source->moments->Mx, source->moments->My,
    987              source->moments->Mxx, source->moments->Myy, source->moments->Mxy);
    988 
    989     psTrace("psModules.objects", 10, "---- end ----\n");
    990     return(true);
    991 }
    992 # endif
    993814
    994815// construct a realization of the source model
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSource.h

    r34403 r36680  
    4040    PM_SOURCE_TMPF_PETRO_KEEP        = 0x0100,
    4141    PM_SOURCE_TMPF_PETRO_SKIP        = 0x0200,
     42    PM_SOURCE_TMPF_EXT_FIT           = 0x0400,  // not just galaxies (trails as well)
     43    PM_SOURCE_TMPF_PETRO             = 0x0800,
    4244} pmSourceTmpF;
    4345
     
    117119    pmSourceExtendedPars *extpars;      ///< extended source parameters
    118120    pmSourceDiffStats *diffStats;       ///< extra parameters for difference detections
     121    pmSourceGalaxyFits *galaxyFits;     ///< fits to galaxy models (psphotFullForce only)
     122    pmSourceLensing *lensingOBJ;        ///< lensing moments parameters (per object)
     123    pmSourceLensing *lensingPSF;        ///< lensing moments parameters (psf, interpolated)
    119124    psArray *radialAper;                ///< radial flux in circular apertures
    120125    pmSource *parent;                   ///< reference to the master source from which this is derived
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceContour.c

    r34403 r36680  
    4040#include "pmSourceDiffStats.h"
    4141#include "pmSourceSatstar.h"
     42#include "pmSourceLensing.h"
    4243#include "pmSource.h"
    4344
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceExtendedPars.c

    r34403 r36680  
    286286    return pars;
    287287}
     288
     289// *** pmSourceExtFitPars describes extra metadata related to an extended fit
     290static void pmSourceGalaxyFitsFree (pmSourceGalaxyFits *tmp) {
     291 
     292    psFree (tmp->Flux);
     293    psFree (tmp->dFlux);
     294    psFree (tmp->chisq);
     295
     296    return;
     297}
     298
     299pmSourceGalaxyFits *pmSourceGalaxyFitsAlloc (void) {
     300
     301    pmSourceGalaxyFits *tmp = (pmSourceGalaxyFits *) psAlloc(sizeof(pmSourceGalaxyFits));
     302    psMemSetDeallocator(tmp, (psFreeFunc) pmSourceGalaxyFitsFree);
     303
     304    tmp->Flux  = psVectorAllocEmpty (25, PS_TYPE_F32);
     305    tmp->dFlux = psVectorAllocEmpty (25, PS_TYPE_F32);
     306    tmp->chisq = psVectorAllocEmpty (25, PS_TYPE_F32);
     307    tmp->nPix = 0;
     308
     309    return tmp;
     310}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceExtendedPars.h

    r32347 r36680  
    8282} pmSourceExtFitPars;
    8383
     84typedef struct {
     85  psVector *Flux;
     86  psVector *dFlux;
     87  psVector *chisq;
     88  int nPix;
     89} pmSourceGalaxyFits;
     90
    8491pmSourceRadialFlux *pmSourceRadialFluxAlloc();
    8592bool psMemCheckSourceRadialFlux(psPtr ptr);
     
    109116pmSourceExtFitPars *pmSourceExtFitParsAlloc (void);
    110117
     118pmSourceGalaxyFits *pmSourceGalaxyFitsAlloc (void);
     119
    111120/// @}
    112121# endif /* PM_SOURCE_H */
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceFitModel.c

    r35768 r36680  
    4040#include "pmSourceDiffStats.h"
    4141#include "pmSourceSatstar.h"
     42#include "pmSourceLensing.h"
    4243#include "pmSource.h"
    4344#include "pmSourcePhotometry.h"
     
    5960    opt->maxTol = 1.00;
    6061    opt->weight = 1.00;
     62    opt->nsigma = 5.00;
    6163    opt->maxChisqDOF = NAN;
    6264    opt->poissonErrors = true;
     
    6668    opt->gainFactorMode = 0;
    6769    opt->chisqConvergence = true;
     70    opt->isInteractive = false;
    6871
    6972    return opt;
     
    247250    myMin->gainFactorMode = options->gainFactorMode;
    248251    myMin->chisqConvergence = options->chisqConvergence;
     252    myMin->isInteractive = options->isInteractive;
    249253
    250254    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
     
    279283    // set the model success or failure status
    280284    model->flags |= PM_MODEL_STATUS_FITTED;
    281     if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;
     285    if (!fitStatus) {
     286        if (isnan(myMin->value)) {
     287          model->flags |= PM_MODEL_STATUS_NAN_CHISQ;
     288        } else {
     289          model->flags |= PM_MODEL_STATUS_NONCONVERGE;
     290        }
     291    }
    282292
    283293    if (myMin->chisqConvergence) {
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceFitModel.h

    r35768 r36680  
    2121    PM_SOURCE_FIT_EXT_AND_SKY,
    2222    PM_SOURCE_FIT_INDEX,
     23    PM_SOURCE_FIT_SHAPE,
    2324    PM_SOURCE_FIT_NO_INDEX,
    2425    PM_SOURCE_FIT_TRAIL,
     
    3334    float weight;                       ///< use this weight for constant-weight fits
    3435    float covarFactor;                  ///< covariance factor for calculating the chisq
     36    float nsigma;                       ///< how far out to convolve
    3537    bool poissonErrors;                 ///< use poisson errors for fits?
    3638    bool saveCovariance;
    3739    int gainFactorMode;
    3840    bool chisqConvergence;
     41    bool isInteractive;
    3942} pmSourceFitOptions;
    4043
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceFitPCM.c

    r35768 r36680  
    3838#include "pmSourceDiffStats.h"
    3939#include "pmSourceSatstar.h"
     40#include "pmSourceLensing.h"
    4041#include "pmSource.h"
    4142#include "pmSourcePhotometry.h"
     
    5152# define TIMING 0
    5253
     54bool pmSourceChisqModelFlux (pmSource *source, pmModel *model, psImageMaskType maskVal);
     55
    5356bool pmSourceFitPCM (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
    5457   
     
    6871    myMin->chisqConvergence = fitOptions->chisqConvergence;
    6972    myMin->gainFactorMode = fitOptions->gainFactorMode;
     73    myMin->isInteractive = fitOptions->isInteractive;
    7074
    7175    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
     
    112116    } else {
    113117        // xxx this is wrong because it does not convolve with the psf
    114         pmSourceChisqUnsubtracted (source, pcm->modelConv, maskVal);
     118        pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize);
     119        pmSourceChisqModelFlux (source, pcm->modelConv, maskVal);
    115120    }
    116121    if (TIMING) { t4 = psTimerMark ("pmSourceFitPCM"); }
     
    118123    // set the model success or failure status
    119124    pcm->modelConv->flags |= PM_MODEL_STATUS_FITTED;
    120     if (!fitStatus) pcm->modelConv->flags |= PM_MODEL_STATUS_NONCONVERGE;
     125
     126    if (!fitStatus) {
     127        if (isnan(myMin->value)) {
     128            pcm->modelConv->flags |= PM_MODEL_STATUS_NAN_CHISQ;
     129        } else {
     130            pcm->modelConv->flags |= PM_MODEL_STATUS_NONCONVERGE;
     131        }
     132    }
    121133
    122134    if (myMin->chisqConvergence) {
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceFitSet.c

    r35768 r36680  
    3939#include "pmSourceDiffStats.h"
    4040#include "pmSourceSatstar.h"
     41#include "pmSourceLensing.h"
    4142#include "pmSource.h"
    4243#include "pmSourcePhotometry.h"
     
    352353        // set the model success or failure status
    353354        model->flags |= PM_MODEL_STATUS_FITTED;
    354         if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;
     355        if (!fitStatus) {
     356          if (isnan(myMin->value)) {
     357            model->flags |= PM_MODEL_STATUS_NAN_CHISQ;
     358          } else {
     359            model->flags |= PM_MODEL_STATUS_NONCONVERGE;
     360          }
     361        }
    355362
    356363        // models can go insane: reject these
     
    570577    myMin->gainFactorMode = options->gainFactorMode;
    571578    myMin->chisqConvergence = options->chisqConvergence;
     579    myMin->isInteractive = options->isInteractive;
    572580
    573581    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceGroups.c

    r34403 r36680  
    2525#include "pmSourceDiffStats.h"
    2626#include "pmSourceSatstar.h"
     27#include "pmSourceLensing.h"
    2728#include "pmSource.h"
    2829#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO.c

    r35610 r36680  
    4747#include "pmSourceDiffStats.h"
    4848#include "pmSourceSatstar.h"
     49#include "pmSourceLensing.h"
    4950#include "pmSource.h"
    5051#include "pmSourceFitModel.h"
     
    6162static bool pmReadoutReadXFIT(pmFPAfile *file, pmReadout *readout, char * exttype, psMetadata *hduHeader, psString xfitname, psArray *sources, long *sourceIndex);
    6263static bool pmReadoutReadXRAD(pmFPAfile *file, pmReadout *readout, char * exttype, psMetadata *hduHeader, psString xfitname, psArray *sources, long *sourceIndex);
     64static bool pmReadoutReadXGAL(pmFPAfile *file, pmReadout *readout, char * exttype, psMetadata *hduHeader, psString xfitname, psArray *sources, long *sourceIndex);
    6365
    6466// lookup the EXTNAME values used for table data and image header segments
     
    6971                        psString *xfitname,    // Extension name for extended fitted measurements
    7072                        psString *xradname,    // Extension name for radial apertures
     73                        psString *xgalname,    // Extension name for galaxy shapes
    7174                        const pmFPAfile *file, // File of interest
    7275                        const pmFPAview *view  // View to level of interest
     
    140143        }
    141144        *xradname = pmFPAfileNameFromRule (rule, file, view);
     145    }
     146
     147    // EXTNAME for radial apertures
     148    if (xgalname) {
     149        const char *rule = psMetadataLookupStr(&status, menu, "CMF.XGAL");
     150        if (!rule) {
     151            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XGAL in EXTNAME.RULES in camera.config");
     152            return false;
     153        }
     154        *xgalname = pmFPAfileNameFromRule (rule, file, view);
    142155    }
    143156
     
    362375            status &= pmSourcesWrite_##TYPE##_XRAD (file->fits, readout, sources, file->header, xradname, recipe); \
    363376        }                                                               \
     377        if (xgalname) {                                                 \
     378            status &= pmSourcesWrite_##TYPE##_XGAL (file->fits, readout, sources, xgalname, recipe); \
     379        }                                                               \
    364380    }
    365381
     
    464480        }
    465481
    466         // if this is not TRUE, the output files only contain the psf measurements.
    467         bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_ANALYSIS");
     482        // if none of these are TRUE, the output files only contain the psf measurements.
     483        bool doPetrosian = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
     484        bool doAnnuli    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
     485        bool XSRC_OUTPUT = doPetrosian || doAnnuli;
    468486        bool XFIT_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_FITS");
    469487        bool XRAD_OUTPUT = psMetadataLookupBool(&status, recipe, "RADIAL_APERTURES");
     488        bool XGAL_OUTPUT = psMetadataLookupBool(&status, recipe, "GALAXY_SHAPES");
    470489
    471490        // define the EXTNAME values for the different data segments:
     
    476495        psString xfitname = NULL;
    477496        psString xradname = NULL;
     497        psString xgalname = NULL;
    478498        if (!pmSourceIOextnames(&headname, &dataname, &deteffname,
    479499                                XSRC_OUTPUT ? &xsrcname : NULL,
    480500                                XFIT_OUTPUT ? &xfitname : NULL,
    481501                                XRAD_OUTPUT ? &xradname : NULL,
     502                                XGAL_OUTPUT ? &xgalname : NULL,
    482503                                file, view)) {
    483504            return false;
     
    563584                psMetadataAddStr (outhead, PS_LIST_TAIL, "XRADNAME", PS_META_REPLACE, "name of XRAD table extension", xradname);
    564585            }
     586            if (xgalname) {
     587                psMetadataAddStr (outhead, PS_LIST_TAIL, "XGALNAME", PS_META_REPLACE, "name of XGAL table extension", xgalname);
     588            }
    565589
    566590            // these are case-sensitive since the EXTYPE is case-sensitive
     
    574598            PM_SOURCES_WRITE("PS1_V3",    CMF_PS1_V3);
    575599            PM_SOURCES_WRITE("PS1_V4",    CMF_PS1_V4);
     600            PM_SOURCES_WRITE("PS1_V5",    CMF_PS1_V5);
    576601            PM_SOURCES_WRITE("PS1_SV1",   CMF_PS1_SV1);
    577602            PM_SOURCES_WRITE("PS1_SV2",   CMF_PS1_SV2);
     
    609634        psFree (xfitname);
    610635        psFree (xradname);
     636        psFree (xgalname);
    611637        psFree (deteffname);
    612638
     
    620646        psFree (xfitname);
    621647        psFree (xradname);
     648        psFree (xgalname);
    622649        psFree (deteffname);
    623650        return false;
    624651
     652      case PM_FPA_FILE_CFF: {
     653        // determine the output table format
     654        psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, "PSPHOT");
     655        if (!status) {
     656            psError(PS_ERR_UNKNOWN, true, "missing recipe PSPHOT in config data");
     657            return false;
     658        }
     659
     660        hdu = pmFPAviewThisHDU (view, fpa);
     661        pmConfigConformHeader(hdu->header, file->format);
     662        psFitsWriteBlank (file->fits, hdu->header, NULL);
     663        file->header = hdu->header;
     664        file->wrote_phu = true;
     665        if (!pmSourcesWrite_CFF(readout, file->fits, sources, hdu->header, recipe)) {
     666            psError(PS_ERR_UNKNOWN, false, "failed to write CFF");
     667            return false;
     668        }
     669        break;
     670      }
     671       
    625672      default:
    626673        fprintf (stderr, "warning: type mismatch\n");
     
    914961    psArray *sources = NULL;
    915962    pmHDU *hdu;
     963
     964    // define the EXTNAME values for the different data segments:
     965    psString headname = NULL;
     966    psString dataname = NULL;
     967    psString deteffname = NULL;
     968    psString xsrcname = NULL;
     969    psString xfitname = NULL;
     970    psString xradname = NULL;
     971    psString xgalname = NULL;
     972
     973    psMetadata *tableHeader = NULL;
     974    char *xtension = NULL;
    916975
    917976    switch (file->type) {
     
    9631022        hdu = pmFPAviewThisHDU (view, file->fpa);
    9641023
    965         // define the EXTNAME values for the different data segments:
    966         psString headname = NULL;
    967         psString dataname = NULL;
    968         psString deteffname = NULL;
    969         psString xsrcname = NULL;
    970         psString xfitname = NULL;
    971         psString xradname = NULL;
    972 
    9731024        // determine the output table format. Assume if we need to output extendend source
    9741025        // parameters that they may exist in the input.
     
    9811032        }
    9821033
    983         // if this is not TRUE, the output files only contain the psf measurements.
    984         bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_ANALYSIS");
     1034        // if none of these are TRUE, we only read the psf measurements
     1035        // XXX: shouldn't we look for these extensions and read the regardless of the recipe values?
     1036        bool doPetrosian = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
     1037        bool doAnnuli    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
     1038        bool XSRC_OUTPUT = doPetrosian || doAnnuli;
    9851039        bool XFIT_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_FITS");
    9861040        bool XRAD_OUTPUT = psMetadataLookupBool(&status, recipe, "RADIAL_APERTURES");
     1041        bool XGAL_OUTPUT = psMetadataLookupBool(&status, recipe, "GALAXY_SHAPES");
    9871042
    9881043        if (!pmSourceIOextnames(&headname, &dataname, &deteffname,
     
    9901045                XFIT_OUTPUT ? &xfitname : NULL,
    9911046                XRAD_OUTPUT ? &xradname : NULL,
     1047                XGAL_OUTPUT ? &xgalname : NULL,
    9921048                file, view)) {
    9931049            return false;
     
    10331089        }
    10341090
    1035         psMetadata *tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
     1091        tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
    10361092        if (!tableHeader) psAbort("cannot read table header");
    10371093
    1038         char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
     1094        xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
    10391095        if (!xtension) psAbort("cannot read table type");
    10401096        if (strcmp (xtension, "BINTABLE")) {
     
    10621118            PM_SOURCES_READ_PSF("PS1_V3",    CMF_PS1_V3);
    10631119            PM_SOURCES_READ_PSF("PS1_V4",    CMF_PS1_V4);
     1120            PM_SOURCES_READ_PSF("PS1_V5",    CMF_PS1_V5);
    10641121            PM_SOURCES_READ_PSF("PS1_SV1",   CMF_PS1_SV1);
    10651122            PM_SOURCES_READ_PSF("PS1_SV2",   CMF_PS1_SV2);
     
    10691126
    10701127            long *sourceIndex = NULL;
    1071             if (XSRC_OUTPUT || XFIT_OUTPUT || XRAD_OUTPUT) {
     1128            if (XSRC_OUTPUT || XFIT_OUTPUT || XRAD_OUTPUT || XGAL_OUTPUT) {
     1129                // Build sourceIndex. Lookup table from source->seq to index in sources array.
     1130                // Consists of an array of length max(source->seq) + 1.
     1131
     1132                // find maximum sequence number
    10721133                long seq_max = -1;
    10731134                for (long i = sources->n -1; i >= 0; i--) {
     
    10821143                    }
    10831144                }
     1145                // allocate and initialize the index
    10841146                sourceIndex = psAlloc((seq_max + 1) * sizeof(long));
    10851147                for (long i = 0; i < seq_max; i++) {
    10861148                    sourceIndex[i] = -1;
    10871149                }
     1150                // populate the index
    10881151                for (long i = 0; i < sources->n; i++) {
    10891152                    pmSource *source = sources->data[i];
     
    11121175                psFree(xradname);
    11131176            }
     1177            if (XGAL_OUTPUT && xgalname) {
     1178                // a cmf file may have an XGAL extension, but it is not required
     1179                if (!pmReadoutReadXGAL(file, readout, exttype, hdu->header, xgalname, sources, sourceIndex)) {
     1180                    // do anything?
     1181                }
     1182                psFree(xgalname);
     1183            }
    11141184            psFree(sourceIndex);
    11151185
     
    11321202        break;
    11331203
     1204      case PM_FPA_FILE_CFF:
     1205        // read in header, if not yet loaded
     1206        hdu = pmFPAviewThisHDU (view, file->fpa);
     1207
     1208        // look these up in the camera config?
     1209        // headrule = {CHIP.NAME}.hdr
     1210        // datarule = {CHIP.NAME}.cff
     1211
     1212        // define the EXTNAME values for the different data segments:
     1213        headname = pmFPAfileNameFromRule("{CHIP.NAME}.hdr", file, view);
     1214        dataname = pmFPAfileNameFromRule("{CHIP.NAME}.cff", file, view);
     1215
     1216        // advance to the IMAGE HEADER extension
     1217        if (hdu->header == NULL) {
     1218            // if the IMAGE header does not exist, we have no data for this view
     1219            if (!psFitsMoveExtNameClean (file->fits, headname)) {
     1220                readout->data_exists = false;
     1221                psFree (headname);
     1222                psFree (dataname);
     1223                return true;
     1224            }
     1225            hdu->header = psFitsReadHeader (NULL, file->fits);
     1226        }
     1227
     1228        // advance to the table data extension
     1229        // since we have read the IMAGE header, the TABLE header should exist
     1230        if (!psFitsMoveExtName (file->fits, dataname)) {
     1231            psAbort("cannot find data extension %s in %s", dataname, file->filename);
     1232        }
     1233
     1234        tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
     1235        if (!tableHeader) psAbort("cannot read table header");
     1236
     1237        // verify this is a binary table
     1238        char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
     1239        if (!xtension) psAbort("cannot read table type");
     1240        if (strcmp (xtension, "BINTABLE")) {
     1241            psWarning ("no binary table in extension %s, skipping\n", dataname);
     1242            psFree(tableHeader);
     1243            return false;
     1244        }
     1245
     1246        sources = pmSourcesRead_CFF(file->fits, hdu->header);
     1247
     1248        psTrace("psModules.objects", 6, "read CMF table from %s : %s : %s", file->filename, headname, dataname);
     1249        psFree (headname);
     1250        psFree (dataname);
     1251        psFree (tableHeader);
     1252        break;
     1253
    11341254      default:
    11351255        fprintf (stderr, "warning: type mismatch\n");
     
    12721392        PM_SOURCES_READ_XSRC("PS1_V3",    CMF_PS1_V3);
    12731393        PM_SOURCES_READ_XSRC("PS1_V4",    CMF_PS1_V4);
     1394        PM_SOURCES_READ_XSRC("PS1_V5",    CMF_PS1_V5);
    12741395        PM_SOURCES_READ_XSRC("PS1_SV1",   CMF_PS1_SV1);
    12751396        PM_SOURCES_READ_XSRC("PS1_SV2",   CMF_PS1_SV2);
     
    13111432        PM_SOURCES_READ_XFIT("PS1_V3",    CMF_PS1_V3);
    13121433        PM_SOURCES_READ_XFIT("PS1_V4",    CMF_PS1_V4);
     1434        PM_SOURCES_READ_XFIT("PS1_V5",    CMF_PS1_V5);
    13131435        PM_SOURCES_READ_XFIT("PS1_SV1",   CMF_PS1_SV1);
    13141436        PM_SOURCES_READ_XFIT("PS1_SV2",   CMF_PS1_SV2);
     
    13491471        PM_SOURCES_READ_XRAD("PS1_V3",    CMF_PS1_V3);
    13501472        PM_SOURCES_READ_XRAD("PS1_V4",    CMF_PS1_V4);
     1473        PM_SOURCES_READ_XRAD("PS1_V5",    CMF_PS1_V5);
    13511474        PM_SOURCES_READ_XRAD("PS1_SV1",   CMF_PS1_SV1);
    13521475        PM_SOURCES_READ_XRAD("PS1_SV2",   CMF_PS1_SV2);
     
    13581481    return status;
    13591482}
     1483static bool pmReadoutReadXGAL(pmFPAfile *file, pmReadout *readout, char *exttype, psMetadata *hduHeader, psString xgalname, psArray *sources, long *sourceIndex)
     1484{
     1485    if (!psFitsMoveExtNameClean (file->fits, xgalname)) {
     1486        psTrace ("pmFPAfile", 1, "cannot find xgal extension %s in %s, skipping", xgalname, file->filename);
     1487        return false;
     1488    }
     1489
     1490    psMetadata *tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
     1491    if (!tableHeader) psAbort("cannot read table header");
     1492
     1493    char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
     1494    if (!xtension) psAbort("cannot read table type");
     1495    if (strcmp (xtension, "BINTABLE")) {
     1496        psFree(tableHeader);
     1497        psWarning ("no binary table in extension %s, skipping\n", xgalname);
     1498        return false;
     1499    }
     1500
     1501# define PM_SOURCES_READ_XGAL(NAME,TYPE)                                \
     1502    if (!strcmp (exttype, NAME)) {                                      \
     1503        status = pmSourcesRead_##TYPE##_XGAL(file->fits, readout, hduHeader, tableHeader, sources, sourceIndex); \
     1504    }                                                                   
     1505
     1506    bool status = false;
     1507    if (file->type == PM_FPA_FILE_CMF) {
     1508        PM_SOURCES_READ_XGAL("PS1_V1",    CMF_PS1_V1);
     1509        PM_SOURCES_READ_XGAL("PS1_V2",    CMF_PS1_V2);
     1510        PM_SOURCES_READ_XGAL("PS1_V3",    CMF_PS1_V3);
     1511        PM_SOURCES_READ_XGAL("PS1_V4",    CMF_PS1_V4);
     1512        PM_SOURCES_READ_XGAL("PS1_V5",    CMF_PS1_V5);
     1513        PM_SOURCES_READ_XGAL("PS1_SV1",   CMF_PS1_SV1);
     1514        PM_SOURCES_READ_XGAL("PS1_SV2",   CMF_PS1_SV2);
     1515        PM_SOURCES_READ_XGAL("PS1_DV1",   CMF_PS1_DV1);
     1516        PM_SOURCES_READ_XGAL("PS1_DV2",   CMF_PS1_DV2);
     1517        PM_SOURCES_READ_XGAL("PS1_DV3",   CMF_PS1_DV3);
     1518    }
     1519    psFree(tableHeader);
     1520    return status;
     1521}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO.h

    r35610 r36680  
    2121  bool pmSourcesWrite_##TYPE##_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); \
    2222  bool pmSourcesWrite_##TYPE##_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); \
     23  bool pmSourcesWrite_##TYPE##_XGAL(psFits *fits, pmReadout *readout, psArray *sources, char *extname, psMetadata *recipe); \
    2324  psArray *pmSourcesRead_##TYPE (psFits *fits, psMetadata *header); \
    2425  bool pmSourcesRead_##TYPE##_XSRC (psFits *fits, pmReadout *readout, psMetadata *header, psMetadata *tableHeader, psArray *sources, long *index); \
    2526  bool pmSourcesRead_##TYPE##_XFIT (psFits *fits, pmReadout *readout, psMetadata *header, psMetadata *tableHeader, psArray *sources, long *index); \
    2627  bool pmSourcesRead_##TYPE##_XRAD (psFits *fits, pmReadout *readout, psMetadata *header, psMetadata *tableHeader, psArray *sources, long *index);\
     28  bool pmSourcesRead_##TYPE##_XGAL (psFits *fits, pmReadout *readout, psMetadata *header, psMetadata *tableHeader, psArray *sources, long *index);\
    2729 
    2830// All of these functions need to use the same API, even if not all elements are used in a specific case
     
    3537MK_PROTO(CMF_PS1_V3);
    3638MK_PROTO(CMF_PS1_V4);
     39MK_PROTO(CMF_PS1_V5);
    3740MK_PROTO(CMF_PS1_SV1);
    3841MK_PROTO(CMF_PS1_SV2);
     
    5255
    5356psArray *pmSourcesReadCMP (char *filename, psMetadata *header);
     57psArray *pmSourcesRead_CFF (psFits *fits, psMetadata *header);
     58bool pmSourcesWrite_CFF (pmReadout *readout, psFits *fits, psArray *sources, psMetadata *header, psMetadata *recipe);
    5459
    5560bool pmSourcesWritePSFs (psArray *sources, char *filename);
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_CMF.c.in

    r35768 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
     
    178179        @>PS1_V2,PS1_SV?@         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4C",      PS_DATA_F32, "fourth momemt cos theta",                    moments.M_c4);
    179180        @>PS1_V2,PS1_SV?@         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4S",      PS_DATA_F32, "fourth momemt sin theta",                    moments.M_s4);
     181
     182        // Lensing parameters:
     183        if (source->lensingOBJ && source->lensingOBJ->smear) {
     184          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X11_SM_OBJ",  PS_DATA_F32, "smear polarizability element (objects)",     source->lensingOBJ->smear->X11);
     185          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X12_SM_OBJ",  PS_DATA_F32, "smear polarizability element (objects)",     source->lensingOBJ->smear->X12);
     186          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X22_SM_OBJ",  PS_DATA_F32, "smear polarizability element (objects)",     source->lensingOBJ->smear->X22);
     187          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_E1_SM_OBJ",   PS_DATA_F32, "smear polarizability element (objects)",     source->lensingOBJ->smear->e1);
     188          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_E2_SM_OBJ",   PS_DATA_F32, "smear polarizability element (objects)",     source->lensingOBJ->smear->e2);
     189        }
     190
     191        if (source->lensingOBJ && source->lensingOBJ->shear) {
     192          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X11_SH_OBJ",  PS_DATA_F32, "shear polarizability element (objects)",     source->lensingOBJ->shear->X11);
     193          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X12_SH_OBJ",  PS_DATA_F32, "shear polarizability element (objects)",     source->lensingOBJ->shear->X12);
     194          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X22_SH_OBJ",  PS_DATA_F32, "shear polarizability element (objects)",     source->lensingOBJ->shear->X22);
     195          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_E1_SH_OBJ",   PS_DATA_F32, "shear polarizability element (objects)",     source->lensingOBJ->shear->e1);
     196          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_E2_SH_OBJ",   PS_DATA_F32, "shear polarizability element (objects)",     source->lensingOBJ->shear->e2);
     197        }
     198
     199        if (source->lensingOBJ && source->lensingPSF->smear) {
     200          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X11_SM_PSF",  PS_DATA_F32, "smear polarizability element (objects)",     source->lensingPSF->smear->X11);
     201          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X12_SM_PSF",  PS_DATA_F32, "smear polarizability element (objects)",     source->lensingPSF->smear->X12);
     202          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X22_SM_PSF",  PS_DATA_F32, "smear polarizability element (objects)",     source->lensingPSF->smear->X22);
     203          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_E1_SM_PSF",   PS_DATA_F32, "smear polarizability element (objects)",     source->lensingPSF->smear->e1);
     204          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_E2_SM_PSF",   PS_DATA_F32, "smear polarizability element (objects)",     source->lensingPSF->smear->e2);
     205        }
     206
     207        if (source->lensingOBJ && source->lensingPSF->shear) {
     208          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X11_SH_PSF",  PS_DATA_F32, "shear polarizability element (objects)",     source->lensingPSF->shear->X11);
     209          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X12_SH_PSF",  PS_DATA_F32, "shear polarizability element (objects)",     source->lensingPSF->shear->X12);
     210          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_X22_SH_PSF",  PS_DATA_F32, "shear polarizability element (objects)",     source->lensingPSF->shear->X22);
     211          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_E1_SH_PSF",   PS_DATA_F32, "shear polarizability element (objects)",     source->lensingPSF->shear->e1);
     212          @>PS1_V4@               psMetadataAdd (row, PS_LIST_TAIL, "LENS_E2_SH_PSF",   PS_DATA_F32, "shear polarizability element (objects)",     source->lensingPSF->shear->e2);
     213        }
    180214
    181215        @>PS1_V2,PS1_SV?,>PS1_DV1@ psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                        moments.Mrf);
     
    708742            return false;
    709743        }
    710         // Find the source with this sequence number.
    711         // XXX: I am assuming that sources is sorted in order of seq
     744        // Find the source with this sequence number using the sourceIndex.
    712745        long seq = psMetadataLookupU32 (&status, row, "IPP_IDET");
    713         pmSource *source = NULL;
    714 #ifndef ASSUME_SORTED
    715         long j = seq < sources->n ? seq : sources->n - 1;
    716         for (; j >= 0; j--) {
    717             source = sources->data[j];
    718             if (source->seq == seq) {
    719                 break;
    720             }
    721         }
    722 #else
    723746        long j = sourceIndex[seq];
    724747        psAssert(j >= 0 && j < sources->n, "invalid sourceIndex");
    725         source = sources->data[j];
    726 #endif
     748        pmSource *source = sources->data[j];
    727749        if (!source) {
    728750            psError(PS_ERR_UNKNOWN, false, "Failed to find source for row %ld sequence number %ld\n", i, seq);
     
    789811    char name[64];
    790812
     813    pmModelType modelTypeTrail = pmModelClassGetType("PS_MODEL_TRAIL");
     814
    791815    // create a header to hold the output data
    792816    psMetadata *outhead = psMetadataAlloc ();
    793817
     818    pmModelClassWriteHeader(outhead);
     819
    794820    // write the links to the image header
    795821    psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTNAME", PS_META_REPLACE, "xsrc table extension", extname);
     
    798824    sources = psArraySort (sources, pmSourceSortByFlux);
    799825
    800     @>PS1_DV2@ float magOffset;
    801     @>PS1_DV2@ float zeroptErr;
    802     @>PS1_DV2@ float fwhmMajor;
    803     @>PS1_DV2@ float fwhmMinor;
    804     @>PS1_DV2@ pmSourceOutputsCommonValues (&magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
     826    float magOffset;
     827    float zeroptErr;
     828    float fwhmMajor;
     829    float fwhmMinor;
     830    pmSourceOutputsCommonValues (&magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
    805831
    806832    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
     
    823849    @>PS1_DV2@ pmChip *chip = readout->parent->parent;
    824850
     851    pmModelStatus badModel = PM_MODEL_STATUS_NONE;
     852    badModel |= PM_MODEL_STATUS_BADARGS;
     853    badModel |= PM_MODEL_STATUS_OFFIMAGE;
     854    badModel |= PM_MODEL_STATUS_NAN_CHISQ;
     855    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GUESS;
     856    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GRID;
     857    badModel |= PM_MODEL_PCM_FAIL_GUESS;
     858
    825859    table = psArrayAllocEmpty (sources->n);
    826860
     
    847881
    848882            // skip models which were not actually fitted
    849             if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     883            // XXX
     884            if (model->flags & badModel) continue;
    850885
    851886            PAR = model->params->data.F32;
     
    853888            xPos = PAR[PM_PAR_XPOS];
    854889            yPos = PAR[PM_PAR_YPOS];
    855             xErr = dPAR[PM_PAR_XPOS];
    856             yErr = dPAR[PM_PAR_YPOS];
     890
     891            // for the extended source models, we do not always fit the centroid in the non-linear fitting process
     892            // current situation (hard-wired into psphotSourceFits.c:psphotFitPCM,
     893            // SERSIC, DEV, EXP : X,Y not fitted (PCM and not PCM)
     894            // TRAIL : X,Y are fitted
     895            //
     896           
     897            // XXX this should be based on what happened, not on the model type
     898            if (model->type == modelTypeTrail) {
     899                xErr = dPAR[PM_PAR_XPOS];
     900                yErr = dPAR[PM_PAR_YPOS];
     901            } else {
     902                // this is definitely an underestimate since it does not
     903                // account for the extent of the source
     904                xErr = fwhmMajor * model->magErr / 2.35;
     905                yErr = fwhmMinor * model->magErr / 2.35;
     906            }
    857907
    858908            @>PS1_DV2@ psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
     
    870920            row = psMetadataAlloc ();
    871921
    872             // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
    873922            // the psMetadataAdd entry and the double quotes are used by grep to select the output fields for automatic documentation
    874923            // This set of psMetadataAdd Entries marks the "----" "Start of the XFIT segment"
     
    888937            @>PS1_DV2@ float calMag = isfinite(magOffset) ? model->mag + magOffset : NAN;
    889938            @>PS1_DV2@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_CAL_MAG", PS_DATA_F32, "EXT Magnitude using supplied calibration",   calMag);
    890             @>PS1_DV2@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_CHISQ",   PS_DATA_F32, "EXT Magnitude using supplied calibration",   model->chisq);
    891             @>PS1_DV2@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_NDOF",    PS_DATA_S32, "EXT Magnitude using supplied calibration",   model->nDOF);
     939            @>PS1_DV2,PS1_SV?@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_CHISQ",   PS_DATA_F32, "EXT Model Chisq",   model->chisq);
     940            @>PS1_DV2,PS1_SV?@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_NDOF",    PS_DATA_S32, "EXT Model num degrees of freedom",   model->nDOF);
     941            @>PS1_SV1,PS1_SV?@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_MODEL_TYPE",    PS_DATA_S32, "type for chosen EXT_MODEL",   source->modelEXT ? source->modelEXT->type : -1);
     942
     943            // EAM : adding for PV2 outputs:
     944            @>PS1_SV1@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_FLAGS", PS_DATA_S16, "model fit flags (pmModelStatus)", source->modelEXT ? source->modelEXT->flags : 0);
    892945
    893946            @>PS1_DV2@ psMetadataAddF32 (row, PS_LIST_TAIL, "POSANGLE",   0, "position angle at source (degrees)",         posAngle);
     
    946999
    9471000                snprintf (name, 64, "EXT_PAR_%02d", k);
    948 
     1001               
    9491002                if (k < model->params->n) {
    9501003                    psMetadataAddF32 (row, PS_LIST_TAIL, name, 0, "", model->params->data.F32[k]);
     
    9561009            // optionally, write out the covariance matrix values
    9571010            // XXX do I need to pad this to match the biggest covar matrix?
    958             if (model->covar) {
     1011            if (false && model->covar) {
    9591012                for (int iy = 0; iy < model->covar->numCols; iy++) {
    9601013                    for (int ix = iy; ix < model->covar->numCols; ix++) {
     
    10051058        return false;
    10061059    }
     1060    // set up the lookup table to translate between input model types and output model types
     1061    // if not defined it is assumed that the tables are the same
     1062    pmModelClassReadHeader(tableHeader);
    10071063
    10081064    for (long i = 0; i < numSources; i++) {
     
    10131069            return false;
    10141070        }
    1015         // Find the source with this sequence number.
    1016         // XXX: I am assuming that sources is sorted in order of seq.
    10171071        long seq = psMetadataLookupU32 (&status, row, "IPP_IDET");
    1018         long j = seq < sources->n ? seq : sources->n - 1;
    1019         pmSource *source = NULL;
    1020         for (; j >= 0; j--) {
    1021             source = sources->data[j];
    1022             if (source->seq == seq) {
    1023                 break;
    1024             }
    1025         }
     1072        long j = sourceIndex[seq];
     1073        psAssert(j >= 0 && j < sources->n, "invalid sourceIndex");
     1074        pmSource *source = sources->data[j];
    10261075        if (!source) {
    10271076            psError(PS_ERR_UNKNOWN, false, "Failed to find source for row %ld sequence number %ld\n", i, seq);
     
    10571106        model->mag = psMetadataLookupF32(&status, row, "EXT_INST_MAG");
    10581107        model->magErr = psMetadataLookupF32(&status, row, "EXT_INST_MAG_SIG");
     1108
     1109        model->chisq = psMetadataLookupF32(&status, row, "EXT_CHISQ");
     1110        model->nDOF = psMetadataLookupF32(&status, row, "EXT_NDOF");
     1111
     1112        // EXT_MODEL_TYPE gives the model chosen by psphot as the best.
     1113        // Putting this into the XFIT table makes 3 copies of it (one for each model)
     1114        // but since we have many fewer XFIT rows than psf rows that is cheaper than putting it
     1115        // in the psf table.
     1116        psS32 extModelType = psMetadataLookupS32(&status, row, "EXT_MODEL_TYPE");
     1117        if (status) {
     1118            // translate between the type value in xfit and values used by this program
     1119            extModelType = pmModelClassGetLocalType(extModelType);
     1120        } else {
     1121            // older cmfs don't have this column
     1122            extModelType = -1;
     1123        }
    10591124
    10601125        psEllipseAxes axes;
     
    10721137        if (model->params->n > 7) {
    10731138            PAR[7] = psMetadataLookupF32(&status, row, "EXT_PAR_07");
    1074         }
    1075         // read the covariance matrix
    1076         int nparams = model->params->n;
    1077         psImage *covar = psImageAlloc(nparams, nparams, PS_TYPE_F32);
    1078         for (int y = 0; y < nparams; y++) {
    1079             for (int x = 0; x < nparams; x++) {
    1080                 char name[64];
    1081                 snprintf(name, 64, "EXT_COVAR_%02d_%02d", y, x);
    1082                 covar->data.F32[y][x] = psMetadataLookupF32(&status, row, name);
     1139            // XXX add an error:
     1140            // dPAR[7] = psMetadataLookupF32(&status, row, "EXT_PAR_07_");
     1141        }
     1142
     1143        // XXX : make this depend on what is in the cmf
     1144        if (0) {
     1145            // read the covariance matrix
     1146            int nparams = model->params->n;
     1147            psImage *covar = psImageAlloc(nparams, nparams, PS_TYPE_F32);
     1148            for (int y = 0; y < nparams; y++) {
     1149                for (int x = 0; x < nparams; x++) {
     1150                    char name[64];
     1151                    snprintf(name, 64, "EXT_COVAR_%02d_%02d", y, x);
     1152                    covar->data.F32[y][x] = psMetadataLookupF32(&status, row, name);
     1153                }
     1154            }
     1155            model->covar = covar;
     1156        }
     1157
     1158        if (modelType == extModelType) {
     1159            // The software that created this source picked this model as the best of the fits.
     1160            // Set the extModel to point to it.
     1161            // This is important for programs like psastro (skycal) so that its output cmfs
     1162            // will have valid EXT_MODEL_TYPE
     1163            psFree(source->modelEXT);
     1164            source->modelEXT = psMemIncrRefCounter(model);
     1165            source->type = PM_SOURCE_TYPE_EXTENDED;
     1166            if (0) {
     1167                // since FLAGS were read we don't need to do this
     1168                source->mode |= PM_SOURCE_MODE_EXTMODEL;
     1169                source->mode |= PM_SOURCE_MODE_NONLINEAR_FIT;
    10831170            }
    10841171        }
    1085         model->covar = covar;
    10861172
    10871173        psArrayAdd(source->modelFits, 1, model);
    10881174        psFree(model);
    1089 
    10901175        psFree(row);
    10911176    }
     
    12091294
    12101295        write_annuli:
    1211             psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX",       PS_DATA_VECTOR, "flux within annuli",       radFlux);
    1212             psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_ERR",   PS_DATA_VECTOR, "flux error in annuli",     radFluxErr);
    1213             psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_STDEV", PS_DATA_VECTOR, "flux standard deviation",  radFluxStdev);
    1214             psMetadataAdd (row, PS_LIST_TAIL, "APER_FILL",       PS_DATA_VECTOR, "fill factor of annuli",    radFill);
     1296            psMetadataAddVector (row, PS_LIST_TAIL, "APER_FLUX",       PS_META_REPLACE, "flux within annuli",       radFlux);
     1297            psMetadataAddVector (row, PS_LIST_TAIL, "APER_FLUX_ERR",   PS_META_REPLACE, "flux error in annuli",     radFluxErr);
     1298            psMetadataAddVector (row, PS_LIST_TAIL, "APER_FLUX_STDEV", PS_META_REPLACE, "flux standard deviation",  radFluxStdev);
     1299            psMetadataAddVector (row, PS_LIST_TAIL, "APER_FILL",       PS_META_REPLACE, "fill factor of annuli",    radFill);
    12151300            psFree (radFlux);
    12161301            psFree (radFluxErr);
     
    12771362            return false;
    12781363        }
    1279         // Find the source with this sequence number.
    1280         // XXX: I am assuming that sources is sorted in order of seq.
    12811364        long seq = psMetadataLookupU32 (&status, row, "IPP_IDET");
    1282         long j = seq < sources->n ? seq : sources->n - 1;
    1283         pmSource *source = NULL;
    1284         for (; j >= 0; j--) {
    1285             source = sources->data[j];
    1286             if (source->seq == seq) {
    1287                 break;
    1288             }
    1289         }
     1365        long j = sourceIndex[seq];
     1366        psAssert(j >= 0 && j < sources->n, "invalid sourceIndex");
     1367        pmSource *source = sources->data[j];
    12901368        if (!source) {
    12911369            psError(PS_ERR_UNKNOWN, false, "Failed to find source for row %ld sequence number %ld\n", i, seq);
     
    13431421    return true;
    13441422}
     1423
     1424// XXX where should I record the number of columns??
     1425bool pmSourcesWrite_CMF_@CMFMODE@_XGAL (psFits *fits, pmReadout *readout, psArray *sources, char *extname, psMetadata *recipe)
     1426{
     1427    bool status = false;
     1428
     1429    // perform full non-linear fits / extended source analysis?
     1430    if (!psMetadataLookupBool (&status, recipe, "GALAXY_SHAPES")) {
     1431        psLogMsg ("psphot", PS_LOG_INFO, "galaxy shapes were not measured, skipping\n");
     1432        return true;
     1433    }
     1434
     1435    // create a header to hold the output data
     1436    psMetadata *outhead = psMetadataAlloc ();
     1437
     1438    // write the links to the image header
     1439    psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTNAME", PS_META_REPLACE, "galaxy table extension", extname);
     1440
     1441    psMetadataAddStr (outhead, PS_LIST_TAIL, "HI", PS_META_REPLACE, "does this get through?", "THERE");
     1442
     1443    // let's write these out in S/N order
     1444    sources = psArraySort (sources, pmSourceSortByFlux);
     1445
     1446    psArray *table = psArrayAllocEmpty (sources->n);
     1447
     1448    for (int i = 0; i < sources->n; i++) {
     1449
     1450        pmSource *thisSource = sources->data[i];
     1451
     1452        // this is the "real" version of this source
     1453        pmSource *source = thisSource->parent ? thisSource->parent : thisSource;
     1454
     1455        // if we did not fit the galaxy model, modelFits will be NULL
     1456        if (source->modelFits == NULL) continue;
     1457
     1458        // if we did not fit the galaxy model, galaxyFits will also be NULL
     1459        if (source->galaxyFits == NULL) continue;
     1460
     1461        pmModel *model = source->modelFits->data[0];
     1462        if (!model) return false;
     1463
     1464        // X,Y coordinates are stored with the model parameters
     1465        psF32 *PAR = model->params->data.F32;
     1466
     1467        psMetadata *row = psMetadataAlloc ();
     1468
     1469        // we write out the x,y positions so people can link to the psf either way (position or ID)
     1470        psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET",         0, "IPP detection identifier index", source->seq);
     1471        psMetadataAddF32 (row, PS_LIST_TAIL, "X_FIT",            0, "model x coordinate",             PAR[PM_PAR_XPOS]);
     1472        psMetadataAddF32 (row, PS_LIST_TAIL, "Y_FIT",            0, "model y coordinate",             PAR[PM_PAR_YPOS]);
     1473        psMetadataAddF32 (row, PS_LIST_TAIL, "NPIX",             0, "number of pixels for fits",      source->galaxyFits->nPix);
     1474
     1475        psVector *Flux = source->galaxyFits->Flux;
     1476        psVector *dFlux = source->galaxyFits->dFlux;
     1477        psVector *chisq = source->galaxyFits->chisq;
     1478
     1479        psMetadataAddVector (row, PS_LIST_TAIL, "GAL_FLUX",     PS_META_REPLACE, "normalization for galaxy flux", Flux);
     1480        psMetadataAddVector (row, PS_LIST_TAIL, "GAL_FLUX_ERR", PS_META_REPLACE, "error on normalization", dFlux);
     1481        psMetadataAddVector (row, PS_LIST_TAIL, "GAL_CHISQ",    PS_META_REPLACE, "galaxy fit chisq", chisq);
     1482
     1483        psArrayAdd (table, 100, row);
     1484        psFree (row);
     1485    }
     1486
     1487    if (table->n == 0) {
     1488        if (!psFitsWriteBlank (fits, outhead, extname)) {
     1489            psError(psErrorCodeLast(), false, "Unable to write empty sources file.");
     1490            psFree(outhead);
     1491            psFree(table);
     1492            return false;
     1493        }
     1494        psFree (outhead);
     1495        psFree (table);
     1496        return true;
     1497    }
     1498
     1499    psTrace ("pmFPAfile", 5, "writing galaxy data %s\n", extname);
     1500    if (!psFitsWriteTable (fits, outhead, table, extname)) {
     1501        psError(psErrorCodeLast(), false, "writing galaxy data %s\n", extname);
     1502        psFree (outhead);
     1503        psFree(table);
     1504        return false;
     1505    }
     1506    psFree (outhead);
     1507    psFree (table);
     1508    return true;
     1509}
     1510
     1511bool pmSourcesRead_CMF_@CMFMODE@_XGAL(psFits *fits, pmReadout *readout, psMetadata *hduHeader, psMetadata *tableHeader, psArray *sources, long *sourceIndex)
     1512{
     1513    PS_ASSERT_PTR_NON_NULL(fits, false);
     1514    PS_ASSERT_PTR_NON_NULL(sources, false);
     1515
     1516    bool status;
     1517    long numSources = psFitsTableSize(fits); // Number of sources in table
     1518    if (numSources == 0) {
     1519        psError(psErrorCodeLast(), false, "XGAL Table contains no entries\n");
     1520        return false;
     1521    }
     1522
     1523    for (long i = 0; i < numSources; i++) {
     1524        psMetadata *row = psFitsReadTableRow(fits, i); // Table row
     1525        if (!row) {
     1526            psError(psErrorCodeLast(), false, "Unable to read row %ld of sources", i);
     1527            psFree(row);
     1528            return false;
     1529        }
     1530        // Find the source with this sequence number.
     1531        // XXX: I am assuming that sources is sorted in order of seq
     1532        long seq = psMetadataLookupU32 (&status, row, "IPP_IDET");
     1533        long j = sourceIndex[seq];
     1534        psAssert(j >= 0 && j < sources->n, "invalid sourceIndex");
     1535
     1536        pmSource *source = sources->data[j];
     1537        if (!source) {
     1538            psError(PS_ERR_UNKNOWN, false, "Failed to find source for row %ld sequence number %ld\n", i, seq);
     1539            psFree(row);
     1540            return false;
     1541        }
     1542
     1543        psVector *Flux  = psMetadataLookupVector(&status, row, "GAL_FLUX");
     1544        psVector *dFlux = psMetadataLookupVector(&status, row, "GAL_FLUX_ERR");
     1545        psVector *chisq = psMetadataLookupVector(&status, row, "GAL_CHISQ");
     1546
     1547        if (Flux && Flux->n > 0) {
     1548            psFree(source->galaxyFits);
     1549            source->galaxyFits = pmSourceGalaxyFitsAlloc();
     1550            source->galaxyFits->nPix = psMetadataLookupF32(&status, row, "NPIX");
     1551
     1552            psFree(source->galaxyFits->Flux);
     1553            source->galaxyFits->Flux  = psMemIncrRefCounter(Flux);
     1554            psFree(source->galaxyFits->dFlux);
     1555            source->galaxyFits->dFlux = psMemIncrRefCounter(dFlux);
     1556            psFree(source->galaxyFits->chisq);
     1557            source->galaxyFits->chisq = psMemIncrRefCounter(chisq);
     1558        }
     1559
     1560        psFree(row);
     1561    }
     1562
     1563    return true;
     1564}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_CMP.c

    r35768 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_MatchedRefs.c

    r35560 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_OBJ.c

    r35768 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_PS1_CAL_0.c

    r35768 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
     
    713714    return true;
    714715}
     716
     717bool pmSourcesWrite_PS1_CAL_0_XGAL (psFits *fits, pmReadout *readout, psArray *sources, char *extname, psMetadata *recipe)
     718{
     719    return true;
     720}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_PS1_DEV_0.c

    r35768 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
     
    255256    return true;
    256257}
     258
     259bool pmSourcesWrite_PS1_DEV_0_XGAL(psFits *fits, pmReadout *readout, psArray *sources, char *extname, psMetadata *recipe)
     260{
     261    return true;
     262}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_PS1_DEV_1.c

    r35768 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
     
    595596    return true;
    596597}
     598
     599bool pmSourcesWrite_PS1_DEV_1_XGAL(psFits *fits, pmReadout *readout, psArray *sources, char *extname, psMetadata *recipe)
     600{
     601    return true;
     602}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_RAW.c

    r34403 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_SMPDATA.c

    r35768 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
     
    225226    return true;
    226227}
     228
     229bool pmSourcesWrite_SMPDATA_XGAL(psFits *fits, pmReadout *readout, psArray *sources, char *extname, psMetadata *recipe)
     230{
     231    return true;
     232}
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceIO_SX.c

    r35768 r36680  
    4444#include "pmSourceDiffStats.h"
    4545#include "pmSourceSatstar.h"
     46#include "pmSourceLensing.h"
    4647#include "pmSource.h"
    4748#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceMasks.h

    r34403 r36680  
    5656    PM_SOURCE_MODE2_DIFF_SELF_MATCH       = 0x00000800, ///< positive detection match is probably this source
    5757    PM_SOURCE_MODE2_SATSTAR_PROFILE       = 0x00001000, ///< saturated source is modeled with a radial profile
     58
     59    PM_SOURCE_MODE2_ECONTOUR_FEW_PTS      = 0x00002000, ///< too few points to measure the elliptical contour
     60    PM_SOURCE_MODE2_RADBIN_NAN_CENTER     = 0x00004000, ///< radial bins failed with too many NaN center bin
     61    PM_SOURCE_MODE2_PETRO_NAN_CENTER      = 0x00008000, ///< petrosian radial bins failed with too many NaN center bin
     62    PM_SOURCE_MODE2_PETRO_NO_PROFILE      = 0x00010000, ///< petrosian not build because radial bins missing
     63
     64    PM_SOURCE_MODE2_PETRO_INSIG_RATIO     = 0x00020000, ///< insignificant measurement of petrosian ratio
     65    PM_SOURCE_MODE2_PETRO_RATIO_ZEROBIN   = 0x00040000, ///< petrosian ratio in the 0th bin (likely bad)
     66   
     67    PM_SOURCE_MODE2_EXT_FITS_RUN          = 0x00080000, ///< we attempted to run extended fits on this source
     68    PM_SOURCE_MODE2_EXT_FITS_FAIL         = 0x00100000, ///< at least one of the model fits failed
     69    PM_SOURCE_MODE2_EXT_FITS_RETRY        = 0x00200000, ///< one of the model fits was re-tried with new window
     70    PM_SOURCE_MODE2_EXT_FITS_NONE         = 0x00400000, ///< ALL of the model fits failed
     71   
     72   
    5873} pmSourceMode2;
    5974
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceMatch.c

    r35383 r36680  
    2525#include "pmSourceDiffStats.h"
    2626#include "pmSourceSatstar.h"
     27#include "pmSourceLensing.h"
    2728#include "pmSource.h"
    2829#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceMoments.c

    r35560 r36680  
    4242#include "pmSourceDiffStats.h"
    4343#include "pmSourceSatstar.h"
     44#include "pmSourceLensing.h"
    4445#include "pmSource.h"
    4546
     
    6566void pmSourceMomentsSetVerbose(bool state){ beVerbose = state; }
    6667
     68bool pmSourceMomentsHighOrder    (pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal);
     69bool pmSourceMomentsRadialMoment (pmSource *source, float radius, float minKronRadius, psImageMaskType maskVal);
     70bool pmSourceMomentsKronFluxes   (pmSource *source, float sigma,  float minSN, psImageMaskType maskVal);
     71
    6772// if mode & EXTERNAL or mode2 & MATCHED, do not re-calculate the centroid (use peak as centroid)
    68 
    6973bool pmSourceMoments(pmSource *source, float radius, float sigma, float minSN, float minKronRadius, psImageMaskType maskVal)
    7074{
     
    7478    PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false);
    7579
    76     // this function assumes the sky has been well-subtracted for the image
    77     float sky = 0.0;
    78 
    7980    if (source->moments == NULL) {
    8081      source->moments = pmMomentsAlloc();
    8182    }
    82 
    83     float Sum = 0.0;
    84     float Var = 0.0;
    85     float SumCore = 0.0;
    86     float VarCore = 0.0;
    87     float R2 = PS_SQR(radius);
    88     float minSN2 = PS_SQR(minSN);
    89     float rsigma2 = 0.5 / PS_SQR(sigma);
    9083
    9184    // a note about coordinates: coordinates of objects throughout psphot refer to the primary
     
    110103    // of any object drops pretty quickly outside 1-2 sigmas.  (The exception is bright
    111104    // saturated stars, for which we need to use a very large radius here)
     105    // NOTE: if (mode & EXTERNAL) or (mode2 & MATCHED), do not re-calculate the centroid (use peak as centroid)
     106    // (we still call this function because it sets moments->Sum,SN,Peak,nPixels
    112107    if (!pmSourceMomentsGetCentroid (source, 1.5*sigma, 0.0, minSN, maskVal, source->peak->xf, source->peak->yf)) {
    113108        return false;
    114109    }
    115110
     111    pmSourceMomentsHighOrder (source, radius, sigma, minSN, maskVal);
     112
     113    // now calculate the 1st radial moment (for kron flux) using symmetrical averaging
     114    pmSourceMomentsRadialMoment (source, radius, minKronRadius, maskVal);
     115
     116    // now calculate the kron flux values using the 1st radial moment
     117    pmSourceMomentsKronFluxes (source, sigma, minSN, maskVal);
     118
     119    psTrace ("psModules.objects", 4, "Mrf: %f  KronFlux: %f  Mxx: %f  Mxy: %f  Myy: %f  Mxxx: %f  Mxxy: %f  Mxyy: %f  Myyy: %f  Mxxxx: %f  Mxxxy: %f  Mxxyy: %f  Mxyyy: %f  Mxyyy: %f\n",
     120             source->moments->Mrf,   source->moments->KronFlux,
     121             source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy,
     122             source->moments->Mxxx,  source->moments->Mxxy,  source->moments->Mxyy,  source->moments->Myyy,
     123             source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy);
     124
     125    psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f  My: %f  Sum: %f  Mxx: %f  Mxy: %f  Myy: %f  Npix: %d\n",
     126             source->peak->xf, source->peak->yf,
     127             source->peak->rawFlux, sqrt(source->peak->detValue),
     128             source->moments->Mx, source->moments->My,
     129             source->moments->Sum,
     130             source->moments->Mxx, source->moments->Mxy, source->moments->Myy,
     131             source->moments->nPixels);
     132
     133    return(true);
     134}
     135
     136bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) {
     137
     138    // First Pass: calculate the first moments (these are subtracted from the coordinates below)
     139    // Sum = SUM (z - sky)
     140    // X1  = SUM (x - xc)*(z - sky)
     141    // .. etc
     142
     143    float sky = 0.0;
     144
     145    float peakPixel = -PS_MAX_F32;
     146    psS32 numPixels = 0;
     147    float Sum = 0.0;
     148    float Var = 0.0;
     149    float X1 = 0.0;
     150    float Y1 = 0.0;
     151    float R2 = PS_SQR(radius);
     152    float minSN2 = PS_SQR(minSN);
     153    float rsigma2 = 0.5 / PS_SQR(sigma);
     154
     155    float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage
     156    float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage
     157
     158    // we are guaranteed to have a valid pixel and variance at this location (right? right?)
     159    // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]);
     160    // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
     161    // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
     162    // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel");
     163
     164    // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should
     165    // not depend on the fractional pixel location of the source.  However, the aperture
     166    // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel
     167    // position of the expected centroid
     168
     169    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
     170
     171        float yDiff = row + 0.5 - yPeak;
     172        if (fabs(yDiff) > radius) continue;
     173
     174        float *vPix = source->pixels->data.F32[row];
     175        float *vWgt = source->variance ? source->variance->data.F32[row] : source->pixels->data.F32[row];
     176
     177        psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
     178        // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];
     179
     180        for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
     181            if (vMsk) {
     182                if (*vMsk & maskVal) {
     183                    vMsk++;
     184                    continue;
     185                }
     186                vMsk++;
     187            }
     188            if (isnan(*vPix)) continue;
     189
     190            float xDiff = col + 0.5 - xPeak;
     191            if (fabs(xDiff) > radius) continue;
     192
     193            // radius is just a function of (xDiff, yDiff)
     194            float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
     195            if (r2 > R2) continue;
     196
     197            float pDiff = *vPix - sky;
     198            float wDiff = *vWgt;
     199
     200            // skip pixels below specified significance level.  for a PSFs, this
     201            // over-weights the wings of bright stars compared to those of faint stars.
     202            // for the estimator used for extended source analysis (where the window
     203            // function is allowed to be arbitrarily large), we need to clip to avoid
     204            // negative second moments.
     205            if (PS_SQR(pDiff) < minSN2*wDiff) continue; //
     206            if ((minSN > 0.0) && (pDiff < 0)) continue; //
     207
     208            // Apply a Gaussian window function.  Be careful with the window function.  S/N
     209            // weighting over weights the sky for faint sources
     210            if (sigma > 0.0) {
     211                float z  = r2*rsigma2;
     212                assert (z >= 0.0);
     213                float weight  = exp(-z);
     214
     215                wDiff *= weight;
     216                pDiff *= weight;
     217            }
     218
     219            Var += wDiff;
     220            Sum += pDiff;
     221
     222            float xWght = xDiff * pDiff;
     223            float yWght = yDiff * pDiff;
     224
     225            X1  += xWght;
     226            Y1  += yWght;
     227
     228            peakPixel = PS_MAX (*vPix, peakPixel);
     229            numPixels++;
     230        }
     231    }
     232
     233    // if we have less than (1/4) of the possible pixels (in circle or box), force a retry
     234    int minPixels = PS_MIN(0.75*R2, source->pixels->numCols*source->pixels->numRows/4.0);
     235
     236    // XXX EAM - the limit is a bit arbitrary.  make it user defined?
     237    if ((numPixels < minPixels) || (Sum <= 0)) {
     238        psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n", numPixels, minPixels, Sum);
     239        return (false);
     240    }
     241
     242    // calculate the first moment.
     243    float Mx = X1/Sum;
     244    float My = Y1/Sum;
     245    if ((fabs(Mx) > radius) || (fabs(My) > radius)) {
     246        psTrace ("psModules.objects", 3, "extreme centroid swing; invalid peak %d, %d\n", source->peak->x, source->peak->y);
     247        return (false);
     248    }
     249    if ((fabs(Mx) > 2.0) || (fabs(My) > 2.0)) {
     250        psTrace ("psModules.objects", 3, " big centroid swing; ok peak? %d, %d\n", source->peak->x, source->peak->y);
     251    }
     252
     253    psTrace ("psModules.objects", 5, "id: %d, sky: %f  Mx: %f  My: %f  Sum: %f  X1: %f  Y1: %f  Npix: %d\n", source->id, sky, Mx, My, Sum, X1, Y1, numPixels);
     254
     255    // add back offset of peak in primary image
     256    // also offset from pixel index to pixel coordinate
     257    // (the calculation above uses pixel index instead of coordinate)
     258    // 0.5 PIX: moments are calculated using the pixel index and converted here to pixel coords
     259
     260    // we only update the centroid if the position is not supplied from elsewhere
     261    bool skipCentroid = false;
     262    skipCentroid |= (source->mode  & PM_SOURCE_MODE_EXTERNAL); // skip externally supplied positions
     263    skipCentroid |= (source->mode2 & PM_SOURCE_MODE2_MATCHED); // skip sources defined by other image positions
     264
     265    if (skipCentroid) {
     266        source->moments->Mx = source->peak->xf;
     267        source->moments->My = source->peak->yf;
     268    } else {
     269        source->moments->Mx = Mx + xGuess;
     270        source->moments->My = My + yGuess;
     271    }
     272
     273    source->moments->Sum = Sum;
     274    source->moments->SN  = Sum / sqrt(Var);
     275    source->moments->Peak = peakPixel;
     276    source->moments->nPixels = numPixels;
     277
     278    return true;
     279}
     280
     281float pmSourceMinKronRadius(psArray *sources, float PSF_SN_LIM) {
     282
     283    psVector *radii = psVectorAllocEmpty(100, PS_TYPE_F32);
     284
     285    for (int i = 0; i < sources->n; i++) {
     286        pmSource *src = sources->data[i]; // Source of interest
     287        if (!src || !src->moments) {
     288            continue;
     289        }
     290
     291        if (src->mode & PM_SOURCE_MODE_BLEND) {
     292            continue;
     293        }
     294
     295        if (!src->moments->nPixels) continue;
     296
     297        if (src->moments->SN < PSF_SN_LIM) continue;
     298
     299        // XXX put in Mxx,Myy cut based on clump location
     300
     301        psVectorAppend(radii, src->moments->Mrf);
     302    }
     303
     304    // find the peak in this image
     305    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
     306
     307    if (!psVectorStats (stats, radii, NULL, NULL, 0)) {
     308        psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
     309        psFree(stats);
     310        return NAN;
     311    }
     312
     313    float minRadius = stats->sampleMedian;
     314
     315    psFree(radii);
     316    psFree(stats);
     317    return minRadius;
     318}
     319
     320bool pmSourceMomentsHighOrder (pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal) {
     321
     322    // this function assumes the sky has been well-subtracted for the image
     323    float Sum = 0.0;
     324    float R2 = PS_SQR(radius);
     325    float minSN2 = PS_SQR(minSN);
     326    float rsigma2 = 0.5 / PS_SQR(sigma);
     327
    116328    // Now calculate higher-order moments, using the above-calculated first moments to adjust coordinates
    117     // Xn  = SUM (x - xc)^n * (z - sky)
     329    // Xn  = SUM (x - xc)^n * (z - sky) -- note that sky is 0.0 by definition here
    118330    float XX = 0.0;
    119331    float XY = 0.0;
     
    129341    float YYYY = 0.0;
    130342
    131     Sum = 0.0;  // the second pass may include slightly different pixels, re-determine Sum
    132 
    133     // float dX = source->moments->Mx - source->peak->xf;
    134     // float dY = source->moments->My - source->peak->yf;
    135     // float dR = hypot(dX, dY);
    136     // float Xo = (dR < 2.0) ? source->moments->Mx : source->peak->xf;
    137     // float Yo = (dR < 2.0) ? source->moments->My : source->peak->yf;
    138343    float Xo = source->moments->Mx;
    139344    float Yo = source->moments->My;
     
    154359
    155360        psImageMaskType  *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
    156         // psImageMaskType  *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];
    157361
    158362        for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
     
    173377            if (r2 > R2) continue;
    174378
    175             float fDiff = *vPix - sky;
     379            float fDiff = *vPix;
    176380            float pDiff = fDiff;
    177381            float wDiff = *vWgt;
     
    181385            // stars.
    182386            if (PS_SQR(pDiff) < minSN2*wDiff) continue;
    183             if ((minSN > 0.0) && (pDiff < 0)) continue; //
     387            if ((minSN > 0.0) && (pDiff < 0)) continue;
    184388
    185389            // Apply a Gaussian window function.  Be careful with the window function.  S/N
    186             // weighting over weights the sky for faint sources
     390            // weighting over-weights the sky for faint sources
    187391            if (sigma > 0.0) {
    188392                float z = r2 * rsigma2;
     
    230434            XYYY  += xyyy;
    231435            YYYY  += yyyy;
    232 
    233             // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?)
    234             // XXX float r = sqrt(r2);
    235             // XXX float rf = r * fDiff;
    236             // XXX float rh = sqrt(r) * fDiff;
    237             // XXX float rs = fDiff;
    238             // XXX
    239             // XXX float rfw = r * pDiff;
    240             // XXX float rhw = sqrt(r) * pDiff;
    241             // XXX
    242             // XXX RF  += rf;
    243             // XXX RH  += rh;
    244             // XXX RS  += rs;
    245             // XXX
    246             // XXX RFW  += rfw;
    247             // XXX RHW  += rhw;
    248436        }
    249437    }
     438    // NOT needed : source->moments->wSum = Sum;
     439
    250440    source->moments->Mxx = XX/Sum;
    251441    source->moments->Mxy = XY/Sum;
     
    263453    source->moments->Myyyy = YYYY/Sum;
    264454
    265     // *** now calculate the 1st radial moment (for kron flux) -- symmetrical averaging
     455    return true;
     456}
     457
     458bool pmSourceMomentsRadialMoment (pmSource *source, float radius, float minKronRadius, psImageMaskType maskVal) {
     459
    266460
    267461    float **vPix = source->pixels->data.F32;
    268     float **vWgt = source->variance ? source->variance->data.F32 : source->pixels->data.F32;
    269462    psImageMaskType **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA;
    270463
     
    272465    float RH = 0.0;
    273466    float RS = 0.0;
     467
     468    // centroid around which to calculate the moments
     469    float Xo = source->moments->Mx;
     470    float Yo = source->moments->My;
     471
     472    // center of mass in subimage.  Note: the calculation below uses pixel index, so we correct
     473    // xCM, yCM from pixel coords to pixel index here.
     474    float xCM = Xo - 0.5 - source->pixels->col0; // coord of peak in subimage
     475    float yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage
     476
     477    float R2 = PS_SQR(radius);
    274478
    275479    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
     
    304508            if (r2 > R2) continue;
    305509
    306             float fDiff1 = vPix[row][col] - sky;
    307             float fDiff2 = vPix[yFlip][xFlip] - sky;
     510            float fDiff1 = vPix[row][col];
     511            float fDiff2 = vPix[yFlip][xFlip];
    308512            float pDiff = (fDiff1 > 0.0) ? sqrt(fabs(fDiff1*fDiff2)) : -sqrt(fabs(fDiff1*fDiff2));
    309513
     
    329533        kronRefRadius = MIN(radius, kronRefRadius);
    330534    }
    331     source->moments->Mrf = kronRefRadius;
    332 
    333     // *** now calculate the kron flux values using the 1st radial moment
    334 
    335     float radKinner = 1.0*kronRefRadius;
    336     float radKron   = 2.5*kronRefRadius;
    337     float radKouter = 4.0*kronRefRadius;
     535
     536    // if source is externally supplied and it already has a finite Mrf do not change it
     537    if (! ((source->mode & PM_SOURCE_MODE_EXTERNAL) && isfinite(source->moments->Mrf))) {
     538        source->moments->Mrf = kronRefRadius;
     539    }
     540
     541    return true;
     542}
     543
     544bool pmSourceMomentsKronFluxes (pmSource *source, float sigma, float minSN, psImageMaskType maskVal) {
     545
     546    float **vPix = source->pixels->data.F32;
     547    float **vWgt = source->variance ? source->variance->data.F32 : source->pixels->data.F32;
     548    psImageMaskType **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA;
     549
     550    float radKinner = 1.0*source->moments->Mrf;
     551    float radKron   = 2.5*source->moments->Mrf;
     552    float radKouter = 4.0*source->moments->Mrf;
    338553
    339554    int nKronPix = 0;
     
    341556    int nInner = 0;
    342557    int nOuter = 0;
    343     Sum = Var = 0.0;
     558   
     559    float Sum = 0.0;
     560    float Var = 0.0;
     561    float SumCore = 0.0;
     562    float VarCore = 0.0;
    344563    float SumInner = 0.0;
    345564    float SumOuter = 0.0;
     565
     566    // centroid around which to calculate the moments
     567    float Xo = source->moments->Mx;
     568    float Yo = source->moments->My;
     569
     570    // center of mass in subimage.  Note: the calculation below uses pixel index, so we correct
     571    // xCM, yCM from pixel coords to pixel index here.
     572    float xCM = Xo - 0.5 - source->pixels->col0; // coord of peak in subimage
     573    float yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage
     574
     575    float minSN2 = PS_SQR(minSN);
    346576
    347577    // calculate the Kron flux, and related fluxes (NO symmetrical averaging)
     
    362592            float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
    363593
    364             float fDiff1 = vPix[row][col] - sky;
     594            float fDiff1 = vPix[row][col];
    365595            float pDiff = fDiff1;
    366596            float wDiff = vWgt[row][col];
     
    376606                Var += wDiff;
    377607                nKronPix ++;
    378                 // if (beVerbose) fprintf (stderr, "mome: %d %d  %f  %f  %f\n", col, row, sky, *vPix, Sum);
    379608            }
    380609
     
    397626    }
    398627    // *** should I rescale these fluxes by pi R^2 / nNpix?
    399     // XXX source->moments->KronCore    = SumCore       * M_PI * PS_SQR(sigma) / nCorePix;
    400     // XXX source->moments->KronCoreErr = sqrt(VarCore) * M_PI * PS_SQR(sigma) / nCorePix;
    401     // XXX source->moments->KronFlux    = Sum       * M_PI * PS_SQR(radKron) / nKronPix;
    402     // XXX source->moments->KronFluxErr = sqrt(Var) * M_PI * PS_SQR(radKron) / nKronPix;
    403     // XXX source->moments->KronFinner = SumInner * M_PI * (PS_SQR(radKron)   - PS_SQR(radKinner)) / nInner;
    404     // XXX source->moments->KronFouter = SumOuter * M_PI * (PS_SQR(radKouter) -   PS_SQR(radKron)) / nOuter;
     628    // XXX source->moments->KronCore    = SumCore       * M_PI *  PS_SQR(sigma) / nCorePix;
     629    // XXX source->moments->KronCoreErr = sqrt(VarCore) * M_PI *  PS_SQR(sigma) / nCorePix;
     630    // XXX source->moments->KronFlux    = Sum           * M_PI * PS_SQR(radKron) / nKronPix;
     631    // XXX source->moments->KronFluxErr = sqrt(Var)     * M_PI * PS_SQR(radKron) / nKronPix;
     632    // XXX source->moments->KronFinner  = SumInner      * M_PI * (PS_SQR(radKron)   - PS_SQR(radKinner)) / nInner;
     633    // XXX source->moments->KronFouter  = SumOuter      * M_PI * (PS_SQR(radKouter) -   PS_SQR(radKron)) / nOuter;
    405634
    406635    source->moments->KronCore    = SumCore;
     
    408637    source->moments->KronFlux    = Sum;
    409638    source->moments->KronFluxErr = sqrt(Var);
    410     source->moments->KronFinner = SumInner;
    411     source->moments->KronFouter = SumOuter;
     639    source->moments->KronFinner  = SumInner;
     640    source->moments->KronFouter  = SumOuter;
    412641
    413642    // XXX not sure I should save this here...
     
    416645    source->moments->KronRadiusPSF  = source->moments->Mrf;
    417646
    418     psTrace ("psModules.objects", 4, "Mrf: %f  KronFlux: %f  Mxx: %f  Mxy: %f  Myy: %f  Mxxx: %f  Mxxy: %f  Mxyy: %f  Myyy: %f  Mxxxx: %f  Mxxxy: %f  Mxxyy: %f  Mxyyy: %f  Mxyyy: %f\n",
    419              source->moments->Mrf,   source->moments->KronFlux,
    420              source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy,
    421              source->moments->Mxxx,  source->moments->Mxxy,  source->moments->Mxyy,  source->moments->Myyy,
    422              source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy);
    423 
    424     psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f  My: %f  Sum: %f  Mxx: %f  Mxy: %f  Myy: %f  sky: %f  Npix: %d\n",
    425              source->peak->xf, source->peak->yf, source->peak->rawFlux, sqrt(source->peak->detValue), source->moments->Mx,   source->moments->My, Sum, source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy, sky, source->moments->nPixels);
    426 
    427     return(true);
    428 }
    429 
    430 bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) {
    431 
    432     // First Pass: calculate the first moments (these are subtracted from the coordinates below)
    433     // Sum = SUM (z - sky)
    434     // X1  = SUM (x - xc)*(z - sky)
    435     // .. etc
    436 
    437     float sky = 0.0;
    438 
    439     float peakPixel = -PS_MAX_F32;
    440     psS32 numPixels = 0;
    441     float Sum = 0.0;
    442     float Var = 0.0;
    443     float X1 = 0.0;
    444     float Y1 = 0.0;
    445     float R2 = PS_SQR(radius);
    446     float minSN2 = PS_SQR(minSN);
    447     float rsigma2 = 0.5 / PS_SQR(sigma);
    448 
    449     float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage
    450     float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage
    451 
    452     // we are guaranteed to have a valid pixel and variance at this location (right? right?)
    453     // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]);
    454     // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
    455     // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
    456     // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel");
    457 
    458     // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should
    459     // not depend on the fractional pixel location of the source.  However, the aperture
    460     // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel
    461     // position of the expected centroid
    462 
    463     for (psS32 row = 0; row < source->pixels->numRows ; row++) {
    464 
    465         float yDiff = row + 0.5 - yPeak;
    466         if (fabs(yDiff) > radius) continue;
    467 
    468         float *vPix = source->pixels->data.F32[row];
    469         float *vWgt = source->variance ? source->variance->data.F32[row] : source->pixels->data.F32[row];
    470 
    471         psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
    472         // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];
    473 
    474         for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
    475             if (vMsk) {
    476                 if (*vMsk & maskVal) {
    477                     vMsk++;
    478                     continue;
    479                 }
    480                 vMsk++;
    481             }
    482             if (isnan(*vPix)) continue;
    483 
    484             float xDiff = col + 0.5 - xPeak;
    485             if (fabs(xDiff) > radius) continue;
    486 
    487             // radius is just a function of (xDiff, yDiff)
    488             float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
    489             if (r2 > R2) continue;
    490 
    491             float pDiff = *vPix - sky;
    492             float wDiff = *vWgt;
    493 
    494             // skip pixels below specified significance level.  for a PSFs, this
    495             // over-weights the wings of bright stars compared to those of faint stars.
    496             // for the estimator used for extended source analysis (where the window
    497             // function is allowed to be arbitrarily large), we need to clip to avoid
    498             // negative second moments.
    499             if (PS_SQR(pDiff) < minSN2*wDiff) continue; //
    500             if ((minSN > 0.0) && (pDiff < 0)) continue; //
    501 
    502             // Apply a Gaussian window function.  Be careful with the window function.  S/N
    503             // weighting over weights the sky for faint sources
    504             if (sigma > 0.0) {
    505                 float z  = r2*rsigma2;
    506                 assert (z >= 0.0);
    507                 float weight  = exp(-z);
    508 
    509                 wDiff *= weight;
    510                 pDiff *= weight;
    511             }
    512 
    513             Var += wDiff;
    514             Sum += pDiff;
    515 
    516             float xWght = xDiff * pDiff;
    517             float yWght = yDiff * pDiff;
    518 
    519             X1  += xWght;
    520             Y1  += yWght;
    521 
    522             peakPixel = PS_MAX (*vPix, peakPixel);
    523             numPixels++;
    524         }
    525     }
    526 
    527     // if we have less than (1/4) of the possible pixels (in circle or box), force a retry
    528     int minPixels = PS_MIN(0.75*R2, source->pixels->numCols*source->pixels->numRows/4.0);
    529 
    530     // XXX EAM - the limit is a bit arbitrary.  make it user defined?
    531     if ((numPixels < minPixels) || (Sum <= 0)) {
    532         psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n", numPixels, minPixels, Sum);
    533         return (false);
    534     }
    535 
    536     // calculate the first moment.
    537     float Mx = X1/Sum;
    538     float My = Y1/Sum;
    539     if ((fabs(Mx) > radius) || (fabs(My) > radius)) {
    540         psTrace ("psModules.objects", 3, "extreme centroid swing; invalid peak %d, %d\n", source->peak->x, source->peak->y);
    541         return (false);
    542     }
    543     if ((fabs(Mx) > 2.0) || (fabs(My) > 2.0)) {
    544         psTrace ("psModules.objects", 3, " big centroid swing; ok peak? %d, %d\n", source->peak->x, source->peak->y);
    545     }
    546 
    547     psTrace ("psModules.objects", 5, "id: %d, sky: %f  Mx: %f  My: %f  Sum: %f  X1: %f  Y1: %f  Npix: %d\n", source->id, sky, Mx, My, Sum, X1, Y1, numPixels);
    548 
    549     // add back offset of peak in primary image
    550     // also offset from pixel index to pixel coordinate
    551     // (the calculation above uses pixel index instead of coordinate)
    552     // 0.5 PIX: moments are calculated using the pixel index and converted here to pixel coords
    553 
    554     // we only update the centroid if the position is not supplied from elsewhere
    555     bool skipCentroid = false;
    556     skipCentroid |= (source->mode  & PM_SOURCE_MODE_EXTERNAL); // skip externally supplied positions
    557     skipCentroid |= (source->mode2 & PM_SOURCE_MODE2_MATCHED); // skip sources defined by other image positions
    558 
    559     if (skipCentroid) {
    560         source->moments->Mx = source->peak->xf;
    561         source->moments->My = source->peak->yf;
    562     } else {
    563         source->moments->Mx = Mx + xGuess;
    564         source->moments->My = My + yGuess;
    565     }
    566 
    567     source->moments->Sum = Sum;
    568     source->moments->SN  = Sum / sqrt(Var);
    569     source->moments->Peak = peakPixel;
    570     source->moments->nPixels = numPixels;
    571 
    572647    return true;
    573648}
    574 
    575 float pmSourceMinKronRadius(psArray *sources, float PSF_SN_LIM) {
    576 
    577     psVector *radii = psVectorAllocEmpty(100, PS_TYPE_F32);
    578 
    579     for (int i = 0; i < sources->n; i++) {
    580         pmSource *src = sources->data[i]; // Source of interest
    581         if (!src || !src->moments) {
    582             continue;
    583         }
    584 
    585         if (src->mode & PM_SOURCE_MODE_BLEND) {
    586             continue;
    587         }
    588 
    589         if (!src->moments->nPixels) continue;
    590 
    591         if (src->moments->SN < PSF_SN_LIM) continue;
    592 
    593         // XXX put in Mxx,Myy cut based on clump location
    594 
    595         psVectorAppend(radii, src->moments->Mrf);
    596     }
    597 
    598     // find the peak in this image
    599     psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
    600 
    601     if (!psVectorStats (stats, radii, NULL, NULL, 0)) {
    602         psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
    603         psFree(stats);
    604         return NAN;
    605     }
    606 
    607     float minRadius = stats->sampleMedian;
    608 
    609     psFree(radii);
    610     psFree(stats);
    611     return minRadius;
    612 }
    613 
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceOutputs.c

    r35768 r36680  
    3333#include "pmSourceDiffStats.h"
    3434#include "pmSourceSatstar.h"
     35#include "pmSourceLensing.h"
    3536#include "pmSource.h"
    3637#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourcePhotometry.c

    r34498 r36680  
    4040#include "pmSourceDiffStats.h"
    4141#include "pmSourceSatstar.h"
     42#include "pmSourceLensing.h"
    4243#include "pmSource.h"
    4344#include "pmSourceFitModel.h"
     
    113114    source->apFluxErr = NAN;
    114115
     116    pmModelStatus badModel = PM_MODEL_STATUS_NONE;
     117    badModel |= PM_MODEL_STATUS_BADARGS;
     118    badModel |= PM_MODEL_STATUS_OFFIMAGE;
     119    badModel |= PM_MODEL_STATUS_NAN_CHISQ;
     120    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GUESS;
     121    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GRID;
     122    badModel |= PM_MODEL_PCM_FAIL_GUESS;
     123
    115124    // XXXXXX review:
    116125    // Select the 'best' model -- this is used for PSF_QF,_PERFECT & ???. isPSF is true if this
     
    162171        for (int i = 0; i < source->modelFits->n; i++) {
    163172            pmModel *model = source->modelFits->data[i];
    164             if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     173            if (model->flags & badModel) continue;
    165174            status = pmSourcePhotometryModel (&model->mag, NULL, model);
    166175            if (model == source->modelEXT) foundEXT = true;
     
    902911}
    903912
     913bool pmSourceChisqModelFlux (pmSource *source, pmModel *model, psImageMaskType maskVal)
     914{
     915    PS_ASSERT_PTR_NON_NULL(source, false);
     916    PS_ASSERT_PTR_NON_NULL(model, false);
     917
     918    float dC = 0.0;
     919    int Npix = 0;
     920
     921    psVector *params = model->params;
     922    psImage  *image = source->pixels;
     923    psImage  *modelFlux = source->modelFlux;
     924    psImage  *mask = source->maskObj;
     925    psImage  *variance = source->variance;
     926
     927    float Io = params->data.F32[PM_PAR_I0];
     928
     929    for (int iy = 0; iy < image->numRows; iy++) {
     930        for (int ix = 0; ix < image->numCols; ix++) {
     931
     932            // skip pixels which are masked
     933            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal) continue;
     934
     935            if (variance->data.F32[iy][ix] <= 0) continue;
     936
     937            dC += PS_SQR (image->data.F32[iy][ix] - Io*modelFlux->data.F32[iy][ix]) / variance->data.F32[iy][ix];
     938            Npix ++;
     939        }
     940    }
     941    model->nPix = Npix;
     942    model->nDOF = Npix - model->nPar;
     943    model->chisq = dC;
     944    model->chisqNorm = dC / model->nDOF;
     945
     946    return (true);
     947}
     948
    904949double pmSourceModelWeight(const pmSource *Mi, int term, const pmSourceFitVarMode fitVarMode, const float covarFactor, psImageMaskType maskVal)
    905950{
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourcePlotApResid.c

    r34403 r36680  
    4242#include "pmSourceDiffStats.h"
    4343#include "pmSourceSatstar.h"
     44#include "pmSourceLensing.h"
    4445#include "pmSource.h"
    4546#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourcePlotMoments.c

    r34403 r36680  
    4545#include "pmSourceDiffStats.h"
    4646#include "pmSourceSatstar.h"
     47#include "pmSourceLensing.h"
    4748#include "pmSource.h"
    4849#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourcePlotPSFModel.c

    r35768 r36680  
    4646#include "pmSourceDiffStats.h"
    4747#include "pmSourceSatstar.h"
     48#include "pmSourceLensing.h"
    4849#include "pmSource.h"
    4950#include "pmSourceFitModel.h"
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceSky.c

    r35560 r36680  
    4141#include "pmSourceDiffStats.h"
    4242#include "pmSourceSatstar.h"
     43#include "pmSourceLensing.h"
    4344#include "pmSource.h"
    4445
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceUtils.c

    r35560 r36680  
    4141#include "pmSourceDiffStats.h"
    4242#include "pmSourceSatstar.h"
     43#include "pmSourceLensing.h"
    4344#include "pmSource.h"
    4445
  • branches/eam_branches/ps2-tc3-20130727/psModules/src/objects/pmSourceVisual.c

    r35768 r36680  
    2323#include "pmSourceDiffStats.h"
    2424#include "pmSourceSatstar.h"
     25#include "pmSourceLensing.h"
    2526#include "pmSource.h"
    2627#include "pmSourceFitModel.h"
Note: See TracChangeset for help on using the changeset viewer.