IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 31153


Ignore:
Timestamp:
Apr 4, 2011, 1:04:41 PM (15 years ago)
Author:
eugene
Message:

updates to pmPeak to better distinguish peak flux versions; updates to visualization; add bits for substantial suspect masking; consolidate assignment of source position and flux based on peak, moments, etc; improve footprint culling process; fix PSF_QF and PSF_QF_PERFECT calculations; fix source model chisq values

Location:
trunk/psModules
Files:
64 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/psModules

    • Property svn:ignore
      •  

        old new  
        2828ChangeLog
        2929psmodules-*.tar.*
         30a.out.dSYM
  • trunk/psModules/src/astrom/pmAstrometryObjects.c

    r27554 r31153  
    893893        // XXX this function is crashing
    894894        pmAstromVisualPlotGridMatch(raw, ref, gridNP, stats->offset.x, stats->offset.y, maxOffpix, Scale, Offset);
    895         pmAstromVisualPlotGridMatchOverlay(raw, ref);
     895        pmAstromVisualPlotGridMatchOverlay(raw, ref, stats->offset);
    896896
    897897        psFree (imStats);
  • trunk/psModules/src/astrom/pmAstrometryVisual.c

    r26260 r31153  
    2121#include "pmKapaPlots.h"
    2222#include "pmVisual.h"
    23 
    24 //variables to determine when things are plotted
     23#include "pmVisualUtils.h"
     24
     25// variables to determine when things are plotted
    2526static bool plotGridMatch        = true;
    2627static bool plotTweak            = true;
     
    3738
    3839// variables to store plotting window indices
    39 static int kapa = -1;
     40static int kapa1 = -1;
    4041static int kapa2 = -1;
    41 
    42 //helper prototypes
     42static int kapa3 = -1;
     43
     44// helper prototypes
    4345bool residPlot (psArray *rawstars, psArray *refstars, psArray *match, psMetadata *recipe,
    4446                char *title);
     
    4951bool pmAstromVisualClose(void)
    5052{
    51     if(kapa != -1)
    52         KiiClose(kapa);
    53     if(kapa2 != -1)
    54         KiiClose(kapa2);
     53    if (kapa1 != -1) KiiClose(kapa1);
     54    if (kapa2 != -1) KiiClose(kapa2);
    5555    return true;
    5656}
     
    6060bool pmAstromVisualPlotRawStars (psArray *rawstars, pmFPA *fpa, pmChip *chip, psMetadata *recipe)
    6161{
    62     // make sure we want to plot this
    63     if (!plotRawStars || !pmVisualIsVisual()) return true;
    64 
    65     //set up plot region
    66     if (!pmVisualInitWindow (&kapa, "psastro:plots")){
    67         return false;
    68     }
     62    if (!plotRawStars) return true;
     63    if (!pmVisualTestLevel("psastro.plot1", 1)) return true;
     64    if (!pmVisualInitWindow (&kapa1, "psastro:plots")) return false;
     65
    6966    Graphdata graphdata;
    7067    KapaSection section;
    7168
    7269    KapaInitGraph (&graphdata);
    73     KapaClearPlots (kapa);
     70    KapaClearPlots (kapa1);
     71    section.bg = KapaColorByName ("none"); // XXX probably should be 'none'
    7472
    7573    graphdata.color = KapaColorByName ("black");
     
    7876    graphdata.style = 2;
    7977
    80     section.dx = 0.4;
    81     section.dy = 0.4;
    82 
    83     //initialize and populate plotting vectors
     78    section.dx = 0.5;
     79    section.dy = 0.5;
     80
     81    // initialize and populate plotting vectors
    8482    bool status = false;
    8583    float iMagMin = psMetadataLookupF32 (&status, recipe, "PSASTRO.PLOT.INST.MAG.MIN");
     
    9492    section.name = NULL;
    9593    psStringAppend (&section.name, "a0");
    96     KapaSetSection (kapa, &section);
     94    KapaSetSection (kapa1, &section);
    9795    psFree (section.name);
    9896
    99     //Chip coordinates
     97    // Chip coordinates
    10098    int n = 0;
    10199    for (int i = 0; i < rawstars->n; i++) {
     
    112110    xVec->n = yVec->n = zVec->n = n;
    113111
    114     KapaSendLabel(kapa, "Chip", KAPA_LABEL_XP);
    115     KapaSendLabel(kapa, "X", KAPA_LABEL_XM);
    116     KapaSendLabel(kapa, "Y", KAPA_LABEL_YM);
    117     pmVisualTriplePlot (kapa, &graphdata, xVec, yVec, zVec, false);
    118 
    119     //Focal Plane Coordinates
     112    KapaSendLabel(kapa1, "Chip", KAPA_LABEL_XP);
     113    KapaSendLabel(kapa1, "X", KAPA_LABEL_XM);
     114    KapaSendLabel(kapa1, "Y", KAPA_LABEL_YM);
     115    pmVisualTriplePlot (kapa1, &graphdata, xVec, yVec, zVec, false);
     116
     117    // Focal Plane Coordinates
    120118    section.x = 0.5;
    121119    section.y = 0.5;
    122120    section.name = NULL;
    123121    psStringAppend (&section.name, "a1");
    124     KapaSetSection (kapa, &section);
     122    KapaSetSection (kapa1, &section);
    125123    psFree (section.name);
    126124
     
    139137    xVec->n = yVec->n = zVec->n = n;
    140138
    141     KapaSendLabel (kapa, "Focal Plane", KAPA_LABEL_XP);
    142     KapaSendLabel (kapa, "L", KAPA_LABEL_XM);
    143     KapaSendLabel (kapa, "M", KAPA_LABEL_YM);
    144     pmVisualTriplePlot (kapa, &graphdata, xVec, yVec, zVec, false);
     139    KapaSendLabel (kapa1, "Focal Plane", KAPA_LABEL_XP);
     140    KapaSendLabel (kapa1, "L", KAPA_LABEL_XM);
     141    KapaSendLabel (kapa1, "M", KAPA_LABEL_YM);
     142    pmVisualTriplePlot (kapa1, &graphdata, xVec, yVec, zVec, false);
    145143
    146144    // Tangent Plane Coordinates
     
    149147    section.name = NULL;
    150148    psStringAppend (&section.name, "a2");
    151     KapaSetSection (kapa, &section);
     149    KapaSetSection (kapa1, &section);
    152150    psFree (section.name);
    153151
     
    166164    xVec->n = yVec->n = zVec->n = n;
    167165
    168     KapaSendLabel (kapa, "Tangential Plane", KAPA_LABEL_XP);
    169     KapaSendLabel (kapa, "P", KAPA_LABEL_XM);
    170     KapaSendLabel (kapa, "Q", KAPA_LABEL_YM);
    171     pmVisualTriplePlot (kapa, &graphdata, xVec, yVec, zVec, false);
    172 
    173     //sky coordinates
     166    KapaSendLabel (kapa1, "Tangential Plane", KAPA_LABEL_XP);
     167    KapaSendLabel (kapa1, "P", KAPA_LABEL_XM);
     168    KapaSendLabel (kapa1, "Q", KAPA_LABEL_YM);
     169    pmVisualTriplePlot (kapa1, &graphdata, xVec, yVec, zVec, false);
     170
     171    // sky coordinates
    174172    section.x = 0.5;
    175173    section.y = 0.0;
    176174    section.name = NULL;
    177175    psStringAppend (&section.name, "a3");
    178     KapaSetSection (kapa, &section);
     176    KapaSetSection (kapa1, &section);
    179177    psFree (section.name);
    180178
     
    193191    xVec->n = yVec->n = zVec->n = n;
    194192
    195     KapaSendLabel (kapa, "Sky", KAPA_LABEL_XP);
    196     KapaSendLabel(kapa, "RA", KAPA_LABEL_XM);
    197     KapaSendLabel(kapa, "Dec", KAPA_LABEL_YM);
    198     pmVisualTriplePlot (kapa, &graphdata, xVec, yVec, zVec, false);
     193    KapaSendLabel (kapa1, "Sky", KAPA_LABEL_XP);
     194    KapaSendLabel(kapa1, "RA", KAPA_LABEL_XM);
     195    KapaSendLabel(kapa1, "Dec", KAPA_LABEL_YM);
     196    pmVisualTriplePlot (kapa1, &graphdata, xVec, yVec, zVec, false);
    199197
    200198    // flip x (East increase to left)
    201199    SWAP (graphdata.xmin, graphdata.xmax);
    202     KapaSetLimits (kapa, &graphdata);
     200    KapaSetLimits (kapa1, &graphdata);
    203201
    204202    // plot label
    205203    section.x = 0.0;
    206204    section.y = 0.0;
    207     section.dx = .95;
    208     section.dy = .95;
     205    section.dx = 1.0;
     206    section.dy = 1.0;
    209207    section.name = NULL;
    210208    psStringAppend (&section.name, "a5");
    211     KapaSetSection (kapa, &section);
    212     KapaSendLabel (kapa, "Raw Star Selection - Initial Astrometry", KAPA_LABEL_XP);
     209    KapaSetSection (kapa1, &section);
     210    KapaSendLabel (kapa1, "Raw Star Selection - Initial Astrometry", KAPA_LABEL_XP);
    213211    psFree (section.name);
    214212
     
    225223bool pmAstromVisualPlotRefStars (psArray *refstars, psMetadata *recipe)
    226224{
    227     //make sure we want to plot this
    228     if (!pmVisualIsVisual() || !plotRefStars) return true;
    229 
    230     //set up plotting variables
    231     if (!pmVisualInitWindow (&kapa, "psastro:plots")) {
    232         return false;
    233     }
     225    if (!plotRefStars) return true;
     226    if (!pmVisualTestLevel("psastro.plot2", 1)) return true;
     227    if (!pmVisualInitWindow (&kapa1, "psastro:plots")) return false;
    234228
    235229    Graphdata graphdata;
    236230    KapaInitGraph (&graphdata);
    237     KapaClearSections (kapa);
     231    KapaClearSections (kapa1);
    238232
    239233    graphdata.color = KapaColorByName ("black");
     
    242236    graphdata.style = 2;
    243237
    244     //initialize and populate plot vectors
     238    // initialize and populate plot vectors
    245239    bool status = false;
    246240    float rMagMin = psMetadataLookupF32 (&status, recipe, "PSASTRO.PLOT.REF.MAG.MIN");
     
    265259    xVec->n = yVec->n = zVec->n = n;
    266260
    267     KapaSendLabel (kapa, "RA", KAPA_LABEL_XM);
    268     KapaSendLabel (kapa, "Dec", KAPA_LABEL_YM);
    269     KapaSendLabel (kapa, "Reference Stars", KAPA_LABEL_XP);
    270     pmVisualTriplePlot(kapa, &graphdata, xVec, yVec, zVec, false);
     261    KapaSendLabel (kapa1, "RA", KAPA_LABEL_XM);
     262    KapaSendLabel (kapa1, "Dec", KAPA_LABEL_YM);
     263    KapaSendLabel (kapa1, "Reference Stars", KAPA_LABEL_XP);
     264    pmVisualTriplePlot(kapa1, &graphdata, xVec, yVec, zVec, false);
    271265
    272266    // flip x (East increase to left)
    273267    SWAP (graphdata.xmin, graphdata.xmax);
    274     KapaSetLimits (kapa, &graphdata);
     268    KapaSetLimits (kapa1, &graphdata);
    275269
    276270    // pause and wait for user input:
     
    290284                                          )
    291285{
    292 
    293     // make sure we want to plot this
    294     if ( !pmVisualIsVisual() || !plotLumFunc ) return true;
    295 
    296     //set up plotting variables
    297     if ( !pmVisualInitWindow (&kapa, "psastro:plots")){
    298         return false;
    299     }
     286    if (!plotLumFunc ) return true;
     287    if (!pmVisualTestLevel("psastro.plot3", 1)) return true;
     288    if (!pmVisualInitWindow (&kapa1, "psastro:plots")) return false;
     289
     290    int colorNone = KapaColorByName ("none"); // XXX probably should be 'none'
    300291
    301292    Graphdata graphdata;
    302     KapaSection section1 = {"s1", .1, .1, .85, .35};
    303     KapaSection section2 =  {"s2", .1, .5, .85, .35};
     293    KapaSection section1 = {"s1", 0.0, 0.0, 1.0, 0.5, colorNone};
     294    KapaSection section2 = {"s2", 0.0, 0.5, 1.0, 0.5, colorNone};
    304295    KapaSection section;
    305     if(rawFunc == NULL)
     296    if (rawFunc == NULL) {
    306297        section = section1;
    307     else
     298    } else {
    308299        section = section2;
    309     if (rawFunc == NULL)
    310         KapaClearPlots(kapa);
     300    }
     301
     302    if (rawFunc == NULL) KapaClearPlots(kapa1);
    311303    KapaInitGraph(&graphdata);
    312304
    313     //Determine Plot Limits
     305    // Determine Plot Limits
    314306    pmVisualScaleGraphdata(&graphdata, Mag, lnMag, false);
    315307
    316     //Make a line for the fit
     308    // Make a line for the fit
    317309    float x[2] = {graphdata.xmin, graphdata.xmax};
    318310    float y[2] = {lumFunc->offset + x[0] * lumFunc->slope,
    319311                 lumFunc->offset + x[1] * lumFunc->slope};
    320312
    321     //Plot Data
    322     KapaSetSection(kapa, &section);
    323     KapaSetLimits(kapa, &graphdata);
    324 
    325     KapaSetFont (kapa, "helvetica", 14);
    326     KapaBox (kapa, &graphdata);
    327     KapaSendLabel (kapa, "Magnitude", KAPA_LABEL_XM);
    328     KapaSendLabel (kapa, "Log(N)", KAPA_LABEL_YM);
     313    // Plot Data
     314    KapaSetSection(kapa1, &section);
     315    KapaSetLimits(kapa1, &graphdata);
     316
     317    KapaSetFont (kapa1, "helvetica", 14);
     318    KapaBox (kapa1, &graphdata);
     319    KapaSendLabel (kapa1, "Magnitude", KAPA_LABEL_XM);
     320    KapaSendLabel (kapa1, "Log(N)", KAPA_LABEL_YM);
    329321    if (rawFunc == NULL)
    330         KapaSendLabel (kapa, "Raw Star Luminosity Function", KAPA_LABEL_XP);
     322        KapaSendLabel (kapa1, "Raw Star Luminosity Function", KAPA_LABEL_XP);
    331323    else
    332         KapaSendLabel (kapa,
     324        KapaSendLabel (kapa1,
    333325                       "Reference Star Luminosity Function, Shifted Raw Fit, and Cutoff",
    334326                       KAPA_LABEL_XP);
    335327    graphdata.color=KapaColorByName("black");
    336328    graphdata.style = 1;
    337     KapaPrepPlot (kapa, lnMag->n, &graphdata);
    338     KapaPlotVector(kapa, lnMag->n,   Mag->data.F32, "x");
    339     KapaPlotVector(kapa, lnMag->n, lnMag->data.F32, "y");
    340 
    341     //Overplot fit
     329    KapaPrepPlot (kapa1, lnMag->n, &graphdata);
     330    KapaPlotVector(kapa1, lnMag->n,   Mag->data.F32, "x");
     331    KapaPlotVector(kapa1, lnMag->n, lnMag->data.F32, "y");
     332
     333    // Overplot fit
    342334    graphdata.style=0;
    343     KapaPrepPlot(kapa,2,&graphdata);
    344     KapaPlotVector(kapa, 2, x, "x");
    345     KapaPlotVector(kapa, 2, y, "y");
    346 
    347     //If rawFunc was supplied, overplot the raw star fit + cutoff
     335    KapaPrepPlot(kapa1,2,&graphdata);
     336    KapaPlotVector(kapa1, 2, x, "x");
     337    KapaPlotVector(kapa1, 2, y, "y");
     338
     339    // If rawFunc was supplied, overplot the raw star fit + cutoff
    348340    if( rawFunc != NULL) {
    349341        double mRef = 0.5*(lumFunc->mMin + lumFunc->mMax);
     
    359351        float y[2] = {graphdata.ymin, graphdata.ymax};
    360352        graphdata.color= KapaColorByName("red");
    361         KapaPrepPlot(kapa, 2, &graphdata);
    362         KapaPlotVector(kapa, 2, x, "x");
    363         KapaPlotVector(kapa, 2, y, "y");
    364         KapaPrepPlot (kapa, 2, &graphdata);
    365         KapaPlotVector (kapa, 2, xraw, "x");
    366         KapaPlotVector (kapa, 2, yraw, "y");
     353        KapaPrepPlot(kapa1, 2, &graphdata);
     354        KapaPlotVector(kapa1, 2, x, "x");
     355        KapaPlotVector(kapa1, 2, y, "y");
     356        KapaPrepPlot (kapa1, 2, &graphdata);
     357        KapaPlotVector (kapa1, 2, xraw, "x");
     358        KapaPlotVector (kapa1, 2, yraw, "y");
    367359
    368360        // pause and wait for user input:
     
    379371                                    )
    380372{
    381 
    382     //make sure we want to plot this
    383     if (!pmVisualIsVisual() || !plotRemoveClumps) return true;
    384 
    385     //set up plot variables
    386     if ( !pmVisualInitWindow (&kapa, "psastro:plots")) {
    387         return false;
    388     }
     373    if (!plotRemoveClumps) return true;
     374    if (!pmVisualTestLevel("psastro.plot4", 1)) return true;
     375    if (!pmVisualInitWindow (&kapa1, "psastro:plots")) return false;
    389376
    390377    KapaSection section;
    391378    Graphdata graphdata;
    392     section.x = 0;
    393     section.dx = .9;
    394     section.y = 0;
    395     section.dy = .9;
     379
     380    KapaClearSections (kapa1);
     381    KapaInitGraph(&graphdata);
     382    section.bg = KapaColorByName ("none"); // XXX probably should be 'none'
     383
     384    section.x = 0.0;
     385    section.dx = 1;
     386    section.y = 0.0;
     387    section.dy = 1.0;
    396388    section.name = NULL;
    397389    psStringAppend( &section.name, "a0");
    398     KapaInitGraph(&graphdata);
    399     KapaSetSection(kapa, &section);
     390    KapaSetSection(kapa1, &section);
    400391    psFree(section.name);
    401392
     
    404395    graphdata.style = 2;
    405396    graphdata.color = KapaColorByName ("black");
    406     KapaClearPlots(kapa);
    407 
    408     //set up plot vectors
     397    KapaClearPlots(kapa1);
     398
     399    // set up plot vectors
    409400    float Xmin = +FLT_MAX;
    410401    float Xmax = -FLT_MAX;
     
    414405    psVector *yVec = psVectorAlloc (input->n, PS_TYPE_F32);
    415406
    416     //determine boundaries for histogram bin calculation
     407    // determine boundaries for histogram bin calculation
    417408    int n = 0;
    418409    for (int i=0; i< input->n; i++) {
     
    430421    xVec->n = yVec->n = n;
    431422
    432     //plot stars
     423    // plot stars
    433424    graphdata.xmax = Xmax;
    434425    graphdata.xmin = Xmin;
    435426    graphdata.ymax = Ymax;
    436427    graphdata.ymin = Ymin;
    437     KapaSetLimits (kapa, &graphdata);
    438     KapaSetFont (kapa, "helvetica", 14);
    439 
    440     KapaBox (kapa, &graphdata);
    441 
    442     KapaSendLabel (kapa, "L (pixels)", KAPA_LABEL_XM);
    443     KapaSendLabel (kapa, "M (pixels)", KAPA_LABEL_YM);
    444     KapaSendLabel (kapa, "Regions Flagged as Clumps (Red Boxes)",
     428    KapaSetLimits (kapa1, &graphdata);
     429    KapaSetFont (kapa1, "helvetica", 14);
     430
     431    KapaBox (kapa1, &graphdata);
     432
     433    KapaSendLabel (kapa1, "L (pixels)", KAPA_LABEL_XM);
     434    KapaSendLabel (kapa1, "M (pixels)", KAPA_LABEL_YM);
     435    KapaSendLabel (kapa1, "Regions Flagged as Clumps (Red Boxes)",
    445436                   KAPA_LABEL_XP);
    446437
    447     KapaPrepPlot (kapa, xVec->n, &graphdata);
    448     KapaPlotVector (kapa, xVec->n, xVec->data.F32, "x");
    449     KapaPlotVector (kapa, yVec->n, yVec->data.F32, "y");
     438    KapaPrepPlot (kapa1, xVec->n, &graphdata);
     439    KapaPlotVector (kapa1, xVec->n, xVec->data.F32, "x");
     440    KapaPlotVector (kapa1, yVec->n, yVec->data.F32, "y");
    450441
    451442    graphdata.color = KapaColorByName ("red");
    452443    graphdata.style = 0;
    453444
    454     //overplot clumpy regions excluded from analysis
    455     for(int i = 0; i < count->numCols; i++) {
     445    // overplot clumpy regions excluded from analysis
     446    for (int i = 0; i < count->numCols; i++) {
    456447        for (int j = 0; j < count->numRows; j++) {
    457             if(count->data.U32[j][i] <= limit) continue; //not a clump
     448            if(count->data.U32[j][i] <= limit) continue; // not a clump
    458449            float Xbot = (i - 5) * scale + Xmin;
    459450            float Ybot = (j - 5) * scale + Ymin;
     
    462453            float x[5] = {Xbot, Xbot + scale, Xbot + scale, Xbot, Xbot};
    463454            float y[5] = {Ybot, Ybot, Ybot + scale, Ybot + scale, Ybot};
    464             KapaPrepPlot (kapa, 5, &graphdata);
    465             KapaPlotVector (kapa, 5, x, "x");
    466             KapaPlotVector (kapa, 5, y, "y");
     455            KapaPrepPlot (kapa1, 5, &graphdata);
     456            KapaPlotVector (kapa1, 5, x, "x");
     457            KapaPlotVector (kapa1, 5, y, "y");
    467458        }
    468459    }
    469460
    470     //ask for user input and finish
     461    // ask for user input and finish
    471462    pmVisualAskUser (&plotRemoveClumps);
    472463    psFree (xVec);
     
    483474                                  )
    484475{
    485 
    486     //make sure we want to plot this
    487     if (!pmVisualIsVisual() || !plotOneChipFit)
    488         return true;
    489 
    490     if(!pmVisualInitWindow(&kapa, "psastro:plots") || !pmVisualInitWindow(&kapa2, "psastro:plots")) {
    491         return false;
    492     }
    493 
    494     //plot the residuals
     476    if (!plotOneChipFit) return true;
     477    if (!pmVisualTestLevel("psastro.plot5", 1)) return true;
     478    if (!pmVisualInitWindow(&kapa1, "psastro:plot1")) return false;
     479    if (!pmVisualInitWindow(&kapa2, "psastro:plot2")) return false;
     480    if (!pmVisualInitWindow(&kapa3, "psastro:plot3")) return false;
     481
     482    // plot the residuals
    495483    if (!residPlot(rawstars, refstars, match, recipe, "Single Chip Fit Residuals (Chip Coordinates)")) {
    496484        plotOneChipFit = false;
     
    498486    }
    499487
    500     //ask for user input and finish
     488    // ask for user input and finish
    501489    pmVisualAskUser(&plotOneChipFit);
    502490    return true;
     
    509497                                )
    510498{
    511     //make sure we want to plot this
    512     if(!pmVisualIsVisual() || !plotFixChips) return true;
    513 
    514     if(!pmVisualInitWindow(&kapa, "psastro:plots")) {
    515         return false;
    516     }
    517 
    518     KapaSection section = {"s1", .05, .05, .9, .9};
     499    if (!plotFixChips) return true;
     500    if (!pmVisualTestLevel("psastro.plot6", 1)) return true;
     501    if (!pmVisualInitWindow(&kapa1, "psastro:plots")) return false;
     502
     503    int colorNone = KapaColorByName ("none"); // XXX probably should be 'none'
     504
     505    KapaSection section = {"s1", 0.0, 0.0, 1.0, 1.0, colorNone};
    519506    Graphdata graphdata;
    520     KapaInitGraph( &graphdata);
    521     KapaClearPlots (kapa);
     507    KapaInitGraph (&graphdata);
     508    KapaClearPlots (kapa1);
    522509    graphdata.ptype = 2;
    523510    graphdata.style = 2;
     
    559546    }
    560547
    561     //set up graph
     548    // set up graph
    562549    pmVisualScaleGraphdata(&graphdata, xOld, yOld, true);
    563     pmVisualInitGraph(kapa, &section, &graphdata);
    564     KapaSendLabel (kapa, "L (FP)", KAPA_LABEL_XM);
    565     KapaSendLabel (kapa, "M (FP)", KAPA_LABEL_YM);
    566     KapaSendLabel (kapa, "Chip corners before (black) and after (red) FixChips", KAPA_LABEL_XP);
    567     KapaPrepPlot (kapa, xOld->n, &graphdata);
    568     KapaPlotVector (kapa, xOld->n, xOld->data.F32, "x");
    569     KapaPlotVector (kapa, xOld->n, yOld->data.F32, "y");
     550    pmVisualInitGraph(kapa1, &section, &graphdata);
     551    KapaSendLabel (kapa1, "L (FP)", KAPA_LABEL_XM);
     552    KapaSendLabel (kapa1, "M (FP)", KAPA_LABEL_YM);
     553    KapaSendLabel (kapa1, "Chip corners before (black) and after (red) FixChips", KAPA_LABEL_XP);
     554    KapaPrepPlot (kapa1, xOld->n, &graphdata);
     555    KapaPlotVector (kapa1, xOld->n, xOld->data.F32, "x");
     556    KapaPlotVector (kapa1, xOld->n, yOld->data.F32, "y");
    570557
    571558    graphdata.ptype = 1;
    572559    graphdata.color = KapaColorByName("red");
    573     KapaPrepPlot (kapa, xNew->n, &graphdata);
    574     KapaPlotVector (kapa, xNew->n, xNew->data.F32, "x");
    575     KapaPlotVector (kapa, xNew->n, yNew->data.F32, "y");
     560    KapaPrepPlot (kapa1, xNew->n, &graphdata);
     561    KapaPlotVector (kapa1, xNew->n, xNew->data.F32, "x");
     562    KapaPlotVector (kapa1, xNew->n, yNew->data.F32, "y");
    576563
    577564    pmVisualAskUser(&plotFixChips);
     
    591578                                        )
    592579{
    593 
    594     //make sure we want to plot this
    595     if (!pmVisualIsVisual() || !plotAstromGuessCheck) return true;
    596 
    597     //set up graph window
    598     if ( !pmVisualInitWindow (&kapa, "psastro:plots")) {
    599         return false;
    600     }
     580    if (!plotAstromGuessCheck) return true;
     581    if (!pmVisualTestLevel("psastro.plot7", 1)) return true;
     582    if (!pmVisualInitWindow (&kapa1, "psastro:plots")) return false;
    601583
    602584    Graphdata graphdata;
    603585    KapaSection section;
    604     KapaInitGraph(&graphdata);
    605     KapaClearPlots (kapa);
     586    KapaInitGraph (&graphdata);
     587    KapaClearPlots (kapa1);
     588
     589    section.bg = KapaColorByName ("none"); // XXX probably should be 'none'
    606590
    607591    graphdata.color = KapaColorByName ("black");
     
    613597    section.dy = 0.4;
    614598
    615     //Old Corners
     599    // Old Corners
    616600    section.x = 0.30;
    617601    section.y = 0.50;
    618602    section.name = NULL;
    619603    psStringAppend (&section.name, "a0");
    620     KapaSetSection (kapa, &section);
     604    KapaSetSection (kapa1, &section);
    621605    psFree(section.name);
    622606
    623607    pmVisualScaleGraphdata (&graphdata, cornerPo, cornerPo, true);
    624     KapaSetLimits (kapa, &graphdata);
    625     KapaBox (kapa, &graphdata);
    626     KapaSendLabel (kapa, "P (Pixels)", KAPA_LABEL_XM);
    627     KapaSendLabel (kapa, "Q (Pixels)", KAPA_LABEL_YM);
    628     KapaSendLabel (kapa,
     608    KapaSetLimits (kapa1, &graphdata);
     609    KapaBox (kapa1, &graphdata);
     610    KapaSendLabel (kapa1, "P (Pixels)", KAPA_LABEL_XM);
     611    KapaSendLabel (kapa1, "Q (Pixels)", KAPA_LABEL_YM);
     612    KapaSendLabel (kapa1,
    629613                   "Fiducial Points in the Tangent Plane. Black: Initial Astrometry. Red: Final Astrometry",
    630614                   KAPA_LABEL_XP);
    631     KapaPrepPlot (kapa, cornerPo->n, &graphdata);
    632     KapaPlotVector (kapa, cornerPo->n, cornerPo->data.F32, "x");
    633     KapaPlotVector (kapa, cornerQo->n, cornerQo->data.F32, "y");
     615    KapaPrepPlot (kapa1, cornerPo->n, &graphdata);
     616    KapaPlotVector (kapa1, cornerPo->n, cornerPo->data.F32, "x");
     617    KapaPlotVector (kapa1, cornerQo->n, cornerQo->data.F32, "y");
    634618
    635619    // New Corners
     
    637621    graphdata.ptype = 7;
    638622    graphdata.size = 1.5;
    639     KapaPrepPlot (kapa, cornerPn->n, &graphdata);
    640     KapaPlotVector (kapa, cornerPn->n, cornerPn->data.F32, "x");
    641     KapaPlotVector (kapa, cornerQn->n, cornerQn->data.F32, "y");
     623    KapaPrepPlot (kapa1, cornerPn->n, &graphdata);
     624    KapaPlotVector (kapa1, cornerPn->n, cornerPn->data.F32, "x");
     625    KapaPlotVector (kapa1, cornerQn->n, cornerQn->data.F32, "y");
    642626
    643627    // Residuals
     
    655639    section.name = NULL;
    656640    psStringAppend (&section.name, "a1");
    657     KapaSetSection (kapa, &section);
     641    KapaSetSection (kapa1, &section);
    658642    psFree(section.name);
    659643
    660644    pmVisualScaleGraphdata (&graphdata, xResid, yResid, true);
    661     KapaSetLimits (kapa, &graphdata);
    662     KapaBox (kapa, &graphdata);
    663     KapaSendLabel (kapa, "dP", KAPA_LABEL_XM);
    664     KapaSendLabel (kapa, "dQ", KAPA_LABEL_YM);
    665     KapaSendLabel (kapa,
     645    KapaSetLimits (kapa1, &graphdata);
     646    KapaBox (kapa1, &graphdata);
     647    KapaSendLabel (kapa1, "dP", KAPA_LABEL_XM);
     648    KapaSendLabel (kapa1, "dQ", KAPA_LABEL_YM);
     649    KapaSendLabel (kapa1,
    666650                   "Residual of the Fit from the Initial Astrometry to the Final Astrometry",
    667651                   KAPA_LABEL_XP);
    668     KapaPrepPlot (kapa, cornerPd->n, &graphdata);
    669     KapaPlotVector (kapa, cornerPd->n, xResid->data.F32, "x");
    670     KapaPlotVector (kapa, cornerQd->n, yResid->data.F32, "y");
     652    KapaPrepPlot (kapa1, cornerPd->n, &graphdata);
     653    KapaPlotVector (kapa1, cornerPd->n, xResid->data.F32, "x");
     654    KapaPlotVector (kapa1, cornerQd->n, yResid->data.F32, "y");
    671655
    672656    psFree(xResid);
     
    681665                                   )
    682666{
    683     //make sure we want to plot this
    684     if (!pmVisualIsVisual() || !plotCommonScale) return true;
    685 
    686     if (!pmVisualInitWindow(&kapa, "psastro:plots")){
    687         return false;
    688     }
    689 
    690     KapaSection section = {"s1", .05, .05, .9, .9};
     667    if (!plotCommonScale) return true;
     668    if (!pmVisualTestLevel("psastro.plot8", 1)) return true;
     669    if (!pmVisualInitWindow(&kapa1, "psastro:plots")) return false;
     670
     671    int colorNone = KapaColorByName ("none");
     672    KapaSection section = {"s1", 0.0, 0.0, 1.0, 1.0, colorNone};
    691673    Graphdata graphdata;
     674
    692675    psPlane ptCH, ptFP;
    693676    ptCH.x = 0;
     
    698681    int nobj = 0;
    699682
    700     //project each chip corner to the Focal Plane
     683    // project each chip corner to the Focal Plane
    701684    for(int i = 0; i < fpa->chips->n; i++) {
    702685        pmChip *chip = fpa->chips->data[i];
     
    711694    }
    712695
    713     //set up plot window
     696    // set up plot window
    714697    KapaInitGraph (&graphdata);
    715     KapaClearPlots (kapa);
    716     KapaSetSection (kapa, &section);
    717     KapaSetFont (kapa, "helvetica", 14);
    718     pmVisualTriplePlot (kapa, &graphdata, xVec, yVec, oldScale, false);
    719     KapaSendLabel (kapa, "L (FP)", KAPA_LABEL_XM);
    720     KapaSendLabel (kapa, "M (FP)", KAPA_LABEL_YM);
    721     KapaSendLabel (kapa, "Old Pixel Scale of FPA Chips (Not to Scale)", KAPA_LABEL_XP);
     698    KapaClearPlots (kapa1);
     699    KapaSetSection (kapa1, &section);
     700    KapaSetFont (kapa1, "helvetica", 14);
     701    pmVisualTriplePlot (kapa1, &graphdata, xVec, yVec, oldScale, false);
     702    KapaSendLabel (kapa1, "L (FP)", KAPA_LABEL_XM);
     703    KapaSendLabel (kapa1, "M (FP)", KAPA_LABEL_YM);
     704    KapaSendLabel (kapa1, "Old Pixel Scale of FPA Chips (Not to Scale)", KAPA_LABEL_XP);
    722705
    723706    pmVisualAskUser (&plotCommonScale);
     
    733716                                     psArray *match, psMetadata *recipe)
    734717{
    735 
    736     //make sure we want to plot this
    737     if (!pmVisualIsVisual() || !plotMosaicOneChip) return true;
    738 
    739     if(!pmVisualInitWindow(&kapa, "psastro:plots") || !pmVisualInitWindow(&kapa2, "psastro:plots")) {
    740         return false;
    741     }
    742 
    743     //plot the residuals
     718    if (!plotMosaicOneChip) return true;
     719    if (!pmVisualTestLevel("psastro.plot9", 1)) return true;
     720    if (!pmVisualInitWindow(&kapa1, "psastro:plot1")) return false;
     721    if (!pmVisualInitWindow(&kapa2, "psastro:plot2")) return false;
     722    if (!pmVisualInitWindow(&kapa3, "psastro:plot3")) return false;
     723
     724    // plot the residuals
    744725    if (!residPlot(rawstars, refstars, match, recipe, "Single Chip Fit Residuals - Mosaic Mode")) {
    745726        pmVisualSetVisual(false);
     
    747728    }
    748729
    749     //ask for user input and finish
     730    // ask for user input and finish
    750731    pmVisualAskUser(&plotMosaicOneChip);
    751732
     
    758739                                    psMetadata *recipe)
    759740{
    760     //make sure we want to plot this
    761     if (!pmVisualIsVisual() || !plotMosaicMatches) return true;
     741    if (!plotMosaicMatches) return true;
     742    if (!pmVisualTestLevel("psastro.plot10", 1)) return true;
     743    if (!pmVisualInitWindow(&kapa1, "psastro:plot1")) return false;
     744    if (!pmVisualInitWindow(&kapa2, "psastro:plot2")) return false;
     745    if (!pmVisualInitWindow(&kapa3, "psastro:plot3")) return false;
    762746
    763747    char title[60];
    764748    sprintf(title, "Matches found during psastroMosaicSetMatch iteration %d", iteration);
    765 
    766 
    767     if(!pmVisualInitWindow(&kapa, "psastro:plots") || !pmVisualInitWindow(&kapa2, "psastro:plots")) {
    768         return false;
    769     }
    770749
    771750    if (!residPlot(rawstars, refstars, match, recipe, title)){
     
    774753    }
    775754
    776     //ask for user input
     755    // ask for user input
    777756    pmVisualAskUser (&plotMosaicMatches);
    778757    return true;
     
    789768                                  double Offset)
    790769{
    791     //make sure we want to plot this
    792     if (!pmVisualIsVisual() || !plotGridMatch) return true;
    793     if (!pmVisualInitWindow(&kapa, "psastro:plots")){
    794         return false;
    795     }
    796 
    797     KapaSection section = {"s1", 0.05, 0.05, .75, .75};
    798     KapaSection sectionY = {"s2", 0.8, 0.05, .15, .75};
    799     KapaSection sectionX = {"s3", .05, .8, .75, .15};
     770    if (!plotGridMatch) return true;
     771    if (!pmVisualTestLevel("psastro.plot11", 1)) return true;
     772    if (!pmVisualInitWindow(&kapa1, "psastro:plots")) return false;
     773
     774    int colorNone = KapaColorByName ("none");
     775    KapaSection section  = {"s1", 0.00, 0.00, 0.75, 0.75, colorNone};
     776    KapaSection sectionY = {"s2", 0.75, 0.00, 0.25, 0.75, colorNone};
     777    KapaSection sectionX = {"s3", 0.00, 0.75, 0.75, 0.25, colorNone};
    800778
    801779    Graphdata graphdata;
     
    818796
    819797    // set up plot information
    820     KapaClearPlots(kapa);
     798    KapaClearPlots(kapa1);
    821799    KapaInitGraph(&graphdata);
    822     KapaSetSection(kapa, &section);
     800    KapaSetSection(kapa1, &section);
    823801
    824802    graphdata.xmin = -1.0 * maxOffpix;
     
    826804    graphdata.ymin = -1.0 * maxOffpix;
    827805    graphdata.ymax =  1.0 * maxOffpix;
    828     KapaSetLimits(kapa, &graphdata);
    829 
    830     KapaSetFont(kapa, "helvetica", 14);
    831     KapaBox(kapa, &graphdata);
    832     KapaSendLabel (kapa, "X offset (FP)", KAPA_LABEL_XM);
    833     KapaSendLabel (kapa, "Y offset (FP)", KAPA_LABEL_YM);
    834     KapaSendLabel (kapa, "pmAstromGridAngle residuals. Box: Correlation Peak.",
     806    KapaSetLimits(kapa1, &graphdata);
     807
     808    KapaSetFont(kapa1, "helvetica", 14);
     809    KapaBox(kapa1, &graphdata);
     810    KapaSendLabel (kapa1, "X offset (FP)", KAPA_LABEL_XM);
     811    KapaSendLabel (kapa1, "Y offset (FP)", KAPA_LABEL_YM);
     812    KapaSendLabel (kapa1, "pmAstromGridAngle residuals. Box: Correlation Peak.",
    835813                   KAPA_LABEL_XP);
    836814    graphdata.style = 2;
     
    868846    }
    869847
    870     //Plot the offsets
    871     KapaPrepPlot(kapa, nplot, &graphdata);
    872     KapaPlotVector (kapa, nplot, dXplot->data.F32, "x");
    873     KapaPlotVector (kapa, nplot, dYplot->data.F32, "y");
    874 
    875     //Overplot bounding box, peak of distribution
     848    // Plot the offsets
     849    KapaPrepPlot(kapa1, nplot, &graphdata);
     850    KapaPlotVector (kapa1, nplot, dXplot->data.F32, "x");
     851    KapaPlotVector (kapa1, nplot, dYplot->data.F32, "y");
     852
     853    // Overplot bounding box, peak of distribution
    876854    float xbound[5] = { -maxOffpix, maxOffpix, maxOffpix, -maxOffpix, -maxOffpix};
    877855    float ybound[5] = { -maxOffpix, -maxOffpix, maxOffpix, maxOffpix, -maxOffpix};
     
    885863    graphdata.style = 0;
    886864    graphdata.size = 1.0;
    887     KapaPrepPlot(kapa, 5, &graphdata);
    888     KapaPlotVector (kapa, 5, xbound, "x");
    889     KapaPlotVector (kapa, 5, ybound, "y");
    890     KapaPrepPlot(kapa, 5, &graphdata);
    891     KapaPlotVector (kapa, 5, xbin, "x");
    892     KapaPlotVector (kapa, 5, ybin, "y");
    893 
    894     //plot X profile
    895     KapaSetSection(kapa, &sectionX);
     865    KapaPrepPlot(kapa1, 5, &graphdata);
     866    KapaPlotVector (kapa1, 5, xbound, "x");
     867    KapaPlotVector (kapa1, 5, ybound, "y");
     868    KapaPrepPlot(kapa1, 5, &graphdata);
     869    KapaPlotVector (kapa1, 5, xbin, "x");
     870    KapaPlotVector (kapa1, 5, ybin, "y");
     871
     872    // plot X profile
     873    KapaSetSection(kapa1, &sectionX);
    896874    graphdata.color = KapaColorByName("black");
    897875    graphdata.ptype = 1;
     
    899877    graphdata.ymin = 0;
    900878    graphdata.ymax = maxHorizontalSlice + 0.5;
    901     KapaSetLimits(kapa, &graphdata);
    902 
    903     KapaBox(kapa, &graphdata);
    904     KapaPrepPlot(kapa, gridNP->numCols, &graphdata);
    905     KapaPlotVector (kapa, gridNP->numCols, horizontalIndices, "x");
    906     KapaPlotVector (kapa, gridNP->numCols, horizHistSlice, "y");
     879    strcpy (graphdata.labels, "0200");
     880    KapaSetLimits(kapa1, &graphdata);
     881
     882    KapaBox(kapa1, &graphdata);
     883    KapaPrepPlot(kapa1, gridNP->numCols, &graphdata);
     884    KapaPlotVector (kapa1, gridNP->numCols, horizontalIndices, "x");
     885    KapaPlotVector (kapa1, gridNP->numCols, horizHistSlice, "y");
    907886
    908887    float xslice[2] = {offsetX - Scale / 2., offsetX - Scale / 2.};
     
    910889    graphdata.style = 0;
    911890    graphdata.color = KapaColorByName("red");
    912     KapaPrepPlot(kapa, 2, &graphdata);
    913     KapaPlotVector (kapa, 2, xslice, "x");
    914     KapaPlotVector (kapa, 2, yslice, "y");
    915 
    916     //plot Y profile
    917     KapaSetSection(kapa, &sectionY);
     891    KapaPrepPlot(kapa1, 2, &graphdata);
     892    KapaPlotVector (kapa1, 2, xslice, "x");
     893    KapaPlotVector (kapa1, 2, yslice, "y");
     894
     895    // plot Y profile
     896    KapaSetSection(kapa1, &sectionY);
    918897    graphdata.color = KapaColorByName("black");
    919898    graphdata.ptype = 1;
     
    923902    graphdata.xmin = -1.0 ;
    924903    graphdata.xmax = maxVerticalSlice + 0.5;
    925     KapaSetLimits(kapa, &graphdata);
    926 
    927     KapaBox(kapa, &graphdata);
    928     KapaPrepPlot(kapa, gridNP->numRows, &graphdata);
    929     KapaPlotVector (kapa, gridNP->numRows, vertHistSlice, "x");
    930     KapaPlotVector (kapa, gridNP->numRows, verticalIndices, "y");
     904    strcpy (graphdata.labels, "2000");
     905    KapaSetLimits(kapa1, &graphdata);
     906
     907    KapaBox(kapa1, &graphdata);
     908    KapaPrepPlot(kapa1, gridNP->numRows, &graphdata);
     909    KapaPlotVector (kapa1, gridNP->numRows, vertHistSlice, "x");
     910    KapaPlotVector (kapa1, gridNP->numRows, verticalIndices, "y");
    931911
    932912    yslice[0] = yslice[1] = offsetY - Scale / 2.;
     
    934914    graphdata.style = 0;
    935915    graphdata.color = KapaColorByName("red");
    936     KapaPrepPlot(kapa, 2, &graphdata);
    937     KapaPlotVector (kapa, 2, xslice, "x");
    938     KapaPlotVector (kapa, 2, yslice, "y");
     916    KapaPrepPlot(kapa1, 2, &graphdata);
     917    KapaPlotVector (kapa1, 2, xslice, "x");
     918    KapaPlotVector (kapa1, 2, yslice, "y");
    939919
    940920    pmVisualAskUser(&plotGridMatch);
     
    946926
    947927bool pmAstromVisualPlotGridMatchOverlay (const psArray *raw,
    948                                          const psArray *ref)
     928                                         const psArray *ref,
     929                                         const psPlane offset)
    949930{
    950     //make sure we want to plot this
    951     if (!pmVisualIsVisual() || !plotGridMatch) return true;
    952     if (!pmVisualInitWindow(&kapa2, "psastro:plots")){
    953         return false;
    954     }
     931    if (!plotGridMatch) return true;
     932    if (!pmVisualTestLevel("psastro.plot12", 1)) return true;
     933    if (!pmVisualInitWindow(&kapa2, "psastro:plots")) return false;
    955934
    956935    Graphdata graphdata;
     
    980959        graphdata.ymin = PS_MIN(graphdata.ymin, obj->FP->y);
    981960        graphdata.ymax = PS_MAX(graphdata.ymax, obj->FP->y);
    982         xPlot->data.F32[i] = obj->FP->x;
    983         yPlot->data.F32[i] = obj->FP->y;
     961        xPlot->data.F32[i] = obj->FP->x + offset.x;
     962        yPlot->data.F32[i] = obj->FP->y + offset.y;
    984963        zPlot->data.F32[i] = obj->Mag;
    985964    }
     
    999978    // the point size will be scaled from the z vector
    1000979    graphdata.style = 2;
    1001     graphdata.ptype = 7;
     980    graphdata.ptype = 2;
    1002981    graphdata.size = -1;
    1003982    graphdata.color = KapaColorByName ("black");
     
    10521031    )
    10531032{
    1054     //make sure we want to plot this
    1055     if (!pmVisualIsVisual() || !plotTweak) return true;
    1056     if (!pmVisualInitWindow(&kapa, "psastro:plots")) {
    1057         return false;
    1058     }
     1033    if (!plotTweak) return true;
     1034    if (!pmVisualTestLevel("psastro.plot13", 1)) return true;
     1035    if (!pmVisualInitWindow(&kapa1, "psastro:plots")) return false;
    10591036
    10601037    Graphdata graphdata;
    1061     KapaSection section1 = {"s1", 0.05, 0.05, 0.90, 0.4};
    1062     KapaSection section2 = {"s2", 0.05, 0.5, 0.90, 0.4};
     1038
     1039    int colorNone = KapaColorByName ("none"); // XXX probably should be 'none'
     1040    KapaSection section1 = {"s1", 0.0, 0.0, 1.0, 0.5, colorNone};
     1041    KapaSection section2 = {"s2", 0.0, 0.5, 1.0, 0.5, colorNone};
     1042    KapaSection section3 = {"s3", 0.0, 0.0, 1.0, 1.0, colorNone};
    10631043
    10641044    psVector *xIndices = psVectorAlloc (xHist->n, PS_TYPE_F32);
    10651045    psVector *yIndices = psVectorAlloc (yHist->n, PS_TYPE_F32);
    10661046
    1067     //populate the Indices vectors
     1047    // populate the Indices vectors
    10681048    for(int i = 0; i < xHist->n; i++) {
    10691049        xIndices->data.F32[i] = i;
     
    10741054
    10751055    // set up plot information
    1076     KapaClearPlots(kapa);
     1056    KapaClearPlots(kapa1);
    10771057    KapaInitGraph(&graphdata);
    10781058
    10791059    // plot the X histogram
    10801060    pmVisualScaleGraphdata(&graphdata, xIndices, xHist, false);
    1081     KapaSetSection(kapa, &section1);
    1082     KapaSetLimits (kapa, &graphdata);
    1083     KapaSetFont(kapa, "helvetica", 14);
    1084     KapaBox(kapa, &graphdata);
    1085     KapaSendLabel (kapa, "X offset Bin", KAPA_LABEL_XM);
    1086     KapaSendLabel (kapa, "Number of Sources", KAPA_LABEL_YM);
    1087     KapaSendLabel (kapa, "Horizontal Profile",
     1061    KapaSetSection(kapa1, &section1);
     1062    KapaSetLimits (kapa1, &graphdata);
     1063    KapaSetFont(kapa1, "helvetica", 14);
     1064    KapaBox(kapa1, &graphdata);
     1065    KapaSendLabel (kapa1, "X offset Bin", KAPA_LABEL_XM);
     1066    KapaSendLabel (kapa1, "Number of Sources", KAPA_LABEL_YM);
     1067    KapaSendLabel (kapa1, "Horizontal Profile",
    10881068                   KAPA_LABEL_XP);
    10891069    graphdata.style = 1;
     
    10921072    graphdata.color = KapaColorByName ("black");
    10931073
    1094     KapaPrepPlot (kapa, xHist->n, &graphdata);
    1095     KapaPlotVector (kapa, xHist->n, xIndices->data.F32, "x");
    1096     KapaPlotVector (kapa, xHist->n, xHist->data.F32, "y");
    1097 
    1098     //overplot the peak
     1074    KapaPrepPlot (kapa1, xHist->n, &graphdata);
     1075    KapaPlotVector (kapa1, xHist->n, xIndices->data.F32, "x");
     1076    KapaPlotVector (kapa1, xHist->n, xHist->data.F32, "y");
     1077
     1078    // overplot the peak
    10991079    float x[2] = {xBin, xBin};
    11001080    float y[2] = {-500, 500};
    11011081    graphdata.color = KapaColorByName ("red");
    1102     KapaPrepPlot (kapa, 2, &graphdata);
    1103     KapaPlotVector (kapa, 2, x, "x");
    1104     KapaPlotVector (kapa, 2, y, "y");
    1105 
    1106     //plot the Y histogram
     1082    KapaPrepPlot (kapa1, 2, &graphdata);
     1083    KapaPlotVector (kapa1, 2, x, "x");
     1084    KapaPlotVector (kapa1, 2, y, "y");
     1085
     1086    // plot the Y histogram
    11071087    pmVisualScaleGraphdata(&graphdata, yIndices, yHist, false);
    1108     KapaSetSection(kapa, &section2);
    1109     KapaSetLimits (kapa, &graphdata);
    1110     KapaSetFont(kapa, "helvetica", 14);
     1088    KapaSetSection(kapa1, &section2);
     1089    KapaSetLimits (kapa1, &graphdata);
     1090    KapaSetFont(kapa1, "helvetica", 14);
    11111091    graphdata.color = KapaColorByName ("black");
    1112     KapaBox(kapa, &graphdata);
    1113     KapaSendLabel (kapa, "Y offset Bin", KAPA_LABEL_XM);
    1114     KapaSendLabel (kapa, "Number of Sources", KAPA_LABEL_YM);
    1115     KapaSendLabel (kapa, "Vertical Profile",
     1092    KapaBox(kapa1, &graphdata);
     1093    KapaSendLabel (kapa1, "Y offset Bin", KAPA_LABEL_XM);
     1094    KapaSendLabel (kapa1, "Number of Sources", KAPA_LABEL_YM);
     1095    KapaSendLabel (kapa1, "Vertical Profile",
    11161096                   KAPA_LABEL_XP);
    11171097    graphdata.style = 1;
     
    11191099    graphdata.size = 0.4;
    11201100
    1121     KapaPrepPlot (kapa, yHist->n, &graphdata);
    1122     KapaPlotVector (kapa, yHist->n, yIndices->data.F32, "x");
    1123     KapaPlotVector (kapa, yHist->n, yHist->data.F32, "y");
    1124 
    1125     //overplot the peak
     1101    KapaPrepPlot (kapa1, yHist->n, &graphdata);
     1102    KapaPlotVector (kapa1, yHist->n, yIndices->data.F32, "x");
     1103    KapaPlotVector (kapa1, yHist->n, yHist->data.F32, "y");
     1104
     1105    // overplot the peak
    11261106    x[0] = x[1] = yBin;
    11271107    graphdata.color = KapaColorByName ("red");
    1128     KapaPrepPlot (kapa, 2, &graphdata);
    1129     KapaPlotVector (kapa, 2, x, "x");
    1130     KapaPlotVector (kapa, 2, y, "y");
    1131 
    1132     //plot title
     1108    KapaPrepPlot (kapa1, 2, &graphdata);
     1109    KapaPlotVector (kapa1, 2, x, "x");
     1110    KapaPlotVector (kapa1, 2, y, "y");
     1111
     1112    // plot title
    11331113    graphdata.color = KapaColorByName("black");
    1134     KapaSection section3 = {"s3", 0, 0, 1, 1};
    1135     KapaSetSection( kapa, &section3);
    1136     KapaSendLabel (kapa, "Tweaking the Astrometry Grid Solution. Smoothed profiles + peak location",
     1114
     1115    KapaSetSection( kapa1, &section3);
     1116    KapaSendLabel (kapa1, "Tweaking the Astrometry Grid Solution. Smoothed profiles + peak location",
    11371117                   KAPA_LABEL_XP);
    11381118
     
    11421122    psFree(yIndices);
    11431123    return true;
    1144 } //end of pmAstromPlotTweak
     1124} // end of pmAstromPlotTweak
    11451125
    11461126
     
    11491129
    11501130
    1151     //initialize graph information
     1131    // initialize graph information
    11521132    Graphdata graphdata;
    11531133    KapaSection section;
     1134    section.bg = KapaColorByName ("none"); // XXX probably should be 'none'
    11541135
    11551136    KapaInitGraph (&graphdata);
    1156     KapaClearPlots (kapa);
     1137    KapaClearPlots (kapa1);
    11571138
    11581139    graphdata.color = KapaColorByName ("black");
     
    11641145    section.dy = 0.4;
    11651146
    1166     //initialize and populate the plotting vectors
     1147    // initialize and populate the plotting vectors
    11671148    bool status = false;
    11681149    float iMagMin = psMetadataLookupF32 (&status, recipe, "PSASTRO.PLOT.INST.MAG.MIN");
     
    11801161    section.name = NULL;
    11811162    psStringAppend (&section.name, "a0");
    1182     KapaSetSection (kapa, &section);
     1163    KapaSetSection (kapa1, &section);
    11831164    psFree (section.name);
    11841165
     
    12021183    xVec->n = yVec->n = zVec->n = n;
    12031184
    1204     KapaSendLabel (kapa, "X", KAPA_LABEL_XM);
    1205     KapaSendLabel (kapa, "dX", KAPA_LABEL_YM);
    1206     pmVisualTriplePlot (kapa, &graphdata, xVec, yVec, zVec, false);
     1185    KapaSendLabel (kapa1, "X", KAPA_LABEL_XM);
     1186    KapaSendLabel (kapa1, "dX", KAPA_LABEL_YM);
     1187    pmVisualTriplePlot (kapa1, &graphdata, xVec, yVec, zVec, false);
    12071188
    12081189    // X vs dY
     
    12111192    section.name = NULL;
    12121193    psStringAppend (&section.name, "a1");
    1213     KapaSetSection (kapa, &section);
     1194    KapaSetSection (kapa1, &section);
    12141195    psFree (section.name);
    12151196
     
    12331214    xVec->n = yVec->n = zVec->n = n;
    12341215
    1235     KapaSendLabel (kapa, "X", KAPA_LABEL_XM);
    1236     KapaSendLabel (kapa, "dY", KAPA_LABEL_YM);
    1237     pmVisualTriplePlot (kapa, &graphdata, xVec, yVec, zVec, false);
     1216    KapaSendLabel (kapa1, "X", KAPA_LABEL_XM);
     1217    KapaSendLabel (kapa1, "dY", KAPA_LABEL_YM);
     1218    pmVisualTriplePlot (kapa1, &graphdata, xVec, yVec, zVec, false);
    12381219
    12391220    // Y vs dX
     
    12421223    section.name = NULL;
    12431224    psStringAppend (&section.name, "a2");
    1244     KapaSetSection (kapa, &section);
     1225    KapaSetSection (kapa1, &section);
    12451226    psFree (section.name);
    12461227
     
    12641245    xVec->n = yVec->n = zVec->n = n;
    12651246
    1266     KapaSendLabel (kapa, "Y", KAPA_LABEL_XM);
    1267     KapaSendLabel (kapa, "dX", KAPA_LABEL_YM);
    1268     pmVisualTriplePlot (kapa, &graphdata, xVec, yVec, zVec, false);
     1247    KapaSendLabel (kapa1, "Y", KAPA_LABEL_XM);
     1248    KapaSendLabel (kapa1, "dX", KAPA_LABEL_YM);
     1249    pmVisualTriplePlot (kapa1, &graphdata, xVec, yVec, zVec, false);
    12691250
    12701251    // Y vs dY
     
    12731254    section.name = NULL;
    12741255    psStringAppend (&section.name, "a3");
    1275     KapaSetSection (kapa, &section);
     1256    KapaSetSection (kapa1, &section);
    12761257    psFree (section.name);
    12771258
     
    12951276    xVec->n = yVec->n = zVec->n = n;
    12961277
    1297     KapaSendLabel (kapa, "Y", KAPA_LABEL_XM);
    1298     KapaSendLabel (kapa, "dY", KAPA_LABEL_YM);
    1299     pmKapaPlotVectorTriple_AutoLimits_OpenGraph (kapa, &graphdata, xVec, yVec, zVec, false);
     1278    KapaSendLabel (kapa1, "Y", KAPA_LABEL_XM);
     1279    KapaSendLabel (kapa1, "dY", KAPA_LABEL_YM);
     1280    pmKapaPlotVectorTriple_AutoLimits_OpenGraph (kapa1, &graphdata, xVec, yVec, zVec, false);
     1281
     1282    psFree (xVec);
     1283    psFree (yVec);
     1284    psFree (zVec);
    13001285
    13011286    section.x = 0.0;
     
    13051290    section.name = NULL;
    13061291    psStringAppend (&section.name, "a5");
    1307     KapaSetSection (kapa, &section);
    1308     KapaSendLabel (kapa, title, KAPA_LABEL_XP);
     1292    KapaSetSection (kapa1, &section);
     1293    KapaSendLabel (kapa1, title, KAPA_LABEL_XP);
    13091294    psFree (section.name);
    13101295
    1311     //second window
     1296    // ***************************************
     1297    // second window
    13121298
    13131299    KapaInitGraph (&graphdata);
     
    13221308    graphdata.ptype = 7;
    13231309    graphdata.style = 2;
    1324 
    1325     psFree (xVec);
    1326     psFree (yVec);
    1327     psFree (zVec);
    13281310
    13291311    xVec = psVectorAlloc (refstars->n, PS_TYPE_F32);
     
    13461328    pmVisualTriplePlot (kapa2, &graphdata, xVec, yVec, zVec, false);
    13471329
    1348     //rescale the graph to include all points
     1330    // rescale the graph to include all points
    13491331    float xmin = graphdata.xmin;
    13501332    float ymin = graphdata.ymin;
     
    13581340    KapaSetLimits (kapa2, &graphdata);
    13591341
    1360     bool plotTweak;
    1361     pmVisualAskUser(&plotTweak);
     1342    // bool plotTweak;
     1343    // pmVisualAskUser(&plotTweak);
    13621344
    13631345    // X vs Y by mag (raw)
    13641346    graphdata.color = KapaColorByName ("black");
    1365     graphdata.ptype = 2;
     1347    graphdata.ptype = 7;
    13661348    graphdata.style = 2;
    13671349
     
    13891371    pmVisualTripleOverplot (kapa2, &graphdata, xVec, yVec, zVec, false);
    13901372
    1391     //overplot matched stars in blue
     1373    // overplot matched stars in blue
    13921374    psFree (xVec);
    13931375    psFree (yVec);
     
    13981380    zVec = psVectorAlloc (match->n, PS_TYPE_F32);
    13991381
     1382    graphdata.ptype = 2;
    14001383    graphdata.color = KapaColorByName ("blue");
    14011384    n = 0;
     
    14111394        xVec->data.F32[n] = raw->chip->x;
    14121395        yVec->data.F32[n] = raw->chip->y;
    1413         zVec->data.F32[n] = iMagMin;
     1396        zVec->data.F32[n] = raw->Mag;
    14141397        n++;
    14151398    }
    14161399    xVec->n = yVec->n = zVec->n = n;
     1400    fprintf (stderr, "plotting %d matched stars (raw = blue)\n", n);
    14171401    pmVisualTripleOverplot (kapa2, &graphdata, xVec, yVec, zVec, false);
     1402
     1403    if (0) {
     1404        graphdata.ptype = 3;
     1405        graphdata.color = KapaColorByName ("green");
     1406        n = 0;
     1407        for (int i = 0; i < match->n; i++) {
     1408            pmAstromMatch *pair = match->data[i];
     1409            pmAstromObj *raw = rawstars->data[pair->raw];
     1410            pmAstromObj *ref = refstars->data[pair->ref];
     1411            if (raw->Mag < iMagMin) continue;
     1412            if (raw->Mag > iMagMax) continue;
     1413            if (ref->Mag < rMagMin) continue;
     1414            if (ref->Mag > rMagMax) continue;
     1415
     1416            xVec->data.F32[n] = ref->chip->x;
     1417            yVec->data.F32[n] = ref->chip->y;
     1418            zVec->data.F32[n] = ref->Mag;
     1419            n++;
     1420        }
     1421        xVec->n = yVec->n = zVec->n = n;
     1422        fprintf (stderr, "plotting %d matched stars (ref = green)\n", n);
     1423        pmVisualTripleOverplot (kapa2, &graphdata, xVec, yVec, zVec, false);
     1424    }
    14181425
    14191426    psFree (xVec);
    14201427    psFree (yVec);
    14211428    psFree (zVec);
     1429
     1430    // ***************************************
     1431    // third window, pt1
     1432
     1433    xVec = psVectorAlloc (match->n, PS_TYPE_F32);
     1434    yVec = psVectorAlloc (match->n, PS_TYPE_F32);
     1435
     1436    KapaInitGraph (&graphdata);
     1437    KapaClearPlots (kapa3);
     1438
     1439    // X vs Y by mag (ref)
     1440    graphdata.color = KapaColorByName ("black");
     1441    graphdata.ptype = 2;
     1442    graphdata.style = 2;
     1443    graphdata.size = 1;
     1444
     1445    section.x  = 0.0;
     1446    section.y  = 0.0;
     1447    section.dx = 0.5;
     1448    section.dy = 0.5;
     1449    section.name = NULL;
     1450    psStringAppend (&section.name, "s1");
     1451    KapaSetSection (kapa3, &section);
     1452    psFree (section.name);
     1453
     1454    n = 0;
     1455    for (int i = 0; i < match->n; i++) {
     1456        pmAstromMatch *pair = match->data[i];
     1457        pmAstromObj *raw = rawstars->data[pair->raw];
     1458        pmAstromObj *ref = refstars->data[pair->ref];
     1459        if (raw->Mag < iMagMin) continue;
     1460        if (raw->Mag > iMagMax) continue;
     1461        if (ref->Mag < rMagMin) continue;
     1462        if (ref->Mag > rMagMax) continue;
     1463
     1464        xVec->data.F32[n] = raw->Mag;
     1465        yVec->data.F32[n] = raw->chip->y - ref->chip->y;
     1466        n++;
     1467    }
     1468    xVec->n = yVec->n = n;
     1469
     1470    // rescale the graph to include all points
     1471    pmVisualScaleGraphdata(&graphdata, xVec, yVec, true);
     1472    KapaSetLimits (kapa3, &graphdata);
     1473    KapaBox (kapa3, &graphdata);
     1474    KapaSendLabel(kapa1, "raw mag", KAPA_LABEL_XM);
     1475    KapaSendLabel(kapa1, "dY", KAPA_LABEL_YM);
     1476
     1477    KapaPrepPlot (kapa3, xVec->n, &graphdata);
     1478    KapaPlotVector (kapa3, xVec->n, xVec->data.F32, "x");
     1479    KapaPlotVector (kapa3, yVec->n, yVec->data.F32, "y");
     1480
     1481    // ***************************************
     1482    // third window, pt2
     1483
     1484    section.x  = 0.5;
     1485    section.y  = 0.0;
     1486    section.dx = 0.5;
     1487    section.dy = 0.5;
     1488    section.name = NULL;
     1489    psStringAppend (&section.name, "s2");
     1490    KapaSetSection (kapa3, &section);
     1491    psFree (section.name);
     1492
     1493    n = 0;
     1494    for (int i = 0; i < match->n; i++) {
     1495        pmAstromMatch *pair = match->data[i];
     1496        pmAstromObj *raw = rawstars->data[pair->raw];
     1497        pmAstromObj *ref = refstars->data[pair->ref];
     1498        if (raw->Mag < iMagMin) continue;
     1499        if (raw->Mag > iMagMax) continue;
     1500        if (ref->Mag < rMagMin) continue;
     1501        if (ref->Mag > rMagMax) continue;
     1502
     1503        xVec->data.F32[n] = ref->Mag;
     1504        yVec->data.F32[n] = raw->chip->y - ref->chip->y;
     1505        n++;
     1506    }
     1507    xVec->n = yVec->n = n;
     1508
     1509    // rescale the graph to include all points
     1510    pmVisualScaleGraphdata(&graphdata, xVec, yVec, true);
     1511    KapaSetLimits (kapa3, &graphdata);
     1512    KapaBox (kapa3, &graphdata);
     1513    KapaSendLabel(kapa1, "ref mag", KAPA_LABEL_XM);
     1514    KapaSendLabel(kapa1, "dY", KAPA_LABEL_YM);
     1515
     1516    KapaPrepPlot (kapa3, xVec->n, &graphdata);
     1517    KapaPlotVector (kapa3, xVec->n, xVec->data.F32, "x");
     1518    KapaPlotVector (kapa3, yVec->n, yVec->data.F32, "y");
     1519
     1520    // ***************************************
     1521    // third window, pt3
     1522
     1523    section.x  = 0.0;
     1524    section.y  = 0.5;
     1525    section.dx = 0.5;
     1526    section.dy = 0.5;
     1527    section.name = NULL;
     1528    psStringAppend (&section.name, "s3");
     1529    KapaSetSection (kapa3, &section);
     1530    psFree (section.name);
     1531
     1532    n = 0;
     1533    for (int i = 0; i < match->n; i++) {
     1534        pmAstromMatch *pair = match->data[i];
     1535        pmAstromObj *raw = rawstars->data[pair->raw];
     1536        pmAstromObj *ref = refstars->data[pair->ref];
     1537        if (raw->Mag < iMagMin) continue;
     1538        if (raw->Mag > iMagMax) continue;
     1539        if (ref->Mag < rMagMin) continue;
     1540        if (ref->Mag > rMagMax) continue;
     1541
     1542        xVec->data.F32[n] = raw->Mag;
     1543        yVec->data.F32[n] = raw->chip->x - ref->chip->x;
     1544        n++;
     1545    }
     1546    xVec->n = yVec->n = n;
     1547
     1548    // rescale the graph to include all points
     1549    pmVisualScaleGraphdata(&graphdata, xVec, yVec, true);
     1550    KapaSetLimits (kapa3, &graphdata);
     1551    KapaBox (kapa3, &graphdata);
     1552    KapaSendLabel(kapa1, "raw mag", KAPA_LABEL_XM);
     1553    KapaSendLabel(kapa1, "dX", KAPA_LABEL_YM);
     1554
     1555    KapaPrepPlot (kapa3, xVec->n, &graphdata);
     1556    KapaPlotVector (kapa3, xVec->n, xVec->data.F32, "x");
     1557    KapaPlotVector (kapa3, yVec->n, yVec->data.F32, "y");
     1558
     1559    // ***************************************
     1560    // third window, pt4
     1561
     1562    section.x  = 0.5;
     1563    section.y  = 0.5;
     1564    section.dx = 0.5;
     1565    section.dy = 0.5;
     1566    section.name = NULL;
     1567    psStringAppend (&section.name, "s4");
     1568    KapaSetSection (kapa3, &section);
     1569    psFree (section.name);
     1570
     1571    n = 0;
     1572    for (int i = 0; i < match->n; i++) {
     1573        pmAstromMatch *pair = match->data[i];
     1574        pmAstromObj *raw = rawstars->data[pair->raw];
     1575        pmAstromObj *ref = refstars->data[pair->ref];
     1576        if (raw->Mag < iMagMin) continue;
     1577        if (raw->Mag > iMagMax) continue;
     1578        if (ref->Mag < rMagMin) continue;
     1579        if (ref->Mag > rMagMax) continue;
     1580
     1581        xVec->data.F32[n] = ref->Mag;
     1582        yVec->data.F32[n] = raw->chip->x - ref->chip->x;
     1583        n++;
     1584    }
     1585    xVec->n = yVec->n = n;
     1586
     1587    // rescale the graph to include all points
     1588    pmVisualScaleGraphdata(&graphdata, xVec, yVec, true);
     1589    KapaSetLimits (kapa3, &graphdata);
     1590    KapaBox (kapa3, &graphdata);
     1591    KapaSendLabel(kapa1, "ref mag", KAPA_LABEL_XM);
     1592    KapaSendLabel(kapa1, "dX", KAPA_LABEL_YM);
     1593
     1594    KapaPrepPlot (kapa3, xVec->n, &graphdata);
     1595    KapaPlotVector (kapa3, xVec->n, xVec->data.F32, "x");
     1596    KapaPlotVector (kapa3, yVec->n, yVec->data.F32, "y");
     1597
    14221598    return true;
    14231599}
  • trunk/psModules/src/astrom/pmAstrometryVisual.h

    r26260 r31153  
    4747
    4848bool pmAstromVisualPlotGridMatchOverlay (const psArray *raw,
    49                                          const psArray *ref);
     49                                         const psArray *ref,
     50                                         const psPlane offset);
    5051
    5152/**
  • trunk/psModules/src/camera/pmFPA_JPEG.c

    r29544 r31153  
    3535#include "pmFPAfile.h"
    3636#include "pmFPA_JPEG.h"
    37 
    3837
    3938bool pmFPAviewWriteJPEG(const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
     
    227226    char *userOptions = psMetadataLookupStr(&status, options, "OPTIONS"); // Mode for scaling image
    228227    if (userOptions) {
    229         // just use strstr for now
    230         if (strcasestr(userOptions, "+SB")) {
     228        // just use strstr : strcasestr is non-standard an not always available.  replace with our own?
     229        if (strstr(userOptions, "+SB")) {
    231230            jpegOptions->showScale = PS_JPEG_SHOWSCALE_BOTTOM;
    232231        }
    233         if (strcasestr(userOptions, "-X")) {
     232        if (strstr(userOptions, "-X")) {
    234233            jpegOptions->xFlip = true;
    235234        }
    236         if (strcasestr(userOptions, "-Y")) {
     235        if (strstr(userOptions, "-Y")) {
     236            jpegOptions->yFlip = true;
     237        }
     238        // lowercase versions
     239        if (strstr(userOptions, "+sb")) {
     240            jpegOptions->showScale = PS_JPEG_SHOWSCALE_BOTTOM;
     241        }
     242        if (strstr(userOptions, "-x")) {
     243            jpegOptions->xFlip = true;
     244        }
     245        if (strstr(userOptions, "-y")) {
    237246            jpegOptions->yFlip = true;
    238247        }
  • trunk/psModules/src/extras/pmVisual.c

    r30623 r31153  
    1 /** The following are a collection of core procedures to aid the creation of visaual diagnostics
     1/** The following are a collection of core procedures to aid the creation of visual diagnostics
    22 *  @author Chris Beaumont, IfA
    33 *  @date January 23, 2008
     
    8080
    8181bool pmVisualInitWindow (int *kapid, char *name) {
     82
    8283    if (*kapid == -1) {
    8384        *kapid = KapaOpenNamedSocket("kapa", name);
    8485        if (*kapid == -1) {
    85             fprintf (stderr, "Failure to open kapa.\n");
    86             isVisual = false;
     86            fprintf (stderr, "Failure to open kapa; visual mode disabled.\n");
     87            pmVisualSetVisual(false);
    8788            return false;
    8889        }
     
    255256    }
    256257
     258    if (increasing) {
     259        fprintf (stderr, "plotting points scaled from %f to %f\n", zmin, zmax);
     260    } else {
     261        fprintf (stderr, "plotting points scaled from %f to %f\n", zmax, zmin);
     262    }
     263
    257264    float range = zmax - zmin;
    258265    if (range == 0.0) {
  • trunk/psModules/src/extras/pmVisualUtils.c

    r29004 r31153  
    1616#include <pslib.h>
    1717
     18#include <pmVisual.h>
    1819#include <pmVisualUtils.h>
    1920
     
    8990    }
    9091
     92    // turn on overall visualization
     93    pmVisualSetVisual(true);
     94
    9195    // If the component name has no leading dot, then supply it.
    9296    if (comp[0] != '.') {
     
    145149    PS_ASSERT_STRING_NON_EMPTY(func, false);
    146150
    147    // return true if level is set to be shown
     151    // if visualization is turned off, just skip
     152    if (!pmVisualIsVisual()) return false;
     153
     154    // return true if level is set to be shown
    148155    FACILITY(facility, func, name);
     156
    149157    bool valid = level <= getLevel(facility);
    150158
  • trunk/psModules/src/imcombine/pmStack.c

    r29543 r31153  
    3737# if (0)
    3838#define TESTING                         // Enable test output
    39 #define TEST_X 4963                       // x coordinate to examine
    40 #define TEST_Y 5353                       // y coordinate to examine
    41 #define TEST_X 40                       // x coordinate to examine
    42 #define TEST_Y 40                       // y coordinate to examine
     39#define TEST_X 340                       // x coordinate to examine
     40#define TEST_Y 938                       // y coordinate to examine
    4341#define TEST_RADIUS 0.5                 // Radius to examine
    4442# endif
  • trunk/psModules/src/imcombine/pmSubtractionStamps.c

    r31023 r31153  
    11921192    for (int i = 0; i < numIn; i++) {
    11931193        pmSource *source = sources->data[i]; // Source of interest
    1194         if (!source || (source->mode & SOURCE_MASK) || source->psfMag > SOURCE_FAINTEST) {
     1194        if (!source || (source->mode & SOURCE_MASK) ||(source->psfMag > SOURCE_FAINTEST)) {
    11951195            continue;
    11961196        }
    11971197       
     1198        // fprintf (stderr, "%f,%f : %f %f : %f %f\n", source->peak->xf, source->peak->yf,
     1199        // source->psfMag, source->apMag, source->psfMag - source->apMag, source->errMag);
     1200
    11981201        // XXX this is somewhat arbitrary...
    11991202        if (source->errMag > 0.05) continue;
  • trunk/psModules/src/objects/Makefile.am

    r29004 r31153  
    3232        pmSourceFitSet.c \
    3333        pmSourcePhotometry.c \
     34        pmSourceOutputs.c \
    3435        pmSourceIO.c \
    3536        pmSourceIO_RAW.c \
     
    102103        pmSourceFitSet.h \
    103104        pmSourcePhotometry.h \
     105        pmSourceOutputs.h \
    104106        pmSourceIO.h \
    105107        pmSourcePlots.h \
  • trunk/psModules/src/objects/models/pmModel_DEV.c

    r29004 r31153  
    217217bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
    218218{
    219     pmMoments *moments = source->moments;
    220     pmPeak    *peak    = source->peak;
    221     psF32     *PAR  = model->params->data.F32;
    222 
    223     psEllipseMoments emoments;
    224     emoments.x2 = moments->Mxx;
    225     emoments.xy = moments->Mxy;
    226     emoments.y2 = moments->Myy;
    227 
    228     // force the axis ratio to be < 20.0
    229     psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
    230 
    231     if (!isfinite(axes.major)) return false;
    232     if (!isfinite(axes.minor)) return false;
    233     if (!isfinite(axes.theta)) return false;
    234 
    235     psEllipseShape shape = psEllipseAxesToShape (axes);
    236 
    237     if (!isfinite(shape.sx))  return false;
    238     if (!isfinite(shape.sy))  return false;
    239     if (!isfinite(shape.sxy)) return false;
    240 
    241     // the other parameters depend on the guess for PAR_7
     219    psF32 *PAR  = model->params->data.F32;
     220
     221    // sky is set to 0.0
     222    PAR[PM_PAR_SKY]  = 0.0;
     223
     224    // set the shape parameters
     225    if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments)) {
     226      return false;
     227    }
     228
     229    // the normalization is modified by the slope
    242230    float index = 0.5 / ALPHA;
    243231    float bn = 1.9992*index - 0.3271;
    244     // float fR = 1.0 / (sqrt(2.0) * pow (bn, index));
    245232    float Io = exp(0.5*bn);
    246233
    247     float Sxx = PS_MAX(0.5, shape.sx);
    248     float Syy = PS_MAX(0.5, shape.sy);
    249 
    250     PAR[PM_PAR_SKY]  = 0.0;
    251     PAR[PM_PAR_I0]   = peak->flux / Io;
    252     PAR[PM_PAR_XPOS] = peak->xf;
    253     PAR[PM_PAR_YPOS] = peak->yf;
    254     // PAR[PM_PAR_SXX]  = Sxx * fR;
    255     // PAR[PM_PAR_SYY]  = Syy * fR;
    256     PAR[PM_PAR_SXX]  = Sxx;
    257     PAR[PM_PAR_SYY]  = Syy;
    258     PAR[PM_PAR_SXY]  = shape.sxy;
     234    // set the model normalization
     235    if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
     236      return false;
     237    }
     238    PAR[PM_PAR_I0] /= Io;
     239
     240    // set the model position
     241    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     242      return false;
     243    }
    259244
    260245    return(true);
     
    322307    psF64 radius = axes.major * sqrt (2.0) * pow(zn, 0.5 / ALPHA);
    323308
    324     psAssert (isfinite(radius), "fix this code: z should not be nan");
     309    psAssert (isfinite(radius), "fix this code: radius should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)",
     310              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY]);
     311
    325312    return (radius);
    326313}
  • trunk/psModules/src/objects/models/pmModel_EXP.c

    r29004 r31153  
    210210bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
    211211{
    212     pmMoments *moments = source->moments;
    213     pmPeak    *peak    = source->peak;
    214     psF32     *PAR  = model->params->data.F32;
    215 
    216     psEllipseMoments emoments;
    217     emoments.x2 = moments->Mxx;
    218     emoments.xy = moments->Mxy;
    219     emoments.y2 = moments->Myy;
    220 
    221     // force the axis ratio to be < 20.0
    222     psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
    223 
    224     if (!isfinite(axes.major)) return false;
    225     if (!isfinite(axes.minor)) return false;
    226     if (!isfinite(axes.theta)) return false;
    227 
    228     psEllipseShape shape = psEllipseAxesToShape (axes);
    229 
    230     if (!isfinite(shape.sx))  return false;
    231     if (!isfinite(shape.sy))  return false;
    232     if (!isfinite(shape.sxy)) return false;
    233 
     212    psF32 *PAR  = model->params->data.F32;
     213
     214    // sky is set to 0.0
    234215    PAR[PM_PAR_SKY]  = 0.0;
    235     PAR[PM_PAR_I0]   = peak->flux;
    236     PAR[PM_PAR_XPOS] = peak->xf;
    237     PAR[PM_PAR_YPOS] = peak->yf;
    238     PAR[PM_PAR_SXX]  = PS_MAX(0.5, M_SQRT2*shape.sx);
    239     PAR[PM_PAR_SYY]  = PS_MAX(0.5, M_SQRT2*shape.sy);
    240     PAR[PM_PAR_SXY]  = shape.sxy;
     216
     217    // set the shape parameters
     218    if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments)) {
     219      return false;
     220    }
     221
     222    // set the model normalization
     223    if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
     224      return false;
     225    }
     226
     227    // set the model position
     228    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     229      return false;
     230    }
     231
    241232    return(true);
    242233}
     
    303294    psF64 radius = axes.major * sqrt (2.0) * zn;
    304295
    305     psAssert (isfinite(radius), "fix this code: z should not be nan for %f", PAR[PM_PAR_7]);
     296    psAssert (isfinite(radius), "fix this code: radius should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)",
     297              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY]);
    306298    return (radius);
    307299}
  • trunk/psModules/src/objects/models/pmModel_GAUSS.c

    r29004 r31153  
    193193bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
    194194{
    195     pmMoments *moments = source->moments;
    196     pmPeak    *peak    = source->peak;
    197     psF32     *PAR  = model->params->data.F32;
    198 
    199     psEllipseMoments emoments;
    200     emoments.x2 = moments->Mxx;
    201     emoments.y2 = moments->Myy;
    202     emoments.xy = moments->Mxy;
    203 
    204     // force the axis ratio to be < 20.0
    205     psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
    206     psEllipseShape shape = psEllipseAxesToShape (axes);
    207 
     195    psF32 *PAR  = model->params->data.F32;
     196
     197    // sky is set to 0.0
    208198    PAR[PM_PAR_SKY]  = 0.0;
    209     PAR[PM_PAR_I0]   = peak->flux;
    210     PAR[PM_PAR_XPOS] = peak->xf;
    211     PAR[PM_PAR_YPOS] = peak->yf;
    212     PAR[PM_PAR_SXX] = PS_MAX(0.5, M_SQRT2*shape.sx);
    213     PAR[PM_PAR_SYY] = PS_MAX(0.5, M_SQRT2*shape.sy);
    214     PAR[PM_PAR_SXY] = shape.sxy;
     199
     200    // set the shape parameters
     201    if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments)) {
     202      return false;
     203    }
     204
     205    // set the model normalization
     206    if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
     207      return false;
     208    }
     209
     210    // set the model position
     211    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     212      return false;
     213    }
     214
    215215    return(true);
    216216}
     
    258258    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
    259259    psF64 radius = axes.major * sqrt (2.0 * log(PAR[PM_PAR_I0] / flux));
    260     psAssert (isfinite(radius), "fix this code: radius should not be nan for %f", PAR[PM_PAR_I0]);
     260    psAssert (isfinite(radius), "fix this code: radius should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)",
     261              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY]);
    261262
    262263    return (radius);
  • trunk/psModules/src/objects/models/pmModel_PGAUSS.c

    r29004 r31153  
    194194bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
    195195{
    196     pmMoments *moments = source->moments;
    197     pmPeak    *peak    = source->peak;
    198     psF32     *PAR     = model->params->data.F32;
    199 
    200     psEllipseMoments emoments;
    201     emoments.x2 = moments->Mxx;
    202     emoments.xy = moments->Mxy;
    203     emoments.y2 = moments->Myy;
    204 
    205     psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
    206     psEllipseShape shape = psEllipseAxesToShape (axes);
    207 
     196    psF32 *PAR  = model->params->data.F32;
     197
     198    // sky is set to 0.0
    208199    PAR[PM_PAR_SKY]  = 0.0;
    209     PAR[PM_PAR_I0]   = peak->flux;
    210     PAR[PM_PAR_XPOS] = peak->xf;
    211     PAR[PM_PAR_YPOS] = peak->yf;
    212     PAR[PM_PAR_SXX] = PS_MAX(0.5, M_SQRT2*shape.sx);
    213     PAR[PM_PAR_SYY] = PS_MAX(0.5, M_SQRT2*shape.sy);
    214     PAR[PM_PAR_SXY] = shape.sxy;
     200
     201    // set the shape parameters
     202    if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments)) {
     203      return false;
     204    }
     205
     206    // set the model normalization
     207    if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
     208      return false;
     209    }
     210
     211    // set the model position
     212    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     213      return false;
     214    }
     215
    215216    return(true);
    216217}
     
    285286    // choose a z value guaranteed to be beyond our limit
    286287    float z0 = pow((1.0 / limit), (1.0 / 3.0));
    287     psAssert (isfinite(z0), "fix this code: z0 should not be nan for %f", PAR[PM_PAR_I0]);
     288    psAssert (isfinite(z0), "fix this code: z0 should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)",
     289              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY]);
     290
    288291    float z1 = (1.0 / limit);
    289     psAssert (isfinite(z1), "fix this code: z1 should not be nan for %f", PAR[PM_PAR_I0]);
     292    psAssert (isfinite(z1), "fix this code: z1 should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)",
     293              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY]);
     294
    290295    z1 = PS_MAX (z0, z1);
    291296    z0 = 0.0;
  • trunk/psModules/src/objects/models/pmModel_PS1_V1.c

    r29004 r31153  
    213213bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
    214214{
    215     pmMoments *moments = source->moments;
    216     pmPeak    *peak    = source->peak;
    217     psF32     *PAR  = model->params->data.F32;
    218 
    219     psEllipseMoments emoments;
    220     emoments.x2 = moments->Mxx;
    221     emoments.xy = moments->Mxy;
    222     emoments.y2 = moments->Myy;
    223 
    224     // force the axis ratio to be < 20.0
    225     psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
    226 
    227     if (!isfinite(axes.major)) return false;
    228     if (!isfinite(axes.minor)) return false;
    229     if (!isfinite(axes.theta)) return false;
    230 
    231     psEllipseShape shape = psEllipseAxesToShape (axes);
    232 
    233     if (!isfinite(shape.sx))  return false;
    234     if (!isfinite(shape.sy))  return false;
    235     if (!isfinite(shape.sxy)) return false;
    236 
     215    psF32 *PAR  = model->params->data.F32;
     216
     217    // sky is set to 0.0
    237218    PAR[PM_PAR_SKY]  = 0.0;
    238     PAR[PM_PAR_I0]   = peak->flux;
    239     PAR[PM_PAR_XPOS] = peak->xf;
    240     PAR[PM_PAR_YPOS] = peak->yf;
    241     PAR[PM_PAR_SXX]  = PS_MAX(0.5, M_SQRT2*shape.sx);
    242     PAR[PM_PAR_SYY]  = PS_MAX(0.5, M_SQRT2*shape.sy);
    243     PAR[PM_PAR_SXY]  = shape.sxy;
     219
     220    // set the shape parameters
     221    if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments)) {
     222      return false;
     223    }
     224
     225    // set the model normalization
     226    if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
     227      return false;
     228    }
     229
     230    // set the model position
     231    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     232      return false;
     233    }
     234
     235    // extra parameter
    244236    PAR[PM_PAR_7]    = 0.5;
    245237
     
    314306    float z0 = 0.0;
    315307    float z1 = pow((1.0 / limit), (1.0 / ALPHA));
    316     psAssert (isfinite(z1), "fix this code: z1 should not be nan for %f", PAR[PM_PAR_7]);
     308    psAssert (isfinite(z1), "fix this code: z1 should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)",
     309              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY]);
    317310    if (PAR[PM_PAR_7] < 0.0) z1 *= 2.0;
    318311
  • trunk/psModules/src/objects/models/pmModel_QGAUSS.c

    r29004 r31153  
    214214bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
    215215{
    216     pmMoments *moments = source->moments;
    217     pmPeak    *peak    = source->peak;
    218     psF32     *PAR  = model->params->data.F32;
    219 
    220     psEllipseMoments emoments;
    221     emoments.x2 = moments->Mxx;
    222     emoments.xy = moments->Mxy;
    223     emoments.y2 = moments->Myy;
    224 
    225     // force the axis ratio to be < 20.0
    226     psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
    227 
    228     if (!isfinite(axes.major)) return false;
    229     if (!isfinite(axes.minor)) return false;
    230     if (!isfinite(axes.theta)) return false;
    231 
    232     psEllipseShape shape = psEllipseAxesToShape (axes);
    233 
    234     if (!isfinite(shape.sx))  return false;
    235     if (!isfinite(shape.sy))  return false;
    236     if (!isfinite(shape.sxy)) return false;
    237 
     216    psF32 *PAR  = model->params->data.F32;
     217
     218    // sky is set to 0.0
    238219    PAR[PM_PAR_SKY]  = 0.0;
    239     PAR[PM_PAR_I0]   = peak->flux;
    240     PAR[PM_PAR_XPOS] = peak->xf;
    241     PAR[PM_PAR_YPOS] = peak->yf;
    242     PAR[PM_PAR_SXX]  = PS_MAX(0.5, M_SQRT2*shape.sx);
    243     PAR[PM_PAR_SYY]  = PS_MAX(0.5, M_SQRT2*shape.sy);
    244     PAR[PM_PAR_SXY]  = shape.sxy;
     220
     221    // set the shape parameters
     222    if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments)) {
     223      return false;
     224    }
     225
     226    // set the model normalization
     227    if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
     228      return false;
     229    }
     230
     231    // set the model position
     232    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     233      return false;
     234    }
     235
     236    // extra parameter
    245237    PAR[PM_PAR_7]    = 1.0;
    246238
     
    315307    float z0 = 0.0;
    316308    float z1 = pow((1.0 / limit), (1.0 / ALPHA));
    317     psAssert (isfinite(z1), "fix this code: z1 should not be nan for %f", PAR[PM_PAR_7]);
     309    psAssert (isfinite(z1), "fix this code: z1 should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f)",
     310              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY]);
    318311    if (PAR[PM_PAR_7] < 0.0) z1 *= 2.0;
    319312
  • trunk/psModules/src/objects/models/pmModel_RGAUSS.c

    r29004 r31153  
    203203bool PM_MODEL_GUESS (pmModel *model, pmSource *source)
    204204{
    205     pmMoments *moments = source->moments;
    206     pmPeak    *peak    = source->peak;
    207     psF32     *PAR  = model->params->data.F32;
    208 
    209     psEllipseMoments emoments;
    210     emoments.x2 = moments->Mxx;
    211     emoments.xy = moments->Mxy;
    212     emoments.y2 = moments->Myy;
    213 
    214     // force the axis ratio to be < 20.0
    215     psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
    216 
    217     if (!isfinite(axes.major)) return false;
    218     if (!isfinite(axes.minor)) return false;
    219     if (!isfinite(axes.theta)) return false;
    220 
    221     psEllipseShape shape = psEllipseAxesToShape (axes);
    222 
    223     if (!isfinite(shape.sx))  return false;
    224     if (!isfinite(shape.sy))  return false;
    225     if (!isfinite(shape.sxy)) return false;
    226 
     205    psF32 *PAR  = model->params->data.F32;
     206
     207    // sky is set to 0.0
    227208    PAR[PM_PAR_SKY]  = 0.0;
    228     PAR[PM_PAR_I0]   = peak->flux;
    229     PAR[PM_PAR_XPOS] = peak->xf;
    230     PAR[PM_PAR_YPOS] = peak->yf;
    231     PAR[PM_PAR_SXX]  = PS_MAX(0.5, shape.sx);
    232     PAR[PM_PAR_SYY]  = PS_MAX(0.5, shape.sy);
    233     PAR[PM_PAR_SXY]  = shape.sxy;
     209
     210    // set the shape parameters
     211    if (!pmModelSetShape(&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], source->moments)) {
     212      return false;
     213    }
     214
     215    // set the model normalization
     216    if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
     217      return false;
     218    }
     219
     220    // set the model position
     221    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     222      return false;
     223    }
     224
     225    // extra parameter
    234226    PAR[PM_PAR_7]    = 1.5;
    235227
     
    305297    // choose a z value guaranteed to be beyond our limit
    306298    float z0 = pow((1.0 / limit), (1.0 / PAR[PM_PAR_7]));
    307     psAssert (isfinite(z0), "fix this code: z0 should not be nan for %f", PAR[PM_PAR_7]);
     299    psAssert (isfinite(z0), "fix this code: z0 should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f), par 7 = %f",
     300              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], PAR[PM_PAR_7]);
     301
    308302    float z1 = (1.0 / limit);
    309     psAssert (isfinite(z1), "fix this code: z1 should not be nan for %f", PAR[PM_PAR_7]);
     303    psAssert (isfinite(z1), "fix this code: z1 should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f), par 7 = %f",
     304              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], PAR[PM_PAR_7]);
     305
    310306    z1 = PS_MAX (z0, z1);
    311307    z0 = 0.0;
  • trunk/psModules/src/objects/models/pmModel_SERSIC.c

    r29028 r31153  
    222222{
    223223    pmMoments *moments = source->moments;
    224     pmPeak    *peak    = source->peak;
    225224    psF32     *PAR  = model->params->data.F32;
     225
     226    // sky is set to 0.0
     227    PAR[PM_PAR_SKY]  = 0.0;
    226228
    227229    // the other parameters depend on the guess for PAR_7
     
    236238    float Zero  = 1.16 - 0.615 * PAR[PM_PAR_7];
    237239
     240    // Sersic shape is a bit special
    238241    psEllipseMoments emoments;
    239242    emoments.x2 = moments->Mxx;
     
    273276    float Syy = PS_MAX(0.5, shape.sy);
    274277
    275     PAR[PM_PAR_SKY]  = 0.0;
    276     PAR[PM_PAR_I0]   = peak->flux / Io;
    277     PAR[PM_PAR_XPOS] = peak->xf;
    278     PAR[PM_PAR_YPOS] = peak->yf;
    279278    PAR[PM_PAR_SXX]  = Sxx;
    280279    PAR[PM_PAR_SYY]  = Syy;
    281280    PAR[PM_PAR_SXY]  = shape.sxy;
     281
     282    // set the model normalization (adjust for Sersic best guess)
     283    if (!pmModelSetNorm(&PAR[PM_PAR_I0], source)) {
     284      return false;
     285    }
     286    PAR[PM_PAR_I0] /= Io;
     287
     288    // set the model position
     289    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     290      return false;
     291    }
    282292
    283293    return(true);
     
    346356    psF64 radius = axes.major * sqrt (2.0) * pow(zn, 0.5 / PAR[PM_PAR_7]);
    347357
    348     // fprintf (stderr, "sersic model %f %f, n %f, radius: %f, zn: %f, f/Io: %f, major: %f\n", PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], PAR[PM_PAR_7], radius, zn, flux/PAR[PM_PAR_I0], axes.major);
    349 
    350     psAssert (isfinite(radius), "fix this code: z should not be nan for %f", PAR[PM_PAR_7]);
     358    psAssert (isfinite(radius), "fix this code: radius should not be nan for Io = %f, flux = %f, major = %f (%f, %f, %f), par 7 = %f",
     359              PAR[PM_PAR_I0], flux, axes.major, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], PAR[PM_PAR_7]);
    351360    return (radius);
    352361}
  • trunk/psModules/src/objects/pmFootprint.c

    r30621 r31153  
    9898}
    9999
     100// XXX not actually used anywhere
    100101pmFootprint *pmFootprintNormalize(pmFootprint *fp) {
    101102    if (fp != NULL && !fp->normalized) {
    102         fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN);
     103        if (PM_PEAKS_CULL_WITH_SMOOTHED_IMAGE) {
     104            fp->peaks = psArraySort(fp->peaks, pmPeaksSortBySmoothFluxDescend);
     105        } else {
     106            fp->peaks = psArraySort(fp->peaks, pmPeaksSortByRawFluxDescend);
     107        }
    103108        fp->normalized = true;
    104109    }
  • trunk/psModules/src/objects/pmFootprint.h

    r30621 r31153  
    1010#ifndef PM_FOOTPRINT_H
    1111#define PM_FOOTPRINT_H
     12
     13// We need to choose up front if the culling algorithm uses the raw or smoothed image.
     14// depending on which we choose, we should produce sorted peaks based on peak->rawFlux or
     15// peak->smoothFlux
     16
     17# define PM_PEAKS_CULL_WITH_SMOOTHED_IMAGE 1
    1218
    1319typedef struct {
     
    8490                                 const float nsigma_delta, // how many sigma above local background a peak needs to be to survive
    8591                                 const float fPadding, // fractional padding added to stdev since bright peaks have unreasonably high significance
    86                                  const float min_threshold // minimum permitted coll height
     92                                 const float min_threshold, // minimum permitted coll height
     93                                 const float max_threshold,// maximum permitted coll height
     94                                 const bool isWeightVar // the input weight may be variance (sigma^2) or S/N (1/sigma)
    8795    );
    8896
  • trunk/psModules/src/objects/pmFootprintAssignPeaks.c

    r30621 r31153  
    4646     */
    4747    psImage *ids = pmSetFootprintArrayIDs(footprints, true);
    48     assert (ids != NULL);
    49     assert (ids->type.type == PS_TYPE_S32);
    50     const int row0 = ids->row0;
    51     const int col0 = ids->col0;
    52     const int numRows = ids->numRows;
    53     const int numCols = ids->numCols;
     48    if (ids) { assert (ids->type.type == PS_TYPE_S32); }
     49   
     50    const int row0 = ids ? ids->row0 : 0;
     51    const int col0 = ids ? ids->col0 : 0;
     52    const int numRows = ids ? ids->numRows : -1;
     53    const int numCols = ids ? ids->numCols : -1;
    5454
    5555    for (int i = 0; i < peaks->n; i++) {
     
    5858        const int y = peak->y - row0;
    5959       
    60         assert (x >= 0 && x < numCols && y >= 0 && y < numRows);
    61         int id = ids->data.S32[y][x - col0];
     60        if (ids) { assert (x >= 0 && x < numCols && y >= 0 && y < numRows);}
     61        int id = ids ? ids->data.S32[y][x - col0] : 0;
     62        // XXX I think the '[x - col0]' above is just wrong (should be [x], but never gets triggerd.
    6263
    6364        if (id == 0) {                  // peak isn't in a footprint, so make one for it
     
    8687        if (fp->peaks->n == 1) continue;
    8788
    88         fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN);
     89        // make sure the peaks are sorted in a way consistent with our cull process
     90        if (PM_PEAKS_CULL_WITH_SMOOTHED_IMAGE) {
     91            fp->peaks = psArraySort(fp->peaks, pmPeaksSortBySmoothFluxDescend);
     92        } else {
     93            fp->peaks = psArraySort(fp->peaks, pmPeaksSortByRawFluxDescend);
     94        }
    8995
    9096        // XXX check for an assert on duplicates (I don't think they can happen, but
  • trunk/psModules/src/objects/pmFootprintCullPeaks.c

    r30621 r31153  
    3838                                 const float nsigma_delta, // how many sigma above local background a peak needs to be to survive
    3939                                 const float fPadding, // fractional padding added to stdev since bright peaks have unreasonably high significance
    40                                  const float min_threshold) { // minimum permitted coll height
     40                                 const float min_threshold, // minimum permitted coll height
     41                                 const float max_threshold,
     42                                 const bool useSmoothedImage
     43    ) { // maximum permitted coll height
    4144    assert (img != NULL); assert (img->type.type == PS_TYPE_F32);
    4245    assert (weight != NULL); assert (weight->type.type == PS_TYPE_F32);
     
    4447    assert (fp != NULL);
    4548
    46     if (fp->peaks == NULL || fp->peaks->n == 0) { // nothing to do
     49    if (fp->peaks == NULL || fp->peaks->n < 2) { // nothing to do
    4750        return PS_ERR_NONE;
    4851    }
     
    5356
    5457    psImage *subImg = psImageSubset((psImage *)img, subRegion);
    55     psImage *subWt = psImageSubset((psImage *)weight, subRegion);
    56     assert (subImg != NULL && subWt != NULL);
     58    psAssert (subImg, "trouble making local subimage");
    5759
    5860    psImage *idImg = psImageAlloc(subImg->numCols, subImg->numRows, PS_TYPE_S32);
     
    6870    psArrayAdd (brightPeaks, 128, fp->peaks->data[0]);
    6971
     72    // XXX test point
     73    // pmPeak *myPeak = fp->peaks->data[0];
     74    // if ((fabs(myPeak->x - 205) < 100) && (fabs(myPeak->y - 806) < 100)) {
     75    //  fprintf (stderr, "test peak\n");
     76    // }
     77
    7078    // allocate the peakFootprint and peakFPSpans containers -- these are re-used by pmFootprintsFindAtPoint to minimize allocs in this function
    7179    pmFootprint *peakFootprint = pmFootprintAlloc(fp->nspans, subImg);
     
    7785    psImage *subMask = psImageCopy(NULL, subImg, PS_TYPE_IMAGE_MASK);
    7886
    79     // The brightest peak is always safe; go through other peaks trying to cull them
    80     for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop
    81         const pmPeak *peak = fp->peaks->data[i];
    82         int x = peak->x - subImg->col0;
    83         int y = peak->y - subImg->row0;
    84         //
    85         // Find the level nsigma below the peak that must separate the peak
    86         // from any of its friends
    87         //
    88         assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows);
    89 
    90         // const float stdev = sqrt(subWt->data.F32[y][x]);
    91         // float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev;
    92 
    93         const float stdev = sqrt(subWt->data.F32[y][x]);
    94         const float flux = subImg->data.F32[y][x];
    95         const float fStdev = fabs(stdev/flux);
    96         const float stdev_pad = fabs(flux * hypot(fStdev, fPadding));
    97         // if flux is negative, careful with fStdev
    98 
    99         float threshold = flux - nsigma_delta*stdev_pad;
    100 
    101         if (isnan(threshold)) {
    102             // min_threshold is assumed to be below the detection threshold,
    103             // so all the peaks are pmFootprint, and this isn't the brightest
    104             continue;
    105         }
    106 
    107         // XXX EAM : if stdev >= 0, i'm not sure how this can ever be true?
    108         if (threshold > subImg->data.F32[y][x]) {
    109             threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON;
    110         }
    111 
    112         if (threshold < min_threshold) {
    113             threshold = min_threshold;
    114         }
    115 
    116         // init peakFootprint here?
    117         pmFootprintsFindAtPoint(peakFootprint, peakFPSpans, subImg, subMask, threshold, brightPeaks, peak->y, peak->x);
    118         if (peakFPSpans->nStartSpans > 2000) {
    119             // dumpfootprints(peakFootprint, peakFPSpans);
    120             // fprintf (stderr, "big footprint %d : %d\n", peakFootprint->nspans, peakFPSpans->nStartSpans);
    121             fprintf (stderr, "big test footprint: %f %f to %f %f (%d pix)\n", peakFootprint->bbox.x0, peakFootprint->bbox.y0, peakFootprint->bbox.x1, peakFootprint->bbox.y1, peakFootprint->npix);
    122         }
    123 
    124         // at this point brightPeaks only has the peaks brighter than the current
    125 
    126         // we set the IDs to either 1 (in peak) or 0 (not in peak)
    127         pmSetFootprintID (idImg, peakFootprint, IN_PEAK);
    128 
    129         // If this peak has not already been assigned to a source, then we can look for any
    130         // brighter peaks within its footprint. Check if any of the previous (brighter) peaks
    131         // are within the footprint of this peak If so, the current peak is bogus; drop it.
    132         bool keep = true;
    133         for (int j = 0; keep && !peak->assigned && (j < brightPeaks->n); j++) {
    134             const pmPeak *peak2 = fp->peaks->data[j];
    135             int x2 = peak2->x - subImg->col0;
    136             int y2 = peak2->y - subImg->row0;
    137             if (idImg->data.S32[y2][x2] == IN_PEAK) {
    138                 // There's a brighter peak within the footprint above threshold; so cull our initial peak
    139                 keep = false;
    140             }
    141         }
    142         if (!keep) {
    143             psAssert (!peak->assigned, "logic error: trying to drop a previously-assigned peak");  // we should not drop any already assigned peaks.
    144             continue;
    145         }
    146 
    147         psArrayAdd (brightPeaks, 128, fp->peaks->data[i]);
     87    // if we have many peaks in a large footprint, we waste a lot of time generating nearly identical footprints
     88    // here we attempt to cull peaks drawing a single footprint for all peaks in some threshold range
     89    // fprintf (stderr, "footprint: %d x %d : %d pix, %d peaks\n", subImg->numCols, subImg->numRows, fp->npix, (int) fp->peaks->n);
     90    if ((fp->npix > 30000) && (fp->peaks->n > 10)) {
     91
     92        // max flux is above threshold for brightest peak
     93        pmPeak *maxPeak = fp->peaks->data[0];
     94        float maxFlux = useSmoothedImage ? maxPeak->smoothFlux : maxPeak->rawFlux;
     95
     96        // we have a relationship between the bin and the threshold of:
     97        // threshold = 0.25 beta^2 bin^2 + minThreshold
     98        // thus, the max bin is: sqrt(4.0*(maxThreshold - minThreshold)/ALPHA^2)
     99
     100# define ALPHA 0.1
     101       
     102        float beta = nsigma_delta * ALPHA;
     103        float beta2 = PS_SQR(beta);
     104        int nBins = sqrt(4.0*(maxFlux - min_threshold)/beta2) + 10; // let's be extra generous
     105
     106        // create a vector to store the threshold bins used for each peak
     107        psVector *threshbins = psVectorAlloc(fp->peaks->n, PS_TYPE_S32);
     108        threshbins->data.S32[0] = -1; // we skip the first peak
     109
     110        /// create a vector to track if a peak has been tried or not:
     111        psVector *peaktried = psVectorAlloc(fp->peaks->n, PS_TYPE_U8);
     112        psVectorInit(peaktried, 0);
     113        peaktried->data.U8[0] = true; // we skip the first peak
     114
     115        psVector *threshbounds = psVectorAlloc(nBins, PS_TYPE_F32);
     116        for (int i = 0; i < nBins; i++) {
     117            threshbounds->data.F32[i] = 0.25*beta2*PS_SQR(i) + min_threshold;       
     118        }
     119        psAssert(threshbounds->data.F32[threshbounds->n-1] > maxFlux, "upper limit does not include max flux");
     120
     121        psHistogram *threshist = psHistogramAllocGeneric(threshbounds);
     122
     123        // assign the peaks to the histogram bins based on their nominal thresholsd
     124        for (int i = 1; i < fp->peaks->n; i++) {
     125            const pmPeak *peak = fp->peaks->data[i];
     126            float flux = useSmoothedImage ? peak->smoothFlux : peak->rawFlux;
     127            float stdev = useSmoothedImage ? peak->smoothFluxStdev : peak->rawFluxStdev;
     128
     129            // if flux is negative, careful with fStdev
     130            const float fStdev = fabs(stdev/flux);
     131            const float stdev_pad = fabs(flux * hypot(fStdev, fPadding));
     132
     133            float threshold = flux - nsigma_delta*stdev_pad;
     134            psAssert(!isnan(threshold), "impossible");
     135
     136            if (threshold <= min_threshold) {
     137                threshist->nums->data.F32[0] += 1.0;
     138                threshbins->data.S32[i] = 0;
     139                continue;
     140            }
     141            int bin = sqrt(4.0*(threshold - min_threshold)/beta2);
     142            psAssert(bin >= 0, "impossible bin");
     143
     144            bin = PS_MIN(bin, threshist->nums->n - 1);
     145            threshist->nums->data.F32[bin] += 1.0;
     146           
     147            // record the bin selected for this peak
     148            threshbins->data.S32[i] = bin;
     149        }
     150
     151        // XXX TEST: did we assign correctly
     152# if (0)
     153        int nPeaks = 1; // we don't put the brightest in the histogram
     154        for (int i = 0; i < threshist->nums->n; i++) {
     155            if (threshist->nums->data.F32[i] > 0) {
     156                fprintf (stderr, "%f : %f : %d\n", threshist->bounds->data.F32[i], threshist->bounds->data.F32[i+1], (int)threshist->nums->data.F32[i]);
     157                nPeaks += threshist->nums->data.F32[i];
     158            }
     159        }
     160        fprintf (stderr, "%d peaks vs %d in histogram\n", (int) fp->peaks->n, nPeaks);
     161# endif
     162
     163        // XXX for the moment, we will use the alternate cull for all peaks -- it might be
     164        // faster to use the standard process for the peaks for which the threshold bin
     165        // contains < N sources (N ~ 5-10?)
     166
     167        // loop over the threshold bins from brightest to faintest
     168        for (int i = threshist->nums->n - 1; i >= 0; i--) {
     169            if (threshist->nums->data.F32[i] == 0) continue;
     170
     171            // we are going to examine the footprints at this threshold
     172            float threshold = 0.5*(threshist->bounds->data.F32[i] + threshist->bounds->data.F32[i+1]);
     173                   
     174            // generate all footprints corresponding to this threshold
     175            psArray *myFP = pmFootprintsFind(subImg, threshold, 5);
     176            if (!myFP) {
     177                psWarning ("missing footprint?");
     178                continue;
     179            }
     180            if (!myFP->n) {
     181                psWarning ("empty footprint?");
     182                continue;
     183            }
     184
     185            // an array to track if the footprint has a brighter peak or not
     186            psVector *found = psVectorAlloc(myFP->n + 1, PS_TYPE_U8);
     187            psVectorInit(found, 0);
     188            int nFound = 0;
     189
     190            // set IDs to distinguish the footprints
     191            psImageInit(idImg, 0);
     192            pmSetFootprintArrayIDsForImage(idImg, myFP, true);
     193       
     194            // check which footprints contain already-accepted (brighter) peaks
     195            // (we can give up if/when we found a peak for all footprints)
     196            for (int j = 0; (j < brightPeaks->n) && (nFound < found->n); j++) {
     197                const pmPeak *peak = brightPeaks->data[j];
     198                int x = peak->x - subImg->col0;
     199                int y = peak->y - subImg->row0;
     200                int myID = idImg->data.S32[y][x];
     201                psAssert(myID >= 0, "impossible");
     202                psAssert(myID < found->n, "impossible");
     203
     204                if (myID == 0) continue; // bright peak is not in a footprint
     205                if (found->data.U8[myID]) continue; // we already know this footprint contains a peak
     206                found->data.U8[myID] = true;
     207                nFound ++;
     208            }
     209       
     210            // check the peaks from this threshold bin: if they land in a footprint which has
     211            // been found, we should drop that peak.  otherwise, keep it
     212            for (int j = 0; j < fp->peaks->n; j++) {
     213                pmPeak *peak = fp->peaks->data[j];
     214                if (peak->assigned) continue; // peak is already claimed by a source -- don't cull
     215
     216                // skip peaks if we've already tried them
     217                if (peaktried->data.U8[j]) continue;
     218
     219                // is this peak in the threshold bin of interest?
     220                if (threshbins->data.S32[j] != i) continue;
     221               
     222                // do not try this peak again
     223                peaktried->data.U8[j] = true;
     224
     225                int x = peak->x - subImg->col0;
     226                int y = peak->y - subImg->row0;
     227                int myID = idImg->data.S32[y][x];
     228                psAssert(myID < found->n, "impossible");
     229
     230                // a peak in this threshold bin without a valid footprint comes from a region
     231                // with only a handful of pixels (1 or more from the peak itself).  It probably
     232                // cannot be joined to a neighbor
     233                if (myID == 0) {
     234                    psArrayAdd (brightPeaks, 128, peak);
     235                    continue;
     236                }
     237
     238                // keep this peak if found->data.U8[myID] == false (no brighter peak in the footprint)
     239                if (!found->data.U8[myID]) {
     240                    // fprintf (stderr, "keeping %d: %d,%d\n", j, peak->x, peak->y);
     241                    psArrayAdd (brightPeaks, 128, peak);
     242                    continue;
     243                }
     244                // fprintf (stderr, "skipping %d: %d,%d\n", j, peak->x, peak->y);
     245            }
     246            psFree (myFP);
     247            psFree (found);
     248        }
     249        psFree (threshist);
     250        psFree (threshbounds);
     251        psFree (threshbins);
     252        psFree (peaktried);
     253
     254    } else {
     255
     256        // The brightest peak is always safe; go through other peaks trying to cull them
     257        for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop
     258            const pmPeak *peak = fp->peaks->data[i];
     259
     260            float flux  = useSmoothedImage ? peak->smoothFlux      : peak->rawFlux;
     261            float stdev = useSmoothedImage ? peak->smoothFluxStdev : peak->rawFluxStdev;
     262
     263            // if flux is negative, careful with fStdev
     264            const float fStdev = fabs(stdev/flux);
     265            const float stdev_pad = fabs(flux * hypot(fStdev, fPadding));
     266
     267            float threshold = flux - nsigma_delta*stdev_pad;
     268
     269            if (isnan(threshold)) {
     270                // min_threshold is assumed to be below the detection threshold,
     271                // so all the peaks are pmFootprint, and this isn't the brightest
     272                continue;
     273            }
     274
     275            // just in case, force the threshold below the peak source flux
     276            if (threshold > flux) {
     277                threshold = flux - 10*FLT_EPSILON;
     278            }
     279
     280            if (threshold < min_threshold) {
     281                threshold = min_threshold;
     282            }
     283            if (threshold > max_threshold) {
     284                threshold = max_threshold;
     285            }
     286
     287            pmFootprintsFindAtPoint(peakFootprint, peakFPSpans, subImg, subMask, threshold, brightPeaks, peak->y, peak->x);
     288            // if (peakFPSpans->nStartSpans > 2000) {
     289            //  // dumpfootprints(peakFootprint, peakFPSpans);
     290            //  // fprintf (stderr, "big footprint %d : %d\n", peakFootprint->nspans, peakFPSpans->nStartSpans);
     291            //  // fprintf (stderr, "big test footprint: %f %f to %f %f (%d pix)\n", peakFootprint->bbox.x0, peakFootprint->bbox.y0, peakFootprint->bbox.x1, peakFootprint->bbox.y1, peakFootprint->npix);
     292            // }
     293
     294            // at this point brightPeaks only has the peaks brighter than the current
     295
     296            // we set the IDs to either 1 (in peak) or 0 (not in peak)
     297            pmSetFootprintID (idImg, peakFootprint, IN_PEAK);
     298
     299            // If this peak has not already been assigned to a source, then we can look for any
     300            // brighter peaks within its footprint. Check if any of the previous (brighter) peaks
     301            // are within the footprint of this peak If so, the current peak is bogus; drop it.
     302            bool keep = true;
     303            for (int j = 0; keep && !peak->assigned && (j < brightPeaks->n); j++) {
     304                // const pmPeak *peak2 = fp->peaks->data[j]; XXX isn't this an error?  we only care about the kept brighter peak, right?
     305                const pmPeak *peak2 = brightPeaks->data[j];
     306                int x2 = peak2->x - subImg->col0;
     307                int y2 = peak2->y - subImg->row0;
     308                if (idImg->data.S32[y2][x2] == IN_PEAK) {
     309                    // There's a brighter peak within the footprint above threshold; so cull our initial peak
     310                    keep = false;
     311                }
     312            }
     313            if (!keep) {
     314                psAssert (!peak->assigned, "logic error: trying to drop a previously-assigned peak");  // we should not drop any already assigned peaks.
     315                continue;
     316            }
     317            psArrayAdd (brightPeaks, 128, fp->peaks->data[i]);
     318        }
    148319    }
    149320
     
    153324    psFree(idImg);
    154325    psFree(subImg);
    155     psFree(subWt);
    156326    psFree(subMask);
    157327    psFree(peakFootprint);
  • trunk/psModules/src/objects/pmFootprintFindAtPoint.c

    r29004 r31153  
    3131 *
    3232 * This is the guts of pmFootprintsFindAtPoint
     33 *
     34 * This function is/was ill-defined if pixel values are NAN.  we should either treat NAN as >
     35 * threshold or < threshold, but the current (r29004) code is ambiguous.
     36 * EAM : change code so NAN is always > threshold
    3337 */
    3438bool pmFootprintSpansBuild(pmFootprint *fp, // the footprint that we're building
     
    103107        for (int j = x0 - 1; j >= -1; j--) {
    104108            double pixVal = (j < 0) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);
    105             if ((maskRow[j] & PM_STARTSPAN_DETECTED) || pixVal < threshold) {
     109            bool belowThreshold = (pixVal < threshold) && isfinite(pixVal);
     110            if ((maskRow[j] & PM_STARTSPAN_DETECTED) || belowThreshold)  {
    106111                if (j < x0 - 1) {       // we found some pixels above threshold
    107112                    nx0 = j + 1;
     
    119124            for (int j = nx0 + 1; j <= numCols; j++) {
    120125                double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);
    121                 if ((maskRow[j] & PM_STARTSPAN_DETECTED) || pixVal < threshold) {
     126                bool belowThreshold = (pixVal < threshold) && isfinite(pixVal);
     127                if ((maskRow[j] & PM_STARTSPAN_DETECTED) || belowThreshold) {
    122128                    nx1 = j - 1;
    123129                    break;
     
    146152        for (int j = nx1 + 1; j <= x1 + 1; j++) {
    147153            double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);
    148             if (!(maskRow[j] & PM_STARTSPAN_DETECTED) && pixVal >= threshold) {
     154            bool aboveThreshold = (pixVal >= threshold) || !isfinite(pixVal);
     155            if (!(maskRow[j] & PM_STARTSPAN_DETECTED) && aboveThreshold) {
    149156                int sx0 = j++;          // span that we're working on is sx0:sx1
    150157                int sx1 = -1;           // We know that if we got here, we'll also set sx1
    151158                for (; j <= numCols; j++) {
    152159                    double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);
    153                     if ((maskRow[j] & PM_STARTSPAN_DETECTED) || pixVal < threshold) { // end of span
     160                    bool belowThreshold = (pixVal < threshold) && isfinite(pixVal);
     161                    if ((maskRow[j] & PM_STARTSPAN_DETECTED) || belowThreshold) { // end of span
    154162                        sx1 = j;
    155163                        break;
     
    306314        for (i = col; i >= 0; i--) {
    307315            pixVal = F32 ? imgRowF32[i] : imgRowS32[i];
    308             if ((maskRow[i] & PM_STARTSPAN_DETECTED) || pixVal < threshold) {
     316            bool belowThreshold = (pixVal < threshold) && isfinite(pixVal);
     317            if ((maskRow[i] & PM_STARTSPAN_DETECTED) || belowThreshold) {
    309318                break;
    310319            }
     
    313322        for (i = col; i < numCols; i++) {
    314323            pixVal = F32 ? imgRowF32[i] : imgRowS32[i];
    315             if ((maskRow[i] & PM_STARTSPAN_DETECTED) || pixVal < threshold) {
     324            bool belowThreshold = (pixVal < threshold) && isfinite(pixVal);
     325            if ((maskRow[i] & PM_STARTSPAN_DETECTED) || belowThreshold) {
    316326                break;
    317327            }
  • trunk/psModules/src/objects/pmFootprintIDs.c

    r29004 r31153  
    6666
    6767   if (footprints->n == 0) {
    68        psError(PS_ERR_BAD_PARAMETER_SIZE, true, "You didn't provide any footprints");
     68       // XXX this was an error, but is an allowed condition -- NULL returned image means no footprints for any peaks
     69       // psError(PS_ERR_BAD_PARAMETER_SIZE, true, "You didn't provide any footprints");
    6970       return NULL;
    7071   }
  • trunk/psModules/src/objects/pmModel.c

    r30621 r31153  
    4141    psFree(tmp->params);
    4242    psFree(tmp->dparams);
     43    psFree(tmp->covar);
    4344    psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
    4445}
     
    6667    tmp->chisqNorm = NAN;
    6768    tmp->nDOF  = 0;
     69    tmp->nPar  = 0;
    6870    tmp->nPix  = 0;
    6971    tmp->nIter = 0;
     
    7173    tmp->flags = PM_MODEL_STATUS_NONE;
    7274    tmp->residuals = NULL;              // do not free: the model does not own this memory
     75    tmp->covar = NULL;
    7376    tmp->isPCM = false;
    7477
  • trunk/psModules/src/objects/pmModel.h

    r30621 r31153  
    3333    psVector *params;                   ///< Paramater values.
    3434    psVector *dparams;                  ///< Parameter errors.
     35    psImage *covar;                     ///< Optional covariance matrix
    3536    float chisq;                        ///< Fit chi-squared.
    3637    float chisqNorm;                    ///< re-normalized fit chi-squared.
     
    3839    float magErr;                       ///< integrated model magnitude error
    3940    int nPix;                           ///< number of pixels used for fit
    40     int nDOF;                           ///< number of degrees of freedom
     41    int nPar;                           ///< number of parameters in fit
     42    int nDOF;                           ///< number of degrees of freedom (nDOF = nPix - nPar)
    4143    int nIter;                          ///< number of iterations to reach min
    4244    pmModelStatus flags;                ///< model status flags
  • trunk/psModules/src/objects/pmModelUtils.c

    r29004 r31153  
    107107    return true;
    108108}
     109
     110bool pmModelSetShape (float *Sxx, float *Sxy, float *Syy, pmMoments *moments) {
     111
     112    psEllipseMoments emoments;
     113    emoments.x2 = moments->Mxx;
     114    emoments.xy = moments->Mxy;
     115    emoments.y2 = moments->Myy;
     116
     117    // force the axis ratio to be < 20.0
     118    psEllipseAxes axes = psEllipseMomentsToAxes (emoments, 20.0);
     119
     120    if (!isfinite(axes.major)) return false;
     121    if (!isfinite(axes.minor)) return false;
     122    if (!isfinite(axes.theta)) return false;
     123
     124    psEllipseShape shape = psEllipseAxesToShape (axes);
     125
     126    if (!isfinite(shape.sx))  return false;
     127    if (!isfinite(shape.sy))  return false;
     128    if (!isfinite(shape.sxy)) return false;
     129
     130    // set the shape parameters
     131    *Sxx  = PS_MAX(0.5, M_SQRT2*shape.sx);
     132    *Syy  = PS_MAX(0.5, M_SQRT2*shape.sy);
     133    *Sxy  = shape.sxy;
     134
     135    return true;
     136}
     137
     138bool pmModelSetNorm (float *Io, pmSource *source) {
     139
     140    *Io = source->peak->rawFlux;
     141    if (!isfinite(*Io) && !source->moments) return false;
     142
     143    *Io = source->moments->Peak;
     144    if (!isfinite(*Io)) return false;
     145
     146    return true;
     147}
     148
     149bool pmModelSetPosition (float *Xo, float *Yo, pmSource *source) {
     150
     151    bool useMoments = pmSourcePositionUseMoments(source);
     152   
     153    if (useMoments) {
     154        *Xo = source->moments->Mx;
     155        *Yo = source->moments->My;
     156    } else {
     157        *Xo = source->peak->xf;
     158        *Yo = source->peak->yf;
     159    }
     160
     161    return true;
     162}
  • trunk/psModules/src/objects/pmModelUtils.h

    r15843 r31153  
    4242    );
    4343
    44 
     44bool pmModelSetPosition (float *Xo, float *Yo, pmSource *source);
     45bool pmModelSetNorm (float *Io, pmSource *source);
     46bool pmModelSetShape (float *Sxx, float *Sxy, float *Syy, pmMoments *moments);
    4547
    4648/// @}
  • trunk/psModules/src/objects/pmMoments.h

    r29004 r31153  
    5151    int nPixels;  ///< Number of pixels used.
    5252
    53     float KronFlux;    ///< Kron flux (flux in 2.5*Mrf)
     53    float KronCore;    ///< flux in r < 1.0*Mrf
     54    float KronCoreErr;    ///< error on flux in r < 1.0*Mrf
     55
     56    float KronFlux;    ///< Kron flux (flux in r < 2.5*Mrf)
    5457    float KronFluxErr; ///< Kron flux error
    5558
    56     float KronFinner;    ///< Kron flux (flux in 2.5*Mrf)
    57     float KronFouter;    ///< Kron flux (flux in 2.5*Mrf)
    58 
     59    float KronFinner;    ///< Kron flux (flux in 1.0*Mrf < r < 2.5*Mrf)
     60    float KronFouter;    ///< Kron flux (flux in 2.5*Mrf < r < 4.0*Mrf)
    5961}
    6062pmMoments;
  • trunk/psModules/src/objects/pmPCMdata.c

    r29546 r31153  
    254254
    255255    pcm->nPix = nPix;
    256     pcm->nDOF = nPix - nParams - 1;
     256    pcm->nPar = nParams;
     257    pcm->nDOF = nPix - nParams;
    257258
    258259    return pcm;
     
    341342        return false;
    342343    }
    343     pcm->nDOF = pcm->nPix - nParams - 1;
     344    pcm->nPar = nParams;
     345    pcm->nDOF = pcm->nPix - nParams;
    344346
    345347    // has the source pixel window changed?
  • trunk/psModules/src/objects/pmPCMdata.h

    r30621 r31153  
    3333    psMinConstraint *constraint;
    3434    int nPix;
     35    int nPar;
    3536    int nDOF;
    3637} pmPCMdata;
  • trunk/psModules/src/objects/pmPSF.c

    r29004 r31153  
    430430        return NAN;
    431431    }
     432
     433    // get the model full-width at half-max
     434    float fwhmMajor = 2*model->modelRadius (model->params, 0.5);
     435
     436# if (0)
    432437    psF32 *params = model->params->data.F32; // Model parameters
    433438    psEllipseAxes axes = pmPSF_ModelToAxes(params, MAX_AXIS_RATIO); // Ellipse axes
     
    439444
    440445    return fwhm;
    441 }
     446# else
     447
     448    psFree(model);
     449
     450    return fwhmMajor;
     451# endif
     452}
  • trunk/psModules/src/objects/pmPSFtryFitPSF.c

    r30621 r31153  
    109109
    110110        // This function calculates the psf and aperture magnitudes
    111         status = pmSourceMagnitudes (source, psfTry->psf, PM_SOURCE_PHOT_INTERP, maskVal, markVal); // raw PSF mag, AP mag
     111        status = pmSourceMagnitudes (source, psfTry->psf, PM_SOURCE_PHOT_INTERP, maskVal, markVal, options->apRadius); // raw PSF mag, AP mag
    112112        if (!status || isnan(source->apMag)) {
    113113            psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); // clear the circular mask
  • trunk/psModules/src/objects/pmPeaks.c

    r29004 r31153  
    115115XXX: Macro this.
    116116*****************************************************************************/
     117# if (0)
    117118static bool isItInThisRegion(const psRegion valid,
    118119                             psS32 x,
     
    130131    return(false);
    131132}
     133# endif
    132134
    133135/******************************************************************************
     
    148150    tmp->x = x;
    149151    tmp->y = y;
    150     tmp->value = value;
    151     tmp->flux = value;
    152     tmp->SN = 0;
     152    tmp->detValue        = value;
     153    tmp->rawFlux         = value; // set this by default: it is up to the user to supply a better value
     154    tmp->rawFluxStdev    = NAN;
     155    tmp->smoothFlux      = value; // set this by default: it is up to the user to supply a better value
     156    tmp->smoothFluxStdev = NAN;
     157    // tmp->SN = 0;
    153158    tmp->xf = x;
    154159    tmp->yf = y;
     
    170175
    171176
    172 // psSort comparison function for peaks
     177// psSort comparison functions for peaks
    173178// XXX: Add error-checking for NULL args
    174 int pmPeaksCompareAscend (const void **a, const void **b)
    175 {
    176     psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     179int pmPeaksSortByDetValueAscend (const void **a, const void **b)
     180{
    177181    pmPeak *A = *(pmPeak **)a;
    178182    pmPeak *B = *(pmPeak **)b;
     
    180184    psF32 diff;
    181185
    182     diff = A->value - B->value;
     186    diff = A->detValue - B->detValue;
    183187    if (diff < FLT_EPSILON) {
    184         psTrace("psModules.objects", 10, "---- %s(-1) end ----\n", __func__);
    185188        return (-1);
    186189    } else if (diff > FLT_EPSILON) {
    187         psTrace("psModules.objects", 10, "---- %s(+1) end ----\n", __func__);
    188190        return (+1);
    189191    }
    190     psTrace("psModules.objects", 10, "---- %s(0) end ----\n", __func__);
    191192    return (0);
    192193}
    193 
    194 // psSort comparison function for peaks
    195 // XXX: Add error-checking for NULL args
    196 int pmPeaksCompareDescend (const void **a, const void **b)
    197 {
    198     psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
     194int pmPeaksSortByDetValueDescend (const void **a, const void **b)
     195{
    199196    pmPeak *A = *(pmPeak **)a;
    200197    pmPeak *B = *(pmPeak **)b;
     
    202199    psF32 diff;
    203200
    204     diff = A->value - B->value;
     201    diff = A->detValue - B->detValue;
    205202    if (diff < FLT_EPSILON) {
    206         psTrace("psModules.objects", 10, "---- %s(+1) end ----\n", __func__);
    207203        return (+1);
    208204    } else if (diff > FLT_EPSILON) {
    209         psTrace("psModules.objects", 10, "---- %s(-1) end ----\n", __func__);
    210205        return (-1);
    211206    }
    212     psTrace("psModules.objects", 10, "---- %s(0) end ----\n", __func__);
    213207    return (0);
    214208}
    215 
    216 // sort by SN (descending)
    217 int pmPeakSortBySN (const void **a, const void **b)
     209int pmPeaksSortByRawFluxAscend (const void **a, const void **b)
    218210{
    219211    pmPeak *A = *(pmPeak **)a;
    220212    pmPeak *B = *(pmPeak **)b;
    221213
    222     psF32 fA = A->SN;
    223     psF32 fB = B->SN;
    224     if (isnan (fA)) fA = 0;
    225     if (isnan (fB)) fB = 0;
    226 
    227     psF32 diff = fA - fB;
    228     if (diff > FLT_EPSILON) return (-1);
    229     if (diff < FLT_EPSILON) return (+1);
     214    psF32 diff;
     215
     216    diff = A->rawFlux - B->rawFlux;
     217    if (diff < FLT_EPSILON) {
     218        return (-1);
     219    } else if (diff > FLT_EPSILON) {
     220        return (+1);
     221    }
    230222    return (0);
    231223}
    232 
    233 // sort by Y (ascending)
    234 int pmPeakSortByY (const void **a, const void **b)
     224int pmPeaksSortByRawFluxDescend (const void **a, const void **b)
    235225{
    236226    pmPeak *A = *(pmPeak **)a;
    237227    pmPeak *B = *(pmPeak **)b;
    238228
    239     psF32 fA = A->y;
    240     psF32 fB = B->y;
    241 
    242     psF32 diff = fA - fB;
    243     if (diff > FLT_EPSILON) return (+1);
    244     if (diff < FLT_EPSILON) return (-1);
     229    psF32 diff;
     230
     231    diff = A->rawFlux - B->rawFlux;
     232    if (diff < FLT_EPSILON) {
     233        return (+1);
     234    } else if (diff > FLT_EPSILON) {
     235        return (-1);
     236    }
    245237    return (0);
    246238}
     239int pmPeaksSortBySmoothFluxAscend (const void **a, const void **b)
     240{
     241    pmPeak *A = *(pmPeak **)a;
     242    pmPeak *B = *(pmPeak **)b;
     243
     244    psF32 diff;
     245
     246    diff = A->smoothFlux - B->smoothFlux;
     247    if (diff < FLT_EPSILON) {
     248        return (-1);
     249    } else if (diff > FLT_EPSILON) {
     250        return (+1);
     251    }
     252    return (0);
     253}
     254int pmPeaksSortBySmoothFluxDescend (const void **a, const void **b)
     255{
     256    pmPeak *A = *(pmPeak **)a;
     257    pmPeak *B = *(pmPeak **)b;
     258
     259    psF32 diff;
     260
     261    diff = A->smoothFlux - B->smoothFlux;
     262    if (diff < FLT_EPSILON) {
     263        return (+1);
     264    } else if (diff > FLT_EPSILON) {
     265        return (-1);
     266    }
     267    return (0);
     268}
     269
     270// // sort by SN (descending)
     271// int pmPeakSortBySN (const void **a, const void **b)
     272// {
     273//     pmPeak *A = *(pmPeak **)a;
     274//     pmPeak *B = *(pmPeak **)b;
     275//
     276//     psF32 fA = A->flux;
     277//     psF32 fB = B->flux;
     278//     if (isnan (fA)) fA = 0;
     279//     if (isnan (fB)) fB = 0;
     280//
     281//     psF32 diff = fA - fB;
     282//     if (diff > FLT_EPSILON) return (-1);
     283//     if (diff < FLT_EPSILON) return (+1);
     284//     return (0);
     285// }
     286//
     287// // sort by Y (ascending)
     288// int pmPeakSortByY (const void **a, const void **b)
     289// {
     290//     pmPeak *A = *(pmPeak **)a;
     291//     pmPeak *B = *(pmPeak **)b;
     292//
     293//     psF32 fA = A->y;
     294//     psF32 fB = B->y;
     295//
     296//     psF32 diff = fA - fB;
     297//     if (diff > FLT_EPSILON) return (+1);
     298//     if (diff < FLT_EPSILON) return (-1);
     299//     return (0);
     300// }
    247301
    248302/******************************************************************************
     
    554608    return(list);
    555609}
    556 
    557 // return a new array of peaks which are in the valid region and below threshold
    558 // XXX this function is unused and probably could be dropped
    559 psArray *pmPeaksSubset(
    560     psArray *peaks,
    561     psF32 maxValue,
    562     const psRegion valid)
    563 {
    564     psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
    565     PS_ASSERT_PTR_NON_NULL(peaks, NULL);
    566 
    567     psArray *output = psArrayAllocEmpty (200);
    568 
    569     psTrace ("psModules.objects", 3, "list size is %ld\n", peaks->n);
    570 
    571     for (int i = 0; i < peaks->n; i++) {
    572         pmPeak *tmpPeak = (pmPeak *) peaks->data[i];
    573         if (tmpPeak->value > maxValue)
    574             continue;
    575         if (isItInThisRegion(valid, tmpPeak->x, tmpPeak->y))
    576             continue;
    577         psArrayAdd (output, 200, tmpPeak);
    578     }
    579     psTrace("psModules.objects", 10, "---- %s() end ----\n", __func__);
    580     return(output);
    581 }
  • trunk/psModules/src/objects/pmPeaks.h

    r29004 r31153  
    3535    PM_PEAK_EDGE,                       ///< Peak on edge.
    3636    PM_PEAK_FLAT,                       ///< Peak has equal-value neighbors.
     37    PM_PEAK_SUSPECT_SATURATION,         ///< Peak is probably saturated
    3738    PM_PEAK_UNDEF                       ///< Undefined.
    3839} pmPeakType;
     
    4546 *  associated with the source:
    4647 *
     48 *  There are 3 values which define the amplitude of the peak and which may be used to sort the
     49 *  peaks:
     50 *  * detValue - the peak in the detection image (nominally, the S/N)
     51 *  * rawFlux - the peak in the unsmoothed image
     52 *  * smoothFlux - the peak in the smoothed image
     53 *
     54 *  For a given image, peaks do necesarily not have the same sequence for these three values.
     55 *  Depending on the analysis, it may make sense to sort by one or the other of these values
    4756 */
    4857typedef struct
     
    5564    float dx;                           ///< bicube fit error on peak coord (x)
    5665    float dy;                           ///< bicube fit error on peak coord (y)
    57     float value;                        ///< level in detection image
    58     float flux;                         ///< level in unsmoothed sci image
    59     float SN;                           ///< S/N implied by detection level
     66    float detValue;                     ///< peak flux in detection image (= S/N)
     67    float rawFlux;                      ///< peak flux in unsmoothed signal image
     68    float rawFluxStdev;                 ///< peak stdev in unsmoothed signal image
     69    float smoothFlux;                   ///< peak flux in smoothed signal image
     70    float smoothFluxStdev;              ///< peak stdev in smoothed signal image
     71    // float SNestimated;                  ///< S/N estimated from the detection image
    6072    bool assigned;                      ///< is peak assigned to a source?
    6173    pmPeakType type;                    ///< Description of peak.
     
    136148);
    137149
    138 int pmPeaksCompareAscend (const void **a, const void **b);
    139 int pmPeaksCompareDescend (const void **a, const void **b);
    140 
    141 int pmPeakSortBySN (const void **a, const void **b);
    142 int pmPeakSortByY (const void **a, const void **b);
     150int pmPeaksSortByDetValueAscend (const void **a, const void **b);
     151int pmPeaksSortByDetValueDescend (const void **a, const void **b);
     152int pmPeaksSortByRawFluxAscend (const void **a, const void **b);
     153int pmPeaksSortByRawFluxDescend (const void **a, const void **b);
     154int pmPeaksSortBySmoothFluxAscend (const void **a, const void **b);
     155int pmPeaksSortBySmoothFluxDescend (const void **a, const void **b);
    143156
    144157/// @}
  • trunk/psModules/src/objects/pmPhotObj.c

    r29004 r31153  
    6767        return false;
    6868    }
    69     if (!finite(source->peak->xf)) {
     69    if (!isfinite(source->peak->xf)) {
    7070        psError(PS_ERR_UNKNOWN, true, "NAN peak coordinate");
    7171        return false;
    7272    }
    73     if (!finite(source->peak->yf)) {
     73    if (!isfinite(source->peak->yf)) {
    7474        psError(PS_ERR_UNKNOWN, true, "NAN peak coordinate");
    7575        return false;
     
    8181        object->x  = source->peak->xf;
    8282        object->y  = source->peak->yf;
    83         object->SN = source->peak->SN;
     83        object->flux = source->peak->rawFlux;
    8484    } else {
    85         object->SN = PS_MAX(object->SN, source->peak->SN);
     85        object->flux = PS_MAX(object->flux, source->peak->rawFlux);
    8686    }
    8787    psArrayAdd (object->sources, 1, source);
     
    8989}
    9090
    91 // sort by SN (descending)
    92 int pmPhotObjSortBySN (const void **a, const void **b)
     91// sort by flux (descending)
     92int pmPhotObjSortByFlux (const void **a, const void **b)
    9393{
    9494    pmPhotObj *objA = *(pmPhotObj **)a;
    9595    pmPhotObj *objB = *(pmPhotObj **)b;
    9696
    97     psF32 fA = objA->SN;
    98     psF32 fB = objB->SN;
     97    psF32 fA = objA->flux;
     98    psF32 fB = objB->flux;
    9999
    100100    psF32 diff = fA - fB;
  • trunk/psModules/src/objects/pmPhotObj.h

    r29004 r31153  
    3434    float x;
    3535    float y;
    36     float SN;                           // max of peak->SN for all matched sources
     36    float flux;                         // max of peak->rawFlux for all matched sources
    3737} pmPhotObj;
    3838
     
    4141bool pmPhotObjAddSource(pmPhotObj *object, pmSource *source);
    4242
    43 int pmPhotObjSortBySN (const void **a, const void **b);
     43int pmPhotObjSortByFlux (const void **a, const void **b);
    4444int pmPhotObjSortByX (const void **a, const void **b);
    4545
  • trunk/psModules/src/objects/pmSource.c

    r30621 r31153  
    171171    // peak has the same values as the original
    172172    if (in->peak != NULL) {
    173         source->peak = pmPeakAlloc (in->peak->x, in->peak->y, in->peak->value, in->peak->type);
     173        source->peak = pmPeakAlloc (in->peak->x, in->peak->y, in->peak->detValue, in->peak->type);
    174174        source->peak->xf = in->peak->xf;
    175175        source->peak->yf = in->peak->yf;
    176         source->peak->flux = in->peak->flux;
    177         source->peak->SN = in->peak->SN;
     176        source->peak->rawFlux         = in->peak->rawFlux;
     177        source->peak->rawFluxStdev    = in->peak->rawFluxStdev;
     178        source->peak->smoothFlux      = in->peak->smoothFlux;
     179        source->peak->smoothFluxStdev = in->peak->smoothFluxStdev;
     180        // source->peak->SN = in->peak->SN;
    178181    }
    179182
     
    328331*****************************************************************************/
    329332
    330 // XXX EAM include a S/N cutoff in selecting the sources?
    331 // XXX this function should probably accept the values, not a recipe. wrap with a
    332 // psphot-specific function which applies the recipe values
    333 // only apply selection to sources within specified region
    334333pmPSFClump pmSourcePSFClump(psImage **savedImage, psRegion *region, psArray *sources, float PSF_SN_LIM, float PSF_CLUMP_GRID_SCALE, psF32 SX_MAX, psF32 SY_MAX, psF32 AR_MAX)
    335334{
     
    429428
    430429        psfClump.nSigma = stats->sampleStdev;
     430        psfClump.nTotal = nValid;
    431431
    432432        if (savedImage) {
     
    465465        psStats *stats  = NULL;
    466466
    467         // select the single highest peak
    468         psArraySort (peaks, pmPeaksCompareDescend);
     467        // select the single highest peak (note that we only have detValue, not rawFlux, etc
     468        psArraySort (peaks, pmPeaksSortByDetValueDescend);
    469469        clump = peaks->data[0];
    470         psTrace ("psModules.objects", 2, "clump is at %d, %d (%f)\n", clump->x, clump->y, clump->value);
     470        psTrace ("psModules.objects", 2, "clump is at %d, %d (%f)\n", clump->x, clump->y, clump->detValue);
    471471
    472472        // XXX store the mean sigma?
    473473        float meanSigma = psfClump.nSigma;
    474         psfClump.nStars = clump->value;
    475         psfClump.nSigma = clump->value / meanSigma;
     474        psfClump.nStars = clump->detValue;
     475        psfClump.nSigma = clump->detValue / meanSigma;
    476476
    477477        // define section window for clump
     
    643643            }
    644644
     645            // check for insignificant sources or excessively low-surface brightness
     646            float coreSN = source->moments->KronCore / source->moments->KronCoreErr;
     647            float coreKR = source->moments->KronCore / source->moments->KronFlux;
     648
     649            // XXX these values need to be in the recipe...
     650            if (false && isfinite(coreSN) && (coreSN < 5.0)) {
     651                source->type = PM_SOURCE_TYPE_DEFECT;
     652                source->mode |= PM_SOURCE_MODE_DEFECT;
     653                Ncr ++;
     654                continue;
     655            }
     656            if (false && isfinite(coreKR) && (coreKR < 0.1)) {
     657                source->type = PM_SOURCE_TYPE_DEFECT;
     658                source->mode |= PM_SOURCE_MODE_DEFECT;
     659                Ncr ++;
     660                continue;
     661            }
     662
    645663            // likely unsaturated extended source (too large to be stellar)
    646664            if (sigX > clump.X + 3*clump.dX || sigY > clump.Y + 3*clump.dY) {
     
    651669
    652670            // the rest are probable stellar objects
     671            // the vectors below are accumulated to give user feedback on the S/N ranges
    653672            starsn_moments->data.F32[starsn_moments->n] = source->moments->SN;
    654673            starsn_moments->n ++;
    655             starsn_peaks->data.F32[starsn_peaks->n] = source->peak->SN;
     674            starsn_peaks->data.F32[starsn_peaks->n] = sqrt(source->peak->detValue);
    656675            starsn_peaks->n ++;
    657676            Nstar ++;
     
    11491168}
    11501169
     1170// this function decides if the source position should be based on the peak or the moments.
     1171// this is only used if we know we should not use a model fit position (eg, no model, or no
     1172// model yet)
     1173bool pmSourcePositionUseMoments(pmSource *source) {
     1174
     1175    if (!source->moments) return false;          // can't if there are no moments
     1176    if (!source->moments->nPixels) return false; // can't if the moments were not measured
     1177    if (source->mode && PM_SOURCE_MODE_MOMENTS_FAILURE) return false; // can't if the moments failed...
     1178
     1179    if (source->mode & PM_SOURCE_MODE_SATSTAR) return true; // moments are best for SATSTARs
     1180
     1181    float dX = source->moments->Mx - source->peak->xf;
     1182    float dY = source->moments->My - source->peak->yf;
     1183    float dR = hypot(dX, dY);
     1184   
     1185    // only use the moments position if the moment-peak offset is small or the star is saturated
     1186    if (dR > 1.5) return false;
     1187
     1188    return true;
     1189}
     1190
    11511191// sort by SN (descending)
    1152 int pmSourceSortBySN (const void **a, const void **b)
     1192int pmSourceSortByFlux (const void **a, const void **b)
    11531193{
    11541194    pmSource *A = *(pmSource **)a;
    11551195    pmSource *B = *(pmSource **)b;
    11561196
    1157     psF32 fA = (A->peak == NULL) ? 0 : A->peak->SN;
    1158     psF32 fB = (B->peak == NULL) ? 0 : B->peak->SN;
     1197    psF32 fA = (A->peak == NULL) ? 0 : A->peak->rawFlux;
     1198    psF32 fB = (B->peak == NULL) ? 0 : B->peak->rawFlux;
    11591199    if (isnan (fA)) fA = 0;
    11601200    if (isnan (fB)) fB = 0;
     
    11661206}
    11671207
     1208// sort by SN (descending)
     1209int pmSourceSortByParentFlux (const void **a, const void **b)
     1210{
     1211    pmSource *Ao = *(pmSource **)a;
     1212    pmSource *Bo = *(pmSource **)b;
     1213    pmSource *A  = Ao->parent;
     1214    pmSource *B  = Bo->parent;
     1215
     1216    psF32 fA = (A->peak == NULL) ? 0 : A->peak->rawFlux;
     1217    psF32 fB = (B->peak == NULL) ? 0 : B->peak->rawFlux;
     1218    if (isnan (fA)) fA = 0;
     1219    if (isnan (fB)) fB = 0;
     1220
     1221    psF32 diff = fA - fB;
     1222    if (diff > FLT_EPSILON) return (-1);
     1223    if (diff < FLT_EPSILON) return (+1);
     1224    return (0);
     1225}
     1226
    11681227// sort by Y (ascending)
    11691228int pmSourceSortByY (const void **a, const void **b)
     
    12011260    pmSource *A = *(pmSource **)a;
    12021261    pmSource *B = *(pmSource **)b;
     1262
     1263    int iA = A->seq;
     1264    int iB = B->seq;
     1265
     1266    int diff = iA - iB;
     1267    if (diff > 0) return (+1);
     1268    if (diff < 0) return (-1);
     1269    return (0);
     1270}
     1271
     1272// sort by Seq (ascending)
     1273int pmSourceSortByParentSeq (const void **a, const void **b)
     1274{
     1275    pmSource *Ao = *(pmSource **)a;
     1276    pmSource *Bo = *(pmSource **)b;
     1277    pmSource *A  = Ao->parent;
     1278    pmSource *B  = Bo->parent;
    12031279
    12041280    int iA = A->seq;
  • trunk/psModules/src/objects/pmSource.h

    r30621 r31153  
    121121    float dY;
    122122    int nStars;
     123    int nTotal;
    123124    float nSigma;
    124125}
     
    286287bool pmSourceCachePSF (pmSource *source, psImageMaskType maskVal);
    287288
    288 int  pmSourceSortBySN (const void **a, const void **b);
     289bool pmSourcePositionUseMoments(pmSource *source);
     290
    289291int  pmSourceSortByY (const void **a, const void **b);
    290292int  pmSourceSortByX (const void **a, const void **b);
    291293int  pmSourceSortBySeq (const void **a, const void **b);
     294int  pmSourceSortByParentSeq (const void **a, const void **b);
     295int  pmSourceSortByFlux (const void **a, const void **b);
     296int  pmSourceSortByParentFlux (const void **a, const void **b);
    292297
    293298pmSourceMode pmSourceModeFromString (const char *name);
  • trunk/psModules/src/objects/pmSourceExtendedPars.c

    r30621 r31153  
    5555    psFree(radial->flux);
    5656    psFree(radial->fluxErr);
     57    psFree(radial->fluxStdev);
    5758    psFree(radial->fill);
    5859}
     
    6566    radial->flux = NULL;
    6667    radial->fluxErr = NULL;
     68    radial->fluxStdev = NULL;
    6769    radial->fill = NULL;
    6870    return radial;
  • trunk/psModules/src/objects/pmSourceExtendedPars.h

    r28013 r31153  
    2323typedef struct {
    2424    psVector *flux;                     // fluxes measured at above radii
     25    psVector *fluxStdev;                // scatter (standard deviation) of flux
    2526    psVector *fluxErr;                  // formal error on the fluxes (sqrt\sum(variance))
    2627    psVector *fill;                     // angles corresponding to above radial profiles
     
    6364    float petrosianR50;
    6465    float petrosianR50Err;
     66    float petrosianFill;
    6567} pmSourceExtendedPars;
    6668
  • trunk/psModules/src/objects/pmSourceFitModel.c

    r29004 r31153  
    4040#include "pmSourceDiffStats.h"
    4141#include "pmSource.h"
     42#include "pmSourcePhotometry.h"
    4243#include "pmSourceFitModel.h"
    4344
     
    5960    opt->maxChisqDOF = NAN;
    6061    opt->poissonErrors = true;
     62    opt->saveCovariance = false;
    6163
    6264    return opt;
     
    231233        psTrace ("psModules.objects", 4, "%f +/- %f", params->data.F32[i], dparams->data.F32[i]);
    232234    }
     235    if (options->saveCovariance) {
     236        model->covar = psMemIncrRefCounter(covar);
     237    }
     238    model->nIter = myMin->iter;
     239    model->nPar = nParams;
     240
    233241    psTrace ("psModules.objects", 4, "niter: %d, chisq: %f", myMin->iter, myMin->value);
    234242
    235243    // save the resulting chisq, nDOF, nIter
    236     model->chisq = myMin->value;
    237     model->nIter = myMin->iter;
    238     model->nPix  = y->n;
    239     model->nDOF  = y->n - nParams;
    240     model->chisqNorm = model->chisq / model->nDOF;
     244    // NOTE: if (!options->poissonErrors) chisq will be wrong : recalculate
     245    if (options->poissonErrors) {
     246        model->chisq = myMin->value;
     247        model->nPix  = y->n;
     248        model->nDOF  = y->n - model->nPar;
     249        model->chisqNorm = model->chisq / model->nDOF;
     250    } else {
     251        pmSourceChisqUnsubtracted (source, model, maskVal);
     252    }
     253
     254    // set the model success or failure status
    241255    model->flags |= PM_MODEL_STATUS_FITTED;
    242256    if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;
  • trunk/psModules/src/objects/pmSourceFitModel.h

    r29004 r31153  
    3131    float maxChisqDOF;                  ///< convergence criterion
    3232    float weight;                       ///< use this weight for constant-weight fits
     33    float covarFactor;                  ///< covariance factor for calculating the chisq
    3334    bool poissonErrors;                 ///< use poisson errors for fits?
     35    bool saveCovariance;
    3436} pmSourceFitOptions;
    3537
  • trunk/psModules/src/objects/pmSourceFitPCM.c

    r30621 r31153  
    3838#include "pmSourceDiffStats.h"
    3939#include "pmSource.h"
     40#include "pmSourcePhotometry.h"
    4041#include "pmSourceFitModel.h"
    4142#include "pmPCMdata.h"
     
    7071        psTrace ("psModules.objects", 4, "%f +/- %f", params->data.F32[i], dparams->data.F32[i]);
    7172    }
     73    if (fitOptions->saveCovariance) {
     74        psFree(pcm->modelConv->covar);
     75        pcm->modelConv->covar = psMemIncrRefCounter(covar);
     76    }
    7277    psTrace ("psphot", 4, "niter: %d, chisq: %f", myMin->iter, myMin->value);
    7378
     
    7984        }
    8085    }
     86    pcm->modelConv->nIter = myMin->iter;
     87    pcm->modelConv->nPar = pcm->nPar;
    8188
    8289    // save the resulting chisq, nDOF, nIter
    83     pcm->modelConv->chisq = myMin->value;
    84     pcm->modelConv->nIter = myMin->iter;
    85     pcm->modelConv->nPix = pcm->nPix;
    86     pcm->modelConv->nDOF = pcm->nDOF;
    87     pcm->modelConv->chisqNorm = pcm->modelConv->chisq / pcm->modelConv->nDOF;
     90    if (fitOptions->poissonErrors) {
     91        pcm->modelConv->chisq = myMin->value;
     92        pcm->modelConv->nPix = pcm->nPix;
     93        pcm->modelConv->nDOF = pcm->nDOF;
     94        pcm->modelConv->chisqNorm = pcm->modelConv->chisq / pcm->modelConv->nDOF;
     95    } else {
     96        // xxx this is wrong because it does not convolve with the psf
     97        pmSourceChisqUnsubtracted (source, pcm->modelConv, maskVal);
     98    }
     99
     100    // set the model success or failure status
    88101    pcm->modelConv->flags |= PM_MODEL_STATUS_FITTED;
    89102    if (!fitStatus) pcm->modelConv->flags |= PM_MODEL_STATUS_NONCONVERGE;
  • trunk/psModules/src/objects/pmSourceFitSet.c

    r29004 r31153  
    3939#include "pmSourceDiffStats.h"
    4040#include "pmSource.h"
     41#include "pmSourcePhotometry.h"
    4142
    4243#include "pmSourceFitModel.h"
     
    296297
    297298// set the model parameters for this fit set
    298 bool pmSourceFitSetValues (pmSourceFitSetData *set, const psVector *dparam,
    299                            const psVector *param, pmSource *source,
    300                            psMinimization *myMin, int nPix, bool fitStatus)
     299bool pmSourceFitSetValues (pmSourceFitSetData *set,
     300                           const psVector *dparam, const psVector *param, const psImage *covar,
     301                           pmSource *source, psMinimization *myMin, int nPix,
     302                           bool fitStatus, pmSourceFitOptions *options, psImageMaskType maskVal)
    301303{
    302304    PS_ASSERT_PTR_NON_NULL(set, false);
     
    311313
    312314    int n = 0;
     315    int nStart = 0;
    313316    for (int i = 0; i < set->paramSet->n; i++) {
    314317
     
    320323            psTrace ("psModules.objects", 4, "%f +/- %f", param->data.F32[n], dparam->data.F32[n]);
    321324        }
     325        if (options->saveCovariance) {
     326            // we only save the covar matrix for this object with itself (ignore cross terms between objects)
     327            model->covar = psImageAlloc(model->params->n, model->params->n, PS_TYPE_F32);
     328            for (int ix = 0; ix < model->params->n; ix++) {
     329                for (int iy = 0; iy < model->params->n; iy++) {
     330                    model->covar->data.F32[iy][ix] = covar->data.F32[nStart+iy][nStart+ix];
     331                }
     332            }
     333        }
     334        nStart += model->params->n;
    322335        psTrace ("psModules.objects", 4, " src %d", i);
     336
     337        model->nIter = myMin->iter;
     338        // model->nPar is set by pmSourceFitSetMasks
    323339
    324340        // save the resulting chisq, nDOF, nIter
    325341        // these are not unique for any one source
    326         model->chisq = myMin->value;
    327         model->nIter = myMin->iter;
    328         model->nDOF  = nPix - model->params->n;
     342        if (options->poissonErrors) {
     343            model->chisq = myMin->value;
     344            model->nPix  = nPix;
     345            model->nDOF  = nPix - model->nPar;
     346            model->chisqNorm = model->chisq / model->nDOF;
     347        } else {
     348            pmSourceChisqUnsubtracted (source, model, maskVal);
     349        }
    329350
    330351        // set the model success or failure status
     
    380401    for (int i = 0; i < set->paramSet->n; i++) {
    381402        psVector *paramOne = set->paramSet->data[i];
     403        pmModel  *modelOne = set->modelSet->data[i];
    382404
    383405        switch (mode) {
     
    387409                if (j == PM_PAR_I0) continue;
    388410                constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[n + j] = 1;
     411                modelOne->nPar = 1;
    389412            }
    390413            break;
     
    396419                if (j == PM_PAR_I0) continue;
    397420                constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[n + j] = 1;
     421                modelOne->nPar = 3;
    398422            }
    399423            break;
     
    401425            // EXT model fits all params (except sky)
    402426            constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[n + PM_PAR_SKY] = 1;
     427            modelOne->nPar = paramOne->n - 1;
    403428            break;
    404429          default:
     
    550575    }
    551576
    552 // parameter errors from the covariance matrix
     577    // parameter errors from the covariance matrix
    553578    psVector *dparams = psVectorAlloc (thisSet->nParamSet, PS_TYPE_F32);
    554579    for (int i = 0; i < dparams->n; i++) {
     
    558583    }
    559584
    560 // get the Gauss-Newton distance for fixed model parameters
     585    // get the Gauss-Newton distance for fixed model parameters
    561586    if (constraint->paramMask != NULL) {
    562587        psVector *delta = psVectorAlloc (params->n, PS_TYPE_F32);
     
    580605    }
    581606
    582     pmSourceFitSetValues (thisSet, dparams, params, source, myMin, y->n, fitStatus);
     607    pmSourceFitSetValues (thisSet, dparams, params, covar, source, myMin, y->n, fitStatus, options, maskVal);
    583608    psTrace ("psModules.objects", 5, "onPic: %d, fitStatus: %d, nIter: %d, chisq: %f, nPix: %ld\n", onPic, fitStatus, myMin->iter, myMin->value, y->n);
    584609
  • trunk/psModules/src/objects/pmSourceFitSet.h

    r29004 r31153  
    4040bool pmSourceFitSetJoin (psVector *deriv, psVector *param, pmSourceFitSetData *set);
    4141bool pmSourceFitSetSplit (pmSourceFitSetData *set, const psVector *deriv, const psVector *param);
    42 bool pmSourceFitSetValues (pmSourceFitSetData *set, const psVector *dparam, const psVector *param, pmSource *source, psMinimization *myMin, int nPix, bool fitStatus);
     42
     43bool pmSourceFitSetValues (pmSourceFitSetData *set,
     44                           const psVector *dparam, const psVector *param, const psImage *covar,
     45                           pmSource *source, psMinimization *myMin, int nPix,
     46                           bool fitStatus, pmSourceFitOptions *options, psImageMaskType maskVal);
    4347
    4448psF32 pmSourceFitSetFunction(psVector *deriv, const psVector *param, const psVector *x);
     
    5761    psArray *modelSet,                  ///< model to be fitted
    5862    pmSourceFitOptions *options,        ///< define options for fitting process
    59     psImageMaskType maskVal             ///< Vale to mask
     63    psImageMaskType maskVal             ///< Value to mask
    6064
    6165);
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_DV1.c

    r30621 r31153  
    4949
    5050#include "pmSourceIO.h"
     51#include "pmSourceOutputs.h"
    5152
    5253// panstarrs-style FITS table output (header + table in 1st extension)
     
    6263    PS_ASSERT_PTR_NON_NULL(extname, false);
    6364
    64     int i;
    6565    psArray *table;
    6666    psMetadata *row;
    67     psF32 *PAR, *dPAR;
    68     psEllipseAxes axes;
    69     psF32 xPos, yPos;
    70     psF32 xErr, yErr;
    71     psF32 errMag, chisq, apRadius;
    72     psS32 nPix, nDOF;
    7367
    7468    pmChip *chip = readout->parent->parent;
    75     pmFPA  *fpa  = chip->parent;
    76 
    77     bool status1 = false;
    78     bool status2 = false;
    79     float magOffset = NAN;
    80     float exptime   = psMetadataLookupF32 (&status1, fpa->concepts, "FPA.EXPOSURE");
    81     float zeropt    = psMetadataLookupF32(&status2, fpa->concepts, "FPA.ZP");
    82     if (!isfinite(zeropt)) {
    83         zeropt    = psMetadataLookupF32 (&status2, imageHeader, "ZPT_OBS");
    84     }
    85     if (status1 && status2 && (exptime > 0.0)) {
    86         magOffset = zeropt + 2.5*log10(exptime);
    87     }
    88     float zeroptErr = psMetadataLookupF32 (&status2, imageHeader, "ZPT_ERR");
     69
    8970
    9071    // if the sequence is defined, write these in seq order; otherwise
     
    9475        if (source->seq == -1) {
    9576          // let's write these out in S/N order
    96           sources = psArraySort (sources, pmSourceSortBySN);
     77          sources = psArraySort (sources, pmSourceSortByFlux);
    9778        } else {
    9879          sources = psArraySort (sources, pmSourceSortBySeq);
     
    10081    }
    10182
     83    short nImageOverlap;
     84    float magOffset;
     85    float zeroptErr;
     86    float fwhmMajor;
     87    float fwhmMinor;
     88    pmSourceOutputsCommonValues (&nImageOverlap, &magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
     89
    10290    table = psArrayAllocEmpty (sources->n);
    10391
    10492    // we write out PSF-fits for all sources, regardless of quality.  the source flags tell us the state
    10593    // by the time we call this function, all values should be assigned.  let's use asserts to be sure in some cases.
    106     for (i = 0; i < sources->n; i++) {
     94    for (int i = 0; i < sources->n; i++) {
    10795        pmSource *source = (pmSource *) sources->data[i];
    10896
     
    115103        }
    116104
    117         // no difference between PSF and non-PSF model
    118         pmModel *model = source->modelPSF;
    119 
    120         if (model != NULL) {
    121             PAR = model->params->data.F32;
    122             dPAR = model->dparams->data.F32;
    123             xPos = PAR[PM_PAR_XPOS];
    124             yPos = PAR[PM_PAR_YPOS];
    125             if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) {
    126               xErr = dPAR[PM_PAR_XPOS];
    127               yErr = dPAR[PM_PAR_YPOS];
    128             } else {
    129               // in linear-fit mode, there is no error on the centroid
    130               xErr = source->peak->dx;
    131               yErr = source->peak->dy;
    132             }
    133             if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    134                 axes = pmPSF_ModelToAxes (PAR, 20.0);
    135             } else {
    136                 axes.major = NAN;
    137                 axes.minor = NAN;
    138                 axes.theta = NAN;
    139             }
    140             chisq = model->chisq;
    141             nDOF = model->nDOF;
    142             nPix = model->nPix;
    143             apRadius = source->apRadius;
    144             errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
    145         } else {
    146             xPos = source->peak->xf;
    147             yPos = source->peak->yf;
    148             xErr = source->peak->dx;
    149             yErr = source->peak->dy;
    150             axes.major = NAN;
    151             axes.minor = NAN;
    152             axes.theta = NAN;
    153             chisq = NAN;
    154             nDOF = 0;
    155             nPix = 0;
    156             apRadius = NAN;
    157             errMag = NAN;
    158         }
    159 
    160         float calMag = isfinite(magOffset) ? source->psfMag + magOffset : NAN;
    161         float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
    162         psS16 nImageOverlap = 1;
    163 
    164         psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
    165         float posAngle = 0.0;
    166         float pltScale = 0.0;
    167         pmSourceLocalAstrometry (&ptSky, &posAngle, &pltScale, chip, xPos, yPos);
     105        // set the 'best' values for various output fields:
     106        pmSourceOutputs outputs;
     107        pmSourceOutputsSetValues (&outputs, source, chip, fwhmMajor, fwhmMinor, magOffset);
     108
     109        pmSourceOutputsMoments moments;
     110        pmSourceOutputsSetMoments (&moments, source);
    168111
    169112        pmSourceDiffStats diffStats;
     
    175118        row = psMetadataAlloc ();
    176119        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             source->seq);
    177         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           xPos);
    178         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           yPos);
    179         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  xErr); // XXX this is only measured for non-linear fits
    180         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  yErr); // XXX this is only measured for non-linear fits
    181         psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         posAngle*PS_DEG_RAD);
    182         psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       pltScale*PS_DEG_RAD*3600.0);
     120        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           outputs.xPos);
     121        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           outputs.yPos);
     122        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  outputs.xErr); // XXX this is only measured for non-linear fits
     123        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  outputs.yErr); // XXX this is only measured for non-linear fits
     124        psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         outputs.posAngle);
     125        psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       outputs.pltScale);
    183126        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG",     PS_DATA_F32, "PSF fit instrumental magnitude",             source->psfMag);
    184         psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        errMag);
     127        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        source->errMag);
    185128        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX",    PS_DATA_F32, "PSF fit instrumental magnitude",             source->psfFlux);
    186129        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX_SIG",PS_DATA_F32, "Sigma of PSF instrumental magnitude",        source->psfFluxErr);
    187130        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG",           PS_DATA_F32, "magnitude in standard aperture",             source->apMag);
    188         psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              apRadius);
    189         psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           peakMag);
    190         psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   calMag);
     131        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              outputs.apRadius);
     132        psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           outputs.peakMag);
     133        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   outputs.calMag);
    191134        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_SIG",  PS_DATA_F32, "measured scatter of zero point calibration", zeroptErr);
    192         psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                ptSky.r*PS_DEG_RAD);
    193         psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               ptSky.d*PS_DEG_RAD);
     135        psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                outputs.ra);
     136        psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               outputs.dec);
    194137        psMetadataAdd (row, PS_LIST_TAIL, "SKY",              PS_DATA_F32, "Sky level",                                  source->sky);
    195138        psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA",        PS_DATA_F32, "Sigma of sky level",                         source->skyErr);
    196139
    197         psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           chisq);
     140        psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           outputs.chisq);
    198141        psMetadataAdd (row, PS_LIST_TAIL, "CR_NSIGMA",        PS_DATA_F32, "Nsigma deviations from PSF to CF",           source->crNsigma);
    199142        psMetadataAdd (row, PS_LIST_TAIL, "EXT_NSIGMA",       PS_DATA_F32, "Nsigma deviations from PSF to EXT",          source->extNsigma);
    200143
    201         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     axes.major);
    202         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    203         psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
     144        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     outputs.psfMajor);
     145        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     outputs.psfMinor);
     146        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      outputs.psfTheta);
    204147        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeightNotBad);
    205         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    206         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
    207 
    208         // distinguish moments measure from window vs S/N > XX ??
    209         float mxx = source->moments ? source->moments->Mxx : NAN;
    210         float mxy = source->moments ? source->moments->Mxy : NAN;
    211         float myy = source->moments ? source->moments->Myy : NAN;
    212         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      mxx);
    213         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      mxy);
    214         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      myy);
    215 
    216         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NPOS",        PS_DATA_S32, "nPos (n pix > 3 sigma)",                    diffStats.nGood);
    217         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_FRATIO",      PS_DATA_F32, "fPos / (fPos + fNeg)",                      diffStats.fRatio);
    218         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_BAD",  PS_DATA_F32, "nPos / (nPos + nNeg)",                      diffStats.nRatioBad);
    219         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_MASK", PS_DATA_F32, "nPos / (nPos + nMask)",                     diffStats.nRatioMask);
    220         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_ALL",  PS_DATA_F32, "nPos / (nGood + nMask + nBad)",             diffStats.nRatioAll);
     148        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         outputs.nDOF);
     149        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    outputs.nPix);
     150
     151        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                       moments.Mxx);
     152        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                       moments.Mxy);
     153        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                       moments.Myy);
     154
     155        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NPOS",        PS_DATA_S32, "nPos (n pix > 3 sigma)",                     diffStats.nGood);
     156        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_FRATIO",      PS_DATA_F32, "fPos / (fPos + fNeg)",                       diffStats.fRatio);
     157        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_BAD",  PS_DATA_F32, "nPos / (nPos + nNeg)",                       diffStats.nRatioBad);
     158        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_MASK", PS_DATA_F32, "nPos / (nPos + nMask)",                      diffStats.nRatioMask);
     159        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_ALL",  PS_DATA_F32, "nPos / (nGood + nMask + nBad)",              diffStats.nRatioAll);
    221160
    222161        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                      source->mode);
     
    331270        // recreate the peak to match (xPos, yPos) +/- (xErr, yErr)
    332271        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    333         source->peak->flux = peakFlux;
     272        source->peak->rawFlux = peakFlux;
     273        source->peak->smoothFlux = peakFlux;
    334274        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
    335275        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    336276        source->peak->dx   = dPAR[PM_PAR_XPOS];
    337277        source->peak->dy   = dPAR[PM_PAR_YPOS];
    338         if (isfinite (source->errMag) && (source->errMag > 0.0)) {
    339           source->peak->SN = 1.0 / source->errMag;
    340         } else {
    341           source->peak->SN = sqrt(source->peak->flux); // an alternate proxy: various functions sort by peak S/N
    342         }
    343278
    344279        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
     
    353288
    354289        source->moments = pmMomentsAlloc ();
     290        source->moments->Mx = source->peak->xf; // we don't have both Mx,My and xf,yf in the cmf
     291        source->moments->My = source->peak->yf; // we don't have both Mx,My and xf,yf in the cmf
     292
    355293        source->moments->Mxx = psMetadataLookupF32 (&status, row, "MOMENTS_XX");
    356294        source->moments->Mxy = psMetadataLookupF32 (&status, row, "MOMENTS_XY");
     
    395333
    396334    // let's write these out in S/N order
    397     sources = psArraySort (sources, pmSourceSortBySN);
     335    sources = psArraySort (sources, pmSourceSortByFlux);
    398336
    399337    table = psArrayAllocEmpty (sources->n);
     
    568506
    569507    // let's write these out in S/N order
    570     sources = psArraySort (sources, pmSourceSortBySN);
     508    sources = psArraySort (sources, pmSourceSortByFlux);
    571509
    572510    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_DV2.c

    r30621 r31153  
    4949
    5050#include "pmSourceIO.h"
     51#include "pmSourceOutputs.h"
    5152
    5253// panstarrs-style FITS table output (header + table in 1st extension)
     
    6263    PS_ASSERT_PTR_NON_NULL(extname, false);
    6364
    64     int i;
    6565    psArray *table;
    6666    psMetadata *row;
    67     psF32 *PAR, *dPAR;
    68     psEllipseAxes axes;
    69     psF32 xPos, yPos;
    70     psF32 xErr, yErr;
    71     psF32 chisq, apRadius;
    72     psS32 nPix, nDOF;
    7367
    7468    pmChip *chip = readout->parent->parent;
    75     pmFPA  *fpa  = chip->parent;
    76 
    77     bool status1 = false;
    78     bool status2 = false;
    79     float magOffset = NAN;
    80     float exptime   = psMetadataLookupF32 (&status1, fpa->concepts, "FPA.EXPOSURE");
    81     float zeropt    = psMetadataLookupF32(&status2, fpa->concepts, "FPA.ZP");
    82     if (!isfinite(zeropt)) {
    83         zeropt    = psMetadataLookupF32 (&status2, imageHeader, "ZPT_OBS");
    84     }
    85     if (status1 && status2 && (exptime > 0.0)) {
    86         magOffset = zeropt + 2.5*log10(exptime);
    87     }
    88     float zeroptErr = psMetadataLookupF32 (&status2, imageHeader, "ZPT_ERR");
    89 
    90     // we need a measure of the image quality (FWHM) for this image, in order to get the positional errors
    91     float fwhmMajor = psMetadataLookupF32(&status1, readout->analysis, "FWHM_MAJ");
    92     if (!status1) {
    93         fwhmMajor = psMetadataLookupF32(&status1, readout->analysis, "IQ_FW1");
    94         if (!status1) {
    95             fwhmMajor = 5.0; // XXX just a guess!
    96         }
    97     }
    98     float fwhmMinor = psMetadataLookupF32(&status1, readout->analysis, "FWHM_MIN");
    99     if (!status1) {
    100         fwhmMinor = psMetadataLookupF32(&status1, readout->analysis, "IQ_FW2");
    101         if (!status1) {
    102             fwhmMinor = 5.0; // XXX just a guess!
    103         }
    104     }
    10569
    10670    // if the sequence is defined, write these in seq order; otherwise
     
    11074        if (source->seq == -1) {
    11175          // let's write these out in S/N order
    112           sources = psArraySort (sources, pmSourceSortBySN);
     76          sources = psArraySort (sources, pmSourceSortByFlux);
    11377        } else {
    11478          sources = psArraySort (sources, pmSourceSortBySeq);
     
    11882    table = psArrayAllocEmpty (sources->n);
    11983
     84    short nImageOverlap;
     85    float magOffset;
     86    float zeroptErr;
     87    float fwhmMajor;
     88    float fwhmMinor;
     89    pmSourceOutputsCommonValues (&nImageOverlap, &magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
     90
    12091    // we write out PSF-fits for all sources, regardless of quality.  the source flags tell us the state
    12192    // by the time we call this function, all values should be assigned.  let's use asserts to be sure in some cases.
    122     for (i = 0; i < sources->n; i++) {
     93    for (int i = 0; i < sources->n; i++) {
    12394        pmSource *source = (pmSource *) sources->data[i];
    12495
     
    131102        }
    132103
    133         // no difference between PSF and non-PSF model
    134         pmModel *model = source->modelPSF;
    135 
    136         if (model != NULL) {
    137             PAR = model->params->data.F32;
    138             dPAR = model->dparams->data.F32;
    139             xPos = PAR[PM_PAR_XPOS];
    140             yPos = PAR[PM_PAR_YPOS];
    141             if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) {
    142               xErr = dPAR[PM_PAR_XPOS];
    143               yErr = dPAR[PM_PAR_YPOS];
    144             } else {
    145               // in linear-fit mode, there is no error on the centroid
    146                 xErr = fwhmMajor * source->errMag / 2.35;
    147                 yErr = fwhmMinor * source->errMag / 2.35;
    148             }
    149             if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    150                 axes = pmPSF_ModelToAxes (PAR, 20.0);
    151             } else {
    152                 axes.major = NAN;
    153                 axes.minor = NAN;
    154                 axes.theta = NAN;
    155             }
    156             chisq = model->chisq;
    157             nDOF = model->nDOF;
    158             nPix = model->nPix;
    159             apRadius = source->apRadius;
    160         } else {
    161             bool useMoments = true;
    162             useMoments = (useMoments && source->moments);          // can't if there are no moments
    163             useMoments = (useMoments && source->moments->nPixels); // can't if the moments were not measured
    164             useMoments = (useMoments && !(source->mode && PM_SOURCE_MODE_MOMENTS_FAILURE)); // can't if the moments failed...
    165 
    166             if (useMoments) {
    167                 xPos = source->moments->Mx;
    168                 yPos = source->moments->My;
    169                 xErr = fwhmMajor * source->errMag / 2.35;
    170                 yErr = fwhmMinor * source->errMag / 2.35;
    171             } else {
    172                 xPos = source->peak->xf;
    173                 yPos = source->peak->yf;
    174                 xErr = source->peak->dx;
    175                 yErr = source->peak->dy;
    176             }
    177             axes.major = NAN;
    178             axes.minor = NAN;
    179             axes.theta = NAN;
    180             chisq = NAN;
    181             nDOF = 0;
    182             nPix = 0;
    183             apRadius = NAN;
    184         }
    185 
    186         float calMag = isfinite(magOffset) ? source->psfMag + magOffset : NAN;
    187         float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
    188         psS16 nImageOverlap = 1;
    189 
    190         psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
    191         float posAngle = 0.0;
    192         float pltScale = 0.0;
    193         pmSourceLocalAstrometry (&ptSky, &posAngle, &pltScale, chip, xPos, yPos);
     104        // set the 'best' values for various output fields:
     105        pmSourceOutputs outputs;
     106        pmSourceOutputsSetValues (&outputs, source, chip, fwhmMajor, fwhmMinor, magOffset);
     107
     108        pmSourceOutputsMoments moments;
     109        pmSourceOutputsSetMoments (&moments, source);
    194110
    195111        pmSourceDiffStats diffStats;
     
    201117        row = psMetadataAlloc ();
    202118        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             source->seq);
    203         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           xPos);
    204         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           yPos);
    205         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  xErr); // XXX this is only measured for non-linear fits
    206         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  yErr); // XXX this is only measured for non-linear fits
    207         psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         posAngle*PS_DEG_RAD);
    208         psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       pltScale*PS_DEG_RAD*3600.0);
     119        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           outputs.xPos);
     120        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           outputs.yPos);
     121        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  outputs.xErr); // XXX this is only measured for non-linear fits
     122        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  outputs.yErr); // XXX this is only measured for non-linear fits
     123        psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         outputs.posAngle);
     124        psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       outputs.pltScale);
    209125        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG",     PS_DATA_F32, "PSF fit instrumental magnitude",             source->psfMag);
    210126        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        source->errMag);
     
    214130        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG",           PS_DATA_F32, "magnitude in standard aperture",             source->apMag);
    215131        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RAW",       PS_DATA_F32, "magnitude in real aperture",                 source->apMagRaw);
    216         psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              apRadius);
     132        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              outputs.apRadius);
    217133        psMetadataAdd (row, PS_LIST_TAIL, "AP_FLUX",          PS_DATA_F32, "instrumental flux in standard aperture",     source->apFlux);
    218134        psMetadataAdd (row, PS_LIST_TAIL, "AP_FLUX_SIG",      PS_DATA_F32, "aperture flux error",                        source->apFluxErr);
    219135
    220         psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           peakMag);
    221         psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   calMag);
     136        psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           outputs.peakMag);
     137        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   outputs.calMag);
    222138        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_SIG",  PS_DATA_F32, "measured scatter of zero point calibration", zeroptErr);
    223         psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                ptSky.r*PS_DEG_RAD);
    224         psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               ptSky.d*PS_DEG_RAD);
     139        psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                outputs.ra);
     140        psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               outputs.dec);
    225141        psMetadataAdd (row, PS_LIST_TAIL, "SKY",              PS_DATA_F32, "Sky level",                                  source->sky);
    226142        psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA",        PS_DATA_F32, "Sigma of sky level",                         source->skyErr);
    227143
    228         psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           chisq);
     144        psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           outputs.chisq);
    229145        psMetadataAdd (row, PS_LIST_TAIL, "CR_NSIGMA",        PS_DATA_F32, "Nsigma deviations from PSF to CF",           source->crNsigma);
    230146        psMetadataAdd (row, PS_LIST_TAIL, "EXT_NSIGMA",       PS_DATA_F32, "Nsigma deviations from PSF to EXT",          source->extNsigma);
    231147
    232         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     axes.major);
    233         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    234         psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
     148        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     outputs.psfMajor);
     149        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     outputs.psfMinor);
     150        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      outputs.psfTheta);
    235151        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor (bad)",          source->pixWeightNotBad);
    236152        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF_PERFECT",   PS_DATA_F32, "PSF coverage/quality factor (poor)",         source->pixWeightNotPoor);
    237         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    238         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
    239 
    240         // distinguish moments measure from window vs S/N > XX ??
    241         float mxx = source->moments ? source->moments->Mxx : NAN;
    242         float mxy = source->moments ? source->moments->Mxy : NAN;
    243         float myy = source->moments ? source->moments->Myy : NAN;
    244         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      mxx);
    245         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      mxy);
    246         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      myy);
    247 
    248         float Mrf  = source->moments ? source->moments->Mrf : NAN;
    249         float Mrh  = source->moments ? source->moments->Mrh : NAN;
    250         float Krf  = source->moments ? source->moments->KronFlux : NAN;
    251         float dKrf = source->moments ? source->moments->KronFluxErr : NAN;
    252 
    253         float Kinner = source->moments ? source->moments->KronFinner : NAN;
    254         float Kouter = source->moments ? source->moments->KronFouter : NAN;
    255 
    256         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                       Mrf);
    257         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH",       PS_DATA_F32, "half radial moment",                        Mrh);
    258         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX",        PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Krf);
    259         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR",    PS_DATA_F32, "Kron Flux Error",                          dKrf);
    260 
    261         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER",  PS_DATA_F32, "Kron Flux (in 1.0 R1)",                     Kinner);
    262         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER",  PS_DATA_F32, "Kron Flux (in 4.0 R1)",                     Kouter);
    263 
    264         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NPOS",        PS_DATA_S32, "nPos (n pix > 3 sigma)",                    diffStats.nGood);
    265         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_FRATIO",      PS_DATA_F32, "fPos / (fPos + fNeg)",                      diffStats.fRatio);
    266         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_BAD",  PS_DATA_F32, "nPos / (nPos + nNeg)",                      diffStats.nRatioBad);
    267         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_MASK", PS_DATA_F32, "nPos / (nPos + nMask)",                     diffStats.nRatioMask);
    268         psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_ALL",  PS_DATA_F32, "nPos / (nGood + nMask + nBad)",             diffStats.nRatioAll);
     153        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         outputs.nDOF);
     154        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    outputs.nPix);
     155
     156        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                       moments.Mxx);
     157        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                       moments.Mxy);
     158        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                       moments.Myy);
     159
     160        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                        moments.Mrf);
     161        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH",       PS_DATA_F32, "half radial moment",                         moments.Mrh);
     162        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX",        PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Krf);
     163        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR",    PS_DATA_F32, "Kron Flux Error",                            moments.dKrf);
     164        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER",  PS_DATA_F32, "Kron Flux (in 1.0 R1)",                      moments.Kinner);
     165        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER",  PS_DATA_F32, "Kron Flux (in 4.0 R1)",                      moments.Kouter);
     166
     167        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NPOS",        PS_DATA_S32, "nPos (n pix > 3 sigma)",                     diffStats.nGood);
     168        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_FRATIO",      PS_DATA_F32, "fPos / (fPos + fNeg)",                       diffStats.fRatio);
     169        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_BAD",  PS_DATA_F32, "nPos / (nPos + nNeg)",                       diffStats.nRatioBad);
     170        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_MASK", PS_DATA_F32, "nPos / (nPos + nMask)",                      diffStats.nRatioMask);
     171        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_NRATIO_ALL",  PS_DATA_F32, "nPos / (nGood + nMask + nBad)",              diffStats.nRatioAll);
    269172
    270173        psMetadataAdd (row, PS_LIST_TAIL, "DIFF_R_P",         PS_DATA_F32, "distance to positive match source",          diffStats.Rp);
     
    385288        // recreate the peak to match (xPos, yPos) +/- (xErr, yErr)
    386289        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    387         source->peak->flux = peakFlux;
     290        source->peak->rawFlux = peakFlux;
     291        source->peak->smoothFlux = peakFlux;
    388292        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
    389293        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    390294        source->peak->dx   = dPAR[PM_PAR_XPOS];
    391295        source->peak->dy   = dPAR[PM_PAR_YPOS];
    392         if (isfinite (source->errMag) && (source->errMag > 0.0)) {
    393           source->peak->SN = 1.0 / source->errMag;
    394         } else {
    395           source->peak->SN = sqrt(source->peak->flux); // an alternate proxy: various functions sort by peak S/N
    396         }
    397296
    398297        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
     
    408307
    409308        source->moments = pmMomentsAlloc ();
     309        source->moments->Mx = source->peak->xf; // we don't have both Mx,My and xf,yf in the cmf
     310        source->moments->My = source->peak->yf; // we don't have both Mx,My and xf,yf in the cmf
     311
    410312        source->moments->Mxx = psMetadataLookupF32 (&status, row, "MOMENTS_XX");
    411313        source->moments->Mxy = psMetadataLookupF32 (&status, row, "MOMENTS_XY");
     
    456358
    457359    // let's write these out in S/N order
    458     sources = psArraySort (sources, pmSourceSortBySN);
     360    sources = psArraySort (sources, pmSourceSortByFlux);
    459361
    460362    table = psArrayAllocEmpty (sources->n);
     
    629531
    630532    // let's write these out in S/N order
    631     sources = psArraySort (sources, pmSourceSortBySN);
     533    sources = psArraySort (sources, pmSourceSortByFlux);
    632534
    633535    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_SV1.c

    r30621 r31153  
    5050
    5151#include "pmSourceIO.h"
     52#include "pmSourceOutputs.h"
    5253
    5354// panstarrs-style FITS table output (header + table in 1st extension)
     
    6667    psArray *table;
    6768    psMetadata *row;
    68     psF32 *PAR, *dPAR;
    69     psEllipseAxes axes;
    70     psF32 xPos, yPos;
    71     psF32 xErr, yErr;
    72     psF32 errMag, chisq, apRadius;
    73     psS32 nPix, nDOF;
    7469
    7570    pmChip *chip = readout->parent->parent;
    76     pmFPA  *fpa  = chip->parent;
    77 
    78     bool status1 = false;
    79     bool status2 = false;
    80     float magOffset = NAN;
    81     float exptime   = psMetadataLookupF32 (&status1, fpa->concepts, "FPA.EXPOSURE");
    82     float zeropt    = psMetadataLookupF32(&status2, fpa->concepts, "FPA.ZP");
    83     if (!isfinite(zeropt)) {
    84         zeropt    = psMetadataLookupF32 (&status2, imageHeader, "ZPT_OBS");
    85     }
    86     if (status1 && status2 && (exptime > 0.0)) {
    87         magOffset = zeropt + 2.5*log10(exptime);
    88     }
    89     float zeroptErr = psMetadataLookupF32 (&status2, imageHeader, "ZPT_ERR");
    90 
    91     // if the sequence is defined, write these in seq order; otherwise
    92     // write them in S/N order:
     71
     72    // if the sequence is defined, write these in seq order; otherwise write them in S/N order.
     73    // Careful: if we are working with child sources, then we need to sort by the parent info,
     74    // not our info
    9375    if (sources->n > 0) {
    94         pmSource *source = (pmSource *) sources->data[0];
     76        pmSource *source = sources->data[0];
    9577        if (source->seq == -1) {
    96             // let's write these out in S/N order
    97             sources = psArraySort (sources, pmSourceSortBySN);
     78            sources = psArraySort (sources, pmSourceSortByFlux);
    9879        } else {
    9980            sources = psArraySort (sources, pmSourceSortBySeq);
     
    10384    table = psArrayAllocEmpty (sources->n);
    10485
    105 # if (0)
    106     // we use this just to define the output vectors (which must be present for all objects)
    107     bool status = false;
    108     psVector *radMin = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER");
    109     psVector *radMax = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER");
    110     psAssert (radMax, "this must have been defined and tested earlier!");
    111     psAssert (radMax->n, "this must have been defined and tested earlier!");
    112     psAssert (radMin->n == radMax->n, "inconsistent annular bins");
    113 
    114     // write the radial profile apertures to header
    115     for (int i = 0; i < radMax->n; i++) {
    116       sprintf (keyword1, "RMIN_%02d", i);
    117       sprintf (keyword2, "RMAX_%02d", i);
    118       psMetadataAddF32 (imageHeader, PS_LIST_TAIL, keyword1, PS_META_REPLACE, "min radius for SB profile", radMin->data.F32[i]);
    119       psMetadataAddF32 (imageHeader, PS_LIST_TAIL, keyword2, PS_META_REPLACE, "min radius for SB profile", radMax->data.F32[i]);
    120     }
    121 # endif
     86    short nImageOverlap;
     87    float magOffset;
     88    float zeroptErr;
     89    float fwhmMajor;
     90    float fwhmMinor;
     91    pmSourceOutputsCommonValues (&nImageOverlap, &magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
    12292
    12393    // we write out PSF-fits for all sources, regardless of quality.  the source flags tell us the state
    12494    // by the time we call this function, all values should be assigned.  let's use asserts to be sure in some cases.
    12595    for (int i = 0; i < sources->n; i++) {
    126         pmSource *source = (pmSource *) sources->data[i];
    127 
    128         // If source->seq is -1, source was generated in this analysis.  If source->seq is
    129         // not -1, source was read from elsewhere: in the latter case, preserve the source
    130         // ID.  source.seq is used instead of source.id since the latter is a const
    131         // generated on Alloc, and would thus be wrong for read in sources.
     96        // this is the source associated with this image
     97        pmSource *thisSource = sources->data[i];
     98
     99        // this is the "real" version of this source
     100        pmSource *source = thisSource->parent ? thisSource->parent : thisSource;
     101
     102        // If source->seq is -1, source is unique and generated in this analysis.  If
     103        // source->seq is not -1, source was read from elsewhere or tied to other source (eg
     104        // from another image): in the latter case, preserve the source ID.  source.seq is used
     105        // instead of source.id since the latter is a const generated on Alloc, and would thus
     106        // be wrong for read in sources.
    132107        if (source->seq == -1) {
    133108            source->seq = i;
    134109        }
    135110
    136         // no difference between PSF and non-PSF model
    137         pmModel *model = source->modelPSF;
    138 
    139         if (model != NULL) {
    140             PAR = model->params->data.F32;
    141             dPAR = model->dparams->data.F32;
    142             xPos = PAR[PM_PAR_XPOS];
    143             yPos = PAR[PM_PAR_YPOS];
    144             if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) {
    145                 xErr = dPAR[PM_PAR_XPOS];
    146                 yErr = dPAR[PM_PAR_YPOS];
    147             } else {
    148                 // in linear-fit mode, there is no error on the centroid
    149                 xErr = source->peak->dx;
    150                 yErr = source->peak->dy;
    151             }
    152             if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    153                 axes = pmPSF_ModelToAxes (PAR, 20.0);
    154             } else {
    155                 axes.major = NAN;
    156                 axes.minor = NAN;
    157                 axes.theta = NAN;
    158             }
    159             chisq = model->chisq;
    160             nDOF = model->nDOF;
    161             nPix = model->nPix;
    162             apRadius = source->apRadius;
    163             errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
    164         } else {
    165             xPos = source->peak->xf;
    166             yPos = source->peak->yf;
    167             xErr = source->peak->dx;
    168             yErr = source->peak->dy;
    169             axes.major = NAN;
    170             axes.minor = NAN;
    171             axes.theta = NAN;
    172             chisq = NAN;
    173             nDOF = 0;
    174             nPix = 0;
    175             apRadius = NAN;
    176             errMag = NAN;
    177         }
    178 
    179         float calMag = isfinite(magOffset) ? source->psfMag + magOffset : NAN;
    180         float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
    181         psS16 nImageOverlap = 1;
    182 
    183         psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
    184         float posAngle = 0.0;
    185         float pltScale = 0.0;
    186         pmSourceLocalAstrometry (&ptSky, &posAngle, &pltScale, chip, xPos, yPos);
     111        // set the 'best' values for various output fields:
     112        pmSourceOutputs outputs;
     113        pmSourceOutputsSetValues (&outputs, source, chip, fwhmMajor, fwhmMinor, magOffset);
     114
     115        pmSourceOutputsMoments moments;
     116        pmSourceOutputsSetMoments (&moments, source);
    187117
    188118        row = psMetadataAlloc ();
    189119        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             source->seq);
    190         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           xPos);
    191         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           yPos);
    192         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  xErr); // XXX this is only measured for non-linear fits
    193         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  yErr); // XXX this is only measured for non-linear fits
    194         psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         posAngle*PS_DEG_RAD);
    195         psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       pltScale*PS_DEG_RAD*3600.0);
     120        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           outputs.xPos);
     121        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           outputs.yPos);
     122        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  outputs.xErr);
     123        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  outputs.yErr);
     124        psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         outputs.posAngle);
     125        psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       outputs.pltScale);
    196126        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG",     PS_DATA_F32, "PSF fit instrumental magnitude",             source->psfMag);
    197         psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        errMag);
     127        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        source->errMag);
    198128        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX",    PS_DATA_F32, "PSF fit instrumental flux (counts)",         source->psfFlux);
    199129        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX_SIG",PS_DATA_F32, "Sigma of PSF instrumental flux",             source->psfFluxErr);
    200130        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG",           PS_DATA_F32, "magnitude in standard aperture",             source->apMag);
    201131        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RAW",       PS_DATA_F32, "magnitude in reported aperture",             source->apMagRaw);
    202         psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              apRadius);
    203         psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           peakMag);
    204         psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   calMag);
     132        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              outputs.apRadius);
     133        psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           outputs.peakMag);
     134        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   outputs.calMag);
    205135        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_SIG",  PS_DATA_F32, "measured scatter of zero point calibration", zeroptErr);
    206         psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                ptSky.r*PS_DEG_RAD);
    207         psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               ptSky.d*PS_DEG_RAD);
     136        psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                outputs.ra);
     137        psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               outputs.dec);
    208138        psMetadataAdd (row, PS_LIST_TAIL, "SKY",              PS_DATA_F32, "Sky level",                                  source->sky);
    209139        psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA",        PS_DATA_F32, "Sigma of sky level",                         source->skyErr);
    210140
    211         psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           chisq);
     141        psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           outputs.chisq);
    212142        psMetadataAdd (row, PS_LIST_TAIL, "CR_NSIGMA",        PS_DATA_F32, "Nsigma deviations from PSF to CF",           source->crNsigma);
    213143        psMetadataAdd (row, PS_LIST_TAIL, "EXT_NSIGMA",       PS_DATA_F32, "Nsigma deviations from PSF to EXT",          source->extNsigma);
    214144
    215         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     axes.major);
    216         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    217         psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
     145        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     outputs.psfMajor);
     146        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     outputs.psfMinor);
     147        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      outputs.psfTheta);
    218148        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor (bad)",          source->pixWeightNotBad);
    219149        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF_PERFECT",   PS_DATA_F32, "PSF coverage/quality factor (poor)",         source->pixWeightNotPoor);
    220         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    221         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
    222 
    223         // distinguish moments measure from window vs S/N > XX ??
    224         float Mxx = source->moments ? source->moments->Mxx : NAN;
    225         float Mxy = source->moments ? source->moments->Mxy : NAN;
    226         float Myy = source->moments ? source->moments->Myy : NAN;
    227 
    228         float Mrf  = source->moments ? source->moments->Mrf : NAN;
    229         float Mrh  = source->moments ? source->moments->Mrh : NAN;
    230         float Krf  = source->moments ? source->moments->KronFlux : NAN;
    231         float dKrf = source->moments ? source->moments->KronFluxErr : NAN;
    232 
    233         float Kinner = source->moments ? source->moments->KronFinner : NAN;
    234         float Kouter = source->moments ? source->moments->KronFouter : NAN;
    235 
    236         float M_c3 = source->moments ? 1.0*source->moments->Mxxx - 3.0*source->moments->Mxyy : NAN;
    237         float M_s3 = source->moments ? 3.0*source->moments->Mxxy - 1.0*source->moments->Myyy : NAN;
    238         float M_c4 = source->moments ? 1.0*source->moments->Mxxxx - 6.0*source->moments->Mxxyy + 1.0*source->moments->Myyyy : NAN;
    239         float M_s4 = source->moments ? 4.0*source->moments->Mxxxy - 4.0*source->moments->Mxyyy : NAN;
    240 
    241         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      Mxx);
    242         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      Mxy);
    243         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      Myy);
    244 
    245         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3C",      PS_DATA_F32, "third momemt cos theta",                    M_c3);
    246         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3S",      PS_DATA_F32, "third momemt sin theta",                    M_s3);
    247         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4C",      PS_DATA_F32, "fourth momemt cos theta",                   M_c4);
    248         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4S",      PS_DATA_F32, "fourth momemt sin theta",                   M_s4);
    249 
    250         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                       Mrf);
    251         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH",       PS_DATA_F32, "half radial moment",                        Mrh);
    252         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX",        PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Krf);
    253         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR",    PS_DATA_F32, "Kron Flux Error",                          dKrf);
    254 
    255         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Kinner);
    256         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Kouter);
     150        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         outputs.nDOF);
     151        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    outputs.nPix);
     152
     153        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                       moments.Mxx);
     154        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                       moments.Mxy);
     155        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                       moments.Myy);
     156
     157        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3C",      PS_DATA_F32, "third momemt cos theta",                     moments.M_c3);
     158        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3S",      PS_DATA_F32, "third momemt sin theta",                     moments.M_s3);
     159        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4C",      PS_DATA_F32, "fourth momemt cos theta",                    moments.M_c4);
     160        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4S",      PS_DATA_F32, "fourth momemt sin theta",                    moments.M_s4);
     161
     162        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                        moments.Mrf);
     163        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH",       PS_DATA_F32, "half radial moment",                         moments.Mrh);
     164        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX",        PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Krf);
     165        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR",    PS_DATA_F32, "Kron Flux Error",                            moments.dKrf);
     166        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Kinner);
     167        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Kouter);
    257168
    258169        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                     source->mode);
    259170        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2",           PS_DATA_U32, "psphot analysis flags",                     source->mode2);
    260 
    261 # if (0)
    262         // XXX if we have raw radial apertures, write them out here
    263         psVector *radFlux    = psVectorAlloc(radMax->n, PS_TYPE_F32);
    264         psVector *radFluxErr = psVectorAlloc(radMax->n, PS_TYPE_F32);
    265         psVector *radFill    = psVectorAlloc(radMax->n, PS_TYPE_F32);
    266         psVectorInit (radFlux,    NAN);
    267         psVectorInit (radFluxErr, NAN);
    268         psVectorInit (radFill,    NAN);
    269         if (!source->radial) goto empty_annuli;
    270         if (!source->radial->flux) goto empty_annuli;
    271         if (!source->radial->fill) goto empty_annuli;
    272         psAssert (source->radial->flux->n <= radFlux->n, "inconsistent vector lengths");
    273         psAssert (source->radial->fill->n <= radFlux->n, "inconsistent vector lengths");
    274 
    275         // copy the data from fluxVal (which is not guaranteed to be the full length) to radFlux
    276         for (int j = 0; j < source->radial->flux->n; j++) {
    277             radFlux->data.F32[j]    = source->radial->flux->data.F32[j];
    278             radFluxErr->data.F32[j] = source->radial->fluxErr->data.F32[j];
    279             radFill->data.F32[j]    = source->radial->fill->data.F32[j];
    280         }
    281 
    282     empty_annuli:
    283         psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX",     PS_DATA_VECTOR, "flux within annuli",    radFlux);
    284         psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_ERR", PS_DATA_VECTOR, "flux error in annuli",  radFluxErr);
    285         psMetadataAdd (row, PS_LIST_TAIL, "APER_FILL",     PS_DATA_VECTOR, "fill factor of annuli", radFill);
    286         psFree (radFlux);
    287         psFree (radFluxErr);
    288         psFree (radFill);
    289 # endif
    290171
    291172        // XXX not sure how to get this : need to load Nimages with weight?
     
    406287        // recreate the peak to match (xPos, yPos) +/- (xErr, yErr)
    407288        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    408         source->peak->flux = peakFlux;
     289        source->peak->rawFlux = peakFlux;
     290        source->peak->smoothFlux = peakFlux;
    409291        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
    410292        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    411293        source->peak->dx   = dPAR[PM_PAR_XPOS];
    412294        source->peak->dy   = dPAR[PM_PAR_YPOS];
    413         if (isfinite (source->errMag) && (source->errMag > 0.0)) {
    414           source->peak->SN = 1.0 / source->errMag;
    415         } else {
    416           source->peak->SN = sqrt(source->peak->flux); // an alternate proxy: various functions sort by peak S/N
    417         }
    418295
    419296        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
     
    429306
    430307        source->moments = pmMomentsAlloc ();
     308        source->moments->Mx = source->peak->xf; // we don't have both Mx,My and xf,yf in the cmf
     309        source->moments->My = source->peak->yf; // we don't have both Mx,My and xf,yf in the cmf
     310
    431311        source->moments->Mxx = psMetadataLookupF32 (&status, row, "MOMENTS_XX");
    432312        source->moments->Mxy = psMetadataLookupF32 (&status, row, "MOMENTS_XY");
     
    500380
    501381    // let's write these out in S/N order
    502     sources = psArraySort (sources, pmSourceSortBySN);
     382    sources = psArraySort (sources, pmSourceSortByFlux);
    503383
    504384    table = psArrayAllocEmpty (sources->n);
     
    522402    // we write out all sources, regardless of quality.  the source flags tell us the state
    523403    for (int i = 0; i < sources->n; i++) {
    524         pmSource *source = sources->data[i];
     404        // this is the source associated with this image
     405        pmSource *thisSource = sources->data[i];
     406
     407        // this is the "real" version of this source
     408        pmSource *source = thisSource->parent ? thisSource->parent : thisSource;
    525409
    526410        // skip sources without measurements
     
    556440        }
    557441        psMetadataAdd (row, PS_LIST_TAIL, "F25_ARATIO",       PS_DATA_F32, "Axial Ratio of radial profile",              AxialRatio);
    558         psMetadataAdd (row, PS_LIST_TAIL, "F25_THETA",        PS_DATA_F32, "Angle of radial profile ellipse",                  AxialTheta);
     442        psMetadataAdd (row, PS_LIST_TAIL, "F25_THETA",        PS_DATA_F32, "Angle of radial profile ellipse",            AxialTheta);
    559443
    560444        // Petrosian measurements
     
    567451                float mag = (extpars->petrosianFlux > 0.0) ? -2.5*log10(extpars->petrosianFlux) + magOffset : NAN; // XXX zero point
    568452                float magErr = (extpars->petrosianFlux > 0.0) ? extpars->petrosianFlux / extpars->petrosianFluxErr : NAN; // XXX zero point
    569                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude", mag);
    570                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", magErr);
    571                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius (pix)", extpars->petrosianRadius);
    572                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error (pix)", extpars->petrosianRadiusErr);
     453                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",           PS_DATA_F32, "Petrosian Magnitude", mag);
     454                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",       PS_DATA_F32, "Petrosian Magnitude Error", magErr);
     455                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",        PS_DATA_F32, "Petrosian Radius (pix)", extpars->petrosianRadius);
     456                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR",    PS_DATA_F32, "Petrosian Radius Error (pix)", extpars->petrosianRadiusErr);
    573457                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_50",     PS_DATA_F32, "Petrosian R50 (pix)", extpars->petrosianR50);
    574458                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_50_ERR", PS_DATA_F32, "Petrosian R50 Error (pix)", extpars->petrosianR50Err);
    575459                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_90",     PS_DATA_F32, "Petrosian R90 (pix)", extpars->petrosianR90);
    576460                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_90_ERR", PS_DATA_F32, "Petrosian R90 Error (pix)", extpars->petrosianR90Err);
     461                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_FILL",          PS_DATA_F32, "Petrosian Fill Factor", extpars->petrosianFill);
    577462            } else {
    578                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",        PS_DATA_F32, "Petrosian Magnitude",       NAN);
    579                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",    PS_DATA_F32, "Petrosian Magnitude Error", NAN);
    580                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",     PS_DATA_F32, "Petrosian Radius",          NAN);
    581                 psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR", PS_DATA_F32, "Petrosian Radius Error",    NAN);
     463                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG",           PS_DATA_F32, "Petrosian Magnitude",       NAN);
     464                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_MAG_ERR",       PS_DATA_F32, "Petrosian Magnitude Error", NAN);
     465                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS",        PS_DATA_F32, "Petrosian Radius",          NAN);
     466                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_ERR",    PS_DATA_F32, "Petrosian Radius Error",    NAN);
    582467                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_50",     PS_DATA_F32, "Petrosian R50 (pix)", NAN);
    583468                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_50_ERR", PS_DATA_F32, "Petrosian R50 Error (pix)",NAN);
    584469                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_90",     PS_DATA_F32, "Petrosian R90 (pix)", NAN);
    585470                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_RADIUS_90_ERR", PS_DATA_F32, "Petrosian R90 Error (pix)",NAN);
     471                psMetadataAdd (row, PS_LIST_TAIL, "PETRO_FILL",          PS_DATA_F32, "Petrosian Fill Factor", NAN);
    586472            }
    587473        }
     
    672558
    673559    // let's write these out in S/N order
    674     sources = psArraySort (sources, pmSourceSortBySN);
     560    sources = psArraySort (sources, pmSourceSortByFlux);
    675561
    676562    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
    677563    int nParamMax = 0;
    678564    for (int i = 0; i < sources->n; i++) {
    679         pmSource *source = sources->data[i];
     565        // this is the source associated with this image
     566        pmSource *thisSource = sources->data[i];
     567
     568        // this is the "real" version of this source
     569        pmSource *source = thisSource->parent ? thisSource->parent : thisSource;
     570
    680571        if (source->modelFits == NULL) continue;
    681572        for (int j = 0; j < source->modelFits->n; j++) {
     
    691582    for (int i = 0; i < sources->n; i++) {
    692583
    693         pmSource *source = sources->data[i];
     584        pmSource *thisSource = sources->data[i];
     585
     586        // this is the "real" version of this source
     587        pmSource *source = thisSource->parent ? thisSource->parent : thisSource;
    694588
    695589        // XXX if no model fits are saved, write out modelEXT?
     
    747641
    748642                if (k < model->params->n) {
    749                     psMetadataAdd (row, PS_LIST_TAIL, name, PS_DATA_F32, "", model->params->data.F32[k]);
     643                    psMetadataAddF32 (row, PS_LIST_TAIL, name, 0, "", model->params->data.F32[k]);
    750644                } else {
    751                     psMetadataAddF32 (row, PS_LIST_TAIL, name, PS_DATA_F32, "", NAN);
     645                    psMetadataAddF32 (row, PS_LIST_TAIL, name, 0, "", NAN);
    752646                }
    753647            }
    754648
    755             // XXX other parameters which may be set.
    756             // XXX flag / value to define the model
    757             // XXX write out the model type, fit status flags
    758 
     649            // optionally, write out the covariance matrix values
     650            // XXX do I need to pad this to match the biggest covar matrix?
     651            if (model->covar) {
     652                for (int iy = 0; iy < model->covar->numCols; iy++) {
     653                    for (int ix = iy; ix < model->covar->numCols; ix++) {
     654                        snprintf (name, 64, "EXT_COVAR_%02d_%02d", iy, ix);
     655                        psMetadataAddF32 (row, PS_LIST_TAIL, name, 0, "", model->covar->data.F32[iy][ix]);
     656
     657                    }
     658                }                   
     659            }
    759660            psArrayAdd (table, 100, row);
    760661            psFree (row);
     
    790691bool pmSourcesWrite_CMF_PS1_SV1_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe)
    791692{
    792 
     693    bool status = false;
    793694    psArray *table;
    794695    psMetadata *row;
     
    796697    char keyword1[80], keyword2[80];
    797698
     699    // perform full non-linear fits / extended source analysis?
     700    if (!psMetadataLookupBool (&status, recipe, "RADIAL_APERTURES")) {
     701        psLogMsg ("psphot", PS_LOG_INFO, "radial apertures were not measured, skipping\n");
     702        return true;
     703    }
     704
    798705    // create a header to hold the output data
    799706    psMetadata *outhead = psMetadataAlloc ();
     
    803710
    804711    // we use this just to define the output vectors (which must be present for all objects)
    805     bool status = false;
    806712    psVector *radMin = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER");
    807713    psVector *radMax = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER");
     
    818724    }
    819725
     726    // the FWHM values are available if we measured a psf-matched convolved set
    820727    psVector *fwhmValues = psMetadataLookupVector(&status, readout->analysis, "STACK.PSF.FWHM.VALUES");
    821     if (!fwhmValues) {
    822         psError (PM_ERR_CONFIG, true, "convolved or measured FWHM is not defined for this readout");
    823         return false;
    824     }
    825728
    826729    // let's write these out in S/N order
    827     sources = psArraySort (sources, pmSourceSortBySN);
     730    sources = psArraySort (sources, pmSourceSortByFlux);
    828731
    829732    table = psArrayAllocEmpty (sources->n);
     
    832735    for (int i = 0; i < sources->n; i++) {
    833736
    834         pmSource *source = sources->data[i];
     737        // this is the source associated with this image
     738        pmSource *thisSource = sources->data[i];
     739
     740        // this is the "real" version of this source
     741        pmSource *source = thisSource->parent ? thisSource->parent : thisSource;
    835742
    836743        // skip sources without radial aper measurements (or insufficient)
    837         if (source->radialAper == NULL) continue;
    838         psAssert (source->radialAper->n == fwhmValues->n, "inconsistent radial aperture set");
    839 
    840         for (int entry = 0; entry < fwhmValues->n; entry++) {
     744        if (source->radialAper == NULL) continue;
     745
     746        // psAssert (source->radialAper->n == fwhmValues->n, "inconsistent radial aperture set");
     747
     748        for (int entry = 0; entry < source->radialAper->n; entry++) {
    841749
    842750            // choose the convolved EXT model, if available, otherwise the simple one
     
    844752            assert (radialAper);
    845753
    846             bool useMoments = true;
    847             useMoments = (useMoments && source->moments);          // can't if there are no moments
    848             useMoments = (useMoments && source->moments->nPixels); // can't if the moments were not measured
    849             useMoments = (useMoments && !(source->mode && PM_SOURCE_MODE_MOMENTS_FAILURE)); // can't if the moments failed...
    850 
    851             if (useMoments) {
     754            if (pmSourcePositionUseMoments(source)) {
    852755                xPos = source->moments->Mx;
    853756                yPos = source->moments->My;
     
    863766            psMetadataAddF32 (row, PS_LIST_TAIL, "X_APER",           0, "Center of aperture measurements",            xPos);
    864767            psMetadataAddF32 (row, PS_LIST_TAIL, "Y_APER",           0, "Center of aperture measurements",            yPos);
    865             psMetadataAddF32 (row, PS_LIST_TAIL, "PSF_FWHM",         0, "FWHM of matched PSF",                        fwhmValues->data.F32[entry]);
     768            if (fwhmValues) {
     769                psMetadataAddF32 (row, PS_LIST_TAIL, "PSF_FWHM",         0, "FWHM of matched PSF",                    fwhmValues->data.F32[entry]);
     770            } else {
     771                psMetadataAddF32 (row, PS_LIST_TAIL, "PSF_FWHM",         0, "image is not FWHM-matched",              NAN);
     772            }
    866773
    867774            // XXX if we have raw radial apertures, write them out here
    868             psVector *radFlux    = psVectorAlloc(radMax->n, PS_TYPE_F32);
    869             psVector *radFluxErr = psVectorAlloc(radMax->n, PS_TYPE_F32);
    870             psVector *radFill    = psVectorAlloc(radMax->n, PS_TYPE_F32);
     775            psVector *radFlux      = psVectorAlloc(radMax->n, PS_TYPE_F32);
     776            psVector *radFluxErr   = psVectorAlloc(radMax->n, PS_TYPE_F32);
     777            psVector *radFill      = psVectorAlloc(radMax->n, PS_TYPE_F32);
     778            psVector *radFluxStdev = psVectorAlloc(radMax->n, PS_TYPE_F32);
    871779            psVectorInit (radFlux,    NAN);
    872780            psVectorInit (radFluxErr, NAN);
     
    879787            // copy the data from fluxVal (which is not guaranteed to be the full length) to radFlux
    880788            for (int j = 0; j < radialAper->flux->n; j++) {
    881                 radFlux->data.F32[j]    = radialAper->flux->data.F32[j];
    882                 radFluxErr->data.F32[j] = radialAper->fluxErr->data.F32[j];
    883                 radFill->data.F32[j]    = radialAper->fill->data.F32[j];
     789                radFlux->data.F32[j]      = radialAper->flux->data.F32[j];
     790                radFluxErr->data.F32[j]   = radialAper->fluxErr->data.F32[j];
     791                radFluxStdev->data.F32[j] = radialAper->fluxStdev->data.F32[j];
     792                radFill->data.F32[j]      = radialAper->fill->data.F32[j];
    884793            }
    885794
    886795        write_annuli:
    887             psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX",     PS_DATA_VECTOR, "flux within annuli",    radFlux);
    888             psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_ERR", PS_DATA_VECTOR, "flux error in annuli",  radFluxErr);
    889             psMetadataAdd (row, PS_LIST_TAIL, "APER_FILL",     PS_DATA_VECTOR, "fill factor of annuli", radFill);
     796            psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX",       PS_DATA_VECTOR, "flux within annuli",       radFlux);
     797            psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_ERR",   PS_DATA_VECTOR, "flux error in annuli",     radFluxErr);
     798            psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_STDEV", PS_DATA_VECTOR, "flux standard deviation",  radFluxStdev);
     799            psMetadataAdd (row, PS_LIST_TAIL, "APER_FILL",       PS_DATA_VECTOR, "fill factor of annuli",    radFill);
    890800            psFree (radFlux);
    891801            psFree (radFluxErr);
     802            psFree (radFluxStdev);
    892803            psFree (radFill);
    893804
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c

    r30621 r31153  
    4949
    5050#include "pmSourceIO.h"
     51#include "pmSourceOutputs.h"
    5152
    5253// panstarrs-style FITS table output (header + table in 1st extension)
     
    6263    psArray *table;
    6364    psMetadata *row;
    64     int i;
    65     psF32 *PAR, *dPAR;
    66     psEllipseAxes axes;
    67     psF32 xPos, yPos;
    68     psF32 xErr, yErr;
    69     psF32 errMag, chisq, apRadius;
    70     psS32 nPix, nDOF;
    7165
    7266    pmChip *chip = readout->parent->parent;
    73     pmFPA  *fpa  = chip->parent;
    74 
    75     bool status1 = false;
    76     bool status2 = false;
    77     float magOffset = NAN;
    78     float exptime   = psMetadataLookupF32 (&status1, fpa->concepts, "FPA.EXPOSURE");
    79     float zeropt    = psMetadataLookupF32(&status2, fpa->concepts, "FPA.ZP");
    80     if (!isfinite(zeropt)) {
    81         zeropt    = psMetadataLookupF32 (&status2, imageHeader, "ZPT_OBS");
    82     }
    83     if (status1 && status2 && (exptime > 0.0)) {
    84         magOffset = zeropt + 2.5*log10(exptime);
    85     }
    86     float zeroptErr = psMetadataLookupF32 (&status2, imageHeader, "ZPT_ERR");
    8767
    8868    // if the sequence is defined, write these in seq order; otherwise
     
    9272        if (source->seq == -1) {
    9373          // let's write these out in S/N order
    94           sources = psArraySort (sources, pmSourceSortBySN);
     74          sources = psArraySort (sources, pmSourceSortByFlux);
    9575        } else {
    9676          sources = psArraySort (sources, pmSourceSortBySeq);
     
    10080    table = psArrayAllocEmpty (sources->n);
    10181
     82    short nImageOverlap;
     83    float magOffset;
     84    float zeroptErr;
     85    float fwhmMajor;
     86    float fwhmMinor;
     87    pmSourceOutputsCommonValues (&nImageOverlap, &magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
     88
    10289    // we write out PSF-fits for all sources, regardless of quality.  the source flags tell us the state
    10390    // by the time we call this function, all values should be assigned.  let's use asserts to be sure in some cases.
    104     for (i = 0; i < sources->n; i++) {
     91    for (int i = 0; i < sources->n; i++) {
    10592        pmSource *source = (pmSource *) sources->data[i];
    10693
     
    113100        }
    114101
    115         // no difference between PSF and non-PSF model
    116         pmModel *model = source->modelPSF;
    117 
    118         if (model != NULL) {
    119             PAR = model->params->data.F32;
    120             dPAR = model->dparams->data.F32;
    121             xPos = PAR[PM_PAR_XPOS];
    122             yPos = PAR[PM_PAR_YPOS];
    123             if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) {
    124               xErr = dPAR[PM_PAR_XPOS];
    125               yErr = dPAR[PM_PAR_YPOS];
    126             } else {
    127               // in linear-fit mode, there is no error on the centroid
    128               xErr = source->peak->dx;
    129               yErr = source->peak->dy;
    130             }
    131             if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    132                 axes = pmPSF_ModelToAxes (PAR, 20.0);
    133             } else {
    134                 axes.major = NAN;
    135                 axes.minor = NAN;
    136                 axes.theta = NAN;
    137             }
    138             chisq = model->chisq;
    139             nDOF = model->nDOF;
    140             nPix = model->nPix;
    141             apRadius = source->apRadius;
    142             errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
    143         } else {
    144             xPos = source->peak->xf;
    145             yPos = source->peak->yf;
    146             xErr = source->peak->dx;
    147             yErr = source->peak->dy;
    148             axes.major = NAN;
    149             axes.minor = NAN;
    150             axes.theta = NAN;
    151             chisq = NAN;
    152             nDOF = 0;
    153             nPix = 0;
    154             apRadius = NAN;
    155             errMag = NAN;
    156         }
    157 
    158         float calMag = isfinite(magOffset) ? source->psfMag + magOffset : NAN;
    159         float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
    160         psS16 nImageOverlap = 1;
    161 
    162         psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
    163         float posAngle = 0.0;
    164         float pltScale = 0.0;
    165         pmSourceLocalAstrometry (&ptSky, &posAngle, &pltScale, chip, xPos, yPos);
     102        // set the 'best' values for various output fields:
     103        pmSourceOutputs outputs;
     104        pmSourceOutputsSetValues (&outputs, source, chip, fwhmMajor, fwhmMinor, magOffset);
     105
     106        pmSourceOutputsMoments moments;
     107        pmSourceOutputsSetMoments (&moments, source);
    166108
    167109        row = psMetadataAlloc ();
    168110        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             source->seq);
    169         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           xPos);
    170         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           yPos);
    171         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  xErr); // XXX this is only measured for non-linear fits
    172         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  yErr); // XXX this is only measured for non-linear fits
    173         psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F32, "PSF RA coordinate (degrees)",                ptSky.r*PS_DEG_RAD);
    174         psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F32, "PSF DEC coordinate (degrees)",               ptSky.d*PS_DEG_RAD);
    175         psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         posAngle*PS_DEG_RAD);
    176         psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       pltScale*PS_DEG_RAD*3600.0);
     111        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           outputs.xPos);
     112        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           outputs.yPos);
     113        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  outputs.xErr); // XXX this is only measured for non-linear fits
     114        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  outputs.yErr); // XXX this is only measured for non-linear fits
     115        psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F32, "PSF RA coordinate (degrees)",                outputs.ra);
     116        psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F32, "PSF DEC coordinate (degrees)",               outputs.dec);
     117        psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         outputs.posAngle);
     118        psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       outputs.pltScale);
    177119        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG",     PS_DATA_F32, "PSF fit instrumental magnitude",             source->psfMag);
    178         psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        errMag);
     120        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        source->errMag);
    179121        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG",           PS_DATA_F32, "magnitude in standard aperture",             source->apMag);
    180         psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              apRadius);
    181         psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           peakMag);
    182         psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   calMag);
     122        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              outputs.apRadius);
     123        psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           outputs.peakMag);
     124        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   outputs.calMag);
    183125        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_SIG",  PS_DATA_F32, "measured scatter of zero point calibration", zeroptErr);
    184126        psMetadataAdd (row, PS_LIST_TAIL, "SKY",              PS_DATA_F32, "Sky level",                                  source->sky);
    185127        psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA",        PS_DATA_F32, "Sigma of sky level",                         source->skyErr);
    186128
    187         psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           chisq);
     129        psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           outputs.chisq);
    188130        psMetadataAdd (row, PS_LIST_TAIL, "CR_NSIGMA",        PS_DATA_F32, "Nsigma deviations from PSF to CF",           source->crNsigma);
    189131        psMetadataAdd (row, PS_LIST_TAIL, "EXT_NSIGMA",       PS_DATA_F32, "Nsigma deviations from PSF to EXT",          source->extNsigma);
    190132
    191         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     axes.major);
    192         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    193         psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
     133        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     outputs.psfMajor);
     134        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     outputs.psfMinor);
     135        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      outputs.psfTheta);
    194136        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeightNotBad);
    195         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    196         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
    197 
    198         // distinguish moments measure from window vs S/N > XX ??
    199         float mxx = source->moments ? source->moments->Mxx : NAN;
    200         float mxy = source->moments ? source->moments->Mxy : NAN;
    201         float myy = source->moments ? source->moments->Myy : NAN;
    202         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      mxx);
    203         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      mxy);
    204         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      myy);
     137        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         outputs.nDOF);
     138        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    outputs.nPix);
     139
     140        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                       moments.Mxx);
     141        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                       moments.Mxy);
     142        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                       moments.Myy);
    205143
    206144        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                      source->mode);
     
    317255        // recreate the peak to match (xPos, yPos) +/- (xErr, yErr)
    318256        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    319         source->peak->flux = peakFlux;
     257        source->peak->rawFlux = peakFlux;
     258        source->peak->smoothFlux = peakFlux;
    320259        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
    321260        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    322261        source->peak->dx   = dPAR[PM_PAR_XPOS];
    323262        source->peak->dy   = dPAR[PM_PAR_YPOS];
    324         if (isfinite (source->errMag) && (source->errMag > 0.0)) {
    325           source->peak->SN = 1.0 / source->errMag;
    326         } else {
    327           source->peak->SN = sqrt(source->peak->flux); // an alternate proxy: various functions sort by peak S/N
    328         }
    329263
    330264        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
     
    339273
    340274        source->moments = pmMomentsAlloc ();
     275        source->moments->Mx = source->peak->xf; // we don't have both Mx,My and xf,yf in the cmf
     276        source->moments->My = source->peak->yf; // we don't have both Mx,My and xf,yf in the cmf
     277
    341278        source->moments->Mxx = psMetadataLookupF32 (&status, row, "MOMENTS_XX");
    342279        source->moments->Mxy = psMetadataLookupF32 (&status, row, "MOMENTS_XY");
     
    371308
    372309    // let's write these out in S/N order
    373     sources = psArraySort (sources, pmSourceSortBySN);
     310    sources = psArraySort (sources, pmSourceSortByFlux);
    374311
    375312    table = psArrayAllocEmpty (sources->n);
     
    549486
    550487    // let's write these out in S/N order
    551     sources = psArraySort (sources, pmSourceSortBySN);
     488    sources = psArraySort (sources, pmSourceSortByFlux);
    552489
    553490    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_V2.c

    r30621 r31153  
    4949
    5050#include "pmSourceIO.h"
     51#include "pmSourceOutputs.h"
    5152
    5253// panstarrs-style FITS table output (header + table in 1st extension)
     
    6263    psArray *table;
    6364    psMetadata *row;
    64     psF32 *PAR, *dPAR;
    65     psEllipseAxes axes;
    66     psF32 xPos, yPos;
    67     psF32 xErr, yErr;
    68     psF32 errMag, chisq, apRadius;
    69     psS32 nPix, nDOF;
    7065
    7166    pmChip *chip = readout->parent->parent;
    72     pmFPA  *fpa  = chip->parent;
    73 
    74     bool status1 = false;
    75     bool status2 = false;
    76     float magOffset = NAN;
    77     float exptime   = psMetadataLookupF32 (&status1, fpa->concepts, "FPA.EXPOSURE");
    78     float zeropt    = psMetadataLookupF32(&status2, fpa->concepts, "FPA.ZP");
    79     if (!isfinite(zeropt)) {
    80         zeropt    = psMetadataLookupF32 (&status2, imageHeader, "ZPT_OBS");
    81     }
    82     if (status1 && status2 && (exptime > 0.0)) {
    83         magOffset = zeropt + 2.5*log10(exptime);
    84     }
    85     float zeroptErr = psMetadataLookupF32 (&status2, imageHeader, "ZPT_ERR");
    8667
    8768    // if the sequence is defined, write these in seq order; otherwise
     
    9172        if (source->seq == -1) {
    9273            // let's write these out in S/N order
    93             sources = psArraySort (sources, pmSourceSortBySN);
     74            sources = psArraySort (sources, pmSourceSortByFlux);
    9475        } else {
    9576            sources = psArraySort (sources, pmSourceSortBySeq);
     
    9879
    9980    table = psArrayAllocEmpty (sources->n);
     81
     82    short nImageOverlap;
     83    float magOffset;
     84    float zeroptErr;
     85    float fwhmMajor;
     86    float fwhmMinor;
     87    pmSourceOutputsCommonValues (&nImageOverlap, &magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
    10088
    10189    // we write out PSF-fits for all sources, regardless of quality.  the source flags tell us the state
     
    112100        }
    113101
    114         // no difference between PSF and non-PSF model
    115         pmModel *model = source->modelPSF;
    116 
    117         if (model != NULL) {
    118             PAR = model->params->data.F32;
    119             dPAR = model->dparams->data.F32;
    120             xPos = PAR[PM_PAR_XPOS];
    121             yPos = PAR[PM_PAR_YPOS];
    122             if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) {
    123                 xErr = dPAR[PM_PAR_XPOS];
    124                 yErr = dPAR[PM_PAR_YPOS];
    125             } else {
    126                 // in linear-fit mode, there is no error on the centroid
    127                 xErr = source->peak->dx;
    128                 yErr = source->peak->dy;
    129             }
    130             if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    131                 axes = pmPSF_ModelToAxes (PAR, 20.0);
    132             } else {
    133                 axes.major = NAN;
    134                 axes.minor = NAN;
    135                 axes.theta = NAN;
    136             }
    137             chisq = model->chisq;
    138             nDOF = model->nDOF;
    139             nPix = model->nPix;
    140             apRadius = source->apRadius;
    141             errMag = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0];
    142         } else {
    143             xPos = source->peak->xf;
    144             yPos = source->peak->yf;
    145             xErr = source->peak->dx;
    146             yErr = source->peak->dy;
    147             axes.major = NAN;
    148             axes.minor = NAN;
    149             axes.theta = NAN;
    150             chisq = NAN;
    151             nDOF = 0;
    152             nPix = 0;
    153             apRadius = NAN;
    154             errMag = NAN;
    155         }
    156 
    157         float calMag = isfinite(magOffset) ? source->psfMag + magOffset : NAN;
    158         float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
    159         psS16 nImageOverlap = 1;
    160 
    161         psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
    162         float posAngle = 0.0;
    163         float pltScale = 0.0;
    164         pmSourceLocalAstrometry (&ptSky, &posAngle, &pltScale, chip, xPos, yPos);
     102        // set the 'best' values for various output fields:
     103        pmSourceOutputs outputs;
     104        pmSourceOutputsSetValues (&outputs, source, chip, fwhmMajor, fwhmMinor, magOffset);
     105
     106        pmSourceOutputsMoments moments;
     107        pmSourceOutputsSetMoments (&moments, source);
    165108
    166109        row = psMetadataAlloc ();
    167110        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             source->seq);
    168         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           xPos);
    169         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           yPos);
    170         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  xErr); // XXX this is only measured for non-linear fits
    171         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  yErr); // XXX this is only measured for non-linear fits
    172         psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         posAngle*PS_DEG_RAD);
    173         psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       pltScale*PS_DEG_RAD*3600.0);
     111        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           outputs.xPos);
     112        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           outputs.yPos);
     113        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  outputs.xErr); // XXX this is only measured for non-linear fits
     114        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  outputs.yErr); // XXX this is only measured for non-linear fits
     115        psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         outputs.posAngle);
     116        psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       outputs.pltScale);
    174117        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG",     PS_DATA_F32, "PSF fit instrumental magnitude",             source->psfMag);
    175         psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        errMag);
     118        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        source->errMag);
    176119        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG",           PS_DATA_F32, "magnitude in standard aperture",             source->apMag);
    177         psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              apRadius);
    178         psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           peakMag);
    179         psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   calMag);
     120        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              outputs.apRadius);
     121        psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           outputs.peakMag);
     122        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   outputs.calMag);
    180123        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_SIG",  PS_DATA_F32, "measured scatter of zero point calibration", zeroptErr);
    181         psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                ptSky.r*PS_DEG_RAD);
    182         psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               ptSky.d*PS_DEG_RAD);
     124        psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                outputs.ra);
     125        psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               outputs.dec);
    183126        psMetadataAdd (row, PS_LIST_TAIL, "SKY",              PS_DATA_F32, "Sky level",                                  source->sky);
    184127        psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA",        PS_DATA_F32, "Sigma of sky level",                         source->skyErr);
    185128
    186         psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           chisq);
     129        psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           outputs.chisq);
    187130        psMetadataAdd (row, PS_LIST_TAIL, "CR_NSIGMA",        PS_DATA_F32, "Nsigma deviations from PSF to CF",           source->crNsigma);
    188131        psMetadataAdd (row, PS_LIST_TAIL, "EXT_NSIGMA",       PS_DATA_F32, "Nsigma deviations from PSF to EXT",          source->extNsigma);
    189132
    190         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     axes.major);
    191         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    192         psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
     133        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     outputs.psfMajor);
     134        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     outputs.psfMinor);
     135        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      outputs.psfTheta);
    193136        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeightNotBad);
    194         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    195         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
    196 
    197         // distinguish moments measure from window vs S/N > XX ??
    198         float mxx = source->moments ? source->moments->Mxx : NAN;
    199         float mxy = source->moments ? source->moments->Mxy : NAN;
    200         float myy = source->moments ? source->moments->Myy : NAN;
    201         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      mxx);
    202         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      mxy);
    203         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      myy);
     137        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         outputs.nDOF);
     138        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    outputs.nPix);
     139
     140        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                       moments.Mxx);
     141        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                       moments.Mxy);
     142        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                       moments.Myy);
    204143
    205144        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                      source->mode);
     
    322261        // recreate the peak to match (xPos, yPos) +/- (xErr, yErr)
    323262        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    324         source->peak->flux = peakFlux;
     263        source->peak->rawFlux = peakFlux;
     264        source->peak->smoothFlux = peakFlux;
    325265        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
    326266        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    327267        source->peak->dx   = dPAR[PM_PAR_XPOS];
    328268        source->peak->dy   = dPAR[PM_PAR_YPOS];
    329         if (isfinite (source->errMag) && (source->errMag > 0.0)) {
    330           source->peak->SN = 1.0 / source->errMag;
    331         } else {
    332           source->peak->SN = sqrt(source->peak->flux); // an alternate proxy: various functions sort by peak S/N
    333         }
    334269
    335270        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
     
    344279
    345280        source->moments = pmMomentsAlloc ();
     281        source->moments->Mx = source->peak->xf; // we don't have both Mx,My and xf,yf in the cmf
     282        source->moments->My = source->peak->yf; // we don't have both Mx,My and xf,yf in the cmf
     283
    346284        source->moments->Mxx = psMetadataLookupF32 (&status, row, "MOMENTS_XX");
    347285        source->moments->Mxy = psMetadataLookupF32 (&status, row, "MOMENTS_XY");
     
    392330
    393331    // let's write these out in S/N order
    394     sources = psArraySort (sources, pmSourceSortBySN);
     332    sources = psArraySort (sources, pmSourceSortByFlux);
    395333
    396334    table = psArrayAllocEmpty (sources->n);
     
    611549
    612550    // let's write these out in S/N order
    613     sources = psArraySort (sources, pmSourceSortBySN);
     551    sources = psArraySort (sources, pmSourceSortByFlux);
    614552
    615553    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_V3.c

    r30621 r31153  
    4949
    5050#include "pmSourceIO.h"
     51#include "pmSourceOutputs.h"
    5152
    5253// panstarrs-style FITS table output (header + table in 1st extension)
     
    6263    psArray *table;
    6364    psMetadata *row;
    64     psF32 *PAR, *dPAR;
    65     psEllipseAxes axes;
    66     psF32 xPos, yPos;
    67     psF32 xErr, yErr;
    68     psF32 chisq, apRadius;
    69     psS32 nPix, nDOF;
    7065
    7166    pmChip *chip = readout->parent->parent;
    72     pmFPA  *fpa  = chip->parent;
    73 
    74     bool status1 = false;
    75     bool status2 = false;
    76     float magOffset = NAN;
    77     float exptime   = psMetadataLookupF32 (&status1, fpa->concepts, "FPA.EXPOSURE");
    78     float zeropt    = psMetadataLookupF32(&status2, fpa->concepts, "FPA.ZP");
    79     if (!isfinite(zeropt)) {
    80         zeropt    = psMetadataLookupF32 (&status2, imageHeader, "ZPT_OBS");
    81     }
    82     if (status1 && status2 && (exptime > 0.0)) {
    83         magOffset = zeropt + 2.5*log10(exptime);
    84     }
    85     float zeroptErr = psMetadataLookupF32 (&status2, imageHeader, "ZPT_ERR");
    86 
    87     // we need a measure of the image quality (FWHM) for this image, in order to get the positional errors
    88     float fwhmMajor = psMetadataLookupF32(&status1, readout->analysis, "FWHM_MAJ");
    89     if (!status1) {
    90         fwhmMajor = psMetadataLookupF32(&status1, readout->analysis, "IQ_FW1");
    91         if (!status1) {
    92             fwhmMajor = 5.0; // XXX just a guess!
    93         }
    94     }
    95     float fwhmMinor = psMetadataLookupF32(&status1, readout->analysis, "FWHM_MIN");
    96     if (!status1) {
    97         fwhmMinor = psMetadataLookupF32(&status1, readout->analysis, "IQ_FW2");
    98         if (!status1) {
    99             fwhmMinor = 5.0; // XXX just a guess!
    100         }
    101     }
    10267
    10368    // if the sequence is defined, write these in seq order; otherwise
     
    10772        if (source->seq == -1) {
    10873            // let's write these out in S/N order
    109             sources = psArraySort (sources, pmSourceSortBySN);
     74            sources = psArraySort (sources, pmSourceSortByFlux);
    11075        } else {
    11176            sources = psArraySort (sources, pmSourceSortBySeq);
     
    11479
    11580    table = psArrayAllocEmpty (sources->n);
     81
     82    short nImageOverlap;
     83    float magOffset;
     84    float zeroptErr;
     85    float fwhmMajor;
     86    float fwhmMinor;
     87    pmSourceOutputsCommonValues (&nImageOverlap, &magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
    11688
    11789    // we write out PSF-fits for all sources, regardless of quality.  the source flags tell us the state
     
    128100        }
    129101
    130         // no difference between PSF and non-PSF model
    131         pmModel *model = source->modelPSF;
    132 
    133         if (model != NULL) {
    134             PAR = model->params->data.F32;
    135             dPAR = model->dparams->data.F32;
    136             xPos = PAR[PM_PAR_XPOS];
    137             yPos = PAR[PM_PAR_YPOS];
    138             if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) {
    139                 xErr = dPAR[PM_PAR_XPOS];
    140                 yErr = dPAR[PM_PAR_YPOS];
    141             } else {
    142                 xErr = fwhmMajor * source->errMag / 2.35;
    143                 yErr = fwhmMinor * source->errMag / 2.35;
    144             }
    145             if (isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX]) && isfinite(PAR[PM_PAR_SXX])) {
    146                 axes = pmPSF_ModelToAxes (PAR, 20.0);
    147             } else {
    148                 axes.major = NAN;
    149                 axes.minor = NAN;
    150                 axes.theta = NAN;
    151             }
    152             chisq = model->chisq;
    153             nDOF = model->nDOF;
    154             nPix = model->nPix;
    155             apRadius = source->apRadius;
    156         } else {
    157             bool useMoments = true;
    158             useMoments = (useMoments && source->moments);          // can't if there are no moments
    159             useMoments = (useMoments && source->moments->nPixels); // can't if the moments were not measured
    160             useMoments = (useMoments && !(source->mode && PM_SOURCE_MODE_MOMENTS_FAILURE)); // can't if the moments failed...
    161 
    162             if (useMoments) {
    163                 xPos = source->moments->Mx;
    164                 yPos = source->moments->My;
    165                 xErr = fwhmMajor * source->errMag / 2.35;
    166                 yErr = fwhmMinor * source->errMag / 2.35;
    167             } else {
    168                 xPos = source->peak->xf;
    169                 yPos = source->peak->yf;
    170                 xErr = source->peak->dx;
    171                 yErr = source->peak->dy;
    172             }
    173             axes.major = NAN;
    174             axes.minor = NAN;
    175             axes.theta = NAN;
    176             chisq = NAN;
    177             nDOF = 0;
    178             nPix = 0;
    179             apRadius = NAN;
    180         }
    181 
    182         float calMag = isfinite(magOffset) ? source->psfMag + magOffset : NAN;
    183         float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
    184         psS16 nImageOverlap = 1;
    185 
    186         psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
    187         float posAngle = 0.0;
    188         float pltScale = 0.0;
    189         pmSourceLocalAstrometry (&ptSky, &posAngle, &pltScale, chip, xPos, yPos);
     102        // set the 'best' values for various output fields:
     103        pmSourceOutputs outputs;
     104        pmSourceOutputsSetValues (&outputs, source, chip, fwhmMajor, fwhmMinor, magOffset);
     105
     106        pmSourceOutputsMoments moments;
     107        pmSourceOutputsSetMoments (&moments, source);
    190108
    191109        row = psMetadataAlloc ();
    192110        psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET",         PS_DATA_U32, "IPP detection identifier index",             source->seq);
    193         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           xPos);
    194         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           yPos);
    195         psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  xErr);
    196         psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  yErr);
    197         psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         posAngle*PS_DEG_RAD);
    198         psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       pltScale*PS_DEG_RAD*3600.0);
     111        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF",            PS_DATA_F32, "PSF x coordinate",                           outputs.xPos);
     112        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF",            PS_DATA_F32, "PSF y coordinate",                           outputs.yPos);
     113        psMetadataAdd (row, PS_LIST_TAIL, "X_PSF_SIG",        PS_DATA_F32, "Sigma in PSF x coordinate",                  outputs.xErr);
     114        psMetadataAdd (row, PS_LIST_TAIL, "Y_PSF_SIG",        PS_DATA_F32, "Sigma in PSF y coordinate",                  outputs.yErr);
     115        psMetadataAdd (row, PS_LIST_TAIL, "POSANGLE",         PS_DATA_F32, "position angle at source (degrees)",         outputs.posAngle);
     116        psMetadataAdd (row, PS_LIST_TAIL, "PLTSCALE",         PS_DATA_F32, "plate scale at source (arcsec/pixel)",       outputs.pltScale);
    199117        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG",     PS_DATA_F32, "PSF fit instrumental magnitude",             source->psfMag);
    200118        psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_MAG_SIG", PS_DATA_F32, "Sigma of PSF instrumental magnitude",        source->errMag);
     
    203121        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG",           PS_DATA_F32, "magnitude in standard aperture",             source->apMag);
    204122        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RAW",       PS_DATA_F32, "magnitude in reported aperture",             source->apMagRaw);
    205         psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              apRadius);
    206 
    207         psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   calMag);
     123        psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS",    PS_DATA_F32, "radius used for aperture mags",              outputs.apRadius);
     124
     125        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG",      PS_DATA_F32, "PSF Magnitude using supplied calibration",   outputs.calMag);
    208126        psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_SIG",  PS_DATA_F32, "measured scatter of zero point calibration", zeroptErr);
    209127       
    210128        // NOTE: RA & DEC (both double) need to be on an 8-byte boundary...
    211         psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                ptSky.r*PS_DEG_RAD);
    212         psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               ptSky.d*PS_DEG_RAD);
    213 
    214         psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           peakMag);
     129        psMetadataAdd (row, PS_LIST_TAIL, "RA_PSF",           PS_DATA_F64, "PSF RA coordinate (degrees)",                outputs.ra);
     130        psMetadataAdd (row, PS_LIST_TAIL, "DEC_PSF",          PS_DATA_F64, "PSF DEC coordinate (degrees)",               outputs.dec);
     131
     132        psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude",           outputs.peakMag);
    215133        psMetadataAdd (row, PS_LIST_TAIL, "SKY",              PS_DATA_F32, "Sky level",                                  source->sky);
    216134        psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA",        PS_DATA_F32, "Sigma of sky level",                         source->skyErr);
    217135
    218         psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           chisq);
     136        psMetadataAdd (row, PS_LIST_TAIL, "PSF_CHISQ",        PS_DATA_F32, "Chisq of PSF-fit",                           outputs.chisq);
    219137        psMetadataAdd (row, PS_LIST_TAIL, "CR_NSIGMA",        PS_DATA_F32, "Nsigma deviations from PSF to CF",           source->crNsigma);
    220138        psMetadataAdd (row, PS_LIST_TAIL, "EXT_NSIGMA",       PS_DATA_F32, "Nsigma deviations from PSF to EXT",          source->extNsigma);
    221139
    222         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     axes.major);
    223         psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    224         psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
     140        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MAJOR",        PS_DATA_F32, "PSF width (major axis)",                     outputs.psfMajor);
     141        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     outputs.psfMinor);
     142        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      outputs.psfTheta);
    225143        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor (bad)",          source->pixWeightNotBad);
    226144        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF_PERFECT",   PS_DATA_F32, "PSF coverage/quality factor (poor)",         source->pixWeightNotPoor);
    227         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    228         psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
    229 
    230         // distinguish moments measure from window vs S/N > XX ??
    231         float Mxx = source->moments ? source->moments->Mxx : NAN;
    232         float Mxy = source->moments ? source->moments->Mxy : NAN;
    233         float Myy = source->moments ? source->moments->Myy : NAN;
    234 
    235         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      Mxx);
    236         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      Mxy);
    237         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      Myy);
    238 
    239         float M_c3 = source->moments ? 1.0*source->moments->Mxxx - 3.0*source->moments->Mxyy : NAN;
    240         float M_s3 = source->moments ? 3.0*source->moments->Mxxy - 1.0*source->moments->Myyy : NAN;
    241         float M_c4 = source->moments ? 1.0*source->moments->Mxxxx - 6.0*source->moments->Mxxyy + 1.0*source->moments->Myyyy : NAN;
    242         float M_s4 = source->moments ? 4.0*source->moments->Mxxxy - 4.0*source->moments->Mxyyy : NAN;
    243 
    244         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3C",      PS_DATA_F32, "third momemt cos theta",                    M_c3);
    245         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3S",      PS_DATA_F32, "third momemt sin theta",                    M_s3);
    246         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4C",      PS_DATA_F32, "fourth momemt cos theta",                   M_c4);
    247         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4S",      PS_DATA_F32, "fourth momemt sin theta",                   M_s4);
    248 
    249         float Mrf  = source->moments ? source->moments->Mrf : NAN;
    250         float Mrh  = source->moments ? source->moments->Mrh : NAN;
    251         float Krf  = source->moments ? source->moments->KronFlux : NAN;
    252         float dKrf = source->moments ? source->moments->KronFluxErr : NAN;
    253 
    254         float Kinner = source->moments ? source->moments->KronFinner : NAN;
    255         float Kouter = source->moments ? source->moments->KronFouter : NAN;
    256 
    257         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                       Mrf);
    258         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH",       PS_DATA_F32, "half radial moment",                        Mrh);
    259         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX",        PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Krf);
    260         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR",    PS_DATA_F32, "Kron Flux Error",                          dKrf);
    261 
    262         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Kinner);
    263         psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Kouter);
    264 
    265         psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                     source->mode);
    266         psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2",           PS_DATA_U32, "psphot analysis flags",                     source->mode2);
     145        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         outputs.nDOF);
     146        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    outputs.nPix);
     147
     148        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                       moments.Mxx);
     149        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                       moments.Mxy);
     150        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                       moments.Myy);
     151
     152        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3C",      PS_DATA_F32, "third momemt cos theta",                     moments.M_c3);
     153        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3S",      PS_DATA_F32, "third momemt sin theta",                     moments.M_s3);
     154        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4C",      PS_DATA_F32, "fourth momemt cos theta",                    moments.M_c4);
     155        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4S",      PS_DATA_F32, "fourth momemt sin theta",                    moments.M_s4);
     156
     157        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                        moments.Mrf);
     158        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH",       PS_DATA_F32, "half radial moment",                         moments.Mrh);
     159        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX",        PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Krf);
     160        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR",    PS_DATA_F32, "Kron Flux Error",                            moments.dKrf);
     161        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Kinner);
     162        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                      moments.Kouter);
     163        // psMetadataAdd (row, PS_LIST_TAIL, "KRON_CORE_FLUX",   PS_DATA_F32, "Kron Flux (in 1.0 R1)",                      moments.KronCore);
     164        // psMetadataAdd (row, PS_LIST_TAIL, "KRON_CORE_ERROR",  PS_DATA_F32, "Kron Error (in 1.0 R1)",                     moments.KronCoreErr);
     165        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                      source->mode);
     166        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2",           PS_DATA_U32, "psphot analysis flags",                      source->mode2);
    267167        psMetadataAdd (row, PS_LIST_TAIL, "PADDING2",         PS_DATA_S32, "more padding", 0);
    268168
     
    384284        // recreate the peak to match (xPos, yPos) +/- (xErr, yErr)
    385285        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    386         source->peak->flux = peakFlux;
     286        source->peak->rawFlux = peakFlux;
     287        source->peak->smoothFlux = peakFlux;
    387288        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
    388289        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    389290        source->peak->dx   = dPAR[PM_PAR_XPOS];
    390291        source->peak->dy   = dPAR[PM_PAR_YPOS];
    391         if (isfinite (source->errMag) && (source->errMag > 0.0)) {
    392           source->peak->SN = 1.0 / source->errMag;
    393         } else {
    394           source->peak->SN = sqrt(source->peak->flux); // an alternate proxy: various functions sort by peak S/N
    395         }
     292
     293        // we no longer sort by S/N, only flux
     294        // if (isfinite (source->errMag) && (source->errMag > 0.0)) {
     295        //   source->peak->SN = 1.0 / source->errMag;
     296        // } else {
     297        //   source->peak->SN = sqrt(source->peak->flux); // an alternate proxy: various functions sort by peak S/N
     298        // }
    396299
    397300        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
     
    407310
    408311        source->moments = pmMomentsAlloc ();
     312        source->moments->Mx = source->peak->xf; // we don't have both Mx,My and xf,yf in the cmf
     313        source->moments->My = source->peak->yf; // we don't have both Mx,My and xf,yf in the cmf
     314
    409315        source->moments->Mxx = psMetadataLookupF32 (&status, row, "MOMENTS_XX");
    410316        source->moments->Mxy = psMetadataLookupF32 (&status, row, "MOMENTS_XY");
     
    477383
    478384    // let's write these out in S/N order
    479     sources = psArraySort (sources, pmSourceSortBySN);
     385    sources = psArraySort (sources, pmSourceSortByFlux);
    480386
    481387    table = psArrayAllocEmpty (sources->n);
     
    649555
    650556    // let's write these out in S/N order
    651     sources = psArraySort (sources, pmSourceSortBySN);
     557    sources = psArraySort (sources, pmSourceSortByFlux);
    652558
    653559    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
  • trunk/psModules/src/objects/pmSourceIO_PS1_CAL_0.c

    r30621 r31153  
    9191
    9292    // let's write these out in S/N order
    93     sources = psArraySort (sources, pmSourceSortBySN);
     93    sources = psArraySort (sources, pmSourceSortByFlux);
    9494
    9595    table = psArrayAllocEmpty (sources->n);
     
    136136
    137137        float calMag = source->psfMag + magOffset;
    138         float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
     138        float peakMag = (source->peak->rawFlux > 0) ? -2.5*log10(source->peak->rawFlux) : NAN;
    139139        psS16 nImageOverlap = 1;
    140140
     
    294294
    295295        source->peak       = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    296         source->peak->flux = peakFlux;
     296        source->peak->rawFlux = peakFlux;
     297        source->peak->smoothFlux = peakFlux;
    297298        source->peak->dx   = dPAR[PM_PAR_XPOS];
    298299        source->peak->dy   = dPAR[PM_PAR_YPOS];
     
    357358
    358359    // let's write these out in S/N order
    359     sources = psArraySort (sources, pmSourceSortBySN);
     360    sources = psArraySort (sources, pmSourceSortByFlux);
    360361
    361362    table = psArrayAllocEmpty (sources->n);
     
    576577
    577578    // let's write these out in S/N order
    578     sources = psArraySort (sources, pmSourceSortBySN);
     579    sources = psArraySort (sources, pmSourceSortByFlux);
    579580
    580581    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
  • trunk/psModules/src/objects/pmSourceIO_PS1_DEV_0.c

    r30621 r31153  
    101101        }
    102102
    103         float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
     103        float peakMag = (source->peak->rawFlux > 0) ? -2.5*log10(source->peak->rawFlux) : NAN;
    104104        psS16 nImageOverlap = 1;
    105105        psS32 ID = 0; // XXX need to figure out how to generate this
     
    220220
    221221        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    222         source->peak->flux = peakFlux;
     222        source->peak->rawFlux = peakFlux;
     223        source->peak->smoothFlux = peakFlux;
    223224        source->peak->dx   = dPAR[PM_PAR_XPOS];
    224225        source->peak->dy   = dPAR[PM_PAR_YPOS];
  • trunk/psModules/src/objects/pmSourceIO_PS1_DEV_1.c

    r30621 r31153  
    7373
    7474    // let's write these out in S/N order
    75     sources = psArraySort (sources, pmSourceSortBySN);
     75    sources = psArraySort (sources, pmSourceSortByFlux);
    7676
    7777    table = psArrayAllocEmpty (sources->n);
     
    117117        }
    118118
    119         float peakMag = (source->peak->flux > 0) ? -2.5*log10(source->peak->flux) : NAN;
     119        float peakMag = (source->peak->rawFlux > 0) ? -2.5*log10(source->peak->rawFlux) : NAN;
    120120        psS16 nImageOverlap = 1;
    121121
     
    263263
    264264        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    265         source->peak->flux = peakFlux;
     265        source->peak->rawFlux = peakFlux;
     266        source->peak->smoothFlux = peakFlux;
    266267        source->peak->dx   = dPAR[PM_PAR_XPOS];
    267268        source->peak->dy   = dPAR[PM_PAR_YPOS];
     
    307308
    308309    // let's write these out in S/N order
    309     sources = psArraySort (sources, pmSourceSortBySN);
     310    sources = psArraySort (sources, pmSourceSortByFlux);
    310311
    311312    table = psArrayAllocEmpty (sources->n);
     
    480481
    481482    // let's write these out in S/N order
    482     sources = psArraySort (sources, pmSourceSortBySN);
     483    sources = psArraySort (sources, pmSourceSortByFlux);
    483484
    484485    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
  • trunk/psModules/src/objects/pmSourceIO_RAW.c

    r29004 r31153  
    126126                 source[0].apMag, source[0].type, source[0].mode,
    127127                 logChi, logChiNorm,
    128                  source[0].peak->SN,
     128                 source[0].peak->rawFlux,
    129129                 source[0].apRadius,
    130130                 source[0].pixWeightNotBad,
     
    188188                 log10(model[0].chisq/model[0].nDOF),
    189189                 log10(model[0].chisqNorm/model[0].nDOF),
    190                  source[0].peak->SN,
     190                 source[0].peak->rawFlux,
    191191                 source[0].apRadius,
    192192                 source[0].pixWeightNotBad,
     
    234234
    235235        fprintf (f, "%5d %5d  %7.1f  %7.1f %7.1f  %6.3f %6.3f  %8.1f %7.1f %7.1f %7.1f  %4d %2d\n",
    236                  source->peak->x, source->peak->y, source->peak->value,
     236                 source->peak->x, source->peak->y, source->peak->detValue,
    237237                 moment->Mx, moment->My,
    238238                 moment->Mxx, moment->Myy,
     
    270270            continue;
    271271        fprintf (f, "%5d %5d  %8.1f  %7.1f %7.1f  %6.3f %6.3f  %10.1f %7.1f %7.1f %7.1f  %4d %2d %#5x\n",
    272                  source->peak->x, source->peak->y, source->peak->value,
     272                 source->peak->x, source->peak->y, source->peak->detValue,
    273273                 source->moments->Mx, source->moments->My,
    274274                 source->moments->Mxx, source->moments->Myy,
     
    299299            continue;
    300300        fprintf (f, "%5d %5d  %7.1f %7.2f %7.2f %7.2f\n",
    301                  peak->x, peak->y, peak->value, peak->SN, peak->xf, peak->yf);
    302     }
    303     fclose (f);
    304     return true;
    305 }
    306 
     301                 peak->x, peak->y, peak->detValue, peak->rawFlux, peak->xf, peak->yf);
     302    }
     303    fclose (f);
     304    return true;
     305}
     306
  • trunk/psModules/src/objects/pmSourceIO_SMPDATA.c

    r30621 r31153  
    205205
    206206        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    207         source->peak->flux = peakFlux;
    208207
    209208        sources->data[i] = source;
  • trunk/psModules/src/objects/pmSourceMasks.h

    r29546 r31153  
    4646    PM_SOURCE_MODE2_DIFF_WITH_DOUBLE = 0x00000002, ///< diff source matched to positive detections in both images
    4747    PM_SOURCE_MODE2_MATCHED          = 0x00000004, ///< diff source matched to positive detections in both images
     48
     49    PM_SOURCE_MODE2_ON_SPIKE         = 0x00000008, ///< > 25% of (PSF-weighted) pixels land on diffraction spike
     50    PM_SOURCE_MODE2_ON_STARCORE      = 0x00000010, ///< > 25% of (PSF-weighted) pixels land on starcore
     51    PM_SOURCE_MODE2_ON_BURNTOOL      = 0x00000020, ///< > 25% of (PSF-weighted) pixels land on burntool
     52    PM_SOURCE_MODE2_ON_CONVPOOR      = 0x00000040, ///< > 25% of (PSF-weighted) pixels land on convpoor
    4853} pmSourceMode2;
    4954
  • trunk/psModules/src/objects/pmSourceMoments.c

    r29602 r31153  
    8282    psF32 Sum = 0.0;
    8383    psF32 Var = 0.0;
     84    psF32 SumCore = 0.0;
     85    psF32 VarCore = 0.0;
    8486    psF32 R2 = PS_SQR(radius);
    8587    psF32 minSN2 = PS_SQR(minSN);
     
    248250
    249251    int nKronPix = 0;
     252    int nCorePix = 0;
     253    int nInner = 0;
     254    int nOuter = 0;
    250255    Sum = Var = 0.0;
    251256    float SumInner = 0.0;
     
    255260
    256261        psF32 yDiff = row - yCM;
    257         if (fabs(yDiff) > radKron) continue;
     262        if (fabs(yDiff) > radKouter) continue;
    258263
    259264        psF32 *vPix = source->pixels->data.F32[row];
     
    272277
    273278            psF32 xDiff = col - xCM;
    274             if (fabs(xDiff) > radKron) continue;
     279            if (fabs(xDiff) > radKouter) continue;
    275280
    276281            // radKron is just a function of (xDiff, yDiff)
     
    293298            }
    294299
     300            // use sigma (fixed by psf) not a radKron based value
     301            if (r < sigma) {
     302                SumCore += pDiff;
     303                VarCore += wDiff;
     304                nCorePix ++;
     305            }
     306
    295307            if ((r > radKinner) && (r < radKron)) {
    296308                SumInner += pDiff;
     309                nInner ++;
    297310            }
    298311            if ((r > radKron)  && (r < radKouter)) {
    299312                SumOuter += pDiff;
     313                nOuter ++;
    300314            }
    301315        }
    302316    }
    303     source->moments->KronFlux = Sum;
    304     source->moments->KronFinner = SumInner;
    305     source->moments->KronFouter = SumOuter;
    306     source->moments->KronFluxErr = sqrt(Var);
     317    // *** should I rescale these fluxes by pi R^2 / nNpix?
     318    source->moments->KronCore    = SumCore       * M_PI * PS_SQR(sigma) / nCorePix;
     319    source->moments->KronCoreErr = sqrt(VarCore) * M_PI * PS_SQR(sigma) / nCorePix;
     320    source->moments->KronFlux    = Sum       * M_PI * PS_SQR(radKron) / nKronPix;
     321    source->moments->KronFluxErr = sqrt(Var) * M_PI * PS_SQR(radKron) / nKronPix;
     322    source->moments->KronFinner = SumInner * M_PI * (PS_SQR(radKron)   - PS_SQR(radKinner)) / nInner;
     323    source->moments->KronFouter = SumOuter * M_PI * (PS_SQR(radKouter) -   PS_SQR(radKron)) / nOuter;
    307324
    308325    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",
     
    313330
    314331    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",
    315              source->peak->xf, source->peak->yf, source->peak->flux, source->peak->SN, source->moments->Mx,   source->moments->My, Sum, source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy, sky, source->moments->nPixels);
     332             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);
    316333
    317334    return(true);
  • trunk/psModules/src/objects/pmSourcePhotometry.c

    r29935 r31153  
    2323#include "pmFPAMaskWeight.h"
    2424
     25#include "pmConfigMask.h"
    2526#include "pmTrend2D.h"
    2627#include "pmResiduals.h"
     
    4950static float AP_MIN_SN = 0.0;
    5051
    51 bool pmSourceMagnitudesInit (psMetadata *config)
    52 {
    53     PS_ASSERT_PTR_NON_NULL(config, false);
     52// make this a bit more clever and dynamic
     53static psImageMaskType maskSuspect  = 0;
     54static psImageMaskType maskSpike    = 0;
     55static psImageMaskType maskStarCore = 0;
     56static psImageMaskType maskBurntool = 0;
     57static psImageMaskType maskConvPoor = 0;
     58
     59bool pmSourceMagnitudesInit (pmConfig *config, psMetadata *recipe)
     60{
     61    PS_ASSERT_PTR_NON_NULL(recipe, false);
    5462    bool status;
    5563
    56     float limit = psMetadataLookupF32 (&status, config, "AP_MIN_SN");
     64    // we are going to test specially against these poor values
     65    if (config) {
     66        maskSpike    = pmConfigMaskGet("SPIKE", config);
     67        maskStarCore = pmConfigMaskGet("STARCORE", config);
     68        maskBurntool = pmConfigMaskGet("BURNTOOL", config);
     69        maskConvPoor = pmConfigMaskGet("CONV.POOR", config);
     70        maskSuspect  = maskSpike | maskStarCore | maskBurntool | maskConvPoor;
     71    }
     72
     73    float limit = psMetadataLookupF32 (&status, recipe, "AP_MIN_SN");
    5774    if (status) {
    5875        AP_MIN_SN = limit;
     
    7794// XXX masked region should be (optionally) elliptical
    7895// if mode is PM_SOURCE_PHOT_PSFONLY, we skip all other magnitudes
    79 bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psImageMaskType maskVal, psImageMaskType markVal)
     96bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psImageMaskType maskVal, psImageMaskType markVal, float radius)
    8097{
    8198    PS_ASSERT_PTR_NON_NULL(source, false);
     
    166183    // measure the contribution of included pixels
    167184    if (mode & PM_SOURCE_PHOT_WEIGHT) {
    168         pmSourcePixelWeight (&source->pixWeightNotBad, &source->pixWeightNotPoor, model, source->maskObj, maskVal, markVal);
     185        pmSourcePixelWeight (source, model, source->maskObj, maskVal, radius);
    169186    }
    170187
     
    342359
    343360// return source aperture magnitude
    344 bool pmSourcePixelWeight (float *pixWeightNotBad, float *pixWeightNotPoor, pmModel *model, psImage *mask, psImageMaskType maskVal, psImageMaskType markVal)
    345 {
    346     PS_ASSERT_PTR_NON_NULL(pixWeightNotBad, false);
    347     PS_ASSERT_PTR_NON_NULL(pixWeightNotPoor, false);
     361bool pmSourcePixelWeight (pmSource *source, pmModel *model, psImage *mask, psImageMaskType maskVal, float radius)
     362{
     363    PS_ASSERT_PTR_NON_NULL(source, false);
     364    source->pixWeightNotBad = NAN;
     365    source->pixWeightNotPoor = NAN;
     366
    348367    PS_ASSERT_PTR_NON_NULL(mask, false);
    349368    PS_ASSERT_PTR_NON_NULL(model, false);
     
    355374    float value;
    356375
     376    float spikeSum = 0;
     377    float starcoreSum = 0;
     378    float burntoolSum = 0;
     379    float convpoorSum = 0;
     380
    357381    int Xo, Yo, dP;
    358382    int dX, DX, NX;
    359383    int dY, DY, NY;
    360384
    361     *pixWeightNotBad = 0.0;
    362     *pixWeightNotPoor = 0.0;
     385    float radius2 = PS_SQR(radius);
    363386
    364387    // we only care about the value of the object model, not the local sky
     
    387410    NY = mask->numRows;
    388411
     412    psImageMaskType maskBad = maskVal;
     413    maskBad &= ~maskSuspect;
     414
    389415    // measure modelSum and validSum.  this function is applied to a sources' subimage.  the
    390416    // value of DX is chosen (see above) to cover the full possible size of the subimage if it
    391417    // were not by an edge; ie, if the source is cut in half by an image edge, we correctly
    392418    // count the virtual pixels off the edge in normalizing the value of the pixWeight
     419
     420    // we skip any pixels [real or virtual] outside of the specified radius (nominally the aperture radius)
    393421    for (int ix = -DX; ix < DX + 1; ix++) {
     422        if (ix > radius) continue;
    394423        int mx = ix + dX;
    395424        for (int iy = -DY; iy < DY + 1; iy++) {
     425            if (iy > radius) continue;
     426            if (ix*ix + iy*iy > radius2) continue;
    396427            int my = iy + dY;
    397428
     
    409440            if (my >= NY) continue;
    410441
    411             if (!(mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & maskVal)) {
     442            // count pixels which are masked only with bad pixels
     443            if (!(mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & maskBad)) {
    412444                notBadSum += value;
    413445            }
    414             if (!(mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & ~markVal)) {
     446
     447            // count pixels which are masked with an mask bit (bad or poor)
     448            if (!(mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & maskVal)) {
    415449                notPoorSum += value;
    416450            }
     451
     452            // count pixels which are masked with an mask bit (bad or poor)
     453            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & maskSpike) {
     454                spikeSum += value;
     455            }
     456            // count pixels which are masked with an mask bit (bad or poor)
     457            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & maskStarCore) {
     458                starcoreSum += value;
     459            }
     460            // count pixels which are masked with an mask bit (bad or poor)
     461            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & maskBurntool) {
     462                burntoolSum += value;
     463            }
     464            // count pixels which are masked with an mask bit (bad or poor)
     465            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & maskConvPoor) {
     466                convpoorSum += value;
     467            }
    417468        }
    418469    }
    419470    psFree (coord);
    420471
    421     *pixWeightNotBad  = notBadSum  / modelSum;
    422     *pixWeightNotPoor = notPoorSum / modelSum;
     472    source->pixWeightNotBad  = notBadSum  / modelSum;
     473    source->pixWeightNotPoor = notPoorSum / modelSum;
     474
     475    if ((spikeSum/modelSum) > 0.25) {
     476        source->mode2 |= PM_SOURCE_MODE2_ON_SPIKE;
     477    }
     478    if ((starcoreSum/modelSum) > 0.25) {
     479        source->mode2 |= PM_SOURCE_MODE2_ON_STARCORE;
     480    }
     481    if ((burntoolSum/modelSum) > 0.25) {
     482        source->mode2 |= PM_SOURCE_MODE2_ON_BURNTOOL;
     483    }
     484    if ((convpoorSum/modelSum) > 0.25) {
     485        source->mode2 |= PM_SOURCE_MODE2_ON_CONVPOOR;
     486    }
     487
     488    if (isfinite(source->pixWeightNotBad) && isfinite(source->pixWeightNotPoor)) {
     489        psAssert (source->pixWeightNotBad <= source->pixWeightNotPoor, "error: all bad pixels should also be poor");
     490    }
    423491
    424492    return (true);
     
    427495# define FLUX_LIMIT 3.0
    428496
    429 // measure stats that may be using in difference images for distinguishing real sources from bad residuals
     497// measure stats that may be used in difference images for distinguishing real sources from bad residuals
    430498bool pmSourceMeasureDiffStats (pmSource *source, psImageMaskType maskVal, psImageMaskType markVal)
    431499{
     
    673741# endif
    674742
    675 // determine chisq, etc for linear normalization-only fit
    676 bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *variance, psImageMaskType maskVal, const float covarFactor)
     743// determine chisq, nPix, nDOF, chisqNorm : model->nPar must be set
     744bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *variance, psImageMaskType maskVal)
    677745{
    678746    PS_ASSERT_PTR_NON_NULL(model, false);
     
    689757            if (variance->data.F32[j][i] <= 0)
    690758                continue;
    691             dC += PS_SQR (image->data.F32[j][i]) / (covarFactor * variance->data.F32[j][i]);
     759            dC += PS_SQR (image->data.F32[j][i]) / variance->data.F32[j][i];
    692760            Npix ++;
    693761        }
    694762    }
    695763    model->nPix = Npix;
    696     model->nDOF = Npix - 1;
     764    model->nDOF = Npix - model->nPar;
    697765    model->chisq = dC;
     766    model->chisqNorm = dC / model->nDOF;
    698767
    699768    return (true);
    700769}
    701770
     771
     772// return source aperture magnitude
     773bool pmSourceChisqUnsubtracted (pmSource *source, pmModel *model, psImageMaskType maskVal)
     774{
     775    PS_ASSERT_PTR_NON_NULL(source, false);
     776    PS_ASSERT_PTR_NON_NULL(model, false);
     777
     778    float dC = 0.0;
     779    int Npix = 0;
     780
     781    // the model function returns the source flux at a position
     782    psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     783
     784    psVector *params = model->params;
     785    psImage  *image = source->pixels;
     786    psImage  *mask = source->maskObj;
     787    psImage  *variance = source->variance;
     788
     789    int dX = image->col0;
     790    int dY = image->row0;
     791
     792    for (int iy = 0; iy < image->numRows; iy++) {
     793        for (int ix = 0; ix < image->numCols; ix++) {
     794
     795            // skip pixels which are masked
     796            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal) continue;
     797
     798            if (variance->data.F32[iy][ix] <= 0) continue;
     799
     800            coord->data.F32[0] = (psF32) ix + dX + 0.5;
     801            coord->data.F32[1] = (psF32) iy + dY + 0.5;
     802
     803            // for the full model, add all points
     804            float value = model->modelFunc (NULL, params, coord);
     805
     806            // fprintf (stderr, "%d, %d : %f, %f : %f - %f : %f\n",
     807            // ix, iy, coord->data.F32[0], coord->data.F32[1], image->data.F32[iy][ix], value, dC);
     808
     809            dC += PS_SQR (image->data.F32[iy][ix] - value) / variance->data.F32[iy][ix];
     810            Npix ++;
     811        }
     812    }
     813    model->nPix = Npix;
     814    model->nDOF = Npix - model->nPar;
     815    model->chisq = dC;
     816    model->chisqNorm = dC / model->nDOF;
     817
     818    psFree (coord);
     819    return (true);
     820}
    702821
    703822double pmSourceModelWeight(const pmSource *Mi, int term, const bool unweighted_sum, const float covarFactor, psImageMaskType maskVal)
  • trunk/psModules/src/objects/pmSourcePhotometry.h

    r29546 r31153  
    6464);
    6565
    66 bool pmSourceMagnitudesInit (psMetadata *config);
    67 bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psImageMaskType maskVal, psImageMaskType markVal);
     66bool pmSourceMagnitudesInit (pmConfig *config, psMetadata *recipe);
     67bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psImageMaskType maskVal, psImageMaskType markVal, float radius);
    6868
    69 bool pmSourcePixelWeight (float *pixWeightNotBad, float *pixWeightNotPoor, pmModel *model, psImage *mask, psImageMaskType maskVal, psImageMaskType markVal);
     69bool pmSourcePixelWeight (pmSource *source, pmModel *model, psImage *mask, psImageMaskType maskVal, float radius);
    7070
    71 bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *weight, psImageMaskType maskVal, const float covarFactor);
     71bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *weight, psImageMaskType maskVal);
     72bool pmSourceChisqUnsubtracted (pmSource *source, pmModel *model, psImageMaskType maskVal);
    7273
    7374bool pmSourceMeasureDiffStats (pmSource *source, psImageMaskType maskVal, psImageMaskType markVal);
  • trunk/psModules/src/objects/pmSourceVisual.c

    r29004 r31153  
    5656
    5757    if (!pmVisualTestLevel("psphot.psf.metric", 2)) return true;
    58 
    59     if (kapa1 == -1) {
    60         kapa1 = KapaOpenNamedSocket ("kapa", "pmSource:plots");
    61         if (kapa1 == -1) {
    62             fprintf (stderr, "failure to open kapa; visual mode disabled\n");
    63             pmVisualSetVisual(false);
    64             return false;
    65         }
    66     }
     58    if (!pmVisualInitWindow (&kapa1, "pmSource:plots")) return false;
    6759
    6860    KapaClearSections (kapa1);
     
    140132
    141133    if (!pmVisualTestLevel("psphot.psf.subpix", 3)) return true;
    142 
    143     if (kapa1 == -1) {
    144         kapa1 = KapaOpenNamedSocket ("kapa", "pmSource:plots");
    145         if (kapa1 == -1) {
    146             fprintf (stderr, "failure to open kapa; visual mode disabled\n");
    147             pmVisualSetVisual(false);
    148             return false;
    149         }
    150     }
     134    if (!pmVisualInitWindow (&kapa1, "pmSource:plots")) return false;
    151135
    152136    KapaClearSections (kapa1);
    153137    KapaInitGraph (&graphdata);
     138    section.bg = KapaColorByName ("none"); // XXX probably should be 'none'
    154139
    155140    int n;
     
    302287
    303288    if (!pmVisualTestLevel("psphot.psf.fits", 2)) return true;
    304 
    305     if (kapa2 == -1) {
    306         kapa2 = KapaOpenNamedSocket ("kapa", "pmSource:images");
    307         if (kapa2 == -1) {
    308             fprintf (stderr, "failure to open kapa; visual mode disabled\n");
    309             pmVisualSetVisual(false);
    310             return false;
    311         }
    312     }
     289    if (!pmVisualInitWindow (&kapa2, "pmSource:images")) return false;
    313290
    314291    // create images 1/10 scale:
     
    385362    if (!source->pixels) return false;
    386363    if (!source->modelFlux) return false;
    387 
    388     if (kapa2 == -1) {
    389         kapa2 = KapaOpenNamedSocket ("kapa", "pmSource:images");
    390         if (kapa2 == -1) {
    391             fprintf (stderr, "failure to open kapa; visual mode disabled\n");
    392             pmVisualSetVisual(false);
    393             return false;
    394         }
    395     }
     364    if (!pmVisualInitWindow (&kapa2, "pmSource:images")) return false;
    396365
    397366    // KapaClearSections (kapa2);
     
    428397    if (!plotPSF) return true;
    429398    if (!pmVisualTestLevel("psphot.psf.resid", 2)) return true;
    430 
    431     if (kapa1 == -1) {
    432         kapa1 = KapaOpenNamedSocket ("kapa", "pmSource:plots");
    433         if (kapa1 == -1) {
    434             fprintf (stderr, "failure to open kapa; visual mode disabled\n");
    435             pmVisualSetVisual(false);
    436             return false;
    437         }
    438     }
     399    if (!pmVisualInitWindow (&kapa1, "pmSource:plots")) return false;
    439400
    440401    KapaClearPlots (kapa1);
    441402    KapaInitGraph (&graphdata);
     403    section.bg = KapaColorByName ("none"); // XXX probably should be 'none'
    442404
    443405    float Xmin = +1e32;
  • trunk/psModules/test/objects/tap_pmPeaks.c

    r15985 r31153  
    650650    ok(test_pmPeaksInImage(TST02_NUM_ROWS, 2*TST02_NUM_COLS),
    651651      "Tested pmPeaksInImage() on (%d, %d) image", TST02_NUM_ROWS, 2*TST02_NUM_COLS);
    652 
    653 
    654     // ------------------------------------------------------------------------
    655     // Test pmPeaksSubset()
    656     // Calling pmPeaksSubset with NULL psList.  Should generate error.
    657     {
    658         psMemId id = psMemGetId();
    659         psArray *outData = pmPeaksSubset(NULL, 0.0, psRegionSet(0, 0, 0, 0));
    660         ok(outData == NULL, "pmPeaksSubset() returned a NULL with a NULL psArray input");
    661         psFree(outData);
    662         ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
    663     }
    664 
    665 
    666     // Set peaks in input image.  All even-column and even-row pixels are
    667     // set non-zero, all other pixels are set to zero.
    668     psImage *imgData = psImageAlloc(NUM_COLS, NUM_ROWS, PS_TYPE_F32);
    669     psS32 numPeaksOrig = 0;
    670     for (psS32 i = 0 ; i < NUM_ROWS ; i++) {
    671         for (psS32 j = 0 ; j < NUM_COLS ; j++) {
    672             if ((0 == i%2) && (0 == j%2)) {
    673                 imgData->data.F32[i][j] = (float) (i + 10);
    674                 numPeaksOrig++;
    675             } else {
    676                 imgData->data.F32[i][j] = 0.0;
    677             }
    678         }
    679     }
    680     // Call pmPeaksSubset() with large maxValue and disjoint psRegion.
    681     // Should not remove any peaks.
    682     {
    683         psMemId id = psMemGetId();
    684         psArray *outData = pmPeaksInImage(imgData, 0.0);
    685         psArray *outData2 = pmPeaksSubset(outData, PS_MAX_F32, psRegionSet(20, 20, 20, 20));
    686         ok(outData2 != NULL && psMemCheckArray(outData),
    687            "pmPeaksSubset() returned a non-NULL psArray (large maxValue)");
    688         ok(outData2->n == numPeaksOrig,
    689           "pmPeaksSubset() returned correct number of peaks (was %d, should be %d)", outData2->n+1, numPeaksOrig);
    690         psFree(outData);
    691         psFree(outData2);
    692         ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
    693     }
    694 
    695 
    696     // Call pmPeaksSubset() with small maxValue and disjoint psRegion.
    697     // Should not remove any peaks.
    698     {
    699         psMemId id = psMemGetId();
    700         psArray *outData = pmPeaksInImage(imgData, 0.0);
    701         psArray *outData2 = pmPeaksSubset(outData, 0.0, psRegionSet(20, 20, 20, 20));
    702         ok(outData2 != NULL && psMemCheckArray(outData),
    703            "pmPeaksSubset() returned a non-NULL psArray (small maxValue)");
    704         ok(outData2->n == 0,
    705           "pmPeaksSubset() returned correct number of peaks (was %d, should be %d)", outData2->n, 0);
    706         psFree(outData);
    707         psFree(outData2);
    708         ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
    709     }
    710 
    711 
    712     // Call pmPeaksSubset() with large maxValue and enclosing psRegion.
    713     // Should remove aall peaks.
    714     {
    715         psMemId id = psMemGetId();
    716         psArray *outData = pmPeaksInImage(imgData, 0.0);
    717         psRegion tmpRegion = psRegionSet(-PS_MAX_F32, PS_MAX_F32, -PS_MAX_F32, PS_MAX_F32);
    718         psArray *outData2 = pmPeaksSubset(outData, PS_MAX_F32, tmpRegion);
    719         ok(outData2 != NULL && psMemCheckArray(outData),
    720            "pmPeaksSubset() returned a non-NULL psArray (small maxValue, enclosing psRegion)");
    721         ok(outData2->n == 0,
    722           "pmPeaksSubset() returned correct number of peaks (was %d, should be %d)", outData2->n, 0);
    723         psFree(outData);
    724         psFree(outData2);
    725         ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
    726     }
    727 
    728 
    729     // Call pmPeaksSubset() with large maxValue and enclosing psRegion.
    730     // Should remove aall peaks.
    731     {
    732         psMemId id = psMemGetId();
    733         psArray *outData = pmPeaksInImage(imgData, 0.0);
    734         psRegion tmpRegion = psRegionSet(-PS_MAX_F32, PS_MAX_F32, -PS_MAX_F32, PS_MAX_F32);
    735         psArray *outData2 = pmPeaksSubset(outData, 0.0, tmpRegion);
    736         ok(outData2 != NULL && psMemCheckArray(outData),
    737            "pmPeaksSubset() returned a non-NULL psArray (small maxValue, inclusive psRegion)");
    738         ok(outData2->n == 0,
    739           "pmPeaksSubset() returned correct number of peaks (was %d, should be %d)", outData2->n, 0);
    740         psFree(outData);
    741         psFree(outData2);
    742         ok(!psMemCheckLeaks (id, NULL, NULL, false), "no memory leaks");
    743     }
    744652}
  • trunk/psModules/test/objects/tap_pmSource.c

    r24580 r31153  
    2121        pmSourceCacheModel()
    2222        pmSourceCachePSF()
    23         pmSourceSortBySN()      (COMPILER ERRORS)
     23        pmSourceSortByFlux()    (COMPILER ERRORS)
    2424        pmSourceSortByY()       (COMPILER ERRORS)
    2525    Must test
     
    801801
    802802    // ----------------------------------------
    803     // pmSourceSortBySN() tests
    804     // int pmSourceSortBySN (const void **a, const void **b)
    805     // Call pmSourceSortBySN() with acceptable input parameters.
     803    // pmSourceSortByFlux() tests
     804    // int pmSourceSortByFlux (const void **a, const void **b)
     805    // Call pmSourceSortByFlux() with acceptable input parameters.
    806806    // XXX: We don't test with NULL input parameters since this function has no PS_ASSERTS to protect
    807807    // against that.
     
    816816        src2->peak->SN = 20.0;
    817817
    818         int rc = pmSourceSortBySN((const void **) &src1, (const void **) &src2);
    819         ok(rc == 1, "pmSourceSortBySN() returned correct result (source1 < source2) (%d)", rc);
    820         rc = pmSourceSortBySN((const void **) &src2, (const void **) &src1);
    821         ok(rc == -1, "pmSourceSortBySN() returned correct result (source2 < source1) (%d)", rc);
    822         rc = pmSourceSortBySN((const void **) &src1, (const void **) &src1);
    823         ok(rc == 0, "pmSourceSortBySN() returned correct result (source1 == source2) (%d)", rc);
     818        int rc = pmSourceSortByFlux((const void **) &src1, (const void **) &src2);
     819        ok(rc == 1, "pmSourceSortByFlux() returned correct result (source1 < source2) (%d)", rc);
     820        rc = pmSourceSortByFlux((const void **) &src2, (const void **) &src1);
     821        ok(rc == -1, "pmSourceSortByFlux() returned correct result (source2 < source1) (%d)", rc);
     822        rc = pmSourceSortByFlux((const void **) &src1, (const void **) &src1);
     823        ok(rc == 0, "pmSourceSortByFlux() returned correct result (source1 == source2) (%d)", rc);
    824824
    825825        psFree(src1);
Note: See TracChangeset for help on using the changeset viewer.