IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 29004


Ignore:
Timestamp:
Aug 20, 2010, 1:14:11 PM (16 years ago)
Author:
eugene
Message:

Many changes:

  • psphot-related issues

1) added a new feature to psLib/src/fft/psImageFFT to allow for a pre-FFTed kernel generated for a specific image dimension which can then be applied to an arbitrary number of images for convolution -- this avoids the kernel FFT for every image convolution.
2) updated the psMinimizeLMM to include 2 levels of tolerance: minTol and maxTol: if the minimization reaches minTol, it stops. if it only reaches maxTol within maxIter, it stops and is considered successful, if it fails to reach maxTol, then it fails. This allows us to accept fits that are actually acceptable (within error) even if they are not as close as ideally possible.
3) add new stat: psfWeightNotPoor (vs psfWeightNotBad) : the first gives the fraction of psf-weighted unmasked pixels considering any mask bits (except the internal 'mark' bit), while the former considers only 'bad' mask bits -- these are written to QF_PSF and QF_PSF_PERFECT in the CMF files.
4) define user-set parameters for max and min valid flux in the linear fit analysis: Note this was the cause of the non-negative fluxes in forced photometry -- the min limit was hard-wired to 0.0.
5) significance image is now constructed as (image + (image/1000)2) / sqrt(variance) so that bright sources have well-defined peaks (other wise, they become somewhat flat-topped as image = sqrt(variance), leading to ill-defined peaks).
6) modification of the visualization functions to accept facility and level values akin to psTrace
7) modification of the source fitting APIs to allow thread- and source- independent fit options (iterations, tolerances, etc)
8) use Kron magnitude as test for source size (CR vs EXT) instead of PSF-based aperture
9) set a min systematic error in the aperture mags when used for size classification significance
10) threaded the psf-convolved model (PCM) fitting process (extended source fits)
11) for extended sources, adjust the radius based on the footprint and re-calculate moments for guess; save the psf-based moments for output in psf table
12) for Sersic fitting, choose the best index with a grid search using only a few iterations; iterate fully on the selected value.
13) same for Sersic fitting using the PCM fitting process
14) fixed a bug in which the PSF candidate stars which failed in the psf fitting were not correctly unmarked as being PSF stars
15) define galaxy fit radius based on sky stdev (global, not local)
16) move the PCM code to psModules
17) save and report the raw aperture mag in addition to the curve-of-growth corrected one (PS1_V3)
18) save and report the Kron parameters and higher-order moments
19) some psModule header reorganization for code clarity
20) fixed a bug in which the diff stats were counting 'marked' pixels (outside area of interest) as 'masked'.
21) save the radial profile aperture sizes in the headers
22) better guess for Sersic parameters based on moments (requires setting the functional form so that the scale length is right)

  • ppSub-related:

1) ensure masked pixels are NANed in output diff image
2) add code to flag detections if they have bright positive neighbors (+ output of these in PS1_DV2)
3) define separate penalties for each image (based on their fwhm values) (this requires the penalties to be calculated later in the code).
4) define separate apertures for each image for flux normalization
5) choose aperture based on curve-of-growth (was based on fixed fraction of full aperture flux, and thus noisy)
6) some fine tuning of the penalty factor (this still seems arbitrary, and results are somewhat sensitive to the right value)

Location:
trunk
Files:
1 deleted
133 edited
16 copied

Legend:

Unmodified
Added
Removed
  • trunk/psModules

    • Property svn:mergeinfo deleted
  • trunk/psModules/src/camera/pmFPAfileIO.c

    r28340 r29004  
    2424#include "pmFPAfileFitsIO.h"
    2525#include "pmFPAfileFringeIO.h"
     26
     27#include "pmTrend2D.h"
     28#include "pmResiduals.h"
     29#include "pmGrowthCurve.h"
    2630#include "pmSpan.h"
     31#include "pmFootprintSpans.h"
    2732#include "pmFootprint.h"
    2833#include "pmPeaks.h"
    2934#include "pmMoments.h"
    30 #include "pmResiduals.h"
    31 #include "pmGrowthCurve.h"
    32 #include "pmTrend2D.h"
     35#include "pmModelFuncs.h"
     36#include "pmModel.h"
     37#include "pmSourceMasks.h"
     38#include "pmSourceExtendedPars.h"
     39#include "pmSourceDiffStats.h"
     40#include "pmSource.h"
     41#include "pmSourceFitModel.h"
    3342#include "pmPSF.h"
    34 #include "pmModel.h"
    35 #include "pmSource.h"
     43#include "pmPSFtry.h"
     44
    3645#include "pmSourceIO.h"
    37 #include "pmResiduals.h"
    3846#include "pmPSF_IO.h"
     47
    3948#include "pmAstrometryModel.h"
    4049#include "pmAstrometryRefstars.h"
  • trunk/psModules/src/camera/pmReadoutFake.c

    r28405 r29004  
    1010#include "pmFPA.h"
    1111
    12 #include "pmMoments.h"
     12
     13#include "pmTrend2D.h"
    1314#include "pmResiduals.h"
    1415#include "pmGrowthCurve.h"
    15 #include "pmTrend2D.h"
    16 #include "pmPSF.h"
    17 #include "pmModel.h"
    18 #include "pmModelClass.h"
    1916#include "pmSpan.h"
     17#include "pmFootprintSpans.h"
    2018#include "pmFootprint.h"
    2119#include "pmPeaks.h"
     20#include "pmMoments.h"
     21#include "pmModelFuncs.h"
     22#include "pmModel.h"
     23#include "pmModelUtils.h"
     24#include "pmModelClass.h"
     25#include "pmSourceMasks.h"
     26#include "pmSourceExtendedPars.h"
     27#include "pmSourceDiffStats.h"
    2228#include "pmSource.h"
    23 #include "pmSourceUtils.h"
    24 #include "pmModelUtils.h"
     29#include "pmSourceFitModel.h"
     30#include "pmPSF.h"
     31#include "pmPSFtry.h"
     32
    2533#include "pmSourceGroups.h"
    26 
    2734#include "pmReadoutFake.h"
    2835
  • trunk/psModules/src/camera/pmReadoutFake.h

    r26450 r29004  
    22#define PM_READOUT_FAKE_H
    33
    4 #include <pslib.h>
    5 #include <pmHDU.h>
    6 #include <pmFPA.h>
    7 
    8 #include <pmMoments.h>
    9 #include <pmResiduals.h>
    10 #include <pmGrowthCurve.h>
    11 #include <pmTrend2D.h>
    12 #include <pmPSF.h>
    13 #include <pmSourceMasks.h>
     4// #include <pslib.h>
     5// #include <pmHDU.h>
     6// #include <pmFPA.h>
     7//
     8// #include <pmMoments.h>
     9// #include <pmResiduals.h>
     10// #include <pmGrowthCurve.h>
     11// #include <pmTrend2D.h>
     12// #include <pmPSF.h>
     13// #include <pmSourceMasks.h>
    1414
    1515/// Set threading
  • trunk/psModules/src/config/pmConfig.c

    r28287 r29004  
    3232
    3333#include "pmConfig.h"
     34#include "pmVisualUtils.h"
    3435
    3536#ifdef HAVE_NEBCLIENT
     
    638639        psArgumentVerbosity(argc, argv);
    639640        // XXX: substitute the string for the default log level for "2".
     641    }
     642
     643    // Set the visualization levels
     644    // argument format is: -visual (facil) (level)
     645    while ((argNum = psArgumentGet(*argc, argv, "-visual"))) {
     646        if ( (*argc < argNum + 3) ) {
     647            psError(PS_ERR_IO, true, "-visual switch specified without facility and level.");
     648            return NULL;
     649        }
     650        psArgumentRemove(argNum, argc, argv);
     651        pmVisualSetLevel(argv[argNum], atoi(argv[argNum+1]));
     652        psArgumentRemove(argNum, argc, argv);
     653        psArgumentRemove(argNum, argc, argv);
     654    }
     655    if ((argNum = psArgumentGet(*argc, argv, "-visual-all"))) {
     656        pmVisualSetLevel(".", 10);
     657        psArgumentRemove(argNum, argc, argv);
     658    }
     659    if ((argNum = psArgumentGet(*argc, argv, "-visual-levels"))) {
     660        pmVisualPrintLevels(stdout);
     661        psArgumentRemove(argNum, argc, argv);
    640662    }
    641663
  • trunk/psModules/src/detrend/pmMaskStats.c

    r28100 r29004  
    77
    88#include <pslib.h>
    9 #include <psmodules.h>
    109
    1110#include "pmHDU.h"
     
    1615#include "pmFPAAstrometry.h"
    1716
     17#include "pmMaskStats.h"
    1818
    1919#define ESCAPE { \
  • trunk/psModules/src/detrend/pmShutterCorrection.c

    r28405 r29004  
    302302    PS_ASSERT_PTR_NON_NULL(guess, NULL);
    303303
    304     psMinimization *minInfo = psMinimizationAlloc(15, 0.1); // Minimization information
     304    psMinimization *minInfo = psMinimizationAlloc(15, 0.1, 1.0); // Minimization information
    305305
    306306    psVector *params = psVectorAlloc (3, PS_TYPE_F32); // Fitting parameters
  • trunk/psModules/src/extras/Makefile.am

    r27750 r29004  
    99        pmKapaPlots.c \
    1010        pmVisual.c \
     11        pmVisualUtils.c \
    1112        ippStages.c
    1213
     
    1718        pmKapaPlots.h \
    1819        pmVisual.h \
     20        pmVisualUtils.h \
    1921        ippDiffMode.h \
    2022        ippStages.h
  • trunk/psModules/src/extras/pmVisual.c

    r28129 r29004  
    2121#include "pmAstrometryObjects.h"
    2222#include "pmSubtractionStamps.h"
     23
    2324#include "pmTrend2D.h"
     25#include "pmResiduals.h"
     26#include "pmGrowthCurve.h"
     27#include "pmSpan.h"
     28#include "pmFootprintSpans.h"
     29#include "pmFootprint.h"
     30#include "pmPeaks.h"
     31#include "pmMoments.h"
     32#include "pmModelFuncs.h"
     33#include "pmModel.h"
     34#include "pmSourceMasks.h"
     35#include "pmSourceExtendedPars.h"
     36#include "pmSourceDiffStats.h"
     37#include "pmSource.h"
     38#include "pmSourceFitModel.h"
    2439#include "pmPSF.h"
    2540#include "pmPSFtry.h"
    26 #include "pmSource.h"
     41
    2742#include "pmFPAExtent.h"
    28 
    29 # if (HAVE_KAPA)
    30 # include <kapa.h>
    31 # include "pmVisual.h"
    32 # include "pmKapaPlots.h"
    33 # define KAPAX 700
    34 # define KAPAY 700
    3543
    3644#include "pmAstrometryVisual.h"
     
    3846#include "pmStackVisual.h"
    3947#include "pmSourceVisual.h"
     48
     49# if (HAVE_KAPA)
     50# include <kapa.h>
     51#include "pmVisual.h"
     52#include "pmKapaPlots.h"
     53
     54# define KAPAX 700
     55# define KAPAY 700
    4056
    4157//#define TESTING
     
    102118
    103119    /* Wait up to 1.0 second for a response, then continue */
    104     timeout.tv_sec = 2;
     120    timeout.tv_sec = 10;
    105121    timeout.tv_usec = 0;
    106122
  • trunk/psModules/src/imcombine/pmPSFEnvelope.c

    r28332 r29004  
    1010#include "pmHDU.h"
    1111#include "pmFPA.h"
    12 #include "pmReadoutFake.h"
    13 
    14 #include "pmMoments.h"
     12
     13#include "pmTrend2D.h"
    1514#include "pmResiduals.h"
    1615#include "pmGrowthCurve.h"
    17 #include "pmTrend2D.h"
    18 #include "pmPSF.h"
    19 #include "pmModel.h"
    20 #include "pmModelClass.h"
    21 #include "pmModelUtils.h"
    2216#include "pmSpan.h"
     17#include "pmFootprintSpans.h"
    2318#include "pmFootprint.h"
    2419#include "pmPeaks.h"
     20#include "pmMoments.h"
     21#include "pmModelFuncs.h"
     22#include "pmModel.h"
     23#include "pmModelUtils.h"
     24#include "pmModelClass.h"
     25#include "pmSourceMasks.h"
     26#include "pmSourceExtendedPars.h"
     27#include "pmSourceDiffStats.h"
    2528#include "pmSource.h"
    26 #include "pmSourceUtils.h"
    2729#include "pmSourceFitModel.h"
     30#include "pmPSF.h"
    2831#include "pmPSFtry.h"
    2932
    30 
     33#include "pmReadoutFake.h"
    3134#include "pmPSFEnvelope.h"
    3235#include "pmStackVisual.h"
     
    410413    options->chiFluxTrend = false;      // All sources have similar flux, so fitting a trend often fails
    411414
    412     pmSourceFitModelInit(SOURCE_FIT_ITERATIONS, 0.01, VARIANCE_VAL, true);
     415    // options which modify the behavior of the model fitting
     416    options->fitOptions                = pmSourceFitOptionsAlloc();
     417    options->fitOptions->nIter         = SOURCE_FIT_ITERATIONS;
     418    options->fitOptions->minTol        = 0.01;
     419    options->fitOptions->maxTol        = 1.00;
     420    options->fitOptions->poissonErrors = true;
     421    options->fitOptions->weight        = VARIANCE_VAL;
     422    options->fitOptions->mode          = PM_SOURCE_FIT_PSF;
     423
    413424    pmModelClassSetLimits(PM_MODEL_LIMITS_STRICT); // Important for getting a good stack target PSF
    414425
  • trunk/psModules/src/imcombine/pmSubtraction.c

    r28667 r29004  
    3333#define USE_KERNEL_ERR                  // Use kernel error image?
    3434#define NUM_COVAR_POS 5                 // Number of positions for covariance calculation
     35
     36// XXX we need to pass these fwhm values elsewhere.  These should go on one of the structure, but
     37// things are too confusing to do that now.  just save them here.
     38static float FWHM1 = NAN;
     39static float FWHM2 = NAN;
    3540
    3641//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
    752757
    753758
    754 bool pmSubtractionConvolveStamp(pmSubtractionStamp *stamp, const pmSubtractionKernels *kernels, int footprint)
     759bool pmSubtractionConvolveStamp (pmSubtractionStamp *stamp, pmSubtractionKernels *kernels, int footprint)
    755760{
    756761    PS_ASSERT_PTR_NON_NULL(stamp, false);
     
    774779        stamp->convolutions1 = convolveStamp(stamp->convolutions1, stamp->image1, kernels, footprint);
    775780        stamp->convolutions2 = convolveStamp(stamp->convolutions2, stamp->image2, kernels, footprint);
     781        if (!pmSubtractionKernelPenaltiesStamp(stamp, kernels)) {
     782            psAbort("failure in penalties");
     783        }
    776784        break;
    777785      default:
     
    12151223    bool threaded = pmSubtractionThreaded(); // Running threaded?
    12161224
     1225    // XXX This is no longer used
    12171226    psImage *convMask = NULL;           // Convolved mask image (common to inputs 1 and 2)
    12181227    if (subMask) {
     
    14131422    return true;
    14141423}
     1424
     1425bool pmSubtractionGetFWHMs(float *fwhm1, float *fwhm2) {
     1426
     1427  *fwhm1 = FWHM1;
     1428  *fwhm2 = FWHM2;
     1429  return true;
     1430}
     1431
     1432bool pmSubtractionSetFWHMs(float fwhm1, float fwhm2) {
     1433
     1434  FWHM1 = fwhm1;
     1435  FWHM2 = fwhm2;
     1436  return true;
     1437}
  • trunk/psModules/src/imcombine/pmSubtraction.h

    r26893 r29004  
    5959/// Convolve the reference stamp with the kernel components
    6060bool pmSubtractionConvolveStamp(pmSubtractionStamp *stamp, ///< Stamp to convolve
    61                                 const pmSubtractionKernels *kernels, ///< Kernel parameters
     61                                pmSubtractionKernels *kernels, ///< Kernel parameters
    6262                                int footprint ///< Half-size of region over which to calculate equation
    6363    );
     
    157157    );
    158158
     159bool pmSubtractionGetFWHMs(float *fwhm1, float *fwhm2);
     160bool pmSubtractionSetFWHMs(float fwhm1, float fwhm2);
     161
    159162/// @}
    160163#endif
  • trunk/psModules/src/imcombine/pmSubtractionEquation.c

    r28405 r29004  
    3838                                  const psImage *polyValues, // Spatial polynomial values
    3939                                  int footprint, // (Half-)Size of stamp
    40                                   int normWindow, // Window (half-)size for normalisation measurement
     40                                  int normWindow1, // Window (half-)size for normalisation measurement
     41                                  int normWindow2, // Window (half-)size for normalisation measurement
    4142                                  const pmSubtractionEquationCalculationMode mode
    4243                                  )
     
    184185            double one = 1.0;
    185186
    186             if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow)) {
     187            if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow1)) {
    187188                normI1 += ref;
     189            }
     190            if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow2)) {
    188191                normI2 += in;
    189192            }
     
    214217
    215218    *norm = normI2 / normI1;
     219
     220    fprintf (stderr, "normValue: %f %f %f\n", normI1, normI2, *norm);
    216221
    217222    if (mode & PM_SUBTRACTION_EQUATION_NORM) {
     
    262267                                      const psImage *polyValues, // Spatial polynomial values
    263268                                      int footprint, // (Half-)Size of stamp
    264                                       int normWindow, // Window (half-)size for normalisation measurement
     269                                      int normWindow1, // Window (half-)size for normalisation measurement
     270                                      int normWindow2, // Window (half-)size for normalisation measurement
    265271                                      const pmSubtractionEquationCalculationMode mode
    266272                                      )
     
    492498            double i1i2 = i1 * i2;
    493499
    494             if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow)) {
     500            if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow1)) {
    495501                normI1 += i1;
     502            }
     503            if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow2)) {
    496504                normI2 += i2;
    497505            }
     
    522530
    523531    *norm = normI2 / normI1;
     532    fprintf (stderr, "normValue: %f %f %f\n", normI1, normI2, *norm);
    524533
    525534    if (mode & PM_SUBTRACTION_EQUATION_NORM) {
     
    559568// Add in penalty term to least-squares vector
    560569bool calculatePenalty(psImage *matrix,                     // Matrix to which to add in penalty term
    561                              psVector *vector,                    // Vector to which to add in penalty term
    562                              const pmSubtractionKernels *kernels, // Kernel parameters
    563                              float norm                           // Normalisation
    564     )
     570                      psVector *vector,                    // Vector to which to add in penalty term
     571                      const pmSubtractionKernels *kernels, // Kernel parameters
     572                      float norm                           // Normalisation
     573  )
    565574{
    566575    if (kernels->penalty == 0.0) {
     
    568577    }
    569578
    570     psVector *penalties = kernels->penalties; // Penalties for each kernel component
     579    psVector *penalties1 = kernels->penalties1; // Penalties for each kernel component (input)
     580    psVector *penalties2 = kernels->penalties2; // Penalties for each kernel component (ref)
     581
    571582    int spatialOrder = kernels->spatialOrder; // Order of spatial variations
    572583    int numKernels = kernels->num; // Number of kernel components
     
    588599            for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) {
    589600                // Contribution to chi^2: a_i^2 P_i
    590                 psAssert(isfinite(penalties->data.F32[i]), "Invalid penalty");
    591                 matrix->data.F64[index][index] += norm * penalties->data.F32[i];
     601                psAssert(isfinite(penalties1->data.F32[i]), "Invalid penalty");
     602                fprintf (stderr, "penalty: %f + %f (%f * %f)\n", matrix->data.F64[index][index], norm * penalties1->data.F32[i], norm, penalties1->data.F32[i]);
     603                matrix->data.F64[index][index] += norm * penalties1->data.F32[i];
    592604                if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
    593                     matrix->data.F64[index + numParams + 2][index + numParams + 2] += norm * penalties->data.F32[i];
     605                    fprintf (stderr, "penalty: (x^%d y^%d fwhm %f) : %f + %f (%f * %f)\n", kernels->u->data.S32[index], kernels->v->data.S32[index], kernels->widths->data.F32[index],
     606                             matrix->data.F64[index + numParams + 2][index + numParams + 2], norm * penalties2->data.F32[i], norm, penalties2->data.F32[i]);
     607                    matrix->data.F64[index + numParams + 2][index + numParams + 2] += norm * penalties2->data.F32[i];                       
    594608                    // matrix[i][i] is ~ (k_i * I_1)(k_i * I_1)
    595609                    // penalties scale with second moments
     
    682696
    683697    pmSubtractionStampList *stamps = job->args->data[0]; // List of stamps
    684     const pmSubtractionKernels *kernels = job->args->data[1]; // Kernels
     698    pmSubtractionKernels *kernels = job->args->data[1]; // Kernels
    685699    int index = PS_SCALAR_VALUE(job->args->data[2], S32); // Stamp index
    686700    pmSubtractionEquationCalculationMode mode  = PS_SCALAR_VALUE(job->args->data[3], S32); // calculation model
     
    689703}
    690704
    691 bool pmSubtractionCalculateEquationStamp(pmSubtractionStampList *stamps, const pmSubtractionKernels *kernels,
     705bool pmSubtractionCalculateEquationStamp(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels,
    692706                                         int index, const pmSubtractionEquationCalculationMode mode)
    693707{
     
    778792        status = calculateMatrixVector(stamp->matrix, stamp->vector, &stamp->norm, stamp->image2, stamp->image1,
    779793                                       weight, window, stamp->convolutions1, kernels,
    780                                        polyValues, footprint, stamps->normWindow, mode);
     794                                       polyValues, footprint, stamps->normWindow1, stamps->normWindow2, mode);
    781795        break;
    782796      case PM_SUBTRACTION_MODE_2:
    783797        status = calculateMatrixVector(stamp->matrix, stamp->vector, &stamp->norm, stamp->image1, stamp->image2,
    784798                                       weight, window, stamp->convolutions2, kernels,
    785                                        polyValues, footprint, stamps->normWindow, mode);
     799                                       polyValues, footprint, stamps->normWindow2, stamps->normWindow1, mode);
    786800        break;
    787801      case PM_SUBTRACTION_MODE_DUAL:
     
    789803                                           stamp->image1, stamp->image2,
    790804                                           weight, window, stamp->convolutions1, stamp->convolutions2,
    791                                            kernels, polyValues, footprint, stamps->normWindow, mode);
     805                                           kernels, polyValues, footprint, stamps->normWindow1, stamps->normWindow2, mode);
    792806        break;
    793807      default:
     
    830844}
    831845
    832 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, const pmSubtractionKernels *kernels,
     846bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels,
    833847                                    const pmSubtractionEquationCalculationMode mode)
    834848{
     
    9961010            }
    9971011
     1012            // double normValue = 1.0;
    9981013            double normValue = stats->robustMedian;
    9991014            // double bgValue = 0.0;
     
    10231038        }
    10241039# endif
     1040
     1041#if (1)
     1042        for (int i = 0; i < solution->n; i++) {
     1043            fprintf(stderr, "Single solution %d: %lf\n", i, solution->data.F64[i]);
     1044        }
     1045#endif
    10251046
    10261047        if (!kernels->solution1) {
     
    10961117
    10971118        int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation
    1098         calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[normIndex][normIndex] / 1000.0);
     1119        calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[normIndex][normIndex] / 100.0);
    10991120#endif
    11001121
     
    11771198
    11781199
    1179 #ifdef TESTING
     1200#if (1)
    11801201        for (int i = 0; i < solution->n; i++) {
    11811202            fprintf(stderr, "Dual solution %d: %lf\n", i, solution->data.F64[i]);
  • trunk/psModules/src/imcombine/pmSubtractionEquation.h

    r26893 r29004  
    1919/// Calculate the least-squares equation to match the image quality for a single stamp
    2020bool pmSubtractionCalculateEquationStamp(pmSubtractionStampList *stamps, ///< Stamps
    21                                          const pmSubtractionKernels *kernels, ///< Kernel parameters
     21                                         pmSubtractionKernels *kernels, ///< Kernel parameters
    2222                                         int index, ///< Index of stamp
    2323                                         const pmSubtractionEquationCalculationMode mode
     
    2626/// Calculate the least-squares equation to match the image quality
    2727bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, ///< Stamps
    28                                     const pmSubtractionKernels *kernels, ///< Kernel parameters
     28                                    pmSubtractionKernels *kernels, ///< Kernel parameters
    2929                                    const pmSubtractionEquationCalculationMode mode
    3030    );
  • trunk/psModules/src/imcombine/pmSubtractionKernels.c

    r27335 r29004  
    2626    psFree(kernels->vStop);
    2727    psFree(kernels->preCalc);
    28     psFree(kernels->penalties);
     28    psFree(kernels->penalties1);
     29    psFree(kernels->penalties2);
    2930    psFree(kernels->solution1);
    3031    psFree(kernels->solution2);
     
    140141    kernels->v = psVectorRealloc(kernels->v, start + numNew);
    141142    kernels->preCalc = psArrayRealloc(kernels->preCalc, start + numNew);
    142     kernels->penalties = psVectorRealloc(kernels->penalties, start + numNew);
     143
     144    kernels->penalties1 = psVectorRealloc(kernels->penalties1, start + numNew);
     145    kernels->penalties2 = psVectorRealloc(kernels->penalties2, start + numNew);
     146
    143147    kernels->inner = start;
    144148    kernels->num += numNew;
     
    156160            kernels->v->data.S32[index] = v;
    157161            kernels->preCalc->data[index] = NULL;
    158             kernels->penalties->data.F32[index] = kernels->penalty * PS_SQR(PS_SQR(u) + PS_SQR(v));
    159             psAssert (isfinite(kernels->penalties->data.F32[index]), "invalid penalty");
     162
     163            // XXX this needs to be changed to use the *convolved* second moment
     164            kernels->penalties1->data.F32[index] = kernels->penalty * PS_SQR(PS_SQR(u) + PS_SQR(v));
     165            psAssert (isfinite(kernels->penalties1->data.F32[index]), "invalid penalty");
     166
     167            kernels->penalties2->data.F32[index] = kernels->penalty * PS_SQR(PS_SQR(u) + PS_SQR(v));
     168            psAssert (isfinite(kernels->penalties2->data.F32[index]), "invalid penalty");
     169
    160170            psTrace("psModules.imcombine", 7, "Kernel %d: %d %d\n", index, u, v);
    161171        }
     
    166176    kernels->v->n = start + numNew;
    167177    kernels->preCalc->n = start + numNew;
    168     kernels->penalties->n = start + numNew;
     178
     179    kernels->penalties1->n = start + numNew;
     180    kernels->penalties2->n = start + numNew;
    169181
    170182    return true;
    171183}
    172184
    173 bool pmSubtractionKernelPreCalcNormalize(pmSubtractionKernels *kernels, pmSubtractionKernelPreCalc *preCalc,
    174                                          int index, int size, int uOrder, int vOrder, float fwhm,
    175                                          bool AlardLuptonStyle, bool forceZeroNull)
     185static bool pmSubtractionKernelPreCalcNormalize(pmSubtractionKernels *kernels, pmSubtractionKernelPreCalc *preCalc,
     186                                                int index, int uOrder, int vOrder, float fwhm,
     187                                                bool AlardLuptonStyle, bool forceZeroNull)
    176188{
    177189    // we have 4 cases here:
     
    182194
    183195    // Calculate moments
    184     double penalty = 0.0;                   // Moment, for penalty
    185196    double sum = 0.0, sum2 = 0.0;           // Sum of kernel component
    186197    float min = INFINITY, max = -INFINITY;  // Minimum and maximum kernel value
    187     for (int v = -size; v <= size; v++) {
    188         for (int u = -size; u <= size; u++) {
     198
     199    for (int v = preCalc->kernel->yMin; v <= preCalc->kernel->yMax; v++) {
     200        for (int u = preCalc->kernel->xMin; u <= preCalc->kernel->xMax; u++) {
    189201            double value = preCalc->kernel->kernel[v][u];
    190202            double value2 = PS_SQR(value);
    191203            sum += value;
    192204            sum2 += value2;
    193             penalty += value2 * PS_SQR((PS_SQR(u) + PS_SQR(v)));
    194205            min = PS_MIN(value, min);
    195206            max = PS_MAX(value, max);
     
    198209
    199210#if 0
    200     fprintf(stderr, "%d raw: %lf, null: %f, min: %lf, max: %lf, moment: %lf\n", index, sum, preCalc->kernel->kernel[0][0], min, max, penalty);
     211    fprintf(stderr, "%d raw: %lf, null: %f, min: %lf, max: %lf\n", index, sum, preCalc->kernel->kernel[0][0], min, max);
    201212#endif
    202213
     
    207218        if (uOrder % 2 == 0 && vOrder % 2 == 0) {
    208219            // Even functions: normalise to unit sum and subtract null pixel so that sum is zero
    209             scale2D = 1.0 / fabs(sum);
     220            // Re-normalize
     221            // scale2D  = 1.0 / fabs(sum);
     222            scale2D  = 1.0 / sqrt(sum2);
    210223            zeroNull = true;
    211224        } else {
     
    239252
    240253    psBinaryOp(preCalc->kernel->image, preCalc->kernel->image, "*", psScalarAlloc(scale2D, PS_TYPE_F32));
    241     penalty *= 1.0 / sum2;
    242254
    243255    if (zeroNull) {
    244         preCalc->kernel->kernel[0][0] -= 1.0;
    245     }
    246 
    247 #if 0
     256        // preCalc->kernel->kernel[0][0] -= 1.0;
     257        preCalc->kernel->kernel[0][0] -= sum / sqrt (sum2);
     258    }
     259
     260#if 1
    248261    {
    249         double sum = 0.0;   // Sum of kernel component
     262        double Sum = 0.0;   // Sum of kernel component
     263        double Sum2 = 0.0;   // Sum of kernel component
    250264        float min = INFINITY, max = -INFINITY;  // Minimum and maximum kernel value
    251         for (int v = -size; v <= size; v++) {
    252             for (int u = -size; u <= size; u++) {
    253                 sum += preCalc->kernel->kernel[v][u];
     265        for (int v = preCalc->kernel->yMin; v <= preCalc->kernel->yMax; v++) {
     266            for (int u = preCalc->kernel->xMin; u <= preCalc->kernel->xMax; u++) {
     267                double value = preCalc->kernel->kernel[v][u];
     268                Sum += value;
     269                Sum2 += PS_SQR(value);
    254270                min = PS_MIN(preCalc->kernel->kernel[v][u], min);
    255271                max = PS_MAX(preCalc->kernel->kernel[v][u], max);
    256272            }
    257273        }
    258         fprintf(stderr, "%d mod: %lf, null: %f, min: %lf, max: %lf, scale: %f\n", index, sum, preCalc->kernel->kernel[0][0], min, max, scale2D);
     274        fprintf(stderr, "%d sum: %lf, sum2: %lf, null: %f, min: %lf, max: %lf, scale: %f\n", index, Sum, Sum2, preCalc->kernel->kernel[0][0], min, max, scale2D);
    259275    }
    260276#endif
     
    267283    }
    268284    kernels->preCalc->data[index] = preCalc;
    269     kernels->penalties->data.F32[index] = kernels->penalty * penalty;
    270     psAssert (isfinite(kernels->penalties->data.F32[index]), "invalid penalty");
    271     psTrace("psModules.imcombine", 7, "Kernel %d: %f %d %d %f\n", index, fwhm, uOrder, vOrder, penalty);
     285    psTrace("psModules.imcombine", 7, "Kernel %d: %f %d %d\n", index, fwhm, uOrder, vOrder);
    272286
    273287    return true;
     
    321335
    322336                pmSubtractionKernelPreCalc *preCalc = pmSubtractionKernelPreCalcAlloc(PM_SUBTRACTION_KERNEL_ISIS, uOrder, vOrder, size, sigma); // structure to hold precalculated values
    323                 pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, size, uOrder, vOrder, fwhms->data.F32[i], true, false);
    324                 // pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, size, uOrder, vOrder, fwhms->data.F32[i], false, false);
     337                pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, uOrder, vOrder, fwhms->data.F32[i], true, false);
     338                // pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, uOrder, vOrder, fwhms->data.F32[i], false, false);
    325339            }
    326340        }
     
    379393            for (int vOrder = 0; vOrder <= orders->data.S32[i] - uOrder; vOrder++, index++) {
    380394                pmSubtractionKernelPreCalc *preCalc = pmSubtractionKernelPreCalcAlloc(PM_SUBTRACTION_KERNEL_ISIS, uOrder, vOrder, size, sigma); // structure to hold precalculated values
    381                 pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, size, uOrder, vOrder, fwhms->data.F32[i], true, false);
     395                pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, uOrder, vOrder, fwhms->data.F32[i], true, false);
    382396            }
    383397        }
     
    385399            // XXX modify size for hermitians to account for sqrt(2) in Hermitian definition (relative to ISIS Gaussian)
    386400            pmSubtractionKernelPreCalc *preCalc = pmSubtractionKernelPreCalcAlloc(PM_SUBTRACTION_KERNEL_ISIS_RADIAL, order, order, size, sigma / sqrt(2.0)); // structure to hold precalculated values
    387             pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, size, order, order, fwhms->data.F32[i], true, true);
     401            pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, order, order, fwhms->data.F32[i], true, true);
    388402        }
    389403    }
     
    437451            for (int vOrder = 0; vOrder <= orders->data.S32[i] - uOrder; vOrder++, index++) {
    438452                pmSubtractionKernelPreCalc *preCalc = pmSubtractionKernelPreCalcAlloc(PM_SUBTRACTION_KERNEL_HERM, uOrder, vOrder, size, sigma); // structure to hold precalculated values
    439                 pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, size, uOrder, vOrder, fwhms->data.F32[i], true, false);
     453                pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, uOrder, vOrder, fwhms->data.F32[i], true, false);
    440454            }
    441455        }
     
    506520
    507521                // XXX do we use Alard-Lupton normalization (last param true) or not?
    508                 pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, size, uOrder, vOrder, fwhms->data.F32[i], true, false);
     522                pmSubtractionKernelPreCalcNormalize (kernels, preCalc, index, uOrder, vOrder, fwhms->data.F32[i], true, false);
    509523
    510524                // XXXX test demo that deconvolved kernel is valid
     
    572586    kernels->preCalc = psArrayAlloc(numBasisFunctions);
    573587    kernels->penalty = penalty;
    574     kernels->penalties = psVectorAlloc(numBasisFunctions, PS_TYPE_F32);
     588    kernels->penalties1 = psVectorAlloc(numBasisFunctions, PS_TYPE_F32);
     589    psVectorInit(kernels->penalties1, NAN);
     590    kernels->penalties2 = psVectorAlloc(numBasisFunctions, PS_TYPE_F32);
     591    psVectorInit(kernels->penalties2, NAN);
     592    kernels->havePenalties = false;
    575593    kernels->size = size;
    576594    kernels->inner = 0;
     
    771789
    772790    psWarning("Kernel penalty for dual-convolution is not configured for SPAM kernels.");
    773     psVectorInit(kernels->penalties, 0.0);
     791    psVectorInit(kernels->penalties1, 0.0);
     792    psVectorInit(kernels->penalties2, 0.0);
    774793
    775794    return kernels;
     
    866885
    867886    psWarning("Kernel penalty for dual-convolution is not configured for FRIES kernels.");
    868     psVectorInit(kernels->penalties, 0.0);
     887    psVectorInit(kernels->penalties1, 0.0);
     888    psVectorInit(kernels->penalties2, 0.0);
    869889
    870890    return kernels;
     
    10401060                kernels->u->data.S32[index] = uOrder;
    10411061                kernels->v->data.S32[index] = vOrder;
    1042                 kernels->penalties->data.F32[index] = kernels->penalty * fabsf(moment);
    1043                 if (!isfinite(kernels->penalties->data.F32[index])) {
     1062
     1063                // XXX convert to use the convolved 2nd moment
     1064                kernels->penalties1->data.F32[index] = kernels->penalty * fabsf(moment);
     1065                if (!isfinite(kernels->penalties1->data.F32[index])) {
     1066                    psAbort ("invalid penalty");
     1067                }
     1068                kernels->penalties2->data.F32[index] = kernels->penalty * fabsf(moment);
     1069                if (!isfinite(kernels->penalties2->data.F32[index])) {
    10441070                    psAbort ("invalid penalty");
    10451071                }
     
    12471273    out->preCalc = psMemIncrRefCounter(in->preCalc);
    12481274    out->penalty = in->penalty;
    1249     out->penalties = psMemIncrRefCounter(in->penalties);
     1275    out->penalties1 = psMemIncrRefCounter(in->penalties1);
     1276    out->penalties2 = psMemIncrRefCounter(in->penalties2);
    12501277    out->uStop = psMemIncrRefCounter(in->uStop);
    12511278    out->vStop = psMemIncrRefCounter(in->vStop);
  • trunk/psModules/src/imcombine/pmSubtractionKernels.h

    r26893 r29004  
    3939    psArray *preCalc;                   ///< Array of images containing pre-calculated kernel (for ISIS, HERM or DECONV_HERM)
    4040    float penalty;                      ///< Penalty for wideness
    41     psVector *penalties;                ///< Penalty for each kernel component
     41    psVector *penalties1;               ///< Penalty for each kernel component
     42    psVector *penalties2;               ///< Penalty for each kernel component
     43    bool havePenalties;                 ///< flag to test if we have already calculated the penalties or not.
    4244    int size;                           ///< The half-size of the kernel
    4345    int inner;                          ///< The size of an inner region
     
    308310    );
    309311
    310 
    311312#endif
  • trunk/psModules/src/imcombine/pmSubtractionMatch.c

    r28405 r29004  
    13041304    float scale = PS_MAX(fwhm1, fwhm2) / scaleRef;      // Scaling factor
    13051305
     1306    // XXX save these values in a static for later use
     1307    pmSubtractionSetFWHMs(fwhm1, fwhm2);
     1308
    13061309    if (isfinite(scaleMin) && scale < scaleMin) {
    13071310        scale = scaleMin;
  • trunk/psModules/src/imcombine/pmSubtractionMatch.h

    r26893 r29004  
    110110    );
    111111
    112 
    113112#endif
  • trunk/psModules/src/imcombine/pmSubtractionStamps.c

    r27402 r29004  
    77#include <pslib.h>
    88
     9#include "pmErrorCodes.h"
     10#include "pmHDU.h"
     11#include "pmFPA.h"
     12
    913// All these includes required to get stamps out of an array of pmSources
    10 #include "pmMoments.h"
     14#include "pmTrend2D.h"
     15#include "pmResiduals.h"
     16#include "pmGrowthCurve.h"
    1117#include "pmSpan.h"
     18#include "pmFootprintSpans.h"
    1219#include "pmFootprint.h"
    1320#include "pmPeaks.h"
    14 #include "pmResiduals.h"
    15 #include "pmHDU.h"
    16 #include "pmFPA.h"
    17 #include "pmGrowthCurve.h"
    18 #include "pmTrend2D.h"
    19 #include "pmPSF.h"
     21#include "pmMoments.h"
     22#include "pmModelFuncs.h"
    2023#include "pmModel.h"
     24#include "pmSourceMasks.h"
     25#include "pmSourceExtendedPars.h"
     26#include "pmSourceDiffStats.h"
    2127#include "pmSource.h"
    22 #include "pmErrorCodes.h"
    2328
    2429#include "pmSubtraction.h"
     
    4651    psFree(list->y);
    4752    psFree(list->flux);
    48     psFree(list->window);
     53    psFree(list->window1);
     54    psFree(list->window2);
    4955}
    5056
     
    225231    list->y = NULL;
    226232    list->flux = NULL;
    227     list->window = NULL;
    228233    list->normFrac = normFrac;
    229     list->normWindow = 0;
     234    list->window1 = NULL;
     235    list->window2 = NULL;
     236    list->normWindow1 = 0;
     237    list->normWindow2 = 0;
    230238    list->footprint = footprint;
    231239    list->sysErr = sysErr;
     
    248256    out->y = NULL;
    249257    out->flux = NULL;
    250     out->window = psMemIncrRefCounter(in->window);
     258    out->window1 = psMemIncrRefCounter(in->window1);
     259    out->window2 = psMemIncrRefCounter(in->window2);
    251260    out->footprint = in->footprint;
    252     out->normWindow = in->normWindow;
     261    out->normWindow1 = in->normWindow1;
     262    out->normWindow2 = in->normWindow2;
    253263
    254264    for (int i = 0; i < num; i++) {
     
    638648    int size = stamps->footprint; // Size of postage stamps
    639649
    640     psFree (stamps->window);
    641     stamps->window = psKernelAlloc(-size, size, -size, size);
    642     psImageInit(stamps->window->image, 0.0);
     650    psFree (stamps->window1);
     651    stamps->window1 = psKernelAlloc(-size, size, -size, size);
     652    psImageInit(stamps->window1->image, 0.0);
     653
     654    psFree (stamps->window2);
     655    stamps->window2 = psKernelAlloc(-size, size, -size, size);
     656    psImageInit(stamps->window2->image, 0.0);
    643657
    644658    // generate normalizations for each stamp
     
    669683
    670684    // generate the window pixels
    671     double sum = 0.0;                   // Sum inside the window
    672     float maxValue = 0.0;               // Maximum value, for normalisation
     685    double sum1 = 0.0;                   // Sum inside the window
     686    double sum2 = 0.0;                   // Sum inside the window
     687    float maxValue1 = 0.0;               // Maximum value, for normalisation
     688    float maxValue2 = 0.0;               // Maximum value, for normalisation
    673689    for (int y = -size; y <= size; y++) {
    674690        for (int x = -size; x <= size; x++) {
     
    691707            }
    692708            float f1 = stats->robustMedian;
     709
    693710            psStatsInit (stats);
    694711            if (!psVectorStats (stats, flux2, NULL, NULL, 0)) {
     
    697714            float f2 = stats->robustMedian;
    698715
    699             stamps->window->kernel[y][x] = f1 + f2;
     716            stamps->window1->kernel[y][x] = f1;
    700717            if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(size)) {
    701                 sum += stamps->window->kernel[y][x];
    702             }
    703             maxValue = PS_MAX(maxValue, stamps->window->kernel[y][x]);
    704         }
    705     }
    706 
    707     psTrace("psModules.imcombine", 3, "Window total: %f, threshold: %f\n",
    708             sum, (1.0 - stamps->normFrac) * sum);
    709     bool done = false;
    710     for (int radius = 1; radius <= size && !done; radius++) {
    711         double within = 0.0;
     718                sum1 += stamps->window1->kernel[y][x];
     719            }
     720            maxValue1 = PS_MAX(maxValue1, stamps->window1->kernel[y][x]);
     721
     722            stamps->window2->kernel[y][x] = f2;
     723            if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(size)) {
     724                sum2 += stamps->window2->kernel[y][x];
     725            }
     726            maxValue2 = PS_MAX(maxValue2, stamps->window2->kernel[y][x]);
     727        }
     728    }
     729
     730    psTrace("psModules.imcombine", 3, "Window total (1): %f, threshold: %f\n", sum1, (1.0 - stamps->normFrac) * sum1);
     731    psTrace("psModules.imcombine", 3, "Window total (2): %f, threshold: %f\n", sum2, (1.0 - stamps->normFrac) * sum2);
     732
     733# if (0)
     734    // this block attempts to calculate the radius based on the first radial moment
     735    bool done1 = false;
     736    bool done2 = false;
     737    double prior1 = 0.0;
     738    double prior2 = 0.0;
     739    for (int y = -size; y <= size; y++) {
     740        for (int x = -size; x <= size; x++) {
     741            float r = hypot(x, y);
     742            Sr1 += r * stamps->window1->kernel[y][x];
     743            Sr2 += r * stamps->window2->kernel[y][x];
     744            Sf1 += stamps->window1->kernel[y][x];
     745            Sf2 += stamps->window2->kernel[y][x];
     746        }
     747    }
     748   
     749    float R1 = Sr1 / Sf1;
     750    float R2 = Sr2 / Sf2;
     751
     752    stamps->normWindow1 = 2.5*R1;
     753    stamps->normWindow1 = 2.5*R2;
     754# else
     755    // XXX : this block attempts to calculate the radius by looking at the curve of growth (or something vaguely equivalent).
     756    // It did not do very well (though a true curve-of-growth analysis might be better...)
     757    bool done1 = false;
     758    bool done2 = false;
     759    double prior1 = 0.0;
     760    double prior2 = 0.0;
     761    double delta1o = 1.0;
     762    double delta2o = 1.0;
     763    for (int radius = 1; radius <= size && !(done1 && done2); radius++) {
     764        double within1 = 0.0;
     765        double within2 = 0.0;
    712766        for (int y = -radius; y <= radius; y++) {
    713767            for (int x = -radius; x <= radius; x++) {
    714768                if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(radius)) {
    715                     within += stamps->window->kernel[y][x];
     769                    within1 += stamps->window1->kernel[y][x];
    716770                }
    717             }
    718         }
    719         psTrace("psModules.imcombine", 5, "Radius %d: %f\n", radius, within);
    720         if (within > (1.0 - stamps->normFrac) * sum) {
    721             stamps->normWindow = radius;
    722             done = true;
    723         }
    724     }
    725 
    726     psTrace("psModules.imcombine", 3, "Normalisation window radius set to %d\n", stamps->normWindow);
    727     if (stamps->normWindow == 0 || stamps->normWindow >= size) {
    728         psError(PM_ERR_STAMPS, true, "Unable to determine normalisation window size.");
     771                if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(radius)) {
     772                    within2 += stamps->window2->kernel[y][x];
     773                }
     774            }
     775        }
     776        double delta1 = (within1 - prior1) / within1;
     777        if (!done1 && (fabs(delta1) < stamps->normFrac)) {
     778            // interpolate to the radius at which delta2 is normFrac:
     779            stamps->normWindow1 = radius - (stamps->normFrac - delta1) / (delta1o - delta1);
     780            fprintf (stderr, "choosing %f (%d) for 1 (%f : %f)\n", stamps->normWindow1, radius, within1, delta1);
     781            done1 = true;
     782        }
     783        double delta2 = (within2 - prior2) / within2;
     784        if (!done2 && (fabs(delta2) < stamps->normFrac)) {
     785            // interpolate to the radius at which delta2 is normFrac:
     786            stamps->normWindow2 = radius - (stamps->normFrac - delta2) / (delta2o - delta2);
     787            fprintf (stderr, "choosing %f (%d) for 2 (%f : %f)\n", stamps->normWindow2, radius, within2, delta2);
     788            done2 = true;
     789        }
     790        psTrace("psModules.imcombine", 5, "Radius %d: %f (%f) and %f (%f)\n", radius, within1, delta1, within2, delta2);
     791
     792        prior1 = within1;
     793        prior2 = within2;
     794        delta1o = delta1;
     795        delta2o = delta2;
     796
     797        // if (!done1 && (within1 > (1.0 - stamps->normFrac) * sum1)) {
     798        //     stamps->normWindow1 = radius;
     799        //     done1 = true;
     800        // }
     801        // if (!done2 && (within2 > (1.0 - stamps->normFrac) * sum2)) {
     802        //     stamps->normWindow2 = radius;
     803        //     done2 = true;
     804        // }
     805
     806    }
     807# endif
     808
     809    psTrace("psModules.imcombine", 3, "Normalisation window radii set to %f and %f\n", stamps->normWindow1, stamps->normWindow2);
     810    if (stamps->normWindow1 == 0 || stamps->normWindow1 >= size) {
     811        psError(PM_ERR_STAMPS, true, "Unable to determine normalisation window size (1).");
     812        return false;
     813    }
     814    if (stamps->normWindow2 == 0 || stamps->normWindow2 >= size) {
     815        psError(PM_ERR_STAMPS, true, "Unable to determine normalisation window size (2).");
    729816        return false;
    730817    }
     
    733820    for (int y = -size; y <= size; y++) {
    734821        for (int x = -size; x <= size; x++) {
    735             stamps->window->kernel[y][x] /= maxValue;
    736         }
    737     }
    738 
    739 #if 0
     822            stamps->window1->kernel[y][x] /= maxValue1;
     823        }
     824    }
     825    // re-normalize so chisquare values are sensible
     826    for (int y = -size; y <= size; y++) {
     827        for (int x = -size; x <= size; x++) {
     828            stamps->window2->kernel[y][x] /= maxValue2;
     829        }
     830    }
     831
     832#if 1
    740833    {
    741         psFits *fits = psFitsOpen ("window.fits", "w");
    742         psFitsWriteImage (fits, NULL, stamps->window->image, 0, NULL);
     834        psFits *fits = NULL;
     835        fits = psFitsOpen ("window1.fits", "w");
     836        psFitsWriteImage (fits, NULL, stamps->window1->image, 0, NULL);
     837        psFitsClose (fits);
     838        fits = psFitsOpen ("window2.fits", "w");
     839        psFitsWriteImage (fits, NULL, stamps->window2->image, 0, NULL);
    743840        psFitsClose (fits);
    744841    }
     
    747844    psFree (stats);
    748845    psFree (flux1);
    749     psFree(flux2);
     846    psFree (flux2);
    750847    psFree (norm1);
    751848    psFree (norm2);
    752849    return true;
     850}
     851
     852static pthread_mutex_t getPenaltiesMutex = PTHREAD_MUTEX_INITIALIZER;
     853
     854// kernels->penalty is an overall scaling factor (user-supplied)
     855bool pmSubtractionKernelPenaltiesStamp(pmSubtractionStamp *stamp, pmSubtractionKernels *kernels)
     856{
     857    // we only need the penalties if we are doing dual convolution
     858    if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) return true;
     859
     860    // we only calculate the penalties once.
     861    if (kernels->havePenalties) return true;
     862
     863    // in a threaded context, only one thread can calculate the penalties.  attempt to grab a
     864    // mutex before continuing
     865    pthread_mutex_lock(&getPenaltiesMutex);
     866
     867    // did someone else already get the mutex and do this?
     868    if (kernels->havePenalties) {
     869        pthread_mutex_unlock(&getPenaltiesMutex);
     870        return true;
     871    }
     872
     873    for (int i = 0; i < kernels->num; i++) {
     874        pmSubtractionKernelPenalties(stamp, kernels, i);
     875    }
     876
     877    kernels->havePenalties = true;
     878    pthread_mutex_unlock(&getPenaltiesMutex);
     879    return true;
     880}
     881
     882# define EMPIRICAL 0
     883
     884// kernels->penalty is an overall scaling factor (user-supplied)
     885bool pmSubtractionKernelPenalties(pmSubtractionStamp *stamp, pmSubtractionKernels *kernels, int index)
     886{
     887    float penalty1, penalty2;
     888    float fwhm1, fwhm2;
     889
     890    // XXX this is annoyingly hack-ish
     891    pmSubtractionGetFWHMs(&fwhm1, &fwhm2);
     892
     893    bool zeroNull = false;
     894    int uOrder = kernels->u->data.S32[index];
     895    int vOrder = kernels->v->data.S32[index];
     896    if (uOrder % 2 == 0 && vOrder % 2 == 0) zeroNull = true;
     897
     898    if (EMPIRICAL) {
     899        psKernel *convolution1 = stamp->convolutions1->data[index];
     900        penalty1 = pmSubtractionKernelPenaltySingle(convolution1, zeroNull);
     901
     902        psKernel *convolution2 = stamp->convolutions2->data[index];
     903        penalty2 = pmSubtractionKernelPenaltySingle(convolution2, zeroNull);
     904    } else {
     905        pmSubtractionKernelPreCalc *kernel = kernels->preCalc->data[index];
     906        float M2 = pmSubtractionKernelPenaltySingle(kernel->kernel, zeroNull);
     907
     908        penalty1 = M2 + PS_SQR(fwhm1 / 2.35); // rescale the unconvolved second-moment by the image second moment
     909        penalty2 = M2 + PS_SQR(fwhm2 / 2.35); // rescale the unconvolved second-moment by the image second moment
     910    }
     911    kernels->penalties1->data.F32[index] = kernels->penalty * penalty1;
     912    psAssert (isfinite(kernels->penalties1->data.F32[index]), "invalid penalty");
     913
     914    kernels->penalties2->data.F32[index] = kernels->penalty * penalty2;
     915    psAssert (isfinite(kernels->penalties2->data.F32[index]), "invalid penalty");
     916
     917    fprintf(stderr, "penalty1: %f, penalty2: %f\n", penalty1, penalty2);
     918
     919    return true;
     920}
     921
     922float pmSubtractionKernelPenaltySingle(psKernel *kernel, bool zeroNull)
     923{
     924    // Calculate moments
     925    double penalty = 0.0;                   // Moment, for penalty
     926    double sum = 0.0, sum2 = 0.0;           // Sum of kernel component
     927    float min = INFINITY, max = -INFINITY;  // Minimum and maximum kernel value
     928    for (int v = kernel->yMin; v <= kernel->yMax; v++) {
     929        for (int u = kernel->xMin; u <= kernel->xMax; u++) {
     930            double value = kernel->kernel[v][u];
     931            if (false && zeroNull && (u == 0) && (v == 0)) {
     932                value += 1.0;
     933            }
     934            double value2 = PS_SQR(value);
     935            sum += value;
     936            sum2 += value2;
     937            penalty += value2 * PS_SQR((PS_SQR(u) + PS_SQR(v)));
     938            min = PS_MIN(value, min);
     939            max = PS_MAX(value, max);
     940        }
     941    }
     942    penalty *= 1.0 / sum2;
     943
     944    if (1) {
     945        fprintf(stderr, "min: %lf, max: %lf, moment: %lf, flux^2: %lf\n", min, max, penalty, sum2);
     946        // psTrace("psModules.imcombine", 7, "Kernel %d: %f %d %d %f\n", index, fwhm, uOrder, vOrder, penalty);
     947    }
     948
     949    return penalty;
    753950}
    754951
  • trunk/psModules/src/imcombine/pmSubtractionStamps.h

    r26893 r29004  
    2424    psArray *flux;                      ///< Fluxes for possible stamps (or NULL)
    2525    int footprint;                      ///< Half-size of stamps
    26     psKernel *window;                   ///< window function generated from ensemble of stamps
    2726    float normFrac;                     ///< Fraction of flux in window for normalisation window
    28     int normWindow;                     ///< Size of window for measuring normalisation
     27    psKernel *window1;                  ///< window function generated from ensemble of stamps (input 1)
     28    psKernel *window2;                  ///< window function generated from ensemble of stamps (input 2)
     29    float normWindow1;                    ///< Size of window for measuring normalisation
     30    float normWindow2;                    ///< Size of window for measuring normalisation
    2931    float sysErr;                       ///< Systematic error
    3032    float skyErr;                       ///< increase effective readnoise
     
    195197bool pmSubtractionStampsResetStatus (pmSubtractionStampList *stamps);
    196198
     199
     200bool pmSubtractionKernelPenaltiesStamp(pmSubtractionStamp *stamp, pmSubtractionKernels *kernels);
     201bool pmSubtractionKernelPenalties(pmSubtractionStamp *stamp, pmSubtractionKernels *kernels, int index);
     202float pmSubtractionKernelPenaltySingle(psKernel *kernel, bool zeroNull);
     203
    197204#endif
  • trunk/psModules/src/imcombine/pmSubtractionVisual.c

    r26893 r29004  
    2121
    2222#include "pmVisual.h"
     23#include "pmVisualUtils.h"
    2324
    2425#include "pmHDU.h"
     
    6162 *    @return true for success */
    6263bool pmSubtractionVisualPlotConvKernels(psImage *convKernels) {
    63     if (!pmVisualIsVisual() || !plotConvKernels) return true;
     64
     65    if (!pmVisualTestLevel("ppsub.kernels", 1)) return true;
     66
     67    if (!plotConvKernels) return true;
     68
    6469    if (!pmVisualInitWindow(&kapa1, "ppSub:Images")) {
    6570        return false;
     
    7580    @return true for success */
    7681bool pmSubtractionVisualPlotStamps(pmSubtractionStampList *stamps, pmReadout *ro) {
    77     if (!pmVisualIsVisual() || !plotStamps) return true;
     82
     83    if (!pmVisualTestLevel("ppsub.stamps", 1)) return true;
     84
     85    if (!plotStamps) return true;
     86
    7887    if (!pmVisualInitWindow (&kapa1, "ppSub:Images")) {
    7988        return false;
     
    145154bool pmSubtractionVisualPlotLeastSquares (pmSubtractionStampList *stamps, bool dual) {
    146155
    147     if (!pmVisualIsVisual() || !plotLeastSquares) return true;
     156    if (!pmVisualTestLevel("ppsub.chisq", 1)) return true;
     157
     158    if (!plotLeastSquares) return true;
     159
    148160    if (!pmVisualInitWindow (&kapa1, "PPSub:Images")) {
    149161        return false;
     
    204216
    205217bool pmSubtractionVisualShowSubtraction(psImage *image, psImage *ref, psImage *sub) {
    206     if (!pmVisualIsVisual() || !plotImage) return true;
     218
     219    if (!pmVisualTestLevel("ppsub.images.sub", 1)) return true;
     220
     221    if (!plotImage) return true;
     222
    207223    if (!pmVisualInitWindow (&kapa1, "PPSub:Images")) {
    208224        return false;
     
    218234bool pmSubtractionVisualShowKernels(pmSubtractionKernels *kernels) {
    219235
    220     if (!pmVisualIsVisual()) return true;
     236    if (!pmVisualTestLevel("ppsub.kernels.final", 1)) return true;
     237
    221238    if (!pmVisualInitWindow (&kapa1, "PPSub:Images")) {
    222239        return false;
     
    264281bool pmSubtractionVisualShowBasis(pmSubtractionStampList *stamps) {
    265282
    266     if (!pmVisualIsVisual()) return true;
     283    if (!pmVisualTestLevel("ppsub.basis", 1)) return true;
     284
    267285    if (!pmVisualInitWindow (&kapa2, "ppSub:StampMasterImage")) {
    268286        return false;
     
    425443bool pmSubtractionVisualShowFitInit(pmSubtractionStampList *stamps) {
    426444
    427     if (!pmVisualIsVisual()) return true;
     445    if (!pmVisualTestLevel("ppsub.fit", 1)) return true;
    428446
    429447    // generate 4 storage images large enough to hold the N stamps:
     
    462480bool pmSubtractionVisualShowFitAddStamp(psKernel *target, psKernel *source, psKernel *convolution, double background, double norm, int index) {
    463481
    464     if (!pmVisualIsVisual()) return true;
     482    if (!pmVisualTestLevel("ppsub.stamp", 1)) return true;
    465483
    466484    double sum;
     
    543561    }
    544562
    545     if (!pmVisualIsVisual()) return true;
     563    if (!pmVisualTestLevel("ppsub.fit", 1)) return true;
     564
    546565    if (!pmVisualInitWindow(&kapa1, "ppSub:Images")) return false;
    547566    if (!pmVisualInitWindow(&kapa2, "ppSub:Misc")) return false;
     
    605624    Graphdata graphdata;
    606625
    607     if (!pmVisualIsVisual()) return true;
     626    if (!pmVisualTestLevel("ppsub.fit", 1)) return true;
     627
    608628    if (!pmVisualInitWindow(&kapa3, "ppSub:plots")) return false;
    609629
  • trunk/psModules/src/objects/Makefile.am

    r28013 r29004  
    4343        pmSourceIO_CMF_PS1_V1.c \
    4444        pmSourceIO_CMF_PS1_V2.c \
     45        pmSourceIO_CMF_PS1_V3.c \
    4546        pmSourceIO_CMF_PS1_SV1.c \
    4647        pmSourceIO_CMF_PS1_DV1.c \
     48        pmSourceIO_CMF_PS1_DV2.c \
    4749        pmSourceIO_MatchedRefs.c \
    4850        pmSourcePlots.c \
     
    6062        pmPSFtryFitPSF.c \
    6163        pmPSFtryMetric.c \
     64        pmPCMdata.c \
     65        pmPCM_MinimizeChisq.c \
     66        pmSourceFitPCM.c \
    6267        pmTrend2D.c \
    6368        pmGrowthCurveGenerate.c \
     
    7176        models/pmModel_QGAUSS.c \
    7277        models/pmModel_RGAUSS.c \
    73         models/pmModel_SERSIC.c
     78        models/pmModel_SERSIC.c \
     79        models/pmModel_EXP.c \
     80        models/pmModel_DEV.c
    7481
    7582pkginclude_HEADERS = \
     
    8087        pmPeaks.h \
    8188        pmMoments.h \
     89        pmModelFuncs.h \
    8290        pmModel.h \
    8391        pmModelClass.h \
     
    101109        pmPSF_IO.h \
    102110        pmPSFtry.h \
     111        pmPCMdata.h \
    103112        pmTrend2D.h \
    104113        pmGrowthCurve.h \
     
    111120        models/pmModel_QGAUSS.h \
    112121        models/pmModel_RGAUSS.h \
    113         models/pmModel_SERSIC.h
     122        models/pmModel_SERSIC.h \
     123        models/pmModel_EXP.h \
     124        models/pmModel_DEV.h
    114125
    115126CLEANFILES = *~
  • trunk/psModules/src/objects/models/pmModel_GAUSS.c

    r26916 r29004  
    2121#include <stdio.h>
    2222#include <pslib.h>
    23 
     23#include "pmHDU.h"
     24#include "pmFPA.h"
     25
     26#include "pmTrend2D.h"
     27#include "pmResiduals.h"
     28#include "pmGrowthCurve.h"
     29#include "pmSpan.h"
     30#include "pmFootprintSpans.h"
     31#include "pmFootprint.h"
     32#include "pmPeaks.h"
    2433#include "pmMoments.h"
    25 #include "pmPeaks.h"
     34#include "pmModelFuncs.h"
     35#include "pmModel.h"
     36#include "pmModelUtils.h"
     37#include "pmModelClass.h"
     38#include "pmSourceMasks.h"
     39#include "pmSourceExtendedPars.h"
     40#include "pmSourceDiffStats.h"
    2641#include "pmSource.h"
    27 #include "pmModel.h"
     42#include "pmSourceFitModel.h"
     43#include "pmPSF.h"
     44#include "pmPSFtry.h"
     45#include "pmDetections.h"
     46
    2847#include "pmModel_GAUSS.h"
    2948
     49# define PM_MODEL_NPARAM          7
    3050# define PM_MODEL_FUNC            pmModelFunc_GAUSS
    3151# define PM_MODEL_FLUX            pmModelFlux_GAUSS
     
    83103        dPAR[PM_PAR_XPOS] = q*(2*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]);
    84104        dPAR[PM_PAR_YPOS] = q*(2*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]);
     105
    85106        // the extra factor of 2 below is needed to avoid excessive swings
    86107        dPAR[PM_PAR_SXX]  = +4.0*q*px*px/PAR[PM_PAR_SXX];
     
    102123        return true;
    103124    }
    104     psAssert(nParam >= 0 && nParam <= PM_PAR_7, "Parameter index is out of bounds");
     125    psAssert(nParam >= 0 && nParam < PM_MODEL_NPARAM, "Parameter index is out of bounds");
    105126
    106127    // we need to calculate the limits for SXY specially
     
    347368// this test is invalid if the parameters are derived
    348369// from the PSF model
     370// XXX how is this used?  it prevents forced photometry from ever being 'successful'
    349371bool PM_MODEL_FIT_STATUS (pmModel *model)
    350372{
     
    394416    return;
    395417}
    396 
    397 # undef PM_MODEL_FUNC
    398 # undef PM_MODEL_FLUX
    399 # undef PM_MODEL_GUESS
    400 # undef PM_MODEL_LIMITS
    401 # undef PM_MODEL_RADIUS
    402 # undef PM_MODEL_FROM_PSF
    403 # undef PM_MODEL_PARAMS_FROM_PSF
    404 # undef PM_MODEL_FIT_STATUS
    405 # undef PM_MODEL_SET_LIMITS
  • trunk/psModules/src/objects/models/pmModel_PGAUSS.c

    r27565 r29004  
    2121#include <stdio.h>
    2222#include <pslib.h>
    23 
     23#include "pmHDU.h"
     24#include "pmFPA.h"
     25
     26#include "pmTrend2D.h"
     27#include "pmResiduals.h"
     28#include "pmGrowthCurve.h"
     29#include "pmSpan.h"
     30#include "pmFootprintSpans.h"
     31#include "pmFootprint.h"
     32#include "pmPeaks.h"
    2433#include "pmMoments.h"
    25 #include "pmPeaks.h"
     34#include "pmModelFuncs.h"
     35#include "pmModel.h"
     36#include "pmModelUtils.h"
     37#include "pmModelClass.h"
     38#include "pmSourceMasks.h"
     39#include "pmSourceExtendedPars.h"
     40#include "pmSourceDiffStats.h"
    2641#include "pmSource.h"
    27 #include "pmModel.h"
     42#include "pmSourceFitModel.h"
     43#include "pmPSF.h"
     44#include "pmPSFtry.h"
     45#include "pmDetections.h"
     46
    2847#include "pmModel_PGAUSS.h"
    2948
     49# define PM_MODEL_NPARAM          7
    3050# define PM_MODEL_FUNC            pmModelFunc_PGAUSS
    3151# define PM_MODEL_FLUX            pmModelFlux_PGAUSS
     
    103123        return true;
    104124    }
    105     psAssert(nParam >= 0 && nParam <= PM_PAR_7, "Parameter index is out of bounds");
     125    psAssert(nParam >= 0 && nParam < PM_MODEL_NPARAM, "Parameter index is out of bounds");
    106126
    107127    // we need to calculate the limits for SXY specially
     
    448468    return;
    449469}
    450 
    451 # undef PM_MODEL_FUNC
    452 # undef PM_MODEL_FLUX
    453 # undef PM_MODEL_GUESS
    454 # undef PM_MODEL_LIMITS
    455 # undef PM_MODEL_RADIUS
    456 # undef PM_MODEL_FROM_PSF
    457 # undef PM_MODEL_PARAMS_FROM_PSF
    458 # undef PM_MODEL_FIT_STATUS
    459 # undef PM_MODEL_SET_LIMITS
  • trunk/psModules/src/objects/models/pmModel_PS1_V1.c

    r27565 r29004  
    2222#include <stdio.h>
    2323#include <pslib.h>
    24 
     24#include "pmHDU.h"
     25#include "pmFPA.h"
     26
     27#include "pmTrend2D.h"
     28#include "pmResiduals.h"
     29#include "pmGrowthCurve.h"
     30#include "pmSpan.h"
     31#include "pmFootprintSpans.h"
     32#include "pmFootprint.h"
     33#include "pmPeaks.h"
    2534#include "pmMoments.h"
    26 #include "pmPeaks.h"
     35#include "pmModelFuncs.h"
     36#include "pmModel.h"
     37#include "pmModelUtils.h"
     38#include "pmModelClass.h"
     39#include "pmSourceMasks.h"
     40#include "pmSourceExtendedPars.h"
     41#include "pmSourceDiffStats.h"
    2742#include "pmSource.h"
    28 #include "pmModel.h"
     43#include "pmSourceFitModel.h"
     44#include "pmPSF.h"
     45#include "pmPSFtry.h"
     46#include "pmDetections.h"
     47
    2948#include "pmModel_PS1_V1.h"
    3049
     50# define PM_MODEL_NPARAM          8
    3151# define PM_MODEL_FUNC            pmModelFunc_PS1_V1
    3252# define PM_MODEL_FLUX            pmModelFlux_PS1_V1
     
    122142        return true;
    123143    }
    124     psAssert(nParam >= 0 && nParam <= PM_PAR_7, "Parameter index is out of bounds");
     144    psAssert(nParam >= 0 && nParam < PM_MODEL_NPARAM, "Parameter index is out of bounds");
    125145
    126146    // we need to calculate the limits for SXY specially
     
    222242    PAR[PM_PAR_SYY]  = PS_MAX(0.5, M_SQRT2*shape.sy);
    223243    PAR[PM_PAR_SXY]  = shape.sxy;
    224     PAR[PM_PAR_7]    = 1.0;
     244    PAR[PM_PAR_7]    = 0.5;
    225245
    226246    return(true);
     
    468488    return;
    469489}
    470 
    471 # undef PM_MODEL_FUNC
    472 # undef PM_MODEL_FLUX
    473 # undef PM_MODEL_GUESS
    474 # undef PM_MODEL_LIMITS
    475 # undef PM_MODEL_RADIUS
    476 # undef PM_MODEL_FROM_PSF
    477 # undef PM_MODEL_PARAMS_FROM_PSF
    478 # undef PM_MODEL_FIT_STATUS
    479 # undef PM_MODEL_SET_LIMITS
    480 # undef ALPHA
    481 # undef ALPHA_M
  • trunk/psModules/src/objects/models/pmModel_QGAUSS.c

    r27565 r29004  
    2222#include <stdio.h>
    2323#include <pslib.h>
    24 
     24#include "pmHDU.h"
     25#include "pmFPA.h"
     26
     27#include "pmTrend2D.h"
     28#include "pmResiduals.h"
     29#include "pmGrowthCurve.h"
     30#include "pmSpan.h"
     31#include "pmFootprintSpans.h"
     32#include "pmFootprint.h"
     33#include "pmPeaks.h"
    2534#include "pmMoments.h"
    26 #include "pmPeaks.h"
     35#include "pmModelFuncs.h"
     36#include "pmModel.h"
     37#include "pmModelUtils.h"
     38#include "pmModelClass.h"
     39#include "pmSourceMasks.h"
     40#include "pmSourceExtendedPars.h"
     41#include "pmSourceDiffStats.h"
    2742#include "pmSource.h"
    28 #include "pmModel.h"
     43#include "pmSourceFitModel.h"
     44#include "pmPSF.h"
     45#include "pmPSFtry.h"
     46#include "pmDetections.h"
     47
    2948#include "pmModel_QGAUSS.h"
    3049
     50# define PM_MODEL_NPARAM          8
    3151# define PM_MODEL_FUNC            pmModelFunc_QGAUSS
    3252# define PM_MODEL_FLUX            pmModelFlux_QGAUSS
     
    123143        return true;
    124144    }
    125     psAssert(nParam >= 0 && nParam <= PM_PAR_7, "Parameter index is out of bounds");
     145    psAssert(nParam >= 0 && nParam < PM_MODEL_NPARAM, "Parameter index is out of bounds");
    126146
    127147    // we need to calculate the limits for SXY specially
     
    469489    return;
    470490}
    471 
    472 # undef PM_MODEL_FUNC
    473 # undef PM_MODEL_FLUX
    474 # undef PM_MODEL_GUESS
    475 # undef PM_MODEL_LIMITS
    476 # undef PM_MODEL_RADIUS
    477 # undef PM_MODEL_FROM_PSF
    478 # undef PM_MODEL_PARAMS_FROM_PSF
    479 # undef PM_MODEL_FIT_STATUS
    480 # undef PM_MODEL_SET_LIMITS
    481 # undef ALPHA
    482 # undef ALPHA_M
  • trunk/psModules/src/objects/models/pmModel_RGAUSS.c

    r27565 r29004  
    2222#include <stdio.h>
    2323#include <pslib.h>
    24 
     24#include "pmHDU.h"
     25#include "pmFPA.h"
     26
     27#include "pmTrend2D.h"
     28#include "pmResiduals.h"
     29#include "pmGrowthCurve.h"
     30#include "pmSpan.h"
     31#include "pmFootprintSpans.h"
     32#include "pmFootprint.h"
     33#include "pmPeaks.h"
    2534#include "pmMoments.h"
    26 #include "pmPeaks.h"
     35#include "pmModelFuncs.h"
     36#include "pmModel.h"
     37#include "pmModelUtils.h"
     38#include "pmModelClass.h"
     39#include "pmSourceMasks.h"
     40#include "pmSourceExtendedPars.h"
     41#include "pmSourceDiffStats.h"
    2742#include "pmSource.h"
    28 #include "pmModel.h"
     43#include "pmSourceFitModel.h"
     44#include "pmPSF.h"
     45#include "pmPSFtry.h"
     46#include "pmDetections.h"
     47
    2948#include "pmModel_RGAUSS.h"
    3049
     50# define PM_MODEL_NPARAM          8
    3151# define PM_MODEL_FUNC            pmModelFunc_RGAUSS
    3252# define PM_MODEL_FLUX            pmModelFlux_RGAUSS
     
    112132        return true;
    113133    }
    114     psAssert(nParam >= 0 && nParam <= PM_PAR_7, "Parameter index is out of bounds");
     134    psAssert(nParam >= 0 && nParam < PM_MODEL_NPARAM, "Parameter index is out of bounds");
    115135
    116136    // we need to calculate the limits for SXY specially
     
    209229    PAR[PM_PAR_XPOS] = peak->xf;
    210230    PAR[PM_PAR_YPOS] = peak->yf;
    211     PAR[PM_PAR_SXX]  = PS_MAX(0.5, M_SQRT2*shape.sx);
    212     PAR[PM_PAR_SYY]  = PS_MAX(0.5, M_SQRT2*shape.sy);
     231    PAR[PM_PAR_SXX]  = PS_MAX(0.5, shape.sx);
     232    PAR[PM_PAR_SYY]  = PS_MAX(0.5, shape.sy);
    213233    PAR[PM_PAR_SXY]  = shape.sxy;
    214     PAR[PM_PAR_7]    = 2.25;
     234    PAR[PM_PAR_7]    = 1.5;
    215235
    216236    return(true);
     
    463483    return;
    464484}
    465 
    466 # undef PM_MODEL_FUNC
    467 # undef PM_MODEL_FLUX
    468 # undef PM_MODEL_GUESS
    469 # undef PM_MODEL_LIMITS
    470 # undef PM_MODEL_RADIUS
    471 # undef PM_MODEL_FROM_PSF
    472 # undef PM_MODEL_PARAMS_FROM_PSF
    473 # undef PM_MODEL_FIT_STATUS
    474 # undef PM_MODEL_SET_LIMITS
  • trunk/psModules/src/objects/models/pmModel_SERSIC.c

    r26916 r29004  
    1818   * PM_PAR_7   7   - normalized sersic parameter
    1919
    20    note that a standard sersic model uses exp(-K*(z^(1/n) - 1).  the additional elements (K,
     20   note that a standard sersic model uses exp(-K*(z^(1/2n) - 1).  the additional elements (K,
    2121   the -1 offset) are absorbed in this model by the normalization, the exponent, and the
    2222   radial scale.  We fit the elements in this form, then re-normalize them on output.
     
    2525#include <stdio.h>
    2626#include <pslib.h>
    27 
     27#include "pmHDU.h"
     28#include "pmFPA.h"
     29
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
     33#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
     35#include "pmFootprint.h"
     36#include "pmPeaks.h"
    2837#include "pmMoments.h"
    29 #include "pmPeaks.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
    3045#include "pmSource.h"
    31 #include "pmModel.h"
     46#include "pmSourceFitModel.h"
     47#include "pmPSF.h"
     48#include "pmPSFtry.h"
     49#include "pmDetections.h"
     50
    3251#include "pmModel_SERSIC.h"
    3352
     53# define PM_MODEL_NPARAM          8
    3454# define PM_MODEL_FUNC            pmModelFunc_SERSIC
    3555# define PM_MODEL_FLUX            pmModelFlux_SERSIC
     
    4767
    4868// Lax parameter limits
    49 static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.05, 0.05, -1.0, 0.05 };
     69static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.001, 0.001, -1.0, 0.05 };
    5070static float paramsMaxLax[] = { 1.0e5, 1.0e8, 1.0e4, 1.0e4, 100, 100, 1.0, 4.0 };
    5171
     
    84104    assert (z >= 0);
    85105
    86     psF32 f2 = pow(z,PAR[PM_PAR_7]);
    87     psF32 f1 = exp(-f2);
     106    float index = 0.5 / PAR[PM_PAR_7];
     107    float bn = 1.9992*index - 0.3271;
     108    float Io = exp(bn);
     109
     110    psF32 f2 = bn*pow(z,PAR[PM_PAR_7]);
     111    psF32 f1 = Io*exp(-f2);
    88112    psF32 z0 = PAR[PM_PAR_I0]*f1;
    89113    psF32 f0 = PAR[PM_PAR_SKY] + z0;
     
    98122
    99123        // gradient is infinite for z = 0; saturate at z = 0.01
    100         psF32 z1 = (z < 0.01) ? z0*PAR[PM_PAR_7]*pow(0.01,PAR[PM_PAR_7] - 1.0) : z0*PAR[PM_PAR_7]*pow(z,PAR[PM_PAR_7] - 1.0);
     124        psF32 z1 = (z < 0.01) ? z0*bn*PAR[PM_PAR_7]*pow(0.01,PAR[PM_PAR_7] - 1.0) : z0*bn*PAR[PM_PAR_7]*pow(z,PAR[PM_PAR_7] - 1.0);
    101125
    102126        dPAR[PM_PAR_SKY]  = +1.0;
    103127        dPAR[PM_PAR_I0]   = +f1;
    104         dPAR[PM_PAR_7]    = (z == 0.0) ? 0.0 : -z0*f2*log(z);
     128        dPAR[PM_PAR_7]    = (z < 0.01) ? -z0*pow(0.01,PAR[PM_PAR_7])*log(0.01) : -z0*f2*log(z);
     129        dPAR[PM_PAR_7]   *= 3.0;
    105130
    106131        assert (isfinite(z1));
     
    109134        dPAR[PM_PAR_XPOS] = +1.0*z1*(2.0*px/PAR[PM_PAR_SXX] + Y*PAR[PM_PAR_SXY]);
    110135        dPAR[PM_PAR_YPOS] = +1.0*z1*(2.0*py/PAR[PM_PAR_SYY] + X*PAR[PM_PAR_SXY]);
    111         dPAR[PM_PAR_SXX]  = +2.0*z1*px*px/PAR[PM_PAR_SXX];
     136        dPAR[PM_PAR_SXX]  = +2.0*z1*px*px/PAR[PM_PAR_SXX]; // XXX : increase drag?
    112137        dPAR[PM_PAR_SYY]  = +2.0*z1*py*py/PAR[PM_PAR_SYY];
    113         dPAR[PM_PAR_SXY]  = -1.0*z1*X*Y;
    114138        dPAR[PM_PAR_SXY]  = -1.0*z1*X*Y;
    115139    }
     
    127151        return true;
    128152    }
    129     psAssert(nParam >= 0 && nParam <= PM_PAR_7, "Parameter index is out of bounds");
     153    psAssert(nParam >= 0 && nParam < PM_MODEL_NPARAM, "Parameter index is out of bounds");
    130154
    131155    // we need to calculate the limits for SXY specially
     
    201225    psF32     *PAR  = model->params->data.F32;
    202226
     227    // the other parameters depend on the guess for PAR_7
     228    if (!isfinite(PAR[PM_PAR_7])) {
     229        PAR[PM_PAR_7]    = 0.25;
     230    }   
     231    float index = 0.5 / PAR[PM_PAR_7];
     232
     233    // the scale-length is a function of the moments and the index:
     234    // Rmajor_guess = Rmajor_moments * Scale * Zero
     235    float Scale = 0.70 + 0.053 * PAR[PM_PAR_7];
     236    float Zero  = 1.16 - 0.615 * PAR[PM_PAR_7];
     237
    203238    psEllipseMoments emoments;
    204239    emoments.x2 = moments->Mxx;
     
    213248    if (!isfinite(axes.theta)) return false;
    214249
     250    // set a lower limit to avoid absurd solutions..
     251    float Rmajor = PS_MAX(1.0, Scale * axes.major + Zero);
     252    float Rminor = Rmajor * (axes.minor / axes.major);
     253
     254    fprintf (stderr, "guess index: %f : %f, %f -> %f, %f\n", index, axes.major, axes.minor, Rmajor, Rminor);
     255
     256    axes.major = Rmajor;
     257    axes.minor = Rminor;
    215258    psEllipseShape shape = psEllipseAxesToShape (axes);
    216259
     
    219262    if (!isfinite(shape.sxy)) return false;
    220263
     264    float bn = 1.9992*index - 0.3271;
     265    // float fR = 1.0 / (sqrt(2.0) * pow (bn, index));
     266    float Io = exp(0.5*bn);
     267
     268    // XXX do we need this factor of sqrt(2)?
     269    // float Sxx = PS_MAX(0.5, M_SQRT2*shape.sx);
     270    // float Syy = PS_MAX(0.5, M_SQRT2*shape.sy);
     271
     272    float Sxx = PS_MAX(0.5, shape.sx);
     273    float Syy = PS_MAX(0.5, shape.sy);
     274
    221275    PAR[PM_PAR_SKY]  = 0.0;
    222     PAR[PM_PAR_I0]   = peak->flux;
     276    PAR[PM_PAR_I0]   = peak->flux / Io;
    223277    PAR[PM_PAR_XPOS] = peak->xf;
    224278    PAR[PM_PAR_YPOS] = peak->yf;
    225     PAR[PM_PAR_SXX]  = PS_MAX(0.5, M_SQRT2*shape.sx);
    226     PAR[PM_PAR_SYY]  = PS_MAX(0.5, M_SQRT2*shape.sy);
     279    PAR[PM_PAR_SXX]  = Sxx;
     280    PAR[PM_PAR_SYY]  = Syy;
    227281    PAR[PM_PAR_SXY]  = shape.sxy;
    228     PAR[PM_PAR_7]    = 0.5;
    229282
    230283    return(true);
     
    254307    float f1, f2;
    255308    for (z = DZ; z < 50; z += DZ) {
    256         f1 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
     309        // f1 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
     310        f1 = exp(-pow(z,PAR[PM_PAR_7]));
    257311        z += DZ;
    258         f2 = 1.0 / (1 + PAR[PM_PAR_7]*z + pow(z, 2.25));
     312        f2 = exp(-pow(z,PAR[PM_PAR_7]));
    259313        norm += f0 + 4*f1 + f2;
    260314        f0 = f2;
     
    287341
    288342    psEllipseAxes axes = psEllipseShapeToAxes (shape, 20.0);
    289     psF64 sigma = axes.major;
    290 
    291     psF64 limit = flux / PAR[PM_PAR_I0];
    292 
    293     psF64 z = pow (-log(limit), (1.0 / PAR[PM_PAR_7]));
    294     psAssert (isfinite(z), "fix this code: z should not be nan for %f", PAR[PM_PAR_7]);
    295 
    296     psF64 radius = sigma * sqrt (2.0 * z);
    297     psAssert (isfinite(radius), "fix this code: radius should not be nan for %f, %f", PAR[PM_PAR_7], sigma);
    298 
    299     if (isnan(radius))
    300         psAbort("error in code: radius is NaN");
    301 
     343
     344    // f = Io exp(-z^n) -> z^n = ln(Io/f)
     345    psF64 zn = log(PAR[PM_PAR_I0] / flux);
     346    psF64 radius = axes.major * sqrt (2.0) * pow(zn, 0.5 / PAR[PM_PAR_7]);
     347
     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]);
    302351    return (radius);
    303352}
     
    448497    return;
    449498}
    450 
    451 # undef PM_MODEL_FUNC
    452 # undef PM_MODEL_FLUX
    453 # undef PM_MODEL_GUESS
    454 # undef PM_MODEL_LIMITS
    455 # undef PM_MODEL_RADIUS
    456 # undef PM_MODEL_FROM_PSF
    457 # undef PM_MODEL_PARAMS_FROM_PSF
    458 # undef PM_MODEL_FIT_STATUS
    459 # undef PM_MODEL_SET_LIMITS
  • trunk/psModules/src/objects/pmDetEff.c

    r25477 r29004  
    33#endif
    44
     5#include <string.h>
    56#include <pslib.h>
     7#include "pmHDU.h"
     8#include "pmFPA.h"
    69
     10#include "pmTrend2D.h"
     11#include "pmResiduals.h"
     12#include "pmGrowthCurve.h"
     13#include "pmSpan.h"
     14#include "pmFootprintSpans.h"
     15#include "pmFootprint.h"
     16#include "pmPeaks.h"
     17#include "pmMoments.h"
     18#include "pmModelFuncs.h"
     19#include "pmModel.h"
     20#include "pmModelUtils.h"
     21#include "pmModelClass.h"
     22#include "pmSourceMasks.h"
     23#include "pmSourceExtendedPars.h"
     24#include "pmSourceDiffStats.h"
     25#include "pmSource.h"
     26#include "pmSourceFitModel.h"
     27#include "pmPSF.h"
     28#include "pmPSFtry.h"
     29#include "pmDetections.h"
    730#include "pmDetEff.h"
    8 
    931
    1032static void detEffFree(pmDetEff *de)
  • trunk/psModules/src/objects/pmDetEff.h

    r25383 r29004  
    11#ifndef PM_DET_EFF_H
    22#define PM_DET_EFF_H
    3 
    4 #include <pslib.h>
    5 #include <string.h>
    6 
    7 #include "pmFPA.h"
    83
    94#define PM_DETEFF_ANALYSIS "DETEFF"     // Location of detection efficiency on pmReadout.analysis
  • trunk/psModules/src/objects/pmFootprint.c

    r27672 r29004  
    1919#include <pslib.h>
    2020#include "pmSpan.h"
     21#include "pmFootprintSpans.h"
    2122#include "pmFootprint.h"
    2223#include "pmPeaks.h"
  • trunk/psModules/src/objects/pmFootprint.h

    r27672 r29004  
    1010#ifndef PM_FOOTPRINT_H
    1111#define PM_FOOTPRINT_H
    12 
    13 #include <pslib.h>
    14 #include "pmSpan.h"
    15 #include "pmFootprintSpans.h"
    1612
    1713typedef struct {
  • trunk/psModules/src/objects/pmFootprintArrayGrow.c

    r21183 r29004  
    1818#include <pslib.h>
    1919#include "pmSpan.h"
     20#include "pmFootprintSpans.h"
    2021#include "pmFootprint.h"
    2122#include "pmPeaks.h"
  • trunk/psModules/src/objects/pmFootprintArraysMerge.c

    r24274 r29004  
    1818#include <pslib.h>
    1919#include "pmSpan.h"
     20#include "pmFootprintSpans.h"
    2021#include "pmFootprint.h"
    2122#include "pmPeaks.h"
  • trunk/psModules/src/objects/pmFootprintAssignPeaks.c

    r20937 r29004  
    1818#include <pslib.h>
    1919#include "pmSpan.h"
     20#include "pmFootprintSpans.h"
    2021#include "pmFootprint.h"
    2122#include "pmPeaks.h"
  • trunk/psModules/src/objects/pmFootprintCullPeaks.c

    r27672 r29004  
    1919#include <pslib.h>
    2020#include "pmSpan.h"
     21#include "pmFootprintSpans.h"
    2122#include "pmFootprint.h"
    22 #include "pmFootprintSpans.h"
    2323#include "pmPeaks.h"
    2424
  • trunk/psModules/src/objects/pmFootprintFind.c

    r20937 r29004  
    1919#include <pslib.h>
    2020#include "pmSpan.h"
     21#include "pmFootprintSpans.h"
    2122#include "pmFootprint.h"
    2223#include "pmPeaks.h"
  • trunk/psModules/src/objects/pmFootprintFindAtPoint.c

    r27672 r29004  
    1919#include <pslib.h>
    2020#include "pmSpan.h"
     21#include "pmFootprintSpans.h"
    2122#include "pmFootprint.h"
    2223#include "pmPeaks.h"
    23 #include "pmFootprintSpans.h"
    2424
    2525/************************************************************************************************************/
  • trunk/psModules/src/objects/pmFootprintIDs.c

    r27672 r29004  
    1919#include <pslib.h>
    2020#include "pmSpan.h"
     21#include "pmFootprintSpans.h"
    2122#include "pmFootprint.h"
    2223#include "pmPeaks.h"
  • trunk/psModules/src/objects/pmFootprintSpans.c

    r27672 r29004  
    1919#include <pslib.h>
    2020#include "pmSpan.h"
     21#include "pmFootprintSpans.h"
    2122#include "pmFootprint.h"
    2223#include "pmPeaks.h"
    23 #include "pmFootprintSpans.h"
    2424
    2525static void pmStartSpanFree(pmStartSpan *sspan) {
  • trunk/psModules/src/objects/pmFootprintSpans.h

    r27672 r29004  
    1010#ifndef PM_FOOTPRINT_SPANS_H
    1111#define PM_FOOTPRINT_SPANS_H
    12 
    13 #include <pslib.h>
    14 #include "pmSpan.h"
    1512
    1613/* We define two helper structures used in building the pmFootprints:
  • trunk/psModules/src/objects/pmGrowthCurve.c

    r20937 r29004  
    2020#include "pmHDU.h"
    2121#include "pmFPA.h"
     22
     23#include "pmTrend2D.h"
     24#include "pmResiduals.h"
     25#include "pmGrowthCurve.h"
    2226#include "pmSpan.h"
     27#include "pmFootprintSpans.h"
    2328#include "pmFootprint.h"
    2429#include "pmPeaks.h"
    2530#include "pmMoments.h"
    26 #include "pmResiduals.h"
    27 #include "pmGrowthCurve.h"
    28 #include "pmTrend2D.h"
     31#include "pmModelFuncs.h"
     32#include "pmModel.h"
     33#include "pmModelUtils.h"
     34#include "pmModelClass.h"
     35#include "pmSourceMasks.h"
     36#include "pmSourceExtendedPars.h"
     37#include "pmSourceDiffStats.h"
     38#include "pmSource.h"
     39#include "pmSourceFitModel.h"
    2940#include "pmPSF.h"
    30 #include "pmModel.h"
    31 #include "pmSource.h"
     41#include "pmPSFtry.h"
     42#include "pmDetections.h"
     43
    3244#include "psVectorBracket.h"
    3345
  • trunk/psModules/src/objects/pmGrowthCurveGenerate.c

    r27531 r29004  
    2424#include "pmHDU.h"
    2525#include "pmFPA.h"
     26#include "pmFPAMaskWeight.h"
     27#include "psVectorBracket.h"
     28#include "pmErrorCodes.h"
     29
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    2633#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    2735#include "pmFootprint.h"
    2836#include "pmPeaks.h"
    2937#include "pmMoments.h"
    30 #include "pmResiduals.h"
    31 #include "pmGrowthCurve.h"
    32 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3347#include "pmPSF.h"
    34 #include "pmModel.h"
    35 #include "pmSource.h"
    36 #include "pmModelClass.h"
    37 #include "pmModelUtils.h"
     48#include "pmPSFtry.h"
     49#include "pmDetections.h"
     50
    3851#include "pmSourcePhotometry.h"
    39 #include "pmFPAMaskWeight.h"
    40 #include "psVectorBracket.h"
    41 #include "pmErrorCodes.h"
    4252
    4353pmGrowthCurve *pmGrowthCurveForPosition (psImage *image, pmPSF *psf, bool ignore, psImageMaskType maskVal, psImageMaskType markVal, float xc, float yc);
  • trunk/psModules/src/objects/pmModel.c

    r25754 r29004  
    2323#include "pmHDU.h"
    2424#include "pmFPA.h"
     25
     26#include "pmTrend2D.h"
    2527#include "pmResiduals.h"
    2628#include "pmGrowthCurve.h"
    27 #include "pmTrend2D.h"
    28 #include "pmPSF.h"
     29#include "pmSpan.h"
     30#include "pmFootprintSpans.h"
     31#include "pmFootprint.h"
     32#include "pmPeaks.h"
     33#include "pmMoments.h"
     34#include "pmModelFuncs.h"
    2935#include "pmModel.h"
    3036#include "pmModelClass.h"
     
    7581
    7682    for (psS32 i = 0; i < tmp->params->n; i++) {
    77         tmp->params->data.F32[i] = 0.0;
    78         tmp->dparams->data.F32[i] = 0.0;
     83        tmp->params->data.F32[i] = NAN;
     84        tmp->dparams->data.F32[i] = NAN;
    7985    }
    8086
  • trunk/psModules/src/objects/pmModel.h

    r26916 r29004  
    1414# define PM_MODEL_H
    1515
    16 #include <pslib.h>
    17 #include "pmPSF.h"
    18 
    1916/// @addtogroup Objects Object Detection / Analysis Functions
    2017/// @{
     
    2219/* pointers for the functions types below are supplied to each pmModel, and can be used by
    2320   the programmer without needing to know the model class */
    24 
    25 typedef enum {
    26     PM_MODEL_STATUS_NONE         = 0x00, ///< model fit not yet attempted, no other info
    27     PM_MODEL_STATUS_FITTED       = 0x01, ///< model fit completed
    28     PM_MODEL_STATUS_NONCONVERGE  = 0x02, ///< model fit did not converge
    29     PM_MODEL_STATUS_OFFIMAGE     = 0x04, ///< model fit drove out of range
    30     PM_MODEL_STATUS_BADARGS      = 0x08, ///< model fit called with invalid args
    31     PM_MODEL_STATUS_LIMITS       = 0x10  ///< model parameters hit limits
    32 } pmModelStatus;
    33 
    34 typedef enum {
    35     PM_MODEL_OP_NONE    = 0x00,
    36     PM_MODEL_OP_FUNC    = 0x01,
    37     PM_MODEL_OP_RES0    = 0x02,
    38     PM_MODEL_OP_RES1    = 0x04,
    39     PM_MODEL_OP_FULL    = 0x07,
    40     PM_MODEL_OP_SKY     = 0x08,
    41     PM_MODEL_OP_CENTER  = 0x10,
    42     PM_MODEL_OP_NORM    = 0x20,
    43     PM_MODEL_OP_NOISE   = 0x40,
    44 } pmModelOpMode;
    45 
    46 /// Parameter limit types
    47 typedef enum {
    48     PM_MODEL_LIMITS_NONE,               ///< Apply no limits: suitable for debugging
    49     PM_MODEL_LIMITS_IGNORE,             ///< Ignore all limits: fit can go to town
    50     PM_MODEL_LIMITS_LAX,                ///< Lax limits: attempting to reproduce even bad data
    51     PM_MODEL_LIMITS_MODERATE,           ///< Moderate limits: cope with mildly bad data
    52     PM_MODEL_LIMITS_STRICT,             ///< Strict limits: insist on good quality data
    53 } pmModelLimitsType;
    54 
    55 typedef struct pmModel pmModel;
    56 typedef struct pmSource pmSource;
    57 
    58 //  This function is the model chi-square minimization function for this model.
    59 typedef psMinimizeLMChi2Func pmModelFunc;
    60 
    61 //  This function sets the parameter limits for this model.
    62 typedef psMinimizeLMLimitFunc pmModelLimits;
    63 
    64 // This function returns the integrated flux for the given model parameters.
    65 typedef psF64 (*pmModelFlux)(const psVector *params);
    66 
    67 // This function returns the radius at which the given model and parameters
    68 // achieves the given flux.
    69 typedef psF64 (*pmModelRadius)(const psVector *params, double flux);
    70 
    71 //  This function provides the model guess parameters based on the details of
    72 //  the given source.
    73 typedef bool (*pmModelGuessFunc)(pmModel *model, pmSource *source);
    74 
    75 //  This function constructs the PSF model for the given source based on the
    76 //  supplied psf and the EXT model for the object.
    77 typedef bool (*pmModelFromPSFFunc)(pmModel *modelPSF, pmModel *modelEXT, const pmPSF *psf);
    78 
    79 //  This function sets the model parameters based on the PSF for a given coordinate and central
    80 //  intensity
    81 typedef bool (*pmModelParamsFromPSF)(pmModel *model, const pmPSF *psf, float Xo, float Yo, float Io);
    82 
    83 //  This function returns the success / failure status of the given model fit
    84 typedef bool (*pmModelFitStatusFunc)(pmModel *model);
    85 
    86 //  This function sets the parameter limits for the given model
    87 typedef bool (*pmModelSetLimitsFunc)(pmModelLimitsType type);
    8821
    8922/** pmModel data structure
     
    12255    pmModelSetLimitsFunc modelSetLimits;
    12356};
    124 
    125 /** Symbolic names for the elements of [d]params
    126  * Note: these are #defines not enums as a given element of [d]params
    127  * may/will correspond to different parameters in different contexts
    128  */
    129 #define PM_PAR_SKY 0   ///< Sky
    130 #define PM_PAR_I0 1   ///< Central intensity
    131 #define PM_PAR_XPOS 2   ///< X centre of object
    132 #define PM_PAR_YPOS 3   ///< Y centre of object
    133 #define PM_PAR_SXX 4   ///< shape X^2 moment
    134 #define PM_PAR_SYY 5   ///< shape Y^2 moment
    135 #define PM_PAR_SXY 6   ///< shape XY moment
    136 #define PM_PAR_7 7   ///< ??? Unknown parameter
    137 #define PM_PAR_8 8   ///< ??? Unknown parameter
    13857
    13958/** pmModelAlloc()
  • trunk/psModules/src/objects/pmModelClass.c

    r25754 r29004  
    2323#include "pmHDU.h"
    2424#include "pmFPA.h"
     25
     26#include "pmTrend2D.h"
     27#include "pmResiduals.h"
     28#include "pmGrowthCurve.h"
    2529#include "pmSpan.h"
     30#include "pmFootprintSpans.h"
    2631#include "pmFootprint.h"
    2732#include "pmPeaks.h"
    2833#include "pmMoments.h"
    29 #include "pmResiduals.h"
    30 #include "pmGrowthCurve.h"
    31 #include "pmTrend2D.h"
    32 #include "pmPSF.h"
     34#include "pmModelFuncs.h"
    3335#include "pmModel.h"
    34 #include "pmSource.h"
     36#include "pmModelUtils.h"
    3537#include "pmModelClass.h"
     38
    3639#include "pmErrorCodes.h"
    3740
     
    4649# include "models/pmModel_RGAUSS.h"
    4750# include "models/pmModel_SERSIC.h"
     51# include "models/pmModel_EXP.h"
     52# include "models/pmModel_DEV.h"
    4853
    4954static pmModelClass defaultModels[] = {
     
    5358    {"PS_MODEL_PS1_V1",       8, (pmModelFunc)pmModelFunc_PS1_V1,  (pmModelFlux)pmModelFlux_PS1_V1,  (pmModelRadius)pmModelRadius_PS1_V1,  (pmModelLimits)pmModelLimits_PS1_V1,  (pmModelGuessFunc)pmModelGuess_PS1_V1, (pmModelFromPSFFunc)pmModelFromPSF_PS1_V1, (pmModelParamsFromPSF)pmModelParamsFromPSF_PS1_V1, (pmModelFitStatusFunc)pmModelFitStatus_PS1_V1, (pmModelSetLimitsFunc)pmModelSetLimits_PS1_V1 },
    5459    {"PS_MODEL_RGAUSS",       8, (pmModelFunc)pmModelFunc_RGAUSS,  (pmModelFlux)pmModelFlux_RGAUSS,  (pmModelRadius)pmModelRadius_RGAUSS,  (pmModelLimits)pmModelLimits_RGAUSS,  (pmModelGuessFunc)pmModelGuess_RGAUSS, (pmModelFromPSFFunc)pmModelFromPSF_RGAUSS, (pmModelParamsFromPSF)pmModelParamsFromPSF_RGAUSS, (pmModelFitStatusFunc)pmModelFitStatus_RGAUSS, (pmModelSetLimitsFunc)pmModelSetLimits_RGAUSS },
    55     {"PS_MODEL_SERSIC",       8, (pmModelFunc)pmModelFunc_SERSIC,  (pmModelFlux)pmModelFlux_SERSIC,  (pmModelRadius)pmModelRadius_SERSIC,  (pmModelLimits)pmModelLimits_SERSIC,  (pmModelGuessFunc)pmModelGuess_SERSIC, (pmModelFromPSFFunc)pmModelFromPSF_SERSIC, (pmModelParamsFromPSF)pmModelParamsFromPSF_SERSIC, (pmModelFitStatusFunc)pmModelFitStatus_SERSIC, (pmModelSetLimitsFunc)pmModelSetLimits_SERSIC }
     60    {"PS_MODEL_SERSIC",       8, (pmModelFunc)pmModelFunc_SERSIC,  (pmModelFlux)pmModelFlux_SERSIC,  (pmModelRadius)pmModelRadius_SERSIC,  (pmModelLimits)pmModelLimits_SERSIC,  (pmModelGuessFunc)pmModelGuess_SERSIC, (pmModelFromPSFFunc)pmModelFromPSF_SERSIC, (pmModelParamsFromPSF)pmModelParamsFromPSF_SERSIC, (pmModelFitStatusFunc)pmModelFitStatus_SERSIC, (pmModelSetLimitsFunc)pmModelSetLimits_SERSIC },
     61    {"PS_MODEL_EXP",          7, (pmModelFunc)pmModelFunc_EXP,     (pmModelFlux)pmModelFlux_EXP,     (pmModelRadius)pmModelRadius_EXP,     (pmModelLimits)pmModelLimits_EXP,     (pmModelGuessFunc)pmModelGuess_EXP,    (pmModelFromPSFFunc)pmModelFromPSF_EXP,    (pmModelParamsFromPSF)pmModelParamsFromPSF_EXP,    (pmModelFitStatusFunc)pmModelFitStatus_EXP,    (pmModelSetLimitsFunc)pmModelSetLimits_EXP },
     62    {"PS_MODEL_DEV",          7, (pmModelFunc)pmModelFunc_DEV,     (pmModelFlux)pmModelFlux_DEV,     (pmModelRadius)pmModelRadius_DEV,     (pmModelLimits)pmModelLimits_DEV,     (pmModelGuessFunc)pmModelGuess_DEV,    (pmModelFromPSFFunc)pmModelFromPSF_DEV,    (pmModelParamsFromPSF)pmModelParamsFromPSF_DEV,    (pmModelFitStatusFunc)pmModelFitStatus_DEV,    (pmModelSetLimitsFunc)pmModelSetLimits_DEV },
    5663};
    5764
  • trunk/psModules/src/objects/pmModelClass.h

    r25738 r29004  
    2828# ifndef PM_MODEL_CLASS_H
    2929# define PM_MODEL_CLASS_H
    30 
    31 #include <pmModel.h>
    3230
    3331/// @addtogroup Objects Object Detection / Analysis Functions
  • trunk/psModules/src/objects/pmModelUtils.c

    r25754 r29004  
    2222#include "pmHDU.h"
    2323#include "pmFPA.h"
     24
     25#include "pmTrend2D.h"
    2426#include "pmResiduals.h"
    2527#include "pmGrowthCurve.h"
    26 #include "pmTrend2D.h"
     28#include "pmSpan.h"
     29#include "pmFootprintSpans.h"
     30#include "pmFootprint.h"
     31#include "pmPeaks.h"
     32#include "pmMoments.h"
     33#include "pmModelFuncs.h"
     34#include "pmModel.h"
     35#include "pmModelUtils.h"
     36#include "pmModelClass.h"
     37#include "pmSourceMasks.h"
     38#include "pmSourceExtendedPars.h"
     39#include "pmSourceDiffStats.h"
     40#include "pmSource.h"
     41#include "pmSourceFitModel.h"
    2742#include "pmPSF.h"
    28 #include "pmModel.h"
     43
    2944#include "pmErrorCodes.h"
    30 #include "pmModelUtils.h"
    3145
    3246/*****************************************************************************
  • trunk/psModules/src/objects/pmMoments.c

    r24498 r29004  
    2929    psTrace("psModules.objects", 10, "---- %s() begin ----\n", __func__);
    3030    pmMoments *tmp = (pmMoments *) psAlloc(sizeof(pmMoments));
     31
     32    tmp->Mrf = 0.0;
     33    tmp->Mrh = 0.0;
     34    tmp->KronFlux = 0.0;
     35    tmp->KronFluxErr = 0.0;
     36
     37    tmp->KronFinner = 0.0;
     38    tmp->KronFouter = 0.0;
     39
    3140    tmp->Mx = 0.0;
    3241    tmp->My = 0.0;
  • trunk/psModules/src/objects/pmMoments.h

    r23487 r29004  
    2424typedef struct
    2525{
     26    float Mrf;    ///< radial first moment
     27    float Mrh;    ///< radial half moment
     28
    2629    float Mx;     ///< X-coord of centroid.
    2730    float My;     ///< Y-coord of centroid.
     
    4750    float SN;     ///< approx signal-to-noise
    4851    int nPixels;  ///< Number of pixels used.
     52
     53    float KronFlux;    ///< Kron flux (flux in 2.5*Mrf)
     54    float KronFluxErr; ///< Kron flux error
     55
     56    float KronFinner;    ///< Kron flux (flux in 2.5*Mrf)
     57    float KronFouter;    ///< Kron flux (flux in 2.5*Mrf)
     58
    4959}
    5060pmMoments;
  • trunk/psModules/src/objects/pmPSF.c

    r26893 r29004  
    2525#include "pmHDU.h"
    2626#include "pmFPA.h"
     27#include "pmFPAMaskWeight.h"
     28#include "psVectorBracket.h"
     29
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    2733#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    2835#include "pmFootprint.h"
    2936#include "pmPeaks.h"
    3037#include "pmMoments.h"
    31 #include "pmResiduals.h"
    32 #include "pmGrowthCurve.h"
    33 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3447#include "pmPSF.h"
    35 #include "pmModel.h"
    36 #include "pmSource.h"
    37 #include "pmModelClass.h"
    38 #include "pmModelUtils.h"
    39 #include "pmSourcePhotometry.h"
    40 #include "pmFPAMaskWeight.h"
    41 #include "psVectorBracket.h"
     48#include "pmPSFtry.h"
     49#include "pmDetections.h"
     50
    4251#include "pmErrorCodes.h"
    4352
     
    5463
    5564    psFree (options->stats);
     65    psFree (options->fitOptions);
    5666    return;
    5767}
     
    6575
    6676    options->stats         = NULL;
     77    options->fitOptions    = NULL; // XXX this has to be set before calling pmPSF fit functions
    6778
    6879    options->psfTrendMode  = PM_TREND_NONE;
  • trunk/psModules/src/objects/pmPSF.h

    r26893 r29004  
    1414# define PM_PSF_H
    1515
    16 #include <pslib.h>
    17 #include "pmTrend2D.h"
    18 #include "pmGrowthCurve.h"
    19 #include "pmResiduals.h"
    20 #include "pmFPA.h"
    21 
    2216/// @addtogroup Objects Object Detection / Analysis Functions
    2317/// @{
    24 
    25 // type of model carried by the pmModel structure
    26 typedef int pmModelType;
    2718
    2819/** pmPSF data structure
     
    3829 *
    3930 */
    40 typedef struct {
     31struct pmPSF {
    4132    pmModelType type;                   ///< PSF Model in use
    4233    psArray *params;                    ///< Model parameters (psPolynomial2D)
     
    6455    pmGrowthCurve *growth;              ///< apMag vs Radius
    6556    pmResiduals *residuals;             ///< normalized residual image (no spatial variation)
    66 } pmPSF;
     57};
    6758
    6859typedef struct {
     
    8273    float         apRadius;
    8374    bool          chiFluxTrend;         // Fit a trend in Chi2 as a function of flux?
     75    pmSourceFitOptions *fitOptions;
    8476} pmPSFOptions;
    8577
  • trunk/psModules/src/objects/pmPSF_IO.c

    r28449 r29004  
    3838#include "pmFPAfileFitsIO.h"
    3939
     40#include "pmTrend2D.h"
     41#include "pmResiduals.h"
     42#include "pmGrowthCurve.h"
    4043#include "pmSpan.h"
     44#include "pmFootprintSpans.h"
    4145#include "pmFootprint.h"
    4246#include "pmPeaks.h"
    4347#include "pmMoments.h"
    44 #include "pmGrowthCurve.h"
    45 #include "pmResiduals.h"
    46 #include "pmTrend2D.h"
     48#include "pmModelFuncs.h"
     49#include "pmModel.h"
     50#include "pmModelUtils.h"
     51#include "pmModelClass.h"
     52#include "pmSourceMasks.h"
     53#include "pmSourceExtendedPars.h"
     54#include "pmSourceDiffStats.h"
     55#include "pmSource.h"
     56#include "pmSourceFitModel.h"
    4757#include "pmPSF.h"
    48 #include "pmModel.h"
     58#include "pmPSFtry.h"
     59#include "pmDetections.h"
     60
    4961#include "pmPSF_IO.h"
    50 #include "pmSource.h"
    51 #include "pmModelClass.h"
    52 #include "pmModelUtils.h"
    5362#include "pmSourceIO.h"
    5463
  • trunk/psModules/src/objects/pmPSFtry.c

    r25754 r29004  
    1919#include "pmFPA.h"
    2020#include "pmFPAMaskWeight.h"
     21
     22#include "pmTrend2D.h"
     23#include "pmResiduals.h"
     24#include "pmGrowthCurve.h"
    2125#include "pmSpan.h"
     26#include "pmFootprintSpans.h"
    2227#include "pmFootprint.h"
    2328#include "pmPeaks.h"
    2429#include "pmMoments.h"
    25 #include "pmResiduals.h"
    26 #include "pmGrowthCurve.h"
    27 #include "pmTrend2D.h"
     30#include "pmModelFuncs.h"
     31#include "pmModel.h"
     32#include "pmModelUtils.h"
     33#include "pmModelClass.h"
     34#include "pmSourceMasks.h"
     35#include "pmSourceExtendedPars.h"
     36#include "pmSourceDiffStats.h"
     37#include "pmSource.h"
     38#include "pmSourceFitModel.h"
    2839#include "pmPSF.h"
    29 #include "pmModel.h"
    30 #include "pmSource.h"
    31 #include "pmSourceUtils.h"
    3240#include "pmPSFtry.h"
    33 #include "pmModelClass.h"
    34 #include "pmModelUtils.h"
    35 #include "pmSourceFitModel.h"
     41#include "pmDetections.h"
     42
    3643#include "pmSourcePhotometry.h"
    3744#include "pmSourceVisual.h"
  • trunk/psModules/src/objects/pmPSFtryFitEXT.c

    r25754 r29004  
    1919#include "pmFPA.h"
    2020#include "pmFPAMaskWeight.h"
     21
     22#include "pmTrend2D.h"
     23#include "pmResiduals.h"
     24#include "pmGrowthCurve.h"
    2125#include "pmSpan.h"
     26#include "pmFootprintSpans.h"
    2227#include "pmFootprint.h"
    2328#include "pmPeaks.h"
    2429#include "pmMoments.h"
    25 #include "pmResiduals.h"
    26 #include "pmGrowthCurve.h"
    27 #include "pmTrend2D.h"
    28 #include "pmPSF.h"
     30#include "pmModelFuncs.h"
    2931#include "pmModel.h"
     32#include "pmModelUtils.h"
     33#include "pmModelClass.h"
     34#include "pmSourceMasks.h"
     35#include "pmSourceExtendedPars.h"
     36#include "pmSourceDiffStats.h"
    3037#include "pmSource.h"
    3138#include "pmSourceUtils.h"
     39#include "pmSourceFitModel.h"
     40#include "pmPSF.h"
    3241#include "pmPSFtry.h"
    33 #include "pmModelClass.h"
    34 #include "pmModelUtils.h"
    35 #include "pmSourceFitModel.h"
     42#include "pmDetections.h"
     43
    3644#include "pmSourcePhotometry.h"
    3745#include "pmSourceVisual.h"
     
    4452
    4553    psTimerStart ("psf.fit");
     54
     55    // in this segment, we are fitting the full PSF model class (shape unconstrained)
     56    options->fitOptions->mode = PM_SOURCE_FIT_EXT;
    4657
    4758    // maskVal is used to test for rejected pixels, and must include markVal
     
    7384
    7485        // fit model as EXT, not PSF
    75         status = pmSourceFitModel (source, source->modelEXT, PM_SOURCE_FIT_EXT, maskVal);
     86        status = pmSourceFitModel (source, source->modelEXT, options->fitOptions, maskVal);
    7687
    7788        // clear object mask to define valid pixels
  • trunk/psModules/src/objects/pmPSFtryFitPSF.c

    r26027 r29004  
    1717#include "pmFPA.h"
    1818#include "pmFPAMaskWeight.h"
     19
     20#include "pmTrend2D.h"
     21#include "pmResiduals.h"
     22#include "pmGrowthCurve.h"
    1923#include "pmSpan.h"
     24#include "pmFootprintSpans.h"
    2025#include "pmFootprint.h"
    2126#include "pmPeaks.h"
    2227#include "pmMoments.h"
    23 #include "pmResiduals.h"
    24 #include "pmGrowthCurve.h"
    25 #include "pmTrend2D.h"
     28#include "pmModelFuncs.h"
     29#include "pmModel.h"
     30#include "pmModelUtils.h"
     31#include "pmModelClass.h"
     32#include "pmSourceMasks.h"
     33#include "pmSourceExtendedPars.h"
     34#include "pmSourceDiffStats.h"
     35#include "pmSource.h"
     36#include "pmSourceFitModel.h"
    2637#include "pmPSF.h"
    27 #include "pmModel.h"
    28 #include "pmSource.h"
    29 #include "pmSourceUtils.h"
    3038#include "pmPSFtry.h"
    31 #include "pmModelClass.h"
    32 #include "pmModelUtils.h"
    33 #include "pmSourceFitModel.h"
     39#include "pmDetections.h"
     40
    3441#include "pmSourcePhotometry.h"
    3542#include "pmSourceVisual.h"
     
    4249
    4350    psTimerStart ("psf.fit");
     51
     52    // in this segment, we are fitting the fitted PSF model class (shape constrained)
     53    options->fitOptions->mode = PM_SOURCE_FIT_PSF;
    4454
    4555    // maskVal is used to test for rejected pixels, and must include markVal
     
    8191
    8292        // fit the PSF model to the source
    83         status = pmSourceFitModel (source, source->modelPSF, PM_SOURCE_FIT_NORM, maskVal);
     93        status = pmSourceFitModel (source, source->modelPSF, options->fitOptions, maskVal);
    8494
    8595        // skip poor fits
     
    98108
    99109        // This function calculates the psf and aperture magnitudes
    100         status = pmSourceMagnitudes (source, psfTry->psf, PM_SOURCE_PHOT_INTERP, maskVal); // raw PSF mag, AP mag
     110        status = pmSourceMagnitudes (source, psfTry->psf, PM_SOURCE_PHOT_INTERP, maskVal, markVal); // raw PSF mag, AP mag
    101111        if (!status || isnan(source->apMag)) {
    102112            psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); // clear the circular mask
  • trunk/psModules/src/objects/pmPSFtryMakePSF.c

    r25754 r29004  
    1818#include "pmFPA.h"
    1919#include "pmFPAMaskWeight.h"
     20
     21#include "pmTrend2D.h"
     22#include "pmResiduals.h"
     23#include "pmGrowthCurve.h"
    2024#include "pmSpan.h"
     25#include "pmFootprintSpans.h"
    2126#include "pmFootprint.h"
    2227#include "pmPeaks.h"
    2328#include "pmMoments.h"
    24 #include "pmResiduals.h"
    25 #include "pmGrowthCurve.h"
    26 #include "pmTrend2D.h"
     29#include "pmModelFuncs.h"
     30#include "pmModel.h"
     31#include "pmModelUtils.h"
     32#include "pmModelClass.h"
     33#include "pmSourceMasks.h"
     34#include "pmSourceExtendedPars.h"
     35#include "pmSourceDiffStats.h"
     36#include "pmSource.h"
     37#include "pmSourceFitModel.h"
    2738#include "pmPSF.h"
    28 #include "pmModel.h"
    29 #include "pmSource.h"
    30 #include "pmSourceUtils.h"
    3139#include "pmPSFtry.h"
    32 #include "pmModelClass.h"
    33 #include "pmModelUtils.h"
    34 #include "pmSourceFitModel.h"
     40#include "pmDetections.h"
     41
    3542#include "pmSourcePhotometry.h"
    3643#include "pmSourceVisual.h"
  • trunk/psModules/src/objects/pmPSFtryMetric.c

    r26260 r29004  
    1818#include "pmFPA.h"
    1919#include "pmFPAMaskWeight.h"
     20
     21#include "pmTrend2D.h"
     22#include "pmResiduals.h"
     23#include "pmGrowthCurve.h"
    2024#include "pmSpan.h"
     25#include "pmFootprintSpans.h"
    2126#include "pmFootprint.h"
    2227#include "pmPeaks.h"
    2328#include "pmMoments.h"
    24 #include "pmResiduals.h"
    25 #include "pmGrowthCurve.h"
    26 #include "pmTrend2D.h"
     29#include "pmModelFuncs.h"
     30#include "pmModel.h"
     31#include "pmModelUtils.h"
     32#include "pmModelClass.h"
     33#include "pmSourceMasks.h"
     34#include "pmSourceExtendedPars.h"
     35#include "pmSourceDiffStats.h"
     36#include "pmSource.h"
     37#include "pmSourceFitModel.h"
    2738#include "pmPSF.h"
    28 #include "pmModel.h"
    29 #include "pmSource.h"
    30 #include "pmSourceUtils.h"
    3139#include "pmPSFtry.h"
    32 #include "pmModelClass.h"
    33 #include "pmModelUtils.h"
    34 #include "pmSourceFitModel.h"
     40#include "pmDetections.h"
     41
    3542#include "pmSourcePhotometry.h"
    3643#include "pmSourceVisual.h"
  • trunk/psModules/src/objects/pmPSFtryModel.c

    r27818 r29004  
    1919#include "pmFPA.h"
    2020#include "pmFPAMaskWeight.h"
     21
     22#include "pmTrend2D.h"
     23#include "pmResiduals.h"
     24#include "pmGrowthCurve.h"
    2125#include "pmSpan.h"
     26#include "pmFootprintSpans.h"
    2227#include "pmFootprint.h"
    2328#include "pmPeaks.h"
    2429#include "pmMoments.h"
    25 #include "pmResiduals.h"
    26 #include "pmGrowthCurve.h"
    27 #include "pmTrend2D.h"
     30#include "pmModelFuncs.h"
     31#include "pmModel.h"
     32#include "pmModelUtils.h"
     33#include "pmModelClass.h"
     34#include "pmSourceMasks.h"
     35#include "pmSourceExtendedPars.h"
     36#include "pmSourceDiffStats.h"
     37#include "pmSource.h"
     38#include "pmSourceFitModel.h"
    2839#include "pmPSF.h"
    29 #include "pmModel.h"
    30 #include "pmSource.h"
    31 #include "pmSourceUtils.h"
    3240#include "pmPSFtry.h"
    33 #include "pmModelClass.h"
    34 #include "pmModelUtils.h"
    35 #include "pmSourceFitModel.h"
    36 #include "pmSourcePhotometry.h"
     41#include "pmDetections.h"
     42
    3743#include "pmSourceVisual.h"
    3844
     
    4955pmPSFtry *pmPSFtryModel (const psArray *sources, const char *modelName, pmPSFOptions *options, psImageMaskType maskVal, psImageMaskType markVal)
    5056{
     57    assert (options->fitOptions);
     58
    5159    // validate the requested model name
    5260    options->type = pmModelClassGetType (modelName);
  • trunk/psModules/src/objects/pmPeaks.c

    r26893 r29004  
    2222#include <pslib.h>
    2323#include "pmSpan.h"
     24#include "pmFootprintSpans.h"
    2425#include "pmFootprint.h"
    2526#include "pmPeaks.h"
  • trunk/psModules/src/objects/pmPeaks.h

    r27657 r29004  
    1717# ifndef PM_PEAKS_H
    1818# define PM_PEAKS_H
    19 
    20 #include <pslib.h>
    21 #include "pmFootprint.h"
    2219
    2320/// @addtogroup Objects Object Detection / Analysis Functions
  • trunk/psModules/src/objects/pmPhotObj.c

    r28013 r29004  
    1616#include <string.h>
    1717#include <pslib.h>
     18
     19#include "pmHDU.h"
     20#include "pmFPA.h"
     21
     22#include "pmTrend2D.h"
     23#include "pmResiduals.h"
     24#include "pmGrowthCurve.h"
     25#include "pmSpan.h"
     26#include "pmFootprintSpans.h"
     27#include "pmFootprint.h"
     28#include "pmPeaks.h"
     29#include "pmMoments.h"
     30#include "pmModelFuncs.h"
     31#include "pmModel.h"
     32#include "pmModelUtils.h"
     33#include "pmModelClass.h"
     34#include "pmSourceMasks.h"
     35#include "pmSourceExtendedPars.h"
     36#include "pmSourceDiffStats.h"
     37#include "pmSource.h"
     38
    1839#include "pmPhotObj.h"
    19 #include "pmSource.h"
     40
    2041
    2142static void pmPhotObjFree (pmPhotObj *tmp)
     
    82103    return (0);
    83104}
     105
     106// sort by X (ascending)
     107int pmPhotObjSortByX (const void **a, const void **b)
     108{
     109    pmPhotObj *objA = *(pmPhotObj **)a;
     110    pmPhotObj *objB = *(pmPhotObj **)b;
     111
     112    psF32 fA = objA->x;
     113    psF32 fB = objB->x;
     114
     115    psF32 diff = fA - fB;
     116    if (diff > FLT_EPSILON) return (+1);
     117    if (diff < FLT_EPSILON) return (-1);
     118    return (0);
     119}
  • trunk/psModules/src/objects/pmPhotObj.h

    r28013 r29004  
    1010# ifndef PM_PHOT_OBJ_H
    1111# define PM_PHOT_OBJ_H
    12 
    13 #include <pslib.h>
    14 #include "pmPeaks.h"
    15 #include "pmModel.h"
    16 #include "pmMoments.h"
    1712
    1813/// @addtogroup Objects Object Detection / Analysis Functions
     
    4742
    4843int pmPhotObjSortBySN (const void **a, const void **b);
     44int pmPhotObjSortByX (const void **a, const void **b);
    4945
    5046/// @}
  • trunk/psModules/src/objects/pmSource.c

    r28013 r29004  
    2323#include "pmFPA.h"
    2424#include "pmFPAMaskWeight.h"
     25
     26#include "pmTrend2D.h"
     27#include "pmResiduals.h"
     28#include "pmGrowthCurve.h"
    2529#include "pmSpan.h"
     30#include "pmFootprintSpans.h"
    2631#include "pmFootprint.h"
    2732#include "pmPeaks.h"
    2833#include "pmMoments.h"
    29 #include "pmResiduals.h"
    30 #include "pmGrowthCurve.h"
    31 #include "pmTrend2D.h"
    32 #include "pmPSF.h"
     34#include "pmModelFuncs.h"
    3335#include "pmModel.h"
     36#include "pmModelUtils.h"
     37#include "pmModelClass.h"
     38#include "pmSourceMasks.h"
     39#include "pmSourceExtendedPars.h"
     40#include "pmSourceDiffStats.h"
    3441#include "pmSource.h"
    3542
     
    98105    static int id = 1;
    99106    pmSource *source = (pmSource *) psAlloc(sizeof(pmSource));
    100     *(int *)&source->id = id++;
     107    P_PM_SOURCE_SET_ID(source, id++);
     108
    101109    source->seq = -1;
    102110    source->peak = NULL;
     
    114122    source->type = PM_SOURCE_TYPE_UNKNOWN;
    115123    source->mode = PM_SOURCE_MODE_DEFAULT;
     124    source->mode2 = PM_SOURCE_MODE_DEFAULT;
    116125    source->tmpFlags = 0;
    117126    source->extpars = NULL;
     
    131140    source->sky    = NAN;
    132141    source->skyErr = NAN;
    133     source->pixWeight = NAN;
     142    source->pixWeightNotBad = NAN;
     143    source->pixWeightNotPoor = NAN;
    134144
    135145    source->psfChisq = NAN;
     
    142152
    143153/******************************************************************************
    144 pmSourceCopy(): copy the pmSource structure and contents
    145 XXX : are we OK with incrementing the ID?
     154pmSourceCopy(): copy the pmSource, yielding a copy of the source that can be used without
     155affecting the original.  This Copy can be used to allow multiple fit attempts on the same
     156object.  The pixels, variance, and mask arrays all point to the same original subarrays.  The
     157peak and moments point at the original values.
    146158*****************************************************************************/
    147159pmSource *pmSourceCopy(pmSource *in)
     160{
     161    if (in == NULL) {
     162        return(NULL);
     163    }
     164    pmSource *source = pmSourceAlloc ();
     165
     166    // keep the original ID so we can find map back to the original
     167    P_PM_SOURCE_SET_ID(source, in->id);
     168
     169    // peak has the same values as the original
     170    if (in->peak != NULL) {
     171        source->peak = pmPeakAlloc (in->peak->x, in->peak->y, in->peak->value, in->peak->type);
     172        source->peak->xf = in->peak->xf;
     173        source->peak->yf = in->peak->yf;
     174        source->peak->flux = in->peak->flux;
     175        source->peak->SN = in->peak->SN;
     176    }
     177
     178    // copy the values in the moments structure
     179    if (in->moments != NULL) {
     180        source->moments  =  pmMomentsAlloc();
     181        *source->moments = *in->moments;
     182    }
     183
     184    // These images are all views to the parent.  We want a new view, but pointing at the same
     185    // pixels.  Modifying these pixels (ie, subtracting the model) will affect the pixels seen
     186    // by all copies.
     187    source->pixels   = psImageCopyView(NULL, in->pixels);
     188    source->variance   = psImageCopyView(NULL, in->variance);
     189    source->maskView = in->maskView ? psImageCopyView(NULL, in->maskView) : NULL;
     190
     191    // the maskObj is a unique mask array; create a new mask image
     192    source->maskObj = in->maskObj ? psImageCopy (NULL, in->maskObj, PS_TYPE_IMAGE_MASK) : NULL;
     193
     194    source->type = in->type;
     195    source->mode = in->mode;
     196    source->imageID = in->imageID;
     197
     198    return(source);
     199}
     200
     201/******************************************************************************
     202pmSourceCopyData(): this creates a new, duplicate source with the same parameters as the
     203original (but is actually a new source at the same location)
     204*****************************************************************************/
     205pmSource *pmSourceCopyData(pmSource *in)
    148206{
    149207    if (in == NULL) {
     
    482540        }
    483541        psfClump.X  = stats->clippedMean;
    484         psfClump.dX = stats->clippedStdev;
     542        psfClump.dX = hypot(stats->clippedStdev, PSF_CLUMP_GRID_SCALE);
    485543
    486544        if (!psVectorStats (stats, tmpSy, NULL, NULL, 0)) {
     
    489547        }
    490548        psfClump.Y  = stats->clippedMean;
    491         psfClump.dY = stats->clippedStdev;
     549        psfClump.dY = hypot(stats->clippedStdev, PSF_CLUMP_GRID_SCALE);
    492550
    493551        psTrace ("psModules.objects", 2, "clump  X,  Y: %f, %f\n", psfClump.X, psfClump.Y);
     
    910968    bool addNoise = mode & PM_MODEL_OP_NOISE;
    911969
    912     if (source->modelFlux) {
     970    // require the use of pmModelAddWithOffset if we are adding noise (because the model size and norm are rescaled)
     971    if (!addNoise && source->modelFlux) {
    913972        // add in the pixels from the modelFlux image
    914973        int dX = source->modelFlux->col0 - source->pixels->col0;
     
    931990
    932991        psF32 **target = source->pixels->data.F32;
    933         if (addNoise) {
    934             // when adding noise, we assume the shape and Io have been modified
    935             target = source->variance->data.F32;
    936         }
    937992
    938993        for (int iy = 0; iy < source->modelFlux->numRows; iy++) {
     
    9491004            }
    9501005        }
    951         if (!addNoise) {
    952             if (add) {
    953                 source->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;
    954             } else {
    955                 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;
    956             }
     1006        if (add) {
     1007            source->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;
     1008        } else {
     1009            source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;
    9571010        }
    9581011        return true;
     
    9731026        }
    9741027    }
     1028
     1029    return true;
     1030}
     1031
     1032// should we call pmSourceCacheModel if it does not exist?
     1033bool pmSourceNoiseOp (pmSource *source, pmModelOpMode mode, float FACTOR, float SIZE, bool add, psImageMaskType maskVal, int dx, int dy)
     1034{
     1035    assert (mode & PM_MODEL_OP_NOISE);
     1036    PS_ASSERT_PTR_NON_NULL(source, false);
     1037    PS_ASSERT_PTR_NON_NULL(source->peak, false);
     1038
     1039    if (add) {
     1040        psTrace ("psphot", 3, "adding noise to object at %f,%f\n", source->peak->xf, source->peak->yf);
     1041    } else {
     1042        psTrace ("psphot", 3, "removing noise from object at %f,%f\n", source->peak->xf, source->peak->yf);
     1043    }
     1044
     1045    pmSourceNoiseOpModel (source->modelPSF, source, mode, FACTOR, SIZE, add, maskVal, dx, dy);
     1046
     1047    if (source->modelEXT) {
     1048        pmSourceNoiseOpModel (source->modelEXT, source, mode, FACTOR, SIZE, add, maskVal, dx, dy);
     1049    }
     1050
     1051    return true;
     1052}
     1053
     1054bool pmSourceNoiseOpModel (pmModel *model, pmSource *source, pmModelOpMode mode, float FACTOR, float SIZE, bool add, psImageMaskType maskVal, int dx, int dy)
     1055{
     1056    bool status;
     1057    psEllipseShape oldshape;
     1058    psEllipseShape newshape;
     1059    psEllipseAxes axes;
     1060
     1061    if (add) {
     1062        psTrace ("psphot", 4, "adding noise for object at %f,%f\n", model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
     1063    } else {
     1064        psTrace ("psphot", 4, "remove noise for object at %f,%f\n", model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
     1065    }
     1066
     1067    psF32 *PAR = model->params->data.F32;
     1068
     1069    // save original values
     1070    float oldI0  = PAR[PM_PAR_I0];
     1071    oldshape.sx  = PAR[PM_PAR_SXX];
     1072    oldshape.sy  = PAR[PM_PAR_SYY];
     1073    oldshape.sxy = PAR[PM_PAR_SXY];
     1074
     1075    // XXX can this be done more intelligently?
     1076    if (oldI0 == 0.0) return false;
     1077    if (!isfinite(oldI0)) return false;
     1078
     1079    // increase size and height of source
     1080    axes = psEllipseShapeToAxes (oldshape, 20.0);
     1081    axes.major *= SIZE;
     1082    axes.minor *= SIZE;
     1083    newshape = psEllipseAxesToShape (axes);
     1084    PAR[PM_PAR_I0]  = FACTOR*oldI0;
     1085    PAR[PM_PAR_SXX] = newshape.sx;
     1086    PAR[PM_PAR_SYY] = newshape.sy;
     1087    PAR[PM_PAR_SXY] = newshape.sxy;
     1088
     1089    psImage *target = source->variance;
     1090
     1091    if (add) {
     1092        status = pmModelAddWithOffset (target, source->maskObj, model, mode, maskVal, dx, dy);
     1093    } else {
     1094        status = pmModelSubWithOffset (target, source->maskObj, model, mode, maskVal, dx, dy);
     1095    }
     1096
     1097    // restore original values
     1098    PAR[PM_PAR_I0]  = oldI0;
     1099    PAR[PM_PAR_SXX] = oldshape.sx;
     1100    PAR[PM_PAR_SYY] = oldshape.sy;
     1101    PAR[PM_PAR_SXY] = oldshape.sxy;
    9751102
    9761103    return true;
  • trunk/psModules/src/objects/pmSource.h

    r28013 r29004  
    1111# define PM_SOURCE_H
    1212
    13 #include <pslib.h>
    14 #include "pmPeaks.h"
    15 #include "pmModel.h"
    16 #include "pmMoments.h"
    17 #include "pmSourceExtendedPars.h"
    18 #include "pmSourceDiffStats.h"
    19 
    2013/// @addtogroup Objects Object Detection / Analysis Functions
    2114/// @{
    22 
    23 #include <pmSourceMasks.h>
    2415
    2516/** pmSourceType enumeration
     
    7465    pmSourceType type;                  ///< Best identification of object.
    7566    pmSourceMode mode;                  ///< analysis flags set for object.
     67    pmSourceMode2 mode2;                ///< analysis flags set for object.
    7668    pmSourceTmpF tmpFlags;              ///< internal-only flags
    7769    psArray *blends;                    ///< collection of sources thought to be confused with object
     
    8274    float errMag;                       ///< error in psfMag OR extMag (depending on type)
    8375    float apMag;                        ///< apMag corresponding to psfMag or extMag (depending on type)
    84     float pixWeight;                    ///< model-weighted coverage of valid pixels
     76    float apMagRaw;                     ///< raw mag in given aperture
     77    float apRadius;                     ///< radius for aperture magnitude
     78
     79    float pixWeightNotBad;              ///< PSF-weighted coverage of unmasked (not BAD) pixels
     80    float pixWeightNotPoor;             ///< PSF-weighted coverage of unmasked (not POOR) pixels
     81
    8582    float psfChisq;                     ///< probability of PSF
    8683    float crNsigma;                     ///< Nsigma deviation from PSF to CR
    8784    float extNsigma;                    ///< Nsigma deviation from PSF to EXT
    8885    float sky, skyErr;                  ///< The sky and its error at the center of the object
    89     float apRadius;
    9086    psRegion region;                    ///< area on image covered by selected pixels
    9187    pmSourceExtendedPars *extpars;      ///< extended source parameters
     
    113109pmPSFClump;
    114110
     111// private macro to set the source ID (a const)
     112#define P_PM_SOURCE_SET_ID(S,V) { *(int *)&(S)->id = (V); }
    115113
    116114/** pmSourceAlloc()
     
    126124
    127125pmSource  *pmSourceCopy(pmSource *source);
     126pmSource *pmSourceCopyData(pmSource *in);
    128127
    129128// free just the pixels for a source, keeping derived data
     
    242241bool pmSourceSubWithOffset (pmSource *source, pmModelOpMode mode, psImageMaskType maskVal, int dx, int dy);
    243242
     243bool pmSourceNoiseOpModel (pmModel *model, pmSource *source, pmModelOpMode mode, float FACTOR, float SIZE, bool add, psImageMaskType maskVal, int dx, int dy);
     244bool pmSourceNoiseOp (pmSource *source, pmModelOpMode mode, float FACTOR, float SIZE, bool add, psImageMaskType maskVal, int dx, int dy);
     245
    244246bool pmSourceOp (pmSource *source, pmModelOpMode mode, bool add, psImageMaskType maskVal, int dx, int dy);
    245247bool pmSourceCacheModel (pmSource *source, psImageMaskType maskVal);
  • trunk/psModules/src/objects/pmSourceContour.c

    r24887 r29004  
    2323#include "pmHDU.h"
    2424#include "pmFPA.h"
     25
     26#include "pmTrend2D.h"
     27#include "pmResiduals.h"
     28#include "pmGrowthCurve.h"
    2529#include "pmSpan.h"
     30#include "pmFootprintSpans.h"
    2631#include "pmFootprint.h"
    2732#include "pmPeaks.h"
    2833#include "pmMoments.h"
    29 #include "pmResiduals.h"
    30 #include "pmGrowthCurve.h"
    31 #include "pmTrend2D.h"
    32 #include "pmPSF.h"
     34#include "pmModelFuncs.h"
    3335#include "pmModel.h"
     36#include "pmModelUtils.h"
     37#include "pmModelClass.h"
     38#include "pmSourceMasks.h"
     39#include "pmSourceExtendedPars.h"
     40#include "pmSourceDiffStats.h"
    3441#include "pmSource.h"
     42
    3543#include "pmSourceContour.h"
    3644
  • trunk/psModules/src/objects/pmSourceDiffStats.c

    r27531 r29004  
    2929    diffStats->nRatioAll = NAN;
    3030    diffStats->nGood = 0;
     31
     32    diffStats->SNp = NAN;
     33    diffStats->SNm = NAN;
     34    diffStats->Rp = NAN;
     35    diffStats->Rm = NAN;
    3136}
    3237
  • trunk/psModules/src/objects/pmSourceDiffStats.h

    r27531 r29004  
    2929    float nRatioAll;                    // = nGood / (nGood + nMask + nBad)
    3030    int   nGood;                        // nGood as defined above
     31    float SNp;                          // S/N of matched source in positive image
     32    float SNm;                          // S/N of matched source in negative image
     33    float Rp;                           // radius of matched source in positive image
     34    float Rm;                           // radius of matched source in negative image
    3135} pmSourceDiffStats;
    3236
  • trunk/psModules/src/objects/pmSourceFitModel.c

    r26070 r29004  
    2323#include "pmHDU.h"
    2424#include "pmFPA.h"
     25
     26#include "pmTrend2D.h"
     27#include "pmResiduals.h"
     28#include "pmGrowthCurve.h"
    2529#include "pmSpan.h"
     30#include "pmFootprintSpans.h"
    2631#include "pmFootprint.h"
    2732#include "pmPeaks.h"
    2833#include "pmMoments.h"
    29 #include "pmGrowthCurve.h"
    30 #include "pmResiduals.h"
    31 #include "pmTrend2D.h"
    32 #include "pmPSF.h"
     34#include "pmModelFuncs.h"
    3335#include "pmModel.h"
     36#include "pmModelUtils.h"
     37#include "pmModelClass.h"
     38#include "pmSourceMasks.h"
     39#include "pmSourceExtendedPars.h"
     40#include "pmSourceDiffStats.h"
    3441#include "pmSource.h"
    35 #include "pmModelClass.h"
    3642#include "pmSourceFitModel.h"
    3743
    38 // save as static values so they may be set externally
    39 static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
    40 static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
    41 static psF32 PM_SOURCE_FIT_MODEL_WEIGHT = 1.0;
    42 static bool  PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = true;
    43 
    44 bool pmSourceFitModelInit (float nIter, float tol, float weight, bool poissonErrors)
     44void pmSourceFitOptionsFree(pmSourceFitOptions *opt)
    4545{
    46 
    47     PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = nIter;
    48     PM_SOURCE_FIT_MODEL_TOLERANCE = tol;
    49     PM_SOURCE_FIT_MODEL_WEIGHT = weight;
    50     PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = poissonErrors;
    51 
    52     return true;
     46    return;
     47}
     48
     49pmSourceFitOptions *pmSourceFitOptionsAlloc(void) {
     50
     51    pmSourceFitOptions *opt = (pmSourceFitOptions *) psAlloc(sizeof(pmSourceFitOptions));
     52    psMemSetDeallocator(opt, (psFreeFunc) pmSourceFitOptionsFree);
     53
     54    opt->mode = PM_SOURCE_FIT_PSF;
     55    opt->nIter  = 15;
     56    opt->minTol = 0.01;
     57    opt->maxTol = 1.00;
     58    opt->weight = 1.00;
     59    opt->maxChisqDOF = NAN;
     60    opt->poissonErrors = true;
     61
     62    return opt;
    5363}
    5464
    5565bool pmSourceFitModel (pmSource *source,
    5666                       pmModel *model,
    57                        pmSourceFitMode mode,
     67                       pmSourceFitOptions *options,
    5868                       psImageMaskType maskVal)
    5969{
     
    7686    psVector *yErr = psVectorAllocEmpty(nPix, PS_TYPE_F32);
    7787
     88    // XXX for a test, skip the central pixel in the sersic fit
     89    bool skipCenter = false && (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     90    float Xo = model->params->data.F32[PM_PAR_XPOS];
     91    float Yo = model->params->data.F32[PM_PAR_YPOS];
     92
    7893    // fill in the coordinate and value entries
    7994    nPix = 0;
     
    95110            // skip nan values in image
    96111            if (!isfinite(source->variance->data.F32[i][j])) {
    97               fprintf (stderr, "impossible! %x vs %x\n", source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[i][j], maskVal);
    98               continue;
    99             }
    100 
    101             psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     112                fprintf (stderr, "impossible! %x vs %x\n", source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[i][j], maskVal);
     113                continue;
     114            }
    102115
    103116            // Convert i/j to image space:
    104117            // 0.5 PIX: the coordinate values must be in pixel coords, not index           
    105             coord->data.F32[0] = (psF32) (j + 0.5 + source->pixels->col0);
    106             coord->data.F32[1] = (psF32) (i + 0.5 + source->pixels->row0);
     118            float Xv = (psF32) (j + 0.5 + source->pixels->col0);
     119            float Yv = (psF32) (i + 0.5 + source->pixels->row0);
     120
     121            // XXX possible skip of center pixel:
     122            if (skipCenter) {
     123                float r = hypot(Xv - Xo, Yv - Yo);
     124                if (r < 0.75) {
     125                    continue;
     126                }
     127            }
     128
     129            psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     130            coord->data.F32[0] = Xv;
     131            coord->data.F32[1] = Yv;
    107132            x->data[nPix] = (psPtr *) coord;
    108133            y->data.F32[nPix] = source->pixels->data.F32[i][j];
     
    111136            // as variance to avoid the bias from systematic errors here we would just use the
    112137            // source sky variance
    113             if (PM_SOURCE_FIT_MODEL_PIX_WEIGHTS) {
     138            if (options->poissonErrors) {
    114139                yErr->data.F32[nPix] = 1.0 / source->variance->data.F32[i][j];
    115140            } else {
    116                 yErr->data.F32[nPix] = 1.0 / PM_SOURCE_FIT_MODEL_WEIGHT;
     141                yErr->data.F32[nPix] = 1.0 / options->weight;
    117142            }
    118143            nPix++;
     
    133158    // set parameter mask based on fitting mode
    134159    int nParams = 0;
    135     switch (mode) {
    136     case PM_SOURCE_FIT_NORM:
     160    switch (options->mode) {
     161      case PM_SOURCE_FIT_NORM:
    137162        // NORM-only model fits only source normalization (Io)
    138163        nParams = 1;
     
    140165        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
    141166        break;
    142     case PM_SOURCE_FIT_PSF:
     167      case PM_SOURCE_FIT_PSF:
    143168        // PSF model only fits x,y,Io
    144169        nParams = 3;
     
    148173        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_YPOS] = 0;
    149174        break;
    150     case PM_SOURCE_FIT_EXT:
     175      case PM_SOURCE_FIT_EXT:
    151176        // EXT model fits all params (except sky)
    152177        nParams = params->n - 1;
     
    154179        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
    155180        break;
    156     default:
    157         psAbort("invalid fitting mode");
     181      case PM_SOURCE_FIT_INDEX:
     182        // PSF model only fits Io, index (PAR7) -- only Io for models with < 8 params
     183        psVectorInit (constraint->paramMask, 1);
     184        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_I0] = 0;
     185        if (params->n == 7) {
     186            nParams = 1;
     187        } else {
     188            nParams = 2;
     189            constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 0;
     190        }
     191        break;
     192      case PM_SOURCE_FIT_NO_INDEX:
     193        // PSF model only fits Io, index (PAR7) -- only Io for models with < 8 params
     194        psVectorInit (constraint->paramMask, 0);
     195        constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_SKY] = 1;
     196        if (params->n == 7) {
     197            nParams = params->n - 1;
     198        } else {
     199            nParams = params->n - 2;
     200            constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[PM_PAR_7] = 1;
     201        }
     202        break;
     203      default:
     204        psAbort("invalid fitting mode");
    158205    }
    159206    // force the floating parameters to fall within the contraint ranges
    160207    for (int i = 0; i < params->n; i++) {
    161         model->modelLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);
    162         model->modelLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);
     208        model->modelLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);
     209        model->modelLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);
    163210    }
    164211
     
    173220    }
    174221
    175     psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE);
     222    psMinimization *myMin = psMinimizationAlloc (options->nIter, options->minTol, options->maxTol);
    176223
    177224    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
     
    194241    model->flags |= PM_MODEL_STATUS_FITTED;
    195242    if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;
     243    if (myMin->lastDelta > myMin->minTol) model->flags |= PM_MODEL_STATUS_WEAK_FIT;
    196244
    197245    // get the Gauss-Newton distance for fixed model parameters
  • trunk/psModules/src/objects/pmSourceFitModel.h

    r21183 r29004  
    1919    PM_SOURCE_FIT_EXT,
    2020    PM_SOURCE_FIT_PSF_AND_SKY,
    21     PM_SOURCE_FIT_EXT_AND_SKY
     21    PM_SOURCE_FIT_EXT_AND_SKY,
     22    PM_SOURCE_FIT_INDEX,
     23    PM_SOURCE_FIT_NO_INDEX,
    2224} pmSourceFitMode;
    2325
    24 bool pmSourceFitModelInit(
    25     float nIter,   ///< max number of allowed iterations
    26     float tol,      ///< convergence criterion
    27     float weight,      ///< use this weight for constant-weight fits
    28     bool poissonErrors   // use poisson errors for fits?
    29 );
     26typedef struct {
     27    pmSourceFitMode mode;               ///< optionally fit all or a subset of parameters
     28    float nIter;                        ///< max number of allowed iterations
     29    float minTol;                       ///< convergence criterion
     30    float maxTol;                       ///< convergence criterion
     31    float maxChisqDOF;                  ///< convergence criterion
     32    float weight;                       ///< use this weight for constant-weight fits
     33    bool poissonErrors;                 ///< use poisson errors for fits?
     34} pmSourceFitOptions;
     35
     36// the pmSourceFitOptions structure is used to control details of the fitting process
     37pmSourceFitOptions *pmSourceFitOptionsAlloc(void);
     38
     39// bool pmSourceFitModelInit(
     40//     pmSourceFitMode mode,            ///< what parameter set should be fitted?
     41//     float nIter,                     ///< max number of allowed iterations
     42//     float tol,                               ///< convergence criterion
     43//     float weight,                    ///< use this weight for constant-weight fits
     44//     bool poissonErrors                       ///< use poisson errors for fits?
     45// );
    3046
    3147/** pmSourceFitModel()
     
    3854 */
    3955bool pmSourceFitModel(
    40     pmSource *source,   ///< The input pmSource
    41     pmModel *model,   ///< model to be fitted
    42     pmSourceFitMode mode,  ///< define parameters to be fitted
     56    pmSource *source,                   ///< The input pmSource
     57    pmModel *model,                     ///< model to be fitted
     58    pmSourceFitOptions *options,        ///< define parameters to be fitted
    4359    psImageMaskType maskVal             ///< Value to mask
    4460);
    4561
    46 
    47 // initialize data for a group of object models
    48 bool pmSourceFitSetInit (pmModelType type);
    49 
    50 // clear data for a group of object models
    51 void pmSourceFitSetClear (void);
    52 
    53 // function used to set limits for a group of models
    54 bool pmSourceFitSet_CheckLimits (psMinConstraintMode mode, int nParam, float *params, float *betas);
    55 
    56 // function used to fit a group of object models
    57 psF32 pmSourceFitSet_Function(psVector *deriv,
    58                               const psVector *params,
    59                               const psVector *x);
    60 
    61 /** pmSourceFitSet()
    62  *
    63  * Fit the requested model to the specified source. The starting guess for the model is given
    64  * by the input source.model parameter values. The pixels of interest are specified by the
    65  * source.pixels and source.mask entries. This function calls psMinimizeLMChi2() on the image
    66  * data. The function returns TRUE on success or FALSE on failure.
    67  *
    68  */
    69 bool pmSourceFitSet(
    70     pmSource *source,   ///< The input pmSource
    71     psArray *modelSet,   ///< model to be fitted
    72     pmSourceFitMode mode,  ///< define parameters to be fitted
    73     psImageMaskType maskVal             ///< Vale to mask
    74 
    75 );
     62// // initialize data for a group of object models
     63// bool pmSourceFitSetInit (pmModelType type);
     64//
     65// // clear data for a group of object models
     66// void pmSourceFitSetClear (void);
     67//
     68// // function used to set limits for a group of models
     69// bool pmSourceFitSet_CheckLimits (psMinConstraintMode mode, int nParam, float *params, float *betas);
     70//
     71// // function used to fit a group of object models
     72// psF32 pmSourceFitSet_Function(psVector *deriv,
     73//                               const psVector *params,
     74//                               const psVector *x);
     75//
     76// /** pmSourceFitSet()
     77//  *
     78//  * Fit the requested model to the specified source. The starting guess for the model is given
     79//  * by the input source.model parameter values. The pixels of interest are specified by the
     80//  * source.pixels and source.mask entries. This function calls psMinimizeLMChi2() on the image
     81//  * data. The function returns TRUE on success or FALSE on failure.
     82//  *
     83//  */
     84// bool pmSourceFitSet(
     85//     pmSource *source,   ///< The input pmSource
     86//     psArray *modelSet,   ///< model to be fitted
     87//     pmSourceFitMode mode,  ///< define parameters to be fitted
     88//     psImageMaskType maskVal          ///< Vale to mask
     89//
     90// );
    7691
    7792/// @}
  • trunk/psModules/src/objects/pmSourceFitSet.c

    r27903 r29004  
    2222#include "pmHDU.h"
    2323#include "pmFPA.h"
     24
     25#include "pmTrend2D.h"
     26#include "pmResiduals.h"
     27#include "pmGrowthCurve.h"
    2428#include "pmSpan.h"
     29#include "pmFootprintSpans.h"
    2530#include "pmFootprint.h"
    2631#include "pmPeaks.h"
    2732#include "pmMoments.h"
    28 #include "pmGrowthCurve.h"
    29 #include "pmResiduals.h"
    30 #include "pmTrend2D.h"
    31 #include "pmPSF.h"
     33#include "pmModelFuncs.h"
    3234#include "pmModel.h"
     35#include "pmModelUtils.h"
     36#include "pmModelClass.h"
     37#include "pmSourceMasks.h"
     38#include "pmSourceExtendedPars.h"
     39#include "pmSourceDiffStats.h"
    3340#include "pmSource.h"
    34 #include "pmModelClass.h"
     41
    3542#include "pmSourceFitModel.h"
    3643#include "pmSourceFitSet.h"
    3744
    3845// save as static values so they may be set externally
    39 static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
    40 static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
    41 static psF32 PM_SOURCE_FIT_MODEL_WEIGHT = 1.0;
    42 static bool  PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = true;
     46// static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
     47// static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
     48// static psF32 PM_SOURCE_FIT_MODEL_WEIGHT = 1.0;
     49// static bool  PM_SOURCE_FIT_MODEL_PIX_WEIGHTS = true;
    4350
    4451/********************* Source Model Set Functions ***************************/
     
    429436bool pmSourceFitSet (pmSource *source,
    430437                     psArray *modelSet,
    431                      pmSourceFitMode mode,
     438                     pmSourceFitOptions *options,
    432439                     psImageMaskType maskVal)
    433440{
     
    478485            // as variance to avoid the bias from systematic errors here we would just use the
    479486            // source sky variance
    480             if (PM_SOURCE_FIT_MODEL_PIX_WEIGHTS) {
    481                 yErr->data.F32[nPix] = 1.0 / source->variance->data.F32[i][j];
    482             } else {
    483                 yErr->data.F32[nPix] = 1.0 / PM_SOURCE_FIT_MODEL_WEIGHT;
    484             }
    485             nPix++;
    486         }
     487            if (options->poissonErrors) {
     488                yErr->data.F32[nPix] = 1.0 / source->variance->data.F32[i][j];
     489            } else {
     490                yErr->data.F32[nPix] = 1.0 / options->weight;
     491            }
     492            nPix++;
     493        }
    487494    }
    488495    x->n = nPix;
     
    490497    yErr->n = nPix;
    491498
    492     // create the FitSet for this thread and set the initial parameter guesses
     499// create the FitSet for this thread and set the initial parameter guesses
    493500    pmSourceFitSetData *thisSet = pmSourceFitSetDataSet(modelSet);
    494501
    495     // define param and deriv vectors for complete set of parameters
     502// define param and deriv vectors for complete set of parameters
    496503    psVector *params = psVectorAlloc (thisSet->nParamSet, PS_TYPE_F32);
    497504
    498     // set the param and deriv vectors based on the curent values
     505// set the param and deriv vectors based on the curent values
    499506    pmSourceFitSetJoin (NULL, params, thisSet);
    500507
    501     // create the minimization constraints
     508// create the minimization constraints
    502509    psMinConstraint *constraint = psMinConstraintAlloc();
    503510    constraint->paramMask = psVectorAlloc (thisSet->nParamSet, PS_TYPE_VECTOR_MASK);
    504511    constraint->checkLimits = pmSourceFitSetCheckLimits;
    505512
    506     pmSourceFitSetMasks (constraint, thisSet, mode);
    507 
    508     // force the floating parameters to fall within the contraint ranges
     513    pmSourceFitSetMasks (constraint, thisSet, options->mode);
     514
     515// force the floating parameters to fall within the contraint ranges
    509516    for (int i = 0; i < params->n; i++) {
    510         pmSourceFitSetCheckLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);
    511         pmSourceFitSetCheckLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);
     517        pmSourceFitSetCheckLimits (PS_MINIMIZE_PARAM_MIN, i, params->data.F32, NULL);
     518        pmSourceFitSetCheckLimits (PS_MINIMIZE_PARAM_MAX, i, params->data.F32, NULL);
    512519    }
    513520
    514521    if (psTraceGetLevel("psModules.objects") >= 5) {
    515         for (int i = 0; i < params->n; i++) {
    516             fprintf (stderr, "%d %f %d\n", i, params->data.F32[i], constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[i]);
    517         }
     522        for (int i = 0; i < params->n; i++) {
     523            fprintf (stderr, "%d %f %d\n", i, params->data.F32[i], constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[i]);
     524        }
    518525    }
    519526
    520527    if (nPix <  thisSet->nParamSet + 1) {
    521         psTrace (__func__, 4, "insufficient valid pixels\n");
    522         psTrace("psModules.objects", 10, "---- %s() end : fail pixels ----\n", __func__);
    523         for (int i = 0; i < modelSet->n; i++) {
    524             pmModel *model = modelSet->data[i];
    525             model->flags |= PM_MODEL_STATUS_BADARGS;
    526         }
    527         psFree (x);
    528         psFree (y);
    529         psFree (yErr);
    530         psFree (params);
    531         psFree(constraint);
    532         pmSourceFitSetDataClear(); // frees thisSet and removes if from the array of fitSets
    533         return(false);
    534     }
    535 
    536     psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE);
     528        psTrace (__func__, 4, "insufficient valid pixels\n");
     529        psTrace("psModules.objects", 10, "---- %s() end : fail pixels ----\n", __func__);
     530        for (int i = 0; i < modelSet->n; i++) {
     531            pmModel *model = modelSet->data[i];
     532            model->flags |= PM_MODEL_STATUS_BADARGS;
     533        }
     534        psFree (x);
     535        psFree (y);
     536        psFree (yErr);
     537        psFree (params);
     538        psFree(constraint);
     539        pmSourceFitSetDataClear(); // frees thisSet and removes if from the array of fitSets
     540        return(false);
     541    }
     542
     543    psMinimization *myMin = psMinimizationAlloc (options->nIter, options->minTol, options->maxTol);
    537544
    538545    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
     
    540547    fitStatus = psMinimizeLMChi2(myMin, covar, params, constraint, x, y, yErr, pmSourceFitSetFunction);
    541548    if (!fitStatus) {
    542         psTrace("psModules.objects", 4, "Failed to fit model (%ld components)\n", modelSet->n);
    543     }
    544 
    545     // parameter errors from the covariance matrix
     549        psTrace("psModules.objects", 4, "Failed to fit model (%ld components)\n", modelSet->n);
     550    }
     551
     552// parameter errors from the covariance matrix
    546553    psVector *dparams = psVectorAlloc (thisSet->nParamSet, PS_TYPE_F32);
    547554    for (int i = 0; i < dparams->n; i++) {
    548         if ((constraint->paramMask != NULL) && constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[i])
    549             continue;
    550         dparams->data.F32[i] = sqrt(covar->data.F32[i][i]);
    551     }
    552 
    553     // get the Gauss-Newton distance for fixed model parameters
     555        if ((constraint->paramMask != NULL) && constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[i])
     556            continue;
     557        dparams->data.F32[i] = sqrt(covar->data.F32[i][i]);
     558    }
     559
     560// get the Gauss-Newton distance for fixed model parameters
    554561    if (constraint->paramMask != NULL) {
    555         psVector *delta = psVectorAlloc (params->n, PS_TYPE_F32);
    556         psVector *altmask = psVectorAlloc (params->n, PS_TYPE_VECTOR_MASK);
    557         altmask->data.PS_TYPE_VECTOR_MASK_DATA[0] = 1;
    558         for (int i = 1; i < dparams->n; i++) {
    559             altmask->data.PS_TYPE_VECTOR_MASK_DATA[i] = (constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[i]) ? 0 : 1;
    560         }
    561         psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, pmSourceFitSetFunction);
    562 
    563         for (int i = 0; i < dparams->n; i++) {
    564             if (!constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[i])
    565                 continue;
    566             // note that delta is the value *subtracted* from the parameter
    567             // to get the new guess.  for dparams to represent the direction
    568             // of motion, we need to take -delta
    569             dparams->data.F32[i] = -delta->data.F32[i];
    570         }
    571         psFree (delta);
    572         psFree (altmask);
     562        psVector *delta = psVectorAlloc (params->n, PS_TYPE_F32);
     563        psVector *altmask = psVectorAlloc (params->n, PS_TYPE_VECTOR_MASK);
     564        altmask->data.PS_TYPE_VECTOR_MASK_DATA[0] = 1;
     565        for (int i = 1; i < dparams->n; i++) {
     566            altmask->data.PS_TYPE_VECTOR_MASK_DATA[i] = (constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[i]) ? 0 : 1;
     567        }
     568        psMinimizeGaussNewtonDelta(delta, params, altmask, x, y, yErr, pmSourceFitSetFunction);
     569
     570        for (int i = 0; i < dparams->n; i++) {
     571            if (!constraint->paramMask->data.PS_TYPE_VECTOR_MASK_DATA[i])
     572                continue;
     573            // note that delta is the value *subtracted* from the parameter
     574            // to get the new guess.  for dparams to represent the direction
     575            // of motion, we need to take -delta
     576            dparams->data.F32[i] = -delta->data.F32[i];
     577        }
     578        psFree (delta);
     579        psFree (altmask);
    573580    }
    574581
  • trunk/psModules/src/objects/pmSourceFitSet.h

    r23487 r29004  
    5656    pmSource *source,                   ///< The input pmSource
    5757    psArray *modelSet,                  ///< model to be fitted
    58     pmSourceFitMode mode,               ///< define parameters to be fitted
     58    pmSourceFitOptions *options,        ///< define options for fitting process
    5959    psImageMaskType maskVal             ///< Vale to mask
    6060
  • trunk/psModules/src/objects/pmSourceGroups.c

    r26450 r29004  
    66#include <pslib.h>
    77
     8#include "pmHDU.h"
    89#include "pmFPA.h"
     10
     11#include "pmTrend2D.h"
     12#include "pmResiduals.h"
     13#include "pmGrowthCurve.h"
     14#include "pmSpan.h"
     15#include "pmFootprintSpans.h"
     16#include "pmFootprint.h"
     17#include "pmPeaks.h"
     18#include "pmMoments.h"
     19#include "pmModelFuncs.h"
     20#include "pmModel.h"
     21#include "pmModelUtils.h"
     22#include "pmModelClass.h"
     23#include "pmSourceMasks.h"
     24#include "pmSourceExtendedPars.h"
     25#include "pmSourceDiffStats.h"
    926#include "pmSource.h"
     27#include "pmSourceFitModel.h"
     28#include "pmPSF.h"
     29#include "pmPSFtry.h"
     30#include "pmDetections.h"
     31
    1032#include "pmSourceGroups.h"
    1133
  • trunk/psModules/src/objects/pmSourceGroups.h

    r26182 r29004  
    11#ifndef PM_SOURCE_GROUPS_H
    22#define PM_SOURCE_GROUPS_H
    3 
    4 #include <pslib.h>
    5 
    6 #include "pmFPA.h"
    73
    84/// Groups of sources
  • trunk/psModules/src/objects/pmSourceIO.c

    r28013 r29004  
    3131#include "pmConceptsRead.h"
    3232
     33#include "pmTrend2D.h"
     34#include "pmResiduals.h"
     35#include "pmGrowthCurve.h"
    3336#include "pmSpan.h"
     37#include "pmFootprintSpans.h"
    3438#include "pmFootprint.h"
    3539#include "pmPeaks.h"
    3640#include "pmMoments.h"
    37 #include "pmGrowthCurve.h"
    38 #include "pmResiduals.h"
    39 #include "pmTrend2D.h"
     41#include "pmModelFuncs.h"
     42#include "pmModel.h"
     43#include "pmModelUtils.h"
     44#include "pmModelClass.h"
     45#include "pmSourceMasks.h"
     46#include "pmSourceExtendedPars.h"
     47#include "pmSourceDiffStats.h"
     48#include "pmSource.h"
     49#include "pmSourceFitModel.h"
    4050#include "pmPSF.h"
    41 #include "pmModel.h"
     51#include "pmPSFtry.h"
     52
    4253#include "pmDetections.h"
    43 #include "pmSource.h"
    44 #include "pmModelClass.h"
    4554#include "pmDetEff.h"
    4655#include "pmSourceIO.h"
     
    326335}
    327336
     337# define PM_SOURCES_WRITE(NAME,TYPE)                                    \
     338    if (!strcmp (exttype, NAME)) {                                      \
     339        status &= pmSourcesWrite_##TYPE(file->fits, readout, sources, file->header, outhead, dataname, recipe); \
     340        if (xsrcname) {                                                 \
     341            status &= pmSourcesWrite_##TYPE##_XSRC(file->fits, readout, sources, file->header, xsrcname, recipe); \
     342        }                                                               \
     343        if (xfitname) {                                                 \
     344            status &= pmSourcesWrite_##TYPE##_XFIT (file->fits, readout, sources, file->header, xfitname); \
     345        }                                                               \
     346    }
     347
    328348// write out all readout-level Objects files for this cell
    329349bool pmReadoutWriteObjects (pmReadout *readout, const pmFPAview *view, pmFPAfile *file, const pmConfig *config)
     
    360380    }
    361381
     382    // the older types (RAW, OBJ, SX, CMP) are for backwards compatibility -- deprecate eventually?
    362383    switch (file->type) {
    363384      case PM_FPA_FILE_RAW:
     
    518539                psMetadataAddStr (outhead, PS_LIST_TAIL, "XFITNAME", PS_META_REPLACE, "name of XFIT table extension", xfitname);
    519540            }
    520 
    521             // XXX these are case-sensitive since the EXTYPE is case-sensitive
     541   
     542
     543            // these are case-sensitive since the EXTYPE is case-sensitive
    522544            status = true;
    523             if (!strcmp (exttype, "SMPDATA")) {
    524                 status &= pmSourcesWrite_SMPDATA (file->fits, sources, file->header, outhead, dataname);
    525             }
    526             if (!strcmp (exttype, "PS1_DEV_0")) {
    527                 status &= pmSourcesWrite_PS1_DEV_0 (file->fits, sources, file->header, outhead, dataname);
    528             }
    529             if (!strcmp (exttype, "PS1_DEV_1")) {
    530                 status &= pmSourcesWrite_PS1_DEV_1 (file->fits, sources, file->header, outhead, dataname);
    531             }
    532             if (!strcmp (exttype, "PS1_CAL_0")) {
    533                 status &= pmSourcesWrite_PS1_CAL_0 (file->fits, readout, sources, file->header, outhead, dataname);
    534             }
    535             if (!strcmp (exttype, "PS1_V1")) {
    536                 status &= pmSourcesWrite_CMF_PS1_V1 (file->fits, readout, sources, file->header, outhead, dataname);
    537             }
    538             if (!strcmp (exttype, "PS1_V2")) {
    539                 status &= pmSourcesWrite_CMF_PS1_V2 (file->fits, readout, sources, file->header, outhead, dataname);
    540             }
    541             if (!strcmp (exttype, "PS1_SV1")) {
    542                 status &= pmSourcesWrite_CMF_PS1_SV1 (file->fits, readout, sources, file->header, outhead, dataname, recipe);
    543             }
    544             if (!strcmp (exttype, "PS1_DV1")) {
    545                 status &= pmSourcesWrite_CMF_PS1_DV1 (file->fits, readout, sources, file->header, outhead, dataname);
    546             }
    547 
    548             if (xsrcname) {
    549                 if (!strcmp (exttype, "PS1_DEV_1")) {
    550                     status &= pmSourcesWrite_PS1_DEV_1_XSRC (file->fits, sources, xsrcname, recipe);
    551                 }
    552                 if (!strcmp (exttype, "PS1_CAL_0")) {
    553                     status &= pmSourcesWrite_PS1_CAL_0_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
    554                 }
    555                 if (!strcmp (exttype, "PS1_V1")) {
    556                     status &= pmSourcesWrite_CMF_PS1_V1_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
    557                 }
    558                 if (!strcmp (exttype, "PS1_V2")) {
    559                     status &= pmSourcesWrite_CMF_PS1_V2_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
    560                 }
    561                 if (!strcmp (exttype, "PS1_SV1")) {
    562                     status &= pmSourcesWrite_CMF_PS1_SV1_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
    563                 }
    564                 if (!strcmp (exttype, "PS1_DV1")) {
    565                     status &= pmSourcesWrite_CMF_PS1_DV1_XSRC (file->fits, readout, sources, file->header, xsrcname, recipe);
    566                 }
    567             }
    568             if (xfitname) {
    569                 if (!strcmp (exttype, "PS1_DEV_1")) {
    570                     status &= pmSourcesWrite_PS1_DEV_1_XFIT (file->fits, sources, xfitname);
    571                 }
    572                 if (!strcmp (exttype, "PS1_CAL_0")) {
    573                     status &= pmSourcesWrite_PS1_CAL_0_XFIT (file->fits, readout, sources, file->header, xfitname);
    574                 }
    575                 if (!strcmp (exttype, "PS1_V1")) {
    576                     status &= pmSourcesWrite_CMF_PS1_V1_XFIT (file->fits, readout, sources, xfitname);
    577                 }
    578                 if (!strcmp (exttype, "PS1_V2")) {
    579                     status &= pmSourcesWrite_CMF_PS1_V2_XFIT (file->fits, readout, sources, xfitname);
    580                 }
    581                 if (!strcmp (exttype, "PS1_SV1")) {
    582                     status &= pmSourcesWrite_CMF_PS1_SV1_XFIT (file->fits, readout, sources, xfitname);
    583                 }
    584                 if (!strcmp (exttype, "PS1_DV1")) {
    585                     status &= pmSourcesWrite_CMF_PS1_DV1_XFIT (file->fits, readout, sources, xfitname);
    586                 }
    587             }
     545            PM_SOURCES_WRITE("SMPDATA",   SMPDATA);
     546            PM_SOURCES_WRITE("PS1_DEV_0", PS1_DEV_0);
     547            PM_SOURCES_WRITE("PS1_DEV_1", PS1_DEV_1);
     548            PM_SOURCES_WRITE("PS1_CAL_0", PS1_CAL_0);
     549            PM_SOURCES_WRITE("PS1_V1",    CMF_PS1_V1);
     550            PM_SOURCES_WRITE("PS1_V2",    CMF_PS1_V2);
     551            PM_SOURCES_WRITE("PS1_V3",    CMF_PS1_V3);
     552            PM_SOURCES_WRITE("PS1_SV1",   CMF_PS1_SV1);
     553            PM_SOURCES_WRITE("PS1_DV1",   CMF_PS1_DV1);
     554            PM_SOURCES_WRITE("PS1_DV2",   CMF_PS1_DV2);
     555
    588556            psFree (outhead);
    589557            psFree (exttype);
     
    10391007                sources = pmSourcesRead_CMF_PS1_DV1 (file->fits, hdu->header);
    10401008            }
     1009            if (!strcmp (exttype, "PS1_DV2")) {
     1010                sources = pmSourcesRead_CMF_PS1_DV2 (file->fits, hdu->header);
     1011            }
    10411012
    10421013            if (!pmReadoutReadDetEff(file->fits, readout, deteffname)) {
  • trunk/psModules/src/objects/pmSourceIO.h

    r28013 r29004  
    2424bool pmSourcesWriteCMP (psArray *sources, char *filename, psMetadata *header);
    2525
    26 bool pmSourcesWrite_SMPDATA (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
    27 bool pmSourcesWrite_PS1_DEV_0 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
     26bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
    2827
    29 bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
    30 bool pmSourcesWrite_PS1_DEV_1_XSRC (psFits *fits, psArray *sources, char *extname, psMetadata *recipe);
    31 bool pmSourcesWrite_PS1_DEV_1_XFIT (psFits *fits, psArray *sources, char *extname);
     28// All of these functions need to use the same API, even if not all elements are used in a specific case
     29bool pmSourcesWrite_SMPDATA(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     30bool pmSourcesWrite_SMPDATA_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     31bool pmSourcesWrite_SMPDATA_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
    3232
    33 bool pmSourcesWrite_PS1_CAL_0 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
    34 bool pmSourcesWrite_PS1_CAL_0_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
    35 bool pmSourcesWrite_PS1_CAL_0_XFIT (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
     33bool pmSourcesWrite_PS1_DEV_0(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     34bool pmSourcesWrite_PS1_DEV_0_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     35bool pmSourcesWrite_PS1_DEV_0_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
    3636
    37 bool pmSourcesWrite_CMF_PS1_V1 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
    38 bool pmSourcesWrite_CMF_PS1_V1_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
    39 bool pmSourcesWrite_CMF_PS1_V1_XFIT (psFits *fits, pmReadout *readout, psArray *sources, char *extname);
     37bool pmSourcesWrite_PS1_DEV_1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     38bool pmSourcesWrite_PS1_DEV_1_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     39bool pmSourcesWrite_PS1_DEV_1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
    4040
    41 bool pmSourcesWrite_CMF_PS1_V2 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
    42 bool pmSourcesWrite_CMF_PS1_V2_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
    43 bool pmSourcesWrite_CMF_PS1_V2_XFIT (psFits *fits, pmReadout *readout, psArray *sources, char *extname);
     41bool pmSourcesWrite_PS1_CAL_0(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     42bool pmSourcesWrite_PS1_CAL_0_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     43bool pmSourcesWrite_PS1_CAL_0_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
    4444
    45 bool pmSourcesWrite_CMF_PS1_SV1 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
    46 bool pmSourcesWrite_CMF_PS1_SV1_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
    47 bool pmSourcesWrite_CMF_PS1_SV1_XFIT (psFits *fits, pmReadout *readout, psArray *sources, char *extname);
     45bool pmSourcesWrite_CMF_PS1_V1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     46bool pmSourcesWrite_CMF_PS1_V1_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     47bool pmSourcesWrite_CMF_PS1_V1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
    4848
    49 bool pmSourcesWrite_CMF_PS1_DV1 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname);
    50 bool pmSourcesWrite_CMF_PS1_DV1_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
    51 bool pmSourcesWrite_CMF_PS1_DV1_XFIT (psFits *fits, pmReadout *readout, psArray *sources, char *extname);
     49bool pmSourcesWrite_CMF_PS1_V2(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     50bool pmSourcesWrite_CMF_PS1_V2_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     51bool pmSourcesWrite_CMF_PS1_V2_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
    5252
    53 bool pmSource_CMF_WritePHU (const pmFPAview *view, pmFPAfile *file, pmConfig *config);
     53bool pmSourcesWrite_CMF_PS1_V3(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     54bool pmSourcesWrite_CMF_PS1_V3_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     55bool pmSourcesWrite_CMF_PS1_V3_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
     56
     57bool pmSourcesWrite_CMF_PS1_SV1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     58bool pmSourcesWrite_CMF_PS1_SV1_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     59bool pmSourcesWrite_CMF_PS1_SV1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
     60
     61bool pmSourcesWrite_CMF_PS1_DV1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     62bool pmSourcesWrite_CMF_PS1_DV1_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     63bool pmSourcesWrite_CMF_PS1_DV1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
     64
     65bool pmSourcesWrite_CMF_PS1_DV2(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe);
     66bool pmSourcesWrite_CMF_PS1_DV2_XSRC(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe);
     67bool pmSourcesWrite_CMF_PS1_DV2_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname);
    5468
    5569psArray *pmSourcesReadCMP (char *filename, psMetadata *header);
     
    6377psArray *pmSourcesRead_CMF_PS1_SV1 (psFits *fits, psMetadata *header);
    6478psArray *pmSourcesRead_CMF_PS1_DV1 (psFits *fits, psMetadata *header);
     79psArray *pmSourcesRead_CMF_PS1_DV2 (psFits *fits, psMetadata *header);
    6580
    6681bool pmSourcesWritePSFs (psArray *sources, char *filename);
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_DV1.c

    r28013 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
     
    4756// This version has elements intended for difference images & forced photometry:
    4857// diffStats entries (good for dipoles); flux + flux error (for insignificant detections)
    49 bool pmSourcesWrite_CMF_PS1_DV1 (psFits *fits, pmReadout *readout, psArray *sources,
    50                                 psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
     58bool pmSourcesWrite_CMF_PS1_DV1 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe)
    5159{
    5260    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    194202        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    195203        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
    196         psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeight);
     204        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeightNotBad);
    197205        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    198206        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
     
    324332        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    325333        source->peak->flux = peakFlux;
     334        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
     335        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    326336        source->peak->dx   = dPAR[PM_PAR_XPOS];
    327337        source->peak->dy   = dPAR[PM_PAR_YPOS];
    328         source->peak->SN   = sqrt(source->peak->flux); // XXX a proxy: various functions sort by peak S/N
    329 
    330         source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
     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        }
     343
     344        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
    331345        source->crNsigma  = psMetadataLookupF32 (&status, row, "CR_NSIGMA");
    332346        source->extNsigma = psMetadataLookupF32 (&status, row, "EXT_NSIGMA");
     
    536550
    537551// XXX this layout is still the same as PS1_DEV_1
    538 bool pmSourcesWrite_CMF_PS1_DV1_XFIT (psFits *fits, pmReadout *readout, psArray *sources, char *extname)
     552bool pmSourcesWrite_CMF_PS1_DV1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
    539553{
    540554
     
    585599            assert (model);
    586600
     601            // skip models which were not actually fitted
     602            if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     603
    587604            PAR = model->params->data.F32;
    588605            dPAR = model->dparams->data.F32;
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_SV1.c

    r28013 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
     
    4655
    4756// NOTE: this output function is intended for psphotStack analysis: it includes per-psf radial fluxes
    48 // XXX currently in the 'read' function is NOT consistent with the 'write' function (does not read radial fluxes)
     57// XXX currently, the 'read' function is NOT consistent with the 'write' function (does not read radial fluxes)
    4958
    5059bool pmSourcesWrite_CMF_PS1_SV1 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe)
     
    6271    psF32 errMag, chisq, apRadius;
    6372    psS32 nPix, nDOF;
     73    char keyword1[80], keyword2[80];
    6474
    6575    pmChip *chip = readout->parent->parent;
     
    95105    // we use this just to define the output vectors (which must be present for all objects)
    96106    bool status = false;
     107    psVector *radMin = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER");
    97108    psVector *radMax = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER");
    98109    psAssert (radMax, "this must have been defined and tested earlier!");
    99110    psAssert (radMax->n, "this must have been defined and tested earlier!");
     111    psAssert (radMin->n == radMax->n, "inconsistent annular bins");
     112
     113    // write the radial profile apertures to header
     114    for (int i = 0; i < radMax->n; i++) {
     115      sprintf (keyword1, "RMIN_%02d", i);
     116      sprintf (keyword2, "RMAX_%02d", i);
     117      psMetadataAddF32 (imageHeader, PS_LIST_TAIL, keyword1, PS_META_REPLACE, "min radius for SB profile", radMin->data.F32[i]);
     118      psMetadataAddF32 (imageHeader, PS_LIST_TAIL, keyword2, PS_META_REPLACE, "min radius for SB profile", radMax->data.F32[i]);
     119    }
     120
    100121
    101122    // we write out PSF-fits for all sources, regardless of quality.  the source flags tell us the state
     
    193214        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    194215        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
    195         psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeight);
     216        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor (bad)",          source->pixWeightNotBad);
     217        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF_PERFECT",   PS_DATA_F32, "PSF coverage/quality factor (poor)",         source->pixWeightNotPoor);
    196218        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    197219        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
    198220
    199221        // distinguish moments measure from window vs S/N > XX ??
    200         float mxx = source->moments ? source->moments->Mxx : NAN;
    201         float mxy = source->moments ? source->moments->Mxy : NAN;
    202         float myy = source->moments ? source->moments->Myy : NAN;
    203         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      mxx);
    204         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      mxy);
    205         psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      myy);
    206 
    207         psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                      source->mode);
     222        float Mxx = source->moments ? source->moments->Mxx : NAN;
     223        float Mxy = source->moments ? source->moments->Mxy : NAN;
     224        float Myy = source->moments ? source->moments->Myy : NAN;
     225
     226        float Mrf  = source->moments ? source->moments->Mrf : NAN;
     227        float Mrh  = source->moments ? source->moments->Mrh : NAN;
     228        float Krf  = source->moments ? source->moments->KronFlux : NAN;
     229        float dKrf = source->moments ? source->moments->KronFluxErr : NAN;
     230
     231        float Kinner = source->moments ? source->moments->KronFinner : NAN;
     232        float Kouter = source->moments ? source->moments->KronFouter : NAN;
     233
     234        float M_c3 = source->moments ? 1.0*source->moments->Mxxx - 3.0*source->moments->Mxyy : NAN;
     235        float M_s3 = source->moments ? 3.0*source->moments->Mxxy - 1.0*source->moments->Myyy : NAN;
     236        float M_c4 = source->moments ? 1.0*source->moments->Mxxxx - 6.0*source->moments->Mxxyy + 1.0*source->moments->Myyyy : NAN;
     237        float M_s4 = source->moments ? 4.0*source->moments->Mxxxy - 4.0*source->moments->Mxyyy : NAN;
     238
     239        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XX",       PS_DATA_F32, "second moments (X^2)",                      Mxx);
     240        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_XY",       PS_DATA_F32, "second moments (X*Y)",                      Mxy);
     241        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_YY",       PS_DATA_F32, "second moments (Y*Y)",                      Myy);
     242
     243        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3C",      PS_DATA_F32, "third momemt cos theta",                    M_c3);
     244        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M3S",      PS_DATA_F32, "third momemt sin theta",                    M_s3);
     245        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4C",      PS_DATA_F32, "fourth momemt cos theta",                   M_c4);
     246        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_M4S",      PS_DATA_F32, "fourth momemt sin theta",                   M_s4);
     247
     248        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1",       PS_DATA_F32, "first radial moment",                       Mrf);
     249        psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH",       PS_DATA_F32, "half radial moment",                        Mrh);
     250        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX",        PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Krf);
     251        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR",    PS_DATA_F32, "Kron Flux Error",                          dKrf);
     252
     253        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Kinner);
     254        psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER",  PS_DATA_F32, "Kron Flux (in 2.5 R1)",                     Kouter);
     255
     256        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS",            PS_DATA_U32, "psphot analysis flags",                     source->mode);
     257        psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2",           PS_DATA_U32, "psphot analysis flags",                     source->mode2);
    208258
    209259        psVector *radFlux    = psVectorAlloc(radMax->n, PS_TYPE_F32);
     
    352402        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    353403        source->peak->flux = peakFlux;
     404        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
     405        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    354406        source->peak->dx   = dPAR[PM_PAR_XPOS];
    355407        source->peak->dy   = dPAR[PM_PAR_YPOS];
    356         source->peak->SN   = sqrt(source->peak->flux); // XXX a proxy: various functions sort by peak S/N
    357 
    358         source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
     408        if (isfinite (source->errMag) && (source->errMag > 0.0)) {
     409          source->peak->SN = 1.0 / source->errMag;
     410        } else {
     411          source->peak->SN = sqrt(source->peak->flux); // an alternate proxy: various functions sort by peak S/N
     412        }
     413
     414        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
     415        source->pixWeightNotPoor = psMetadataLookupF32 (&status, row, "PSF_QF_PERFECT");
    359416        source->crNsigma  = psMetadataLookupF32 (&status, row, "CR_NSIGMA");
    360417        source->extNsigma = psMetadataLookupF32 (&status, row, "EXT_NSIGMA");
     
    371428        source->moments->Myy = psMetadataLookupF32 (&status, row, "MOMENTS_YY");
    372429
     430        source->moments->Mrf         = psMetadataLookupF32 (&status, row, "MOMENTS_R1");
     431        source->moments->Mrh         = psMetadataLookupF32 (&status, row, "MOMENTS_RH");
     432        source->moments->KronFlux    = psMetadataLookupF32 (&status, row, "KRON_FLUX");
     433        source->moments->KronFluxErr = psMetadataLookupF32 (&status, row, "KRON_FLUX_ERR");
     434
     435        source->moments->KronFinner  = psMetadataLookupF32 (&status, row, "KRON_FLUX_INNER");
     436        source->moments->KronFouter  = psMetadataLookupF32 (&status, row, "KRON_FLUX_OUTER");
     437
     438        // XXX we do not save all of the 3rd and 4th moment parameters. when we load in data,
     439        // we are storing enough information so the output will be consistent with the input
     440        source->moments->Mxxx = +1.0 * psMetadataLookupF32 (&status, row, "MOMENTS_M3C");
     441        source->moments->Mxxy = 0.0;
     442        source->moments->Mxyy = 0.0;
     443        source->moments->Myyy = -1.0 * psMetadataLookupF32 (&status, row, "MOMENTS_M3S");
     444
     445        source->moments->Mxxxx = +1.00 * psMetadataLookupF32 (&status, row, "MOMENTS_M4C");
     446        source->moments->Mxxxy = 0.0;
     447        source->moments->Mxxyy = 0.0;
     448        source->moments->Mxyyy = -0.25 * psMetadataLookupF32 (&status, row, "MOMENTS_M4S");
     449        source->moments->Myyyy = 0.0;
     450
    373451        source->mode = psMetadataLookupU32 (&status, row, "FLAGS");
     452        source->mode2 = psMetadataLookupU32 (&status, row, "FLAGS2");
    374453        assert (status);
    375454
     
    391470    psF32 xErr, yErr;
    392471    int nRow = -1;
     472    char keyword1[80], keyword2[80];
    393473
    394474    // create a header to hold the output data
     
    422502    bool doAnnuli       = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
    423503    bool doPetrosian    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
    424     // bool doIsophotal    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ISOPHOTAL");
    425     // bool doKron         = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_KRON");
    426504
    427505    psVector *radMin = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER");
     
    429507    psAssert (radMin->n == radMax->n, "inconsistent annular bins");
    430508
    431     // int nRadialBins = 0;
    432     // if (doAnnuli) {
    433     //  // get the max count of radial bins
    434     //  for (int i = 0; i < sources->n; i++) {
    435     //      pmSource *source = sources->data[i];
    436     //      if (!source->extpars) continue;
    437     //      if (!source->extpars->radProfile ) continue;
    438     //         if (!source->extpars->radProfile->binSB) continue;
    439     //      nRadialBins = PS_MAX(nRadialBins, source->extpars->radProfile->binSB->n);
    440     //  }
    441     // }
     509    // write the radial profile apertures to header
     510    for (int i = 0; i < radMax->n; i++) {
     511      sprintf (keyword1, "RMIN_%02d", i);
     512      sprintf (keyword2, "RMAX_%02d", i);
     513      psMetadataAddF32 (outhead, PS_LIST_TAIL, keyword1, PS_META_REPLACE, "min radius for SB profile", radMin->data.F32[i]);
     514      psMetadataAddF32 (outhead, PS_LIST_TAIL, keyword2, PS_META_REPLACE, "min radius for SB profile", radMax->data.F32[i]);
     515    }
    442516
    443517    // we write out all sources, regardless of quality.  the source flags tell us the state
    444518    for (int i = 0; i < sources->n; i++) {
    445         // skip source if it is not a ext sourc
    446         // XXX we have two places that extended source parameters are measured:
    447         // psphotExtendedSources, which measures the aperture-like parameters and (potentially) the psf-convolved extended source models,
    448         // psphotFitEXT, which does the simple extended source model fit (not psf-convolved)
    449         // should we require both?
    450 
    451519        pmSource *source = sources->data[i];
    452520
     
    514582        }
    515583
    516 # if (0)
    517         // Kron measurements
    518         if (doKron) {
    519             pmSourceKronValues *kron = source->extpars->kron;
    520             if (kron) {
    521                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       kron->mag);
    522                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", kron->magErr);
    523                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          kron->rad);
    524                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    kron->radErr);
    525             } else {
    526                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG",        PS_DATA_F32, "Kron Magnitude",       NAN);
    527                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_MAG_ERR",    PS_DATA_F32, "Kron Magnitude Error", NAN);
    528                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS",     PS_DATA_F32, "Kron Radius",          NAN);
    529                 psMetadataAdd (row, PS_LIST_TAIL, "KRON_RADIUS_ERR", PS_DATA_F32, "Kron Radius Error",    NAN);
    530             }
    531         }
    532 
    533         // Isophot measurements
    534         // XXX insert header data: isophotal level
    535         if (doIsophotal) {
    536             pmSourceIsophotalValues *isophot = source->extpars->isophot;
    537             if (isophot) {
    538                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       isophot->mag);
    539                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", isophot->magErr);
    540                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          isophot->rad);
    541                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    isophot->radErr);
    542             } else {
    543                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG",        PS_DATA_F32, "Isophot Magnitude",       NAN);
    544                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_MAG_ERR",    PS_DATA_F32, "Isophot Magnitude Error", NAN);
    545                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS",     PS_DATA_F32, "Isophot Radius",          NAN);
    546                 psMetadataAdd (row, PS_LIST_TAIL, "ISOPHOT_RADIUS_ERR", PS_DATA_F32, "Isophot Radius Error",    NAN);
    547             }
    548         }
    549 # endif
    550 
    551584        // Flux Annuli (if we have extended source measurements, we have these.  only optionally save them)
    552585        if (doAnnuli) {
     
    616649
    617650// XXX this layout is still the same as PS1_DEV_1
    618 bool pmSourcesWrite_CMF_PS1_SV1_XFIT (psFits *fits, pmReadout *readout, psArray *sources, char *extname)
     651bool pmSourcesWrite_CMF_PS1_SV1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
    619652{
    620653
     
    665698            assert (model);
    666699
     700            // skip models which were not actually fitted
     701            if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     702
    667703            PAR = model->params->data.F32;
    668704            dPAR = model->dparams->data.F32;
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_V1.c

    r27818 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
     
    4554// followed by a zero-size matrix, followed by the table data
    4655
    47 bool pmSourcesWrite_CMF_PS1_V1 (psFits *fits, pmReadout *readout, psArray *sources,
    48                                 psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
     56bool pmSourcesWrite_CMF_PS1_V1 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe)
    4957{
    5058    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    184192        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    185193        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
    186         psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeight);
     194        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeightNotBad);
    187195        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    188196        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
     
    310318        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    311319        source->peak->flux = peakFlux;
     320        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
     321        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    312322        source->peak->dx   = dPAR[PM_PAR_XPOS];
    313323        source->peak->dy   = dPAR[PM_PAR_YPOS];
    314 
    315         source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
     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        }
     329
     330        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
    316331        source->crNsigma  = psMetadataLookupF32 (&status, row, "CR_NSIGMA");
    317332        source->extNsigma = psMetadataLookupF32 (&status, row, "EXT_NSIGMA");
     
    516531
    517532// XXX this layout is still the same as PS1_DEV_1
    518 bool pmSourcesWrite_CMF_PS1_V1_XFIT (psFits *fits, pmReadout *readout, psArray *sources, char *extname)
     533bool pmSourcesWrite_CMF_PS1_V1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
    519534{
    520535
     
    565580            assert (model);
    566581
     582            // skip models which were not actually fitted
     583            if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     584
    567585            PAR = model->params->data.F32;
    568586            dPAR = model->dparams->data.F32;
  • trunk/psModules/src/objects/pmSourceIO_CMF_PS1_V2.c

    r27818 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
     
    4554// followed by a zero-size matrix, followed by the table data
    4655
    47 bool pmSourcesWrite_CMF_PS1_V2 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
     56bool pmSourcesWrite_CMF_PS1_V2 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe)
    4857{
    4958    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    182191        psMetadataAdd (row, PS_LIST_TAIL, "PSF_MINOR",        PS_DATA_F32, "PSF width (minor axis)",                     axes.minor);
    183192        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
    184         psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeight);
     193        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeightNotBad);
    185194        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NDOF",         PS_DATA_S32, "degrees of freedom",                         nDOF);
    186195        psMetadataAdd (row, PS_LIST_TAIL, "PSF_NPIX",         PS_DATA_S32, "number of pixels in fit",                    nPix);
     
    314323        source->peak = pmPeakAlloc(PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], peakFlux, PM_PEAK_LONE);
    315324        source->peak->flux = peakFlux;
     325        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
     326        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
    316327        source->peak->dx   = dPAR[PM_PAR_XPOS];
    317328        source->peak->dy   = dPAR[PM_PAR_YPOS];
    318         source->peak->SN   = sqrt(source->peak->flux); // XXX a proxy: various functions sort by peak S/N
    319 
    320         source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
     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        }
     334
     335        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
    321336        source->crNsigma  = psMetadataLookupF32 (&status, row, "CR_NSIGMA");
    322337        source->extNsigma = psMetadataLookupF32 (&status, row, "EXT_NSIGMA");
     
    578593
    579594// XXX this layout is still the same as PS1_DEV_1
    580 bool pmSourcesWrite_CMF_PS1_V2_XFIT (psFits *fits, pmReadout *readout, psArray *sources, char *extname)
     595bool pmSourcesWrite_CMF_PS1_V2_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
    581596{
    582597
     
    627642            assert (model);
    628643
     644            // skip models which were not actually fitted
     645            if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     646
    629647            PAR = model->params->data.F32;
    630648            dPAR = model->dparams->data.F32;
  • trunk/psModules/src/objects/pmSourceIO_CMP.c

    r20937 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
  • trunk/psModules/src/objects/pmSourceIO_MatchedRefs.c

    r27177 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
     51
    4252#include "pmAstrometryObjects.h"
    4353#include "pmAstrometryWCS.h"
  • trunk/psModules/src/objects/pmSourceIO_OBJ.c

    r20937 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
  • trunk/psModules/src/objects/pmSourceIO_PS1_CAL_0.c

    r25979 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
     
    4958// XXX how do I generate the source tables which I need to send to PSPS?
    5059
    51 bool pmSourcesWrite_PS1_CAL_0 (psFits *fits, pmReadout *readout, psArray *sources,
    52                                psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
     60bool pmSourcesWrite_PS1_CAL_0 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe)
    5361{
    5462    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    180188        psMetadataAdd (row, PS_LIST_TAIL, "PSF_WIDTH_Y",      PS_DATA_F32, "PSF width in y coordinate",                  axes.minor);
    181189        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
    182         psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeight);
     190        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeightNotBad);
    183191
    184192        // XXX not sure how to get this : need to load Nimages with weight?
     
    289297        source->peak->dx   = dPAR[PM_PAR_XPOS];
    290298        source->peak->dy   = dPAR[PM_PAR_YPOS];
    291 
    292         source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
     299        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
     300        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
     301
     302        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
    293303
    294304        // note that some older versions used PSF_PROBABILITY: this was not well defined.
     
    597607            assert (model);
    598608
     609            // skip models which were not actually fitted
     610            if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     611
    599612            PAR = model->params->data.F32;
    600613            dPAR = model->dparams->data.F32;
  • trunk/psModules/src/objects/pmSourceIO_PS1_DEV_0.c

    r25979 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
     
    4958// XXX how do I generate the source tables which I need to send to PSPS?
    5059// XXX: input parameter imageHeader is never used.
    51 bool pmSourcesWrite_PS1_DEV_0 (psFits *fits, psArray *sources, psMetadata *imageHeader,
    52                                psMetadata *tableHeader, char *extname)
     60bool pmSourcesWrite_PS1_DEV_0 (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe)
    5361{
    5462    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    117125        psMetadataAdd (row, PS_LIST_TAIL, "PSF_WIDTH_Y",      PS_DATA_F32, "PSF width in y coordinate",                  axes.minor);
    118126        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
    119         psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeight);
     127        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeightNotBad);
    120128        // XXX not sure how to get this : need to load Nimages with weight
    121129        psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES",         PS_DATA_U16, "Number of frames overlapping source center", nImageOverlap);
     
    215223        source->peak->dx   = dPAR[PM_PAR_XPOS];
    216224        source->peak->dy   = dPAR[PM_PAR_YPOS];
    217 
    218         source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
     225        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
     226        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
     227
     228        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
    219229
    220230        // XXX other values saved but not loaded?
     
    228238    return (sources);
    229239}
     240
     241bool pmSourcesWrite_PS1_DEV_0_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe)
     242{
     243    return true;
     244}
     245
     246bool pmSourcesWrite_PS1_DEV_0_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
     247{
     248    return true;
     249}
  • trunk/psModules/src/objects/pmSourceIO_PS1_DEV_1.c

    r25979 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
     
    4756// this output format is valid for psphot analysis of an image, and does not include calibrated
    4857// values derived in the DVO database.
    49 // XXX how do I generate the source tables which I need to send to PSPS?
    50 
    51 bool pmSourcesWrite_PS1_DEV_1 (psFits *fits, psArray *sources,
    52                                psMetadata *imageHeader, psMetadata *tableHeader, char *extname)
     58
     59bool pmSourcesWrite_PS1_DEV_1(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe)
    5360{
    5461    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    142149        psMetadataAdd (row, PS_LIST_TAIL, "PSF_WIDTH_Y",      PS_DATA_F32, "PSF width in y coordinate",                  axes.minor);
    143150        psMetadataAdd (row, PS_LIST_TAIL, "PSF_THETA",        PS_DATA_F32, "PSF orientation angle",                      axes.theta);
    144         psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeight);
     151        psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF",           PS_DATA_F32, "PSF coverage/quality factor",                source->pixWeightNotBad);
    145152
    146153        // XXX not sure how to get this : need to load Nimages with weight?
     
    259266        source->peak->dx   = dPAR[PM_PAR_XPOS];
    260267        source->peak->dy   = dPAR[PM_PAR_YPOS];
    261 
    262         source->pixWeight = psMetadataLookupF32 (&status, row, "PSF_QF");
     268        source->peak->xf   = PAR[PM_PAR_XPOS]; // more accurate position
     269        source->peak->yf   = PAR[PM_PAR_YPOS]; // more accurate position
     270
     271        source->pixWeightNotBad = psMetadataLookupF32 (&status, row, "PSF_QF");
    263272
    264273        // note that some older versions used PSF_PROBABILITY: this was not well defined.
     
    281290}
    282291
    283 bool pmSourcesWrite_PS1_DEV_1_XSRC (psFits *fits, psArray *sources, char *extname, psMetadata *recipe)
     292bool pmSourcesWrite_PS1_DEV_1_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe)
    284293{
    285294
     
    453462}
    454463
    455 bool pmSourcesWrite_PS1_DEV_1_XFIT (psFits *fits, psArray *sources, char *extname)
     464bool pmSourcesWrite_PS1_DEV_1_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
    456465{
    457466
     
    502511            assert (model);
    503512
     513            // skip models which were not actually fitted
     514            if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     515
    504516            PAR = model->params->data.F32;
    505517            dPAR = model->dparams->data.F32;
  • trunk/psModules/src/objects/pmSourceIO_RAW.c

    r25754 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
    41 #include "pmSourcePhotometry.h"
     48#include "pmPSFtry.h"
     49
    4250#include "pmSourceIO.h"
    4351
     
    120128                 source[0].peak->SN,
    121129                 source[0].apRadius,
    122                  source[0].pixWeight,
     130                 source[0].pixWeightNotBad,
    123131                 model[0].nDOF,
    124132                 model[0].nIter);
     
    182190                 source[0].peak->SN,
    183191                 source[0].apRadius,
    184                  source[0].pixWeight,
     192                 source[0].pixWeightNotBad,
    185193                 model[0].nDOF,
    186194                 model[0].nIter);
  • trunk/psModules/src/objects/pmSourceIO_SMPDATA.c

    r25979 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmResiduals.h"
    35 #include "pmGrowthCurve.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
     
    4554// followed by a zero-size matrix, followed by the table data
    4655// XXX: input parameter imageHeader is never used
    47 bool pmSourcesWrite_SMPDATA (psFits *fits, psArray *sources, psMetadata *imageHeader,
    48                              psMetadata *tableHeader, char *extname)
     56bool pmSourcesWrite_SMPDATA (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, psMetadata *tableHeader, char *extname, psMetadata *recipe)
    4957{
    5058    PS_ASSERT_PTR_NON_NULL(fits, false);
     
    106114        psMetadataAdd (row, PS_LIST_TAIL, "THETA",   PS_DATA_F32, "", axes.theta);
    107115        psMetadataAdd (row, PS_LIST_TAIL, "DOPHOT",  PS_DATA_U8,  "", type);
    108         psMetadataAdd (row, PS_LIST_TAIL, "WEIGHT",  PS_DATA_U8,  "", PS_MIN (255, PS_MAX(0, 255*source->pixWeight)));
     116        psMetadataAdd (row, PS_LIST_TAIL, "WEIGHT",  PS_DATA_U8,  "", PS_MIN (255, PS_MAX(0, 255*source->pixWeightNotBad)));
    109117        psMetadataAdd (row, PS_LIST_TAIL, "DUMMY",   PS_DATA_U16, "", 0);
    110118
     
    189197        source->apMag  = psMetadataLookupF32 (&status, row, "MAG_AP")  - ZERO_POINT;
    190198
    191         source->pixWeight = psMetadataLookupU8 (&status, row, "WEIGHT")/255.0;
     199        source->pixWeightNotBad = psMetadataLookupU8 (&status, row, "WEIGHT")/255.0;
    192200        int dophot = psMetadataLookupU8 (&status, row, "DOPHOT");
    193201        pmSourceSetDophotType (source, dophot);
     
    204212    return (sources);
    205213}
     214
     215bool pmSourcesWrite_SMPDATA_XSRC (psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe)
     216{
     217    return true;
     218}
     219
     220bool pmSourcesWrite_SMPDATA_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname)
     221{
     222    return true;
     223}
  • trunk/psModules/src/objects/pmSourceIO_SX.c

    r20937 r29004  
    2828#include "pmFPAfile.h"
    2929
     30#include "pmTrend2D.h"
     31#include "pmResiduals.h"
     32#include "pmGrowthCurve.h"
    3033#include "pmSpan.h"
     34#include "pmFootprintSpans.h"
    3135#include "pmFootprint.h"
    3236#include "pmPeaks.h"
    3337#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     38#include "pmModelFuncs.h"
     39#include "pmModel.h"
     40#include "pmModelUtils.h"
     41#include "pmModelClass.h"
     42#include "pmSourceMasks.h"
     43#include "pmSourceExtendedPars.h"
     44#include "pmSourceDiffStats.h"
     45#include "pmSource.h"
     46#include "pmSourceFitModel.h"
    3747#include "pmPSF.h"
    38 #include "pmModel.h"
    39 #include "pmSource.h"
    40 #include "pmModelClass.h"
     48#include "pmPSFtry.h"
     49
    4150#include "pmSourceIO.h"
    4251
  • trunk/psModules/src/objects/pmSourceMasks.h

    r24694 r29004  
    3939} pmSourceMode;
    4040
     41// Bit flags to distinguish analysis results
     42// When adding to or subtracting from this list, please also modify pmSourceMaskHeader
     43typedef enum {
     44    PM_SOURCE_MODE2_DEFAULT          = 0x00000000, ///< Initial value: resets all bits
     45    PM_SOURCE_MODE2_DIFF_WITH_SINGLE = 0x00000001, ///< diff source matched to a single positive detection
     46    PM_SOURCE_MODE2_DIFF_WITH_DOUBLE = 0x00000002, ///< diff source matched to positive detections in both images
     47} pmSourceMode2;
    4148
    4249/// Populate header with mask values
  • trunk/psModules/src/objects/pmSourceMatch.c

    r28518 r29004  
    66#include <string.h>
    77#include <pslib.h>
    8 
     8#include "pmHDU.h"
     9#include "pmFPA.h"
     10
     11#include "pmTrend2D.h"
     12#include "pmResiduals.h"
     13#include "pmGrowthCurve.h"
     14#include "pmSpan.h"
     15#include "pmFootprintSpans.h"
     16#include "pmFootprint.h"
     17#include "pmPeaks.h"
     18#include "pmMoments.h"
     19#include "pmModelFuncs.h"
     20#include "pmModel.h"
     21#include "pmModelUtils.h"
     22#include "pmModelClass.h"
     23#include "pmSourceMasks.h"
     24#include "pmSourceExtendedPars.h"
     25#include "pmSourceDiffStats.h"
    926#include "pmSource.h"
     27#include "pmSourceFitModel.h"
     28#include "pmPSF.h"
     29#include "pmPSFtry.h"
     30#include "pmDetections.h"
     31
    1032#include "pmErrorCodes.h"
    1133
  • trunk/psModules/src/objects/pmSourceMatch.h

    r26076 r29004  
    11#ifndef PM_SOURCE_MATCH_H
    22#define PM_SOURCE_MATCH_H
    3 
    4 #include <pslib.h>
    53
    64/// Mask values for matched sources
  • trunk/psModules/src/objects/pmSourceMoments.c

    r27531 r29004  
    2222#include <strings.h>
    2323#include <pslib.h>
     24
    2425#include "pmHDU.h"
    2526#include "pmFPA.h"
    26 #include "pmFPAMaskWeight.h"
     27
     28#include "pmTrend2D.h"
     29#include "pmResiduals.h"
     30#include "pmGrowthCurve.h"
    2731#include "pmSpan.h"
     32#include "pmFootprintSpans.h"
    2833#include "pmFootprint.h"
    2934#include "pmPeaks.h"
    3035#include "pmMoments.h"
    31 #include "pmResiduals.h"
    32 #include "pmGrowthCurve.h"
    33 #include "pmTrend2D.h"
    34 #include "pmPSF.h"
     36#include "pmModelFuncs.h"
    3537#include "pmModel.h"
     38#include "pmModelUtils.h"
     39#include "pmModelClass.h"
     40#include "pmSourceMasks.h"
     41#include "pmSourceExtendedPars.h"
     42#include "pmSourceDiffStats.h"
    3643#include "pmSource.h"
    3744
     
    5461# define VALID_RADIUS(X,Y,RAD2) (((RAD2) >= (PS_SQR(X) + PS_SQR(Y))) ? 1 : 0)
    5562
     63static bool beVerbose = false;
     64void pmSourceMomentsSetVerbose(bool state){ beVerbose = state; }
     65
    5666bool pmSourceMoments(pmSource *source, psF32 radius, psF32 sigma, psF32 minSN, psImageMaskType maskVal)
    5767{
     
    6171    PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false);
    6272
    63     // use sky from moments if defined, 0.0 otherwise
     73    // use sky from moments if defined, 0.0 otherwise
     74
     75    // XXX this value comes from the sky model at the source center, and tends to over-estimate
     76    // the sky in the vicinity of bright sources.  we are better off assuming the model worked
     77    // well:
    6478    psF32 sky = 0.0;
    65     if (source->moments == NULL) {
    66         source->moments = pmMomentsAlloc();
    67     } else {
    68         sky = source->moments->Sky;
    69     }
     79    // XXX if (source->moments == NULL) {
     80    // XXX     source->moments = pmMomentsAlloc();
     81    // XXX } else {
     82    // XXX     sky = source->moments->Sky;
     83    // XXX }
    7084
    7185    // First Pass: calculate the first moments (these are subtracted from the coordinates below)
     
    131145            psF32 wDiff = *vWgt;
    132146
    133             // skip pixels below specified significance level.  this is allowed, but should be
    134             // avoided -- the over-weights the wings of bright stars compared to those of faint
    135             // stars.
    136             if (PS_SQR(pDiff) < minSN2*wDiff) continue;
    137             // if (pDiff < 0) continue; // XXX : MWV says I should include < 0.0 valued points...
     147            // skip pixels below specified significance level.  for a PSFs, this
     148            // over-weights the wings of bright stars compared to those of faint stars.
     149            // for the estimator used for extended source analysis (where the window
     150            // function is allowed to be arbitrarily large), we need to clip to avoid
     151            // negative second moments.
     152            if (PS_SQR(pDiff) < minSN2*wDiff) continue; //
     153            if ((minSN > 0.0) && (pDiff < 0)) continue; //
    138154
    139155            // Apply a Gaussian window function.  Be careful with the window function.  S/N
     
    197213    // Xn  = SUM (x - xc)^n * (z - sky)
    198214
     215    psF32 RF = 0.0;
     216    psF32 RH = 0.0;
     217    psF32 RS = 0.0;
    199218    psF32 XX = 0.0;
    200219    psF32 XY = 0.0;
     
    244263            if (r > radius) continue;
    245264
    246             psF32 pDiff = *vPix - sky;
     265            psF32 fDiff = *vPix - sky;
     266            psF32 pDiff = fDiff;
    247267            psF32 wDiff = *vWgt;
    248268
     
    257277            if (sigma > 0.0) {
    258278                // XXX a lot of extra flops; can we do pre-calculate?
    259                 psF32 z  = (PS_SQR(xDiff) + PS_SQR(yDiff))*rsigma2;
     279                // XXX we were re-calculating r2 (maybe the compiler caught this?)
     280                // psF32 z  = (PS_SQR(xDiff) + PS_SQR(yDiff))*rsigma2;
     281                psF32 z  = r2 * rsigma2;
    260282                assert (z >= 0.0);
    261283                psF32 weight  = exp(-z);
     
    266288
    267289            Sum += pDiff;
     290
     291# if (1)
     292# if (0)
     293            if (fDiff < 0) continue;
     294# endif
     295            psF32 rf = r * fDiff;
     296            psF32 rh = sqrt(r) * fDiff;
     297            psF32 rs = fDiff;
     298# else
     299            psF32 rf = r * pDiff;
     300            psF32 rh = sqrt(r) * pDiff;
     301            psF32 rs = pDiff;
     302# endif
    268303
    269304            psF32 x = xDiff * pDiff;
     
    284319            psF32 xyyy = xDiff * yyy / r2;
    285320            psF32 yyyy = yDiff * yyy / r2;
     321
     322            RF  += rf;
     323            RH  += rh;
     324            RS  += rs;
    286325
    287326            XX  += xx;
     
    302341    }
    303342
     343    source->moments->Mrf = RF/RS;
     344    source->moments->Mrh = RH/RS;
     345
    304346    source->moments->Mxx = XX/Sum;
    305347    source->moments->Mxy = XY/Sum;
     
    317359    source->moments->Myyyy = YYYY/Sum;
    318360
    319     // if (source->moments->Mxx < 0) {
    320     //  fprintf (stderr, "error: neg second moment??\n");
    321     // }
    322     // if (source->moments->Myy < 0) {
    323     //  fprintf (stderr, "error: neg second moment??\n");
    324     // }
    325 
    326     psTrace ("psModules.objects", 4, "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",
     361    // Calculate the Kron magnitude (make this block optional?)
     362    // float radKron = 2.5*source->moments->Mrf;
     363    float radKinner = 1.0*source->moments->Mrf;
     364    float radKron   = 2.5*source->moments->Mrf;
     365    float radKouter = 4.0*source->moments->Mrf;
     366
     367    int nKronPix = 0;
     368    Sum = Var = 0.0;
     369    float SumInner = 0.0;
     370    float SumOuter = 0.0;
     371
     372    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
     373
     374        psF32 yDiff = row - yCM;
     375        if (fabs(yDiff) > radKron) continue;
     376
     377        psF32 *vPix = source->pixels->data.F32[row];
     378        psF32 *vWgt = source->variance->data.F32[row];
     379        psImageMaskType  *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
     380
     381        for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
     382            if (vMsk) {
     383                if (*vMsk & maskVal) {
     384                    vMsk++;
     385                    continue;
     386                }
     387                vMsk++;
     388            }
     389            if (isnan(*vPix)) continue;
     390
     391            psF32 xDiff = col - xCM;
     392            if (fabs(xDiff) > radKron) continue;
     393
     394            // radKron is just a function of (xDiff, yDiff)
     395            psF32 r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
     396            psF32 r  = sqrt(r2);
     397
     398            psF32 pDiff = *vPix - sky;
     399            psF32 wDiff = *vWgt;
     400
     401            // skip pixels below specified significance level.  this is allowed, but should be
     402            // avoided -- the over-weights the wings of bright stars compared to those of faint
     403            // stars.
     404            if (PS_SQR(pDiff) < minSN2*wDiff) continue;
     405
     406            if (r < radKron) {
     407                Sum += pDiff;
     408                Var += wDiff;
     409                nKronPix ++;
     410                // if (beVerbose) fprintf (stderr, "mome: %d %d  %f  %f  %f\n", col, row, sky, *vPix, Sum);
     411            }
     412
     413            if ((r > radKinner) && (r < radKron)) {
     414                SumInner += pDiff;
     415            }
     416            if ((r > radKron)  && (r < radKouter)) {
     417                SumOuter += pDiff;
     418            }
     419        }
     420    }
     421    source->moments->KronFlux = Sum;
     422    source->moments->KronFinner = SumInner;
     423    source->moments->KronFouter = SumOuter;
     424    source->moments->KronFluxErr = sqrt(Var);
     425
     426    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",
     427             source->moments->Mrf,   source->moments->KronFlux,
    327428             source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy,
    328429             source->moments->Mxxx,  source->moments->Mxxy,  source->moments->Mxyy,  source->moments->Myyy,
  • trunk/psModules/src/objects/pmSourcePhotometry.c

    r28517 r29004  
    2222#include "pmFPA.h"
    2323#include "pmFPAMaskWeight.h"
     24
     25#include "pmTrend2D.h"
     26#include "pmResiduals.h"
     27#include "pmGrowthCurve.h"
    2428#include "pmSpan.h"
     29#include "pmFootprintSpans.h"
    2530#include "pmFootprint.h"
    2631#include "pmPeaks.h"
    2732#include "pmMoments.h"
    28 #include "pmGrowthCurve.h"
    29 #include "pmResiduals.h"
    30 #include "pmTrend2D.h"
     33#include "pmModelFuncs.h"
     34#include "pmModel.h"
     35#include "pmModelUtils.h"
     36#include "pmModelClass.h"
     37#include "pmSourceMasks.h"
     38#include "pmSourceExtendedPars.h"
     39#include "pmSourceDiffStats.h"
     40#include "pmSource.h"
     41#include "pmSourceFitModel.h"
    3142#include "pmPSF.h"
    32 #include "pmModel.h"
    33 #include "pmSource.h"
    34 #include "pmModelClass.h"
     43#include "pmPSFtry.h"
     44
    3545#include "pmSourcePhotometry.h"
    3646
     
    6676
    6777// XXX masked region should be (optionally) elliptical
    68 bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psImageMaskType maskVal)
     78bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psImageMaskType maskVal, psImageMaskType markVal)
    6979{
    7080    PS_ASSERT_PTR_NON_NULL(source, false);
     
    122132        for (int i = 0; i < source->modelFits->n; i++) {
    123133            pmModel *model = source->modelFits->data[i];
     134            if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
    124135            status = pmSourcePhotometryModel (&model->mag, NULL, model);
    125136            if (model == source->modelEXT) foundEXT = true;
     
    145156    // measure the contribution of included pixels
    146157    if (mode & PM_SOURCE_PHOT_WEIGHT) {
    147         pmSourcePixelWeight (&source->pixWeight, model, source->maskObj, maskVal);
     158        pmSourcePixelWeight (&source->pixWeightNotBad, &source->pixWeightNotPoor, model, source->maskObj, maskVal, markVal);
    148159    }
    149160
    150161    // measure the contribution of included pixels
    151162    if (mode & PM_SOURCE_PHOT_DIFFSTATS) {
    152         pmSourceMeasureDiffStats (source, maskVal);
     163        pmSourceMeasureDiffStats (source, maskVal, markVal);
    153164    }
    154165
     
    191202
    192203    // measure object aperture photometry
    193     status = pmSourcePhotometryAper  (&source->apMag, model, flux, mask, maskVal);
     204    status = pmSourcePhotometryAper  (&source->apMagRaw, model, flux, mask, maskVal);
    194205    if (!status) {
    195206        psTrace ("psModules.objects", 3, "fail mag : bad Ap Mag");
     
    199210    // if the aper mag is NAN, the flux < 0.  this can happen for sources near the
    200211    // detection limits (esp near bright neighbors)
     212    source->apMag = source->apMagRaw;
    201213    if (isfinite (source->apMag) && isPSF && psf) {
    202214        if (psf->growth && (mode & PM_SOURCE_PHOT_GROWTH)) {
    203             source->apMag += pmGrowthCurveCorrect (psf->growth, source->apRadius);
     215            source->apMag = source->apMagRaw + pmGrowthCurveCorrect (psf->growth, source->apRadius);
    204216        }
    205217        if (mode & PM_SOURCE_PHOT_APCORR) {
    206218            // XXX this should be removed -- we no longer fit for the 'sky bias'
     219            // XXX is this happening???
    207220            rflux   = pow (10.0, 0.4*source->psfMag);
     221            psAssert (psf->skyBias == 0.0, "sky bias not 0");
     222            psAssert (psf->skySat == 0.0, "sky sat not 0");
    208223            source->apMag -= PS_SQR(source->apRadius)*rflux * psf->skyBias + psf->skySat / rflux;
    209224        }
     
    257272    PS_ASSERT_PTR_NON_NULL(image, false);
    258273    PS_ASSERT_PTR_NON_NULL(mask, false);
    259     PS_ASSERT_PTR_NON_NULL(model, false);
     274
     275    if (DO_SKY) {
     276        PS_ASSERT_PTR_NON_NULL(model, false);
     277    }
    260278
    261279    float apSum = 0;
     
    271289    psF32 **imData = image->data.F32;
    272290    psImageMaskType **mkData = mask->data.PS_TYPE_IMAGE_MASK_DATA;
     291    int nAperPix = 0;
    273292
    274293    // measure apMag
    275     for (int ix = 0; ix < image->numCols; ix++) {
    276         for (int iy = 0; iy < image->numRows; iy++) {
     294    for (int iy = 0; iy < image->numRows; iy++) {
     295        for (int ix = 0; ix < image->numCols; ix++) {
    277296            if (mkData[iy][ix] & maskVal)
    278297                continue;
    279298            apSum += imData[iy][ix] - sky;
     299            nAperPix ++;
     300            // fprintf (stderr, "aper: %d %d  %f  %f  %f\n", ix, iy, sky, imData[iy][ix], apSum);
    280301        }
    281302    }
     
    290311
    291312// return source aperture magnitude
    292 bool pmSourcePixelWeight (float *pixWeight, pmModel *model, psImage *mask, psImageMaskType maskVal)
    293 {
    294     PS_ASSERT_PTR_NON_NULL(pixWeight, false);
     313bool pmSourcePixelWeight (float *pixWeightNotBad, float *pixWeightNotPoor, pmModel *model, psImage *mask, psImageMaskType maskVal, psImageMaskType markVal)
     314{
     315    PS_ASSERT_PTR_NON_NULL(pixWeightNotBad, false);
     316    PS_ASSERT_PTR_NON_NULL(pixWeightNotPoor, false);
    295317    PS_ASSERT_PTR_NON_NULL(mask, false);
    296318    PS_ASSERT_PTR_NON_NULL(model, false);
    297319
    298320    float modelSum = 0;
    299     float validSum = 0;
     321    float notBadSum = 0;
     322    float notPoorSum = 0;
    300323    float sky = 0;
    301324    float value;
     
    305328    int dY, DY, NY;
    306329
    307     *pixWeight = 0.0;
     330    *pixWeightNotBad = 0.0;
     331    *pixWeightNotPoor = 0.0;
    308332
    309333    // we only care about the value of the object model, not the local sky
     
    345369
    346370            // for the full model, add all points
    347             value = model->modelFunc (NULL, params, coord) - sky;
     371            value = fabs(model->modelFunc (NULL, params, coord) - sky);
    348372            modelSum += value;
    349373
    350374            // include count only the unmasked pixels within the image area
    351             if (mx < 0)
    352                 continue;
    353             if (my < 0)
    354                 continue;
    355             if (mx >= NX)
    356                 continue;
    357             if (my >= NY)
    358                 continue;
    359             if (mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & maskVal)
    360                 continue;
    361 
    362             validSum += value;
     375            if (mx < 0) continue;
     376            if (my < 0) continue;
     377            if (mx >= NX) continue;
     378            if (my >= NY) continue;
     379
     380            if (!(mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & maskVal)) {
     381                notBadSum += value;
     382            }
     383            if (!(mask->data.PS_TYPE_IMAGE_MASK_DATA[my][mx] & ~markVal)) {
     384                notPoorSum += value;
     385            }
    363386        }
    364387    }
    365388    psFree (coord);
    366389
    367     if (validSum <= 0)
    368         return false;
    369 
    370     *pixWeight = validSum / modelSum;
     390    *pixWeightNotBad  = notBadSum  / modelSum;
     391    *pixWeightNotPoor = notPoorSum / modelSum;
     392
    371393    return (true);
    372394}
     
    374396# define FLUX_LIMIT 3.0
    375397
    376 // return source aperture magnitude
    377 bool pmSourceMeasureDiffStats (pmSource *source, psImageMaskType maskVal)
     398// measure stats that may be using in difference images for distinguishing real sources from bad residuals
     399bool pmSourceMeasureDiffStats (pmSource *source, psImageMaskType maskVal, psImageMaskType markVal)
    378400{
    379401    PS_ASSERT_PTR_NON_NULL(source, false);
     
    399421    for (int iy = 0; iy < flux->numRows; iy++) {
    400422        for (int ix = 0; ix < flux->numCols; ix++) {
     423            // only count up the stats in the unmarked region (ie, the aperture)
     424            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & markVal) {
     425                continue;
     426            }
    401427            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal) {
    402428                nMask ++;
  • trunk/psModules/src/objects/pmSourcePhotometry.h

    r28426 r29004  
    5252
    5353bool pmSourceMagnitudesInit (psMetadata *config);
    54 bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psImageMaskType maskVal);
    55 bool pmSourcePixelWeight (float *pixWeight, pmModel *model, psImage *mask, psImageMaskType maskVal);
     54bool pmSourceMagnitudes (pmSource *source, pmPSF *psf, pmSourcePhotometryMode mode, psImageMaskType maskVal, psImageMaskType markVal);
     55
     56bool pmSourcePixelWeight (float *pixWeightNotBad, float *pixWeightNotPoor, pmModel *model, psImage *mask, psImageMaskType maskVal, psImageMaskType markVal);
     57
    5658bool pmSourceChisq (pmModel *model, psImage *image, psImage *mask, psImage *weight, psImageMaskType maskVal, const float covarFactor);
    5759
    58 bool pmSourceMeasureDiffStats (pmSource *source, psImageMaskType maskVal);
     60bool pmSourceMeasureDiffStats (pmSource *source, psImageMaskType maskVal, psImageMaskType markVal);
    5961
    6062double pmSourceDataDotModel (const pmSource *Mi, const pmSource *Mj, const bool unweighted_sum, const float covarFactor, psImageMaskType maskVal);
  • trunk/psModules/src/objects/pmSourcePlotApResid.c

    r26893 r29004  
    2525#include "pmFPAview.h"
    2626#include "pmFPAfile.h"
     27
     28#include "pmTrend2D.h"
     29#include "pmResiduals.h"
     30#include "pmGrowthCurve.h"
    2731#include "pmSpan.h"
     32#include "pmFootprintSpans.h"
    2833#include "pmFootprint.h"
    2934#include "pmPeaks.h"
    3035#include "pmMoments.h"
    31 #include "pmResiduals.h"
    32 #include "pmGrowthCurve.h"
    33 #include "pmTrend2D.h"
     36#include "pmModelFuncs.h"
     37#include "pmModel.h"
     38#include "pmModelUtils.h"
     39#include "pmModelClass.h"
     40#include "pmSourceMasks.h"
     41#include "pmSourceExtendedPars.h"
     42#include "pmSourceDiffStats.h"
     43#include "pmSource.h"
     44#include "pmSourceFitModel.h"
    3445#include "pmPSF.h"
    35 #include "pmModel.h"
    3646#include "pmDetections.h"
    37 #include "pmSource.h"
     47
    3848#include "pmSourcePlots.h"
    3949#include "pmKapaPlots.h"
  • trunk/psModules/src/objects/pmSourcePlotMoments.c

    r26893 r29004  
    2828#include "pmFPAview.h"
    2929#include "pmFPAfile.h"
     30
     31#include "pmTrend2D.h"
     32#include "pmResiduals.h"
     33#include "pmGrowthCurve.h"
    3034#include "pmSpan.h"
     35#include "pmFootprintSpans.h"
    3136#include "pmFootprint.h"
    3237#include "pmPeaks.h"
    3338#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     39#include "pmModelFuncs.h"
     40#include "pmModel.h"
     41#include "pmModelUtils.h"
     42#include "pmModelClass.h"
     43#include "pmSourceMasks.h"
     44#include "pmSourceExtendedPars.h"
     45#include "pmSourceDiffStats.h"
     46#include "pmSource.h"
     47#include "pmSourceFitModel.h"
    3748#include "pmPSF.h"
    38 #include "pmModel.h"
    3949#include "pmDetections.h"
    40 #include "pmSource.h"
    4150#include "pmSourcePlots.h"
    4251#include "pmKapaPlots.h"
  • trunk/psModules/src/objects/pmSourcePlotPSFModel.c

    r26893 r29004  
    2828#include "pmFPAview.h"
    2929#include "pmFPAfile.h"
     30
     31
     32#include "pmTrend2D.h"
     33#include "pmResiduals.h"
     34#include "pmGrowthCurve.h"
    3035#include "pmSpan.h"
     36#include "pmFootprintSpans.h"
    3137#include "pmFootprint.h"
    3238#include "pmPeaks.h"
    3339#include "pmMoments.h"
    34 #include "pmGrowthCurve.h"
    35 #include "pmResiduals.h"
    36 #include "pmTrend2D.h"
     40#include "pmModelFuncs.h"
     41#include "pmModel.h"
     42#include "pmModelUtils.h"
     43#include "pmModelClass.h"
     44#include "pmSourceMasks.h"
     45#include "pmSourceExtendedPars.h"
     46#include "pmSourceDiffStats.h"
     47#include "pmSource.h"
     48#include "pmSourceFitModel.h"
    3749#include "pmPSF.h"
    38 #include "pmModel.h"
    3950#include "pmDetections.h"
    40 #include "pmSource.h"
    4151#include "pmSourcePlots.h"
    4252#include "pmKapaPlots.h"
  • trunk/psModules/src/objects/pmSourceSky.c

    r23187 r29004  
    2121#include <string.h>
    2222#include <pslib.h>
     23
    2324#include "pmHDU.h"
    2425#include "pmFPA.h"
    25 #include "pmFPAMaskWeight.h"
     26
     27#include "pmTrend2D.h"
     28#include "pmResiduals.h"
     29#include "pmGrowthCurve.h"
    2630#include "pmSpan.h"
     31#include "pmFootprintSpans.h"
    2732#include "pmFootprint.h"
    2833#include "pmPeaks.h"
    2934#include "pmMoments.h"
    30 #include "pmResiduals.h"
    31 #include "pmGrowthCurve.h"
    32 #include "pmTrend2D.h"
    33 #include "pmPSF.h"
     35#include "pmModelFuncs.h"
    3436#include "pmModel.h"
     37#include "pmModelUtils.h"
     38#include "pmModelClass.h"
     39#include "pmSourceMasks.h"
     40#include "pmSourceExtendedPars.h"
     41#include "pmSourceDiffStats.h"
    3542#include "pmSource.h"
     43
    3644#include "pmSourceSky.h"
    3745
  • trunk/psModules/src/objects/pmSourceUtils.c

    r24578 r29004  
    2121#include <string.h>
    2222#include <pslib.h>
     23
    2324#include "pmHDU.h"
    2425#include "pmFPA.h"
    25 #include "pmFPAMaskWeight.h"
     26
     27#include "pmTrend2D.h"
     28#include "pmResiduals.h"
     29#include "pmGrowthCurve.h"
    2630#include "pmSpan.h"
     31#include "pmFootprintSpans.h"
    2732#include "pmFootprint.h"
    2833#include "pmPeaks.h"
    2934#include "pmMoments.h"
    30 #include "pmResiduals.h"
    31 #include "pmGrowthCurve.h"
    32 #include "pmTrend2D.h"
    33 #include "pmPSF.h"
     35#include "pmModelFuncs.h"
    3436#include "pmModel.h"
     37#include "pmModelUtils.h"
     38#include "pmModelClass.h"
     39#include "pmSourceMasks.h"
     40#include "pmSourceExtendedPars.h"
     41#include "pmSourceDiffStats.h"
    3542#include "pmSource.h"
     43
    3644#include "pmSourceUtils.h"
    3745
  • trunk/psModules/src/objects/pmSourceVisual.c

    r26260 r29004  
    44
    55#include <pslib.h>
     6#include "pmHDU.h"
     7#include "pmFPA.h"
     8
    69#include "pmTrend2D.h"
     10#include "pmResiduals.h"
     11#include "pmGrowthCurve.h"
     12#include "pmSpan.h"
     13#include "pmFootprintSpans.h"
     14#include "pmFootprint.h"
     15#include "pmPeaks.h"
     16#include "pmMoments.h"
     17#include "pmModelFuncs.h"
     18#include "pmModel.h"
     19#include "pmModelUtils.h"
     20#include "pmModelClass.h"
     21#include "pmSourceMasks.h"
     22#include "pmSourceExtendedPars.h"
     23#include "pmSourceDiffStats.h"
     24#include "pmSource.h"
     25#include "pmSourceFitModel.h"
    726#include "pmPSF.h"
    827#include "pmPSFtry.h"
    9 #include "pmSource.h"
     28#include "pmDetections.h"
     29
    1030#include "pmSourceVisual.h"
    1131
     
    1333#include <kapa.h>
    1434#include "pmVisual.h"
     35#include "pmVisualUtils.h"
    1536
    1637// functions used to visualize the analysis as it goes
     
    3455    Graphdata graphdata;
    3556
    36     if (!pmVisualIsVisual()) return true;
     57    if (!pmVisualTestLevel("psphot.psf.metric", 2)) return true;
    3758
    3859    if (kapa1 == -1) {
     
    118139    Graphdata graphdata;
    119140
    120     if (!pmVisualIsVisual()) return true;
     141    if (!pmVisualTestLevel("psphot.psf.subpix", 3)) return true;
    121142
    122143    if (kapa1 == -1) {
     
    280301bool pmSourceVisualShowModelFits (pmPSF *psf, psArray *sources, psImageMaskType maskVal) {
    281302
    282     if (!pmVisualIsVisual()) return true;
     303    if (!pmVisualTestLevel("psphot.psf.fits", 2)) return true;
    283304
    284305    if (kapa2 == -1) {
     
    360381bool pmSourceVisualShowModelFit (pmSource *source) {
    361382
    362     if (!pmVisualIsVisual()) return true;
     383    if (!pmVisualTestLevel("psphot.psf.fitresid", 2)) return true;
     384
    363385    if (!source->pixels) return false;
    364386    if (!source->modelFlux) return false;
     
    404426    Graphdata graphdata;
    405427
    406     if (!pmVisualIsVisual() || !plotPSF) return true;
     428    if (!plotPSF) return true;
     429    if (!pmVisualTestLevel("psphot.psf.resid", 2)) return true;
    407430
    408431    if (kapa1 == -1) {
  • trunk/psModules/src/objects/pmSpan.h

    r20945 r29004  
    1010# ifndef PM_SPAN_H
    1111# define PM_SPAN_H
    12 
    13 #include <pslib.h>
    1412
    1513/// @addtogroup Objects Object Detection / Analysis Functions
  • trunk/psModules/src/objects/pmTrend2D.h

    r25754 r29004  
    1212# ifndef PM_TREND_2D_H
    1313# define PM_TREND_2D_H
    14 
    15 #include <pslib.h>
    1614
    1715/// @addtogroup Objects Object Detection / Analysis Functions
  • trunk/psModules/src/psmodules.h

    r28043 r29004  
    1010#include <pmKapaPlots.h>
    1111#include <pmVisual.h>
     12#include <pmVisualUtils.h>
    1213#include <ippStages.h>
    1314#include <ippDiffMode.h>
     
    113114
    114115// the following headers are from psModule:objects
     116#include <pmTrend2D.h>
     117#include <pmResiduals.h>
     118#include <pmGrowthCurve.h>
     119
    115120#include <pmSpan.h>
    116121#include <pmFootprintSpans.h>
     
    119124#include <pmDetections.h>
    120125#include <pmMoments.h>
     126
     127#include <pmModelFuncs.h>
     128#include <pmModel.h>
     129
     130#include <pmSourceMasks.h>
    121131#include <pmSourceExtendedPars.h>
    122132#include <pmSourceDiffStats.h>
    123 #include <pmResiduals.h>
    124 #include <pmGrowthCurve.h>
    125 #include <pmTrend2D.h>
     133#include <pmSource.h>
     134#include <pmSourceFitModel.h>
    126135#include <pmPSF.h>
    127 #include <pmModel.h>
    128 #include <pmSourceMasks.h>
    129 #include <pmSource.h>
     136#include <pmPSFtry.h>
    130137#include <pmPhotObj.h>
    131138#include <pmSourceUtils.h>
    132139#include <pmSourceIO.h>
    133140#include <pmSourceSky.h>
    134 #include <pmSourceFitModel.h>
    135141#include <pmSourceFitSet.h>
    136142#include <pmSourceContour.h>
    137143#include <pmSourcePlots.h>
    138144#include <pmPSF_IO.h>
    139 #include <pmPSFtry.h>
    140145#include <pmModelClass.h>
    141146#include <pmModelUtils.h>
     
    144149#include <pmSourceMatch.h>
    145150#include <pmDetEff.h>
     151#include <pmPCMdata.h>
    146152
    147153// The following headers are from random locations, here because they cross bounds
  • trunk/psphot

    • Property svn:mergeinfo deleted
  • trunk/psphot/src/Makefile.am

    r28013 r29004  
    163163        psphotOutput.c                 \
    164164        psphotFakeSources.c            \
    165         psphotModelWithPSF.c           \
    166165        psphotExtendedSourceAnalysis.c \
    167166        psphotExtendedSourceAnalysisByObject.c \
    168167        psphotExtendedSourceFits.c     \
    169168        psphotKernelFromPSF.c          \
    170         psphotPSFConvModel.c           \
    171169        psphotFitSet.c                 \
    172170        psphotSourceFreePixels.c       \
  • trunk/psphot/src/psphot.h

    r28013 r29004  
    1212
    1313#define PSPHOT_RECIPE_PSF_FAKE_ALLOW "PSF.FAKE.ALLOW" // Name for recipe component permitting fake PSFs
    14 
    15 // pmPCMData : PSF Convolved Model data storage structure
    16 typedef struct {
    17     psImage *model;
    18     psArray *dmodels;
    19     psImage *modelConv;
    20     psArray *dmodelsConv;
    21 } pmPCMData;
    2214
    2315// top-level psphot functions
     
    114106bool            psphotExtendedSourceFits (pmConfig *config, const pmFPAview *view, const char *filerule);
    115107bool            psphotExtendedSourceFitsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     108bool            psphotExtendedSourceFits_Threaded (psThreadJob *job);
    116109
    117110bool            psphotApResid (pmConfig *config, const pmFPAview *view, const char *filerule);
     
    188181
    189182// functions to set the correct source pixels
    190 bool            psphotInitRadiusPSF(const psMetadata *recipe, const psMetadata *analysis, const pmModelType type);
     183bool            psphotInitRadiusPSF (psMetadata *recipe, pmReadout *readout);
     184bool            psphotInitRadiusEXT (psMetadata *recipe, pmReadout *readout);
    191185
    192186bool            psphotCheckRadiusPSF (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal);
    193187bool            psphotCheckRadiusPSFBlend (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal, float dR);
    194 bool            psphotInitRadiusEXT (psMetadata *recipe, pmModelType type);
    195 bool            psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal);
    196 float           psphotSetRadiusEXT (pmReadout *readout, pmSource *source, psImageMaskType markVal);
     188bool            psphotSetRadiusFootprint (float *radius, pmReadout *readout, pmSource *source, psImageMaskType markVal, float factor);
     189bool            psphotSetRadiusModel (pmModel *model, pmReadout *readout, pmSource *source, psImageMaskType markVal, bool deep);
    197190
    198191bool            psphotDumpMoments (psMetadata *recipe, psArray *sources);
     
    210203//  functions to support the source fitting process
    211204bool            psphotInitLimitsPSF (psMetadata *recipe, pmReadout *readout);
    212 bool            psphotInitLimitsEXT (psMetadata *recipe);
    213 bool            psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal);
    214 bool            psphotFitBlob (pmReadout *readout, pmSource *source, psArray *sources, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal);
    215 bool            psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal);
    216 pmModel        *psphotFitEXT (pmReadout *readout, pmSource *source, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal);
    217 psArray        *psphotFitDBL (pmReadout *readout, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal);
     205bool            psphotInitLimitsEXT (psMetadata *recipe, pmReadout *readout);
     206bool            psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
     207bool            psphotFitBlob (pmReadout *readout, pmSource *source, psArray *sources, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
     208bool            psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
     209pmModel        *psphotFitEXT (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal);
     210psArray        *psphotFitDBL (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
    218211
    219212// functions to support simultaneous multi-source fitting
     
    252245bool            psphotVisualShowBackground (pmConfig *config, const pmFPAview *view, pmReadout *readout);
    253246bool            psphotVisualShowSignificance (psImage *image, float min, float max);
     247bool            psphotVisualShowLogSignificance (psImage *image, float min, float max);
    254248bool            psphotVisualShowPeaks (pmDetections *detections);
    255249bool            psphotVisualShowFootprints (pmDetections *detections);
     
    292286bool psphotRadialBins (psMetadata *recipe, pmSource *source, float radiusMax, float skynoise);
    293287
    294 // structures & functions to support psf-convolved model fitting
    295 
    296 // psf-convolved model fitting
    297 bool psphotModelWithPSF_LMM (
    298     psMinimization *min,
    299     psImage *covar,
    300     psVector *params,
    301     psMinConstraint *constraint,
    302     pmSource *source,
    303     const psKernel *psf,
    304     psMinimizeLMChi2Func func);
    305 
    306 psF32 psphotModelWithPSF_SetABX(
    307     psImage  *alpha,
    308     psVector *beta,
    309     const psVector *params,
    310     const psVector *paramMask,
    311     pmPCMData *pcm,
    312     const pmSource *source,
    313     const psKernel *psf,
    314     psMinimizeLMChi2Func func);
    315 
    316 pmPCMData *pmPCMDataAlloc (
    317     const psVector *params,
    318     const psVector *paramMask,
    319     pmSource *source);
    320 
    321 psImage *pmPCMDataSaveImage (pmPCMData *pcm);
    322 
    323288int psphotKapaOpen (void);
    324289bool psphotKapaClose (void);
     
    364329
    365330bool psphotFitSourcesLinearStack (pmConfig *config, psArray *objects, bool final);
    366 int pmPhotObjSortBySN (const void **a, const void **b);
    367 int pmPhotObjSortByX (const void **a, const void **b);
    368331
    369332typedef enum {
     
    462425bool psphotStackObjectsUnifyPosition (psArray *objects);
    463426
     427bool psphotFitSersicIndex (pmModel *model, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal);
     428
     429bool psphotFitSersicIndexPCM (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
     430pmModel *psphotFitPCM (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
     431
    464432#endif
  • trunk/psphot/src/psphotAddNoise.c

    r28013 r29004  
    3434
    3535    bool status = false;
    36     psEllipseShape oldshape;
    37     psEllipseShape newshape;
    38     psEllipseAxes axes;
    3936
    4037    // find the currently selected readout
     
    8683        if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) continue;
    8784
    88         // select appropriate model
    89         pmModel *model = pmSourceGetModel (NULL, source);
    90         if (model == NULL) continue;  // model must be defined
    91 
    92         if (add) {
    93             psTrace ("psphot", 4, "adding noise for object at %f,%f\n", model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
    94         } else {
    95             psTrace ("psphot", 4, "remove noise for object at %f,%f\n", model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS]);
    96         }
    97 
    98         psF32 *PAR = model->params->data.F32;
    99 
    100         // save original values
    101         float oldI0  = PAR[PM_PAR_I0];
    102         oldshape.sx  = PAR[PM_PAR_SXX];
    103         oldshape.sy  = PAR[PM_PAR_SYY];
    104         oldshape.sxy = PAR[PM_PAR_SXY];
    105 
    106         // XXX can this be done more intelligently?
    107         if (oldI0 == 0.0) continue;
    108         if (!isfinite(oldI0)) continue;
    109 
    110         // increase size and height of source
    111         axes = psEllipseShapeToAxes (oldshape, 20.0);
    112         axes.major *= SIZE;
    113         axes.minor *= SIZE;
    114         newshape = psEllipseAxesToShape (axes);
    115         PAR[PM_PAR_I0]  = FACTOR*oldI0;
    116         PAR[PM_PAR_SXX] = newshape.sx;
    117         PAR[PM_PAR_SYY] = newshape.sy;
    118         PAR[PM_PAR_SXY] = newshape.sxy;
    119 
    120         // XXX if we use pmSourceOp, the size (and possibly Io) will not be respected
    121         pmSourceOp (source, PM_MODEL_OP_FULL | PM_MODEL_OP_NOISE, add, maskVal, 0, 0);
    122 
    123         // restore original values
    124         PAR[PM_PAR_I0]  = oldI0;
    125         PAR[PM_PAR_SXX] = oldshape.sx;
    126         PAR[PM_PAR_SYY] = oldshape.sy;
    127         PAR[PM_PAR_SXY] = oldshape.sxy;
     85        pmSourceNoiseOp (source, PM_MODEL_OP_FULL | PM_MODEL_OP_NOISE, FACTOR, SIZE, add, maskVal, 0, 0);
    12886    }
    12987    if (add) {
     
    13290        psLogMsg ("psphot.noise", PS_LOG_INFO, "sub noise for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.noise"));
    13391    }
     92
    13493    return true;
    13594}
  • trunk/psphot/src/psphotApResid.c

    r28524 r29004  
    459459        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal);
    460460
    461         bool status = pmSourceMagnitudes (source, psf, photMode, maskVal);
     461        bool status = pmSourceMagnitudes (source, psf, photMode, maskVal, markVal);
    462462
    463463        // clear the mask bit
  • trunk/psphot/src/psphotArguments.c

    r25985 r29004  
    176176    }
    177177
    178     // visual : interactive display mode
    179     if ((N = psArgumentGet (argc, argv, "-visual"))) {
    180         psArgumentRemove (N, &argc, argv);
    181         pmVisualSetVisual(true);
    182     }
    183 
    184178    // break : used from recipe throughout psphotReadout
    185179    if ((N = psArgumentGet (argc, argv, "-break"))) {
  • trunk/psphot/src/psphotBlendFit.c

    r28405 r29004  
    6565    assert (status && fitIter > 0);
    6666
    67     float fitTol = psMetadataLookupF32 (&status, recipe, "EXT_FIT_TOL"); // Fit tolerance
    68     assert (status && isfinite(fitTol) && fitTol > 0);
     67    float fitMinTol = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MIN_TOL"); // Fit tolerance
     68    assert (status && isfinite(fitMinTol) && fitMinTol > 0);
     69
     70    float fitMaxTol = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MAX_TOL"); // Fit tolerance
     71    assert (status && isfinite(fitMaxTol) && fitMaxTol > 0);
    6972
    7073    bool poisson = psMetadataLookupBool(&status, recipe, "POISSON.ERRORS.PHOT.LMM"); // Poisson errors?
    7174    assert (status);
    7275
     76    float maxChisqDOF = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MAX_CHISQ"); // Fit tolerance
     77
    7378    float skySig = psMetadataLookupF32(&status, recipe, "SKY_SIG");
    7479    assert (status && isfinite(skySig) && skySig > 0);
    7580
    7681    // Define source fitting parameters for extended source fits
    77     pmSourceFitModelInit(fitIter, fitTol, PS_SQR(skySig), poisson);
     82    pmSourceFitOptions *fitOptions = pmSourceFitOptionsAlloc();
     83    fitOptions->nIter         = fitIter;
     84    fitOptions->minTol        = fitMinTol;
     85    fitOptions->maxTol        = fitMaxTol;
     86    fitOptions->maxChisqDOF   = maxChisqDOF;
     87    fitOptions->poissonErrors = poisson;
     88    fitOptions->weight        = PS_SQR(skySig);
     89    fitOptions->mode          = PM_SOURCE_FIT_PSF;
    7890
    7991    psphotInitLimitsPSF (recipe, readout);
    80     psphotInitLimitsEXT (recipe);
    81     psphotInitRadiusPSF (recipe, readout->analysis, psf->type);
     92    psphotInitLimitsEXT (recipe, readout);
     93    psphotInitRadiusPSF (recipe, readout);
    8294
    8395    // starts the timer, sets up the array of fitSets
     
    88100    if (!sources->n) {
    89101        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping blend");
     102        psFree (fitOptions);
    90103        return true;
    91104    }
     
    112125            psArrayAdd(job->args, 1, psf);
    113126            psArrayAdd(job->args, 1, newSources); // return for new sources
     127            psArrayAdd(job->args, 1, fitOptions); // default fit options
    114128            psFree (newSources);
    115129
     
    121135            if (!psThreadJobAddPending(job)) {
    122136                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     137                psFree (fitOptions);
    123138                return NULL;
    124139            }
    125 
    126 # if (0)
    127             {
    128                 int nfit = 0;
    129                 int npsf = 0;
    130                 int next = 0;
    131                 int nfail = 0;
    132                 psArray *newSources = psArrayAllocEmpty(16);
    133 
    134                 if (!psphotBlendFit_Unthreaded (&nfit, &npsf, &next, &nfail, readout, recipe, cells->data[j], psf, newSources)) {
    135                     psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    136                     return NULL;
    137                 }
    138                 Nfit += nfit;
    139                 Npsf += npsf;
    140                 Next += next;
    141                 Nfail += nfail;
    142 
    143                 // add these back onto sources
    144                 for (int k = 0; k < newSources->n; k++) {
    145                     psArrayAdd (sources, 16, newSources->data[k]);
    146                 }
    147                 psFree (newSources);
    148             }
    149 # endif
    150140        }
    151141
     
    153143        if (!psThreadPoolWait (false)) {
    154144            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     145            psFree (fitOptions);
    155146            return NULL;
    156147        }
     
    163154            } else {
    164155                psScalar *scalar = NULL;
    165                 scalar = job->args->data[5];
     156                scalar = job->args->data[6];
    166157                Nfit += scalar->data.S32;
    167                 scalar = job->args->data[6];
     158                scalar = job->args->data[7];
    168159                Npsf += scalar->data.S32;
    169                 scalar = job->args->data[7];
     160                scalar = job->args->data[8];
    170161                Next += scalar->data.S32;
    171                 scalar = job->args->data[8];
     162                scalar = job->args->data[9];
    172163                Nfail += scalar->data.S32;
    173164
     
    186177      psphotSaveImage (NULL, readout->image,  "image.v2.fits");
    187178    }
     179    psFree (fitOptions);
    188180
    189181    psLogMsg ("psphot.psphotBlendFit", PS_LOG_INFO, "fit models: %f sec for %d objects (%d psf, %d ext, %d failed, %ld skipped)\n", psTimerMark ("psphot.fit.nonlinear"), Nfit, Npsf, Next, Nfail, sources->n - Nfit);
     
    204196    psScalar *scalar = NULL;
    205197
    206     pmReadout *readout  = job->args->data[0];
    207     psMetadata *recipe  = job->args->data[1];
    208     psArray *sources    = job->args->data[2];
    209     pmPSF *psf          = job->args->data[3];
    210     psArray *newSources = job->args->data[4];
     198    pmReadout *readout             = job->args->data[0];
     199    psMetadata *recipe             = job->args->data[1];
     200    psArray *sources               = job->args->data[2];
     201    pmPSF *psf                     = job->args->data[3];
     202    psArray *newSources            = job->args->data[4];
     203    pmSourceFitOptions *fitOptions = job->args->data[5];
    211204
    212205    // bit-masks to test for good/bad pixels
     
    269262        Nfit ++;
    270263
     264        if (0) {
     265            psF32 Mxx = source->moments->Mxx;
     266            psF32 Myy = source->moments->Myy;
     267            fprintf (stderr, "1: Mxx: %f, Myy: %f\n", Mxx, Myy);
     268        }
     269
    271270        // try fitting PSFs or extended sources depending on source->mode
    272271        // these functions subtract the resulting fitted source
    273272        if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    274             if (psphotFitBlob (readout, source, newSources, psf, maskVal, markVal)) {
     273            if (psphotFitBlob (readout, source, newSources, psf, fitOptions, maskVal, markVal)) {
    275274                source->type = PM_SOURCE_TYPE_EXTENDED;
    276275                psTrace ("psphot", 5, "source at %7.1f, %7.1f is ext", source->peak->xf, source->peak->yf);
     
    280279            }
    281280        } else {
    282             if (psphotFitBlend (readout, source, psf, maskVal, markVal)) {
     281            if (psphotFitBlend (readout, source, psf, fitOptions, maskVal, markVal)) {
    283282                source->type = PM_SOURCE_TYPE_STAR;
    284283                psTrace ("psphot", 5, "source at %7.1f, %7.1f is psf", source->peak->xf, source->peak->yf);
     
    289288        }
    290289
     290        if (0) {
     291            psF32 Mxx = source->moments->Mxx;
     292            psF32 Myy = source->moments->Myy;
     293            fprintf (stderr, "2: Mxx: %f, Myy: %f\n", Mxx, Myy);
     294        }
     295
    291296        psTrace ("psphot", 5, "source at %7.1f, %7.1f failed", source->peak->xf, source->peak->yf);
    292297        Nfail ++;
     
    298303
    299304    // change the value of a scalar on the array (wrap this and put it in psArray.h)
    300     scalar = job->args->data[5];
     305    scalar = job->args->data[6];
    301306    scalar->data.S32 = Nfit;
    302307
    303     scalar = job->args->data[6];
     308    scalar = job->args->data[7];
    304309    scalar->data.S32 = Npsf;
    305310
    306     scalar = job->args->data[7];
     311    scalar = job->args->data[8];
    307312    scalar->data.S32 = Next;
    308313
    309     scalar = job->args->data[8];
     314    scalar = job->args->data[9];
    310315    scalar->data.S32 = Nfail;
    311316
  • trunk/psphot/src/psphotChoosePSF.c

    r28013 r29004  
    7474
    7575    // structure to store user options defining the psf
    76     pmPSFOptions *options = pmPSFOptionsAlloc ();
     76    pmPSFOptions *options = pmPSFOptionsAlloc();
    7777
    7878    // load user options from the recipe. no need to check existence -- they are
     
    138138        return false;
    139139    }
    140     float fitTol = psMetadataLookupF32 (&status, recipe, "PSF_FIT_TOL"); // Fit tolerance
    141     if (!status || !isfinite(fitTol) || fitTol <= 0) {
    142         psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSF_FIT_TOL is not positive");
    143         return false;
    144     }
    145     pmSourceFitModelInit(fitIter, fitTol, PS_SQR(SKY_SIG), options->poissonErrorsPhotLMM);
    146 
     140    float fitMinTol = psMetadataLookupF32 (&status, recipe, "PSF_FIT_MIN_TOL"); // Fit tolerance
     141    if (!status || !isfinite(fitMinTol) || fitMinTol <= 0) {
     142        fitMinTol = psMetadataLookupF32 (&status, recipe, "PSF_FIT_TOL"); // Fit tolerance
     143        if (!status || !isfinite(fitMinTol) || fitMinTol <= 0) {
     144            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSF_FIT_MIN_TOL (and PSF_FIT_TOL) not defined or positive");
     145            return false;
     146        }
     147    }
     148    float fitMaxTol = psMetadataLookupF32 (&status, recipe, "PSF_FIT_MAX_TOL"); // Fit tolerance
     149    if (!status || !isfinite(fitMaxTol) || fitMaxTol <= 0) {
     150        fitMaxTol = 1.0;
     151    }
     152    float maxChisqDOF = psMetadataLookupF32 (&status, recipe, "PSF_FIT_MAX_CHISQ"); // Fit tolerance
     153
     154    // options which modify the behavior of the model fitting
     155    options->fitOptions                = pmSourceFitOptionsAlloc();
     156    options->fitOptions->nIter         = fitIter;
     157    options->fitOptions->minTol        = fitMinTol;
     158    options->fitOptions->maxTol        = fitMaxTol;
     159    options->fitOptions->maxChisqDOF   = maxChisqDOF;
     160    options->fitOptions->poissonErrors = options->poissonErrorsPhotLMM;
     161    options->fitOptions->weight        = PS_SQR(SKY_SIG);
     162    options->fitOptions->mode          = PM_SOURCE_FIT_PSF;
     163   
    147164    psArray *stars = psArrayAllocEmpty (sources->n);
    148165
     
    227244
    228245    // try each model option listed in config
     246    // pmPSFtryModel makes a local copy of the sources -- those points are not the same as those for 'sources'
    229247    for (int i = 0; i < modelNames->n; i++) {
    230248        char *modelName = modelNames->data[i];
     
    304322
    305323    // unset the PSFSTAR flag for stars not used for PSF model
     324    // XXX a more efficient way of achieving this would be to record a pair of arrays
     325    // of the source index and the source id for the psf stars.  but that would require we do
     326    // not re-sort the source list in the meanwhile
     327    int nDrop = 0;
    306328    for (int i = 0; i < try->sources->n; i++) {
    307329        pmSource *source = try->sources->data[i];
    308330        if (try->mask->data.PS_TYPE_VECTOR_MASK_DATA[i]) {
    309             source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
    310         }
    311     }
     331            // need to find this source in the original list (these are copies, not pointers)
     332            for (int j = 0; j < sources->n; j++) {
     333                pmSource *realSource = sources->data[j];
     334                if (realSource->id != source->id) continue;
     335                realSource->mode &= ~PM_SOURCE_MODE_PSFSTAR;
     336                source->mode &= ~PM_SOURCE_MODE_PSFSTAR;
     337                nDrop ++;
     338                break;
     339            }
     340        }
     341    }
     342    // fprintf (stderr, "drop %d stars as PSF stars\n", nDrop);
     343
     344    // XXX is this working?
     345    // int N1 = 0;
     346    // for (int i = 0; i < try->sources->n; i++) {
     347    //     pmSource *source = try->sources->data[i];
     348    //  fprintf (stderr, "%llx : %d\n", (long long int) source, (source->mode & PM_SOURCE_MODE_PSFSTAR));
     349    //  if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
     350    //      N1 ++;
     351    //     }
     352    // }
     353    // int N2 = 0;
     354    // for (int i = 0; i < sources->n; i++) {
     355    //     pmSource *source = sources->data[i];
     356    //  fprintf (stderr, "%llx : %d\n", (long long int) source, (source->mode & PM_SOURCE_MODE_PSFSTAR));
     357    //  if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
     358    //      N2 ++;
     359    //     }
     360    // }
     361    // fprintf (stderr, "N1: %d, N2: %d\n", N1, N2);
    312362
    313363    // build a PSF residual image
  • trunk/psphot/src/psphotEllipticalContour.c

    r27819 r29004  
    8282    params->data.F32[PAR_RMIN]    = Rmin;
    8383
    84     psMinimization *myMin = psMinimizationAlloc (25, 0.001);
     84    psMinimization *myMin = psMinimizationAlloc (25, 0.01, 1.00);
    8585    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
    8686   
  • trunk/psphot/src/psphotExtendedSourceAnalysis.c

    r28013 r29004  
    157157        }
    158158
    159 # if (0)
    160         // Isophotal Mags
    161         if (doIsophotal) {
    162             if (!psphotIsophotal (source, recipe, maskVal)) {
    163                 psTrace ("psphot", 5, "failed to measure isophotal mags for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    164             } else {
    165                 psTrace ("psphot", 5, "measured isophotal mags for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    166                 Nisophot ++;
    167                 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS;
    168             }
    169         }
    170         // Kron Mags
    171         if (doKron) {
    172             if (!psphotKron (source, recipe, maskVal)) {
    173                 psTrace ("psphot", 5, "failed to measure kron mags for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    174             } else {
    175                 psTrace ("psphot", 5, "measure kron mags for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    176                 Nkron ++;
    177                 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS;
    178             }
    179         }
    180 # endif
    181 
    182159        // re-subtract the object, leave local sky
    183160        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
  • trunk/psphot/src/psphotExtendedSourceFits.c

    r28013 r29004  
    3131// non-linear model fitting for extended sources
    3232bool psphotExtendedSourceFitsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe) {
     33
     34    bool status;
     35    int Next = 0;
     36    int Nconvolve = 0;
     37    int NconvolvePass = 0;
     38    int Nplain = 0;
     39    int NplainPass = 0;
     40
     41    psTimerStart ("psphot.extended");
     42
     43    // find the currently selected readout
     44    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
     45    psAssert (file, "missing file?");
     46
     47    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     48    psAssert (readout, "missing readout?");
     49
     50    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     51    psAssert (detections, "missing detections?");
     52
     53    psArray *sources = detections->allSources;
     54    psAssert (sources, "missing sources?");
     55
     56    if (!sources->n) {
     57        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source size");
     58        return true;
     59    }
     60
     61    // determine the number of allowed threads
     62    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     63    if (!status) {
     64        nThreads = 0;
     65    }
     66
     67    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     68    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
     69    assert (maskVal);
     70
     71    psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); // Mask value for bad pixels
     72    assert (markVal);
     73
     74    // maskVal is used to test for rejected pixels, and must include markVal
     75    maskVal |= markVal;
     76
     77    // select the collection of desired models
     78    psMetadata *models = psMetadataLookupMetadata (&status, recipe, "EXTENDED_SOURCE_MODELS");
     79    if (!status) {
     80        psWarning ("extended source model fits requested but model model is missing (EXTENDED_SOURCE_MODELS)\n");
     81        return true;
     82    }
     83    if (models->list->n == 0) {
     84        psWarning ("extended source model fits requested but no models are specified\n");
     85        return true;
     86    }
     87
     88    // validate the model entries
     89    psMetadataIterator *iter = psMetadataIteratorAlloc (models, PS_LIST_HEAD, NULL);
     90    psMetadataItem *item = NULL;
     91    while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
     92
     93      if (item->type != PS_DATA_METADATA) {
     94        psAbort ("Invalid type for EXTENDED_SOURCE_MODEL entry %s, not a metadata folder", item->name);
     95        // XXX we could cull the bad entries or build a validated model folder
     96      }
     97
     98      psMetadata *model = (psMetadata *) item->data.md;
     99
     100      // check on the model type
     101      char *modelName = psMetadataLookupStr (&status, model, "MODEL");
     102      int modelType = pmModelClassGetType (modelName);
     103      if (modelType < 0) {
     104        psAbort ("Unknown model class for EXTENDED_SOURCE_MODEL entry %s: %s", item->name, modelName);
     105      }
     106      psMetadataAddS32 (model, PS_LIST_TAIL, "MODEL_TYPE", PS_META_REPLACE, "", modelType);
     107
     108      // check on the SNLIM, set a float value
     109      char *SNword = psMetadataLookupStr (&status, model, "SNLIM");
     110      if (!status) {
     111        psAbort("SNLIM not defined for extended source model %s\n", item->name);
     112      }
     113      float SNlim = atof (SNword);
     114      psMetadataAddF32 (model, PS_LIST_TAIL, "SNLIM_VALUE", PS_META_REPLACE, "", SNlim);
     115
     116      // check on the PSF-Convolution status
     117      char *convolvedWord = psMetadataLookupStr (&status, model, "PSF_CONVOLVED");
     118      if (!status || (strcasecmp (convolvedWord, "true") && strcasecmp (convolvedWord, "false"))) {
     119        psAbort ("PSF_CONVOLVED entry invalid or missing for EXTENDED_SOURCE_MODEL entry %s", item->name);
     120      }
     121      bool convolved = !strcasecmp (convolvedWord, "true");
     122      psMetadataAddBool (model, PS_LIST_TAIL, "PSF_CONVOLVED_VALUE", PS_META_REPLACE, "", convolved);
     123    }
     124    psFree (iter);
     125
     126    // option to limit analysis to a specific region
     127    char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
     128    psRegion *AnalysisRegion = psRegionAlloc(0,0,0,0);
     129    *AnalysisRegion = psRegionForImage(readout->image, psRegionFromString (region));
     130    if (psRegionIsNaN (*AnalysisRegion)) psAbort("analysis region mis-defined");
     131
     132    // what fraction of the PSF is used? (radius in pixels : 2 -> 5x5 box)
     133    int psfSize = psMetadataLookupS32 (&status, recipe, "PCM_BOX_SIZE");
     134    assert (status);
     135
     136    // source analysis is done in S/N order (brightest first)
     137    sources = psArraySort (sources, pmSourceSortBySN);
     138
     139    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     140    int Cx = 1, Cy = 1;
     141    psphotChooseCellSizes (&Cx, &Cy, readout, nThreads);
     142
     143    psArray *cellGroups = psphotAssignSources (Cx, Cy, sources);
     144
     145    for (int i = 0; i < cellGroups->n; i++) {
     146
     147        psArray *cells = cellGroups->data[i];
     148
     149        for (int j = 0; j < cells->n; j++) {
     150
     151            // allocate a job -- if threads are not defined, this just runs the job
     152            psThreadJob *job = psThreadJobAlloc ("PSPHOT_EXTENDED_FIT");
     153
     154            psArrayAdd(job->args, 1, readout);
     155            psArrayAdd(job->args, 1, cells->data[j]); // sources
     156            psArrayAdd(job->args, 1, models);
     157            psArrayAdd(job->args, 1, AnalysisRegion); // XXX make a pointer
     158
     159            PS_ARRAY_ADD_SCALAR(job->args, psfSize, PS_TYPE_S32);
     160            PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK);
     161            PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK);
     162
     163            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Next
     164            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nconvolve
     165            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for NconvolvePass
     166            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nplain
     167            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for NplainPass
     168
     169            if (!psThreadJobAddPending(job)) {
     170                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     171                psFree(AnalysisRegion);
     172                return false;
     173            }
     174        }
     175
     176        // wait for the threads to finish and manage results
     177        if (!psThreadPoolWait (false)) {
     178            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     179            psFree(AnalysisRegion);
     180            return false;
     181        }
     182
     183        // we have only supplied one type of job, so we can assume the types here
     184        psThreadJob *job = NULL;
     185        while ((job = psThreadJobGetDone()) != NULL) {
     186            if (job->args->n < 1) {
     187                fprintf (stderr, "error with job\n");
     188            } else {
     189                psScalar *scalar = NULL;
     190                scalar = job->args->data[7];
     191                Next += scalar->data.S32;
     192                scalar = job->args->data[8];
     193                Nconvolve += scalar->data.S32;
     194                scalar = job->args->data[9];
     195                NconvolvePass += scalar->data.S32;
     196                scalar = job->args->data[10];
     197                Nplain += scalar->data.S32;
     198                scalar = job->args->data[11];
     199                NplainPass += scalar->data.S32;
     200            }
     201            psFree(job);
     202            }
     203    }
     204    psFree (cellGroups);
     205    psFree(AnalysisRegion);
     206
     207    psLogMsg ("psphot", PS_LOG_INFO, "extended source analysis: %f sec for %d objects\n", psTimerMark ("psphot.extended"), Next);
     208    psLogMsg ("psphot", PS_LOG_INFO, "  %d convolved models (%d passed)\n", Nconvolve, NconvolvePass);
     209    psLogMsg ("psphot", PS_LOG_INFO, "  %d plain models (%d passed)\n", Nplain, NplainPass);
     210    return true;
     211}
     212
     213// non-linear model fitting for extended sources
     214bool psphotExtendedSourceFits_Threaded (psThreadJob *job) {
    33215
    34216    bool status;
     
    39221    int NplainPass = 0;
    40222    bool savePics = false;
    41 
    42     // find the currently selected readout
    43     pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
    44     psAssert (file, "missing file?");
    45 
    46     pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
    47     psAssert (readout, "missing readout?");
    48 
    49     pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
    50     psAssert (detections, "missing detections?");
    51 
    52     psArray *sources = detections->allSources;
    53     psAssert (sources, "missing sources?");
    54 
    55     if (!sources->n) {
    56         psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source size");
    57         return true;
    58     }
    59 
    60     // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    61     psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    62     assert (maskVal);
    63 
    64     psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); // Mask value for bad pixels
    65     assert (markVal);
    66 
    67     // maskVal is used to test for rejected pixels, and must include markVal
    68     maskVal |= markVal;
    69 
    70     // select the collection of desired models
    71     psMetadata *models = psMetadataLookupMetadata (&status, recipe, "EXTENDED_SOURCE_MODELS");
    72     if (!status) {
    73         psWarning ("extended source model fits requested but model model is missing (EXTENDED_SOURCE_MODELS)\n");
    74         return true;
    75     }
    76     if (models->list->n == 0) {
    77         psWarning ("extended source model fits requested but no models are specified\n");
    78         return true;
    79     }
    80 
    81     // validate the model entries
    82     psMetadataIterator *iter = psMetadataIteratorAlloc (models, PS_LIST_HEAD, NULL);
    83     psMetadataItem *item = NULL;
    84     while ((item = psMetadataGetAndIncrement (iter)) != NULL) {
    85 
    86       if (item->type != PS_DATA_METADATA) {
    87         psAbort ("Invalid type for EXTENDED_SOURCE_MODEL entry %s, not a metadata folder", item->name);
    88         // XXX we could cull the bad entries or build a validated model folder
    89       }
    90 
    91       psMetadata *model = (psMetadata *) item->data.md;
    92 
    93       // check on the model type
    94       char *modelName = psMetadataLookupStr (&status, model, "MODEL");
    95       int modelType = pmModelClassGetType (modelName);
    96       if (modelType < 0) {
    97         psAbort ("Unknown model class for EXTENDED_SOURCE_MODEL entry %s: %s", item->name, modelName);
    98       }
    99       psMetadataAddS32 (model, PS_LIST_TAIL, "MODEL_TYPE", PS_META_REPLACE, "", modelType);
    100 
    101       // check on the SNLIM, set a float value
    102       char *SNword = psMetadataLookupStr (&status, model, "SNLIM");
    103       if (!status) {
    104         psAbort("SNLIM not defined for extended source model %s\n", item->name);
    105       }
    106       float SNlim = atof (SNword);
    107       psMetadataAddF32 (model, PS_LIST_TAIL, "SNLIM_VALUE", PS_META_REPLACE, "", SNlim);
    108 
    109       // check on the PSF-Convolution status
    110       char *convolvedWord = psMetadataLookupStr (&status, model, "PSF_CONVOLVED");
    111       if (!status || (strcasecmp (convolvedWord, "true") && strcasecmp (convolvedWord, "false"))) {
    112         psAbort ("PSF_CONVOLVED entry invalid or missing for EXTENDED_SOURCE_MODEL entry %s", item->name);
    113       }
    114       bool convolved = !strcasecmp (convolvedWord, "true");
    115       psMetadataAddBool (model, PS_LIST_TAIL, "PSF_CONVOLVED_VALUE", PS_META_REPLACE, "", convolved);
    116     }
    117     psFree (iter);
    118 
    119     // option to limit analysis to a specific region
    120     char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
    121     psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region));
    122     if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");
    123 
    124     // what fraction of the PSF is used? (radius in pixels : 2 -> 5x5 box)
    125     int psfSize = psMetadataLookupS32 (&status, recipe, "PCM_BOX_SIZE");
    126     assert (status);
    127 
    128     // source analysis is done in S/N order (brightest first)
    129     sources = psArraySort (sources, pmSourceSortBySN);
     223    float radius;
     224    psScalar *scalar = NULL;
     225
     226    // arguments: readout, sources, models, region, psfSize, maskVal, markVal
     227    pmReadout *readout      = job->args->data[0];
     228    psArray *sources        = job->args->data[1];
     229    psMetadata *models      = job->args->data[2];
     230    psRegion *region        = job->args->data[3];
     231    int psfSize             = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA);
     232    psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[5],PS_TYPE_IMAGE_MASK_DATA);
     233    psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[6],PS_TYPE_IMAGE_MASK_DATA);
     234
     235    // Define source fitting parameters for extended source fits
     236    pmSourceFitOptions *fitOptions = pmSourceFitOptionsAlloc();
     237    fitOptions->mode          = PM_SOURCE_FIT_EXT;
     238    // XXX for now, use the defaults for the rest:
     239    // fitOptions->nIter         = fitIter;
     240    // fitOptions->tol           = fitTol;
     241    // fitOptions->poissonErrors = poisson;
     242    // fitOptions->weight        = PS_SQR(skySig);
    130243
    131244    // choose the sources of interest
     
    140253
    141254        // XXX this should use peak?
    142         if (source->peak->x < AnalysisRegion.x0) continue;
    143         if (source->peak->y < AnalysisRegion.y0) continue;
    144         if (source->peak->x > AnalysisRegion.x1) continue;
    145         if (source->peak->y > AnalysisRegion.y1) continue;
     255        if (source->peak->x < region->x0) continue;
     256        if (source->peak->y < region->y0) continue;
     257        if (source->peak->x > region->x1) continue;
     258        if (source->peak->y > region->y1) continue;
    146259
    147260        // if model is NULL, we don't have a starting guess
     
    154267        }
    155268        Next ++;
     269
     270        // set the radius based on the footprint (also sets the mask pixels)
     271        if (!psphotSetRadiusFootprint(&radius, readout, source, markVal, 1.0)) {
     272            psFree (fitOptions)
     273            return false;
     274        }
     275
     276        // XXX note that this changes the source moments that are published...
     277        // recalculate the source moments using the larger extended-source moments radius
     278        // at this stage, skip Gaussian windowing, and do not clip pixels by S/N
     279        // this uses the footprint to judge both radius and aperture?
     280        // XXX save the psf-based moments for output
     281        if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) {
     282            // subtract the best fit from the object, leave local sky
     283            pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     284            // XXX raise an error of some kind
     285            continue;
     286        }
    156287
    157288        // save the modelFlux here in case we need to subtract it (for failure)
     
    201332          pmModel *modelFit = NULL;
    202333          if (convolved) {
    203               modelFit = psphotPSFConvModel (readout, source, modelType, maskVal, markVal, psfSize);
     334              modelFit = psphotFitPCM (readout, source, fitOptions, modelType, maskVal, markVal, psfSize);
    204335              if (!modelFit) {
    205336                  psTrace ("psphot", 5, "failed to fit psf-conv model for object at %f, %f", source->moments->Mx, source->moments->My);
     
    215346              psFree (source->modelFlux);
    216347              source->modelFlux = NULL;
    217               modelFit = psphotFitEXT (readout, source, modelType, maskVal, markVal);
     348              modelFit = psphotFitEXT (readout, source, fitOptions, modelType, maskVal, markVal);
    218349              if (!modelFit) {
    219350                  psTrace ("psphot", 5, "failed to fit plain model for object at %f, %f", source->moments->Mx, source->moments->My);
     
    233364
    234365          // test for fit quality / result
     366          modelFit->fitRadius = radius;
    235367          psArrayAdd (source->modelFits, 4, modelFit);
    236368
     
    311443        }
    312444    }
    313 
    314     psLogMsg ("psphot", PS_LOG_INFO, "extended source analysis: %f sec for %d objects\n", psTimerMark ("psphot"), Next);
    315     psLogMsg ("psphot", PS_LOG_INFO, "  %d convolved models (%d passed)\n", Nconvolve, NconvolvePass);
    316     psLogMsg ("psphot", PS_LOG_INFO, "  %d plain models (%d passed)\n", Nplain, NplainPass);
     445    psFree (fitOptions);
     446
     447    // change the value of a scalar on the array (wrap this and put it in psArray.h)
     448    scalar = job->args->data[7];
     449    scalar->data.S32 = Next;
     450
     451    scalar = job->args->data[8];
     452    scalar->data.S32 = Nconvolve;
     453
     454    scalar = job->args->data[9];
     455    scalar->data.S32 = NconvolvePass;
     456
     457    scalar = job->args->data[10];
     458    scalar->data.S32 = Nplain;
     459
     460    scalar = job->args->data[11];
     461    scalar->data.S32 = NplainPass;
     462
    317463    return true;
    318464}
  • trunk/psphot/src/psphotFindDetections.c

    r28013 r29004  
    9090    psphotVisualShowSignificance (significance, -1.0, PS_SQR(3.0*NSIGMA_PEAK));
    9191
    92     // XXX getting some strange results from significance image
    93     if (0) {
    94         psImage *lsig = (psImage *) psUnaryOp (NULL, significance, "log");
    95         psphotVisualShowSignificance (lsig, 0.0, 4.0);
    96         psFree (lsig);
    97     }   
     92    // display the log significance image
     93    psphotVisualShowLogSignificance (significance, 0.0, 4.5);
    9894
    9995    // detect the peaks in the significance image
  • trunk/psphot/src/psphotFitSet.c

    r21183 r29004  
    2424    }
    2525
     26    // Define source fitting parameters for extended source fits
     27    pmSourceFitOptions *fitOptions = pmSourceFitOptionsAlloc();
     28    fitOptions->mode          = PM_SOURCE_FIT_EXT;
     29    // XXX for now, use the defaults for the rest:
     30    // fitOptions->nIter         = fitIter;
     31    // fitOptions->tol           = fitTol;
     32    // fitOptions->poissonErrors = poisson;
     33    // fitOptions->weight        = PS_SQR(skySig);
     34
    2635    // XXX pmSourceFitSet must cache the modelFlux?
    27     pmSourceFitSet (source, modelSet, mode, maskVal);
     36    pmSourceFitSet (source, modelSet, fitOptions, maskVal);
    2837
    2938    // write out positive object
  • trunk/psphot/src/psphotFitSourcesLinear.c

    r28426 r29004  
    100100    if (!status) {
    101101        SKY_FIT_LINEAR = false;
     102    }
     103   
     104    float MIN_VALID_FLUX = psMetadataLookupF32(&status, recipe, "PSF_FIT_MIN_VALID_FLUX");
     105    if (!status) {
     106        MIN_VALID_FLUX = 1e-8;
     107    }
     108    float MAX_VALID_FLUX = psMetadataLookupF32(&status, recipe, "PSF_FIT_MAX_VALID_FLUX");
     109    if (!status) {
     110        MAX_VALID_FLUX = 1e+8;
    102111    }
    103112
     
    228237
    229238    psSparseConstraint constraint;
    230     constraint.paramMin   = 0.0;
    231     constraint.paramMax   = 1e8;
    232     constraint.paramDelta = 1e8;
     239    constraint.paramMin   = MIN_VALID_FLUX;
     240    constraint.paramMax   = MAX_VALID_FLUX;
     241    constraint.paramDelta = 1e7;
    233242
    234243    // solve for normalization terms (need include local sky?)
  • trunk/psphot/src/psphotFitSourcesLinearStack.c

    r28426 r29004  
    170170    return true;
    171171}
    172 
    173 // sort by X (ascending)
    174 int pmPhotObjSortByX (const void **a, const void **b)
    175 {
    176     pmPhotObj *objA = *(pmPhotObj **)a;
    177     pmPhotObj *objB = *(pmPhotObj **)b;
    178 
    179     psF32 fA = objA->x;
    180     psF32 fB = objB->x;
    181 
    182     psF32 diff = fA - fB;
    183     if (diff > FLT_EPSILON) return (+1);
    184     if (diff < FLT_EPSILON) return (-1);
    185     return (0);
    186 }
  • trunk/psphot/src/psphotGuessModels.c

    r28405 r29004  
    8080
    8181    // setup the PSF fit radius details
    82     psphotInitRadiusPSF (recipe, readout->analysis, psf->type);
     82    psphotInitRadiusPSF (recipe, readout);
    8383
    8484    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
  • trunk/psphot/src/psphotLoadSRCTEXT.c

    r25983 r29004  
    8484            source->peak->yf   = PAR[PM_PAR_YPOS]; // but we know the pixel coordinate
    8585
    86             source->pixWeight = 1.0;
     86            source->pixWeightNotBad = 1.0;
     87            source->pixWeightNotPoor = 1.0;
    8788            source->crNsigma  = 0.0;
    8889            source->extNsigma = 0.0;
  • trunk/psphot/src/psphotMagnitudes.c

    r28405 r29004  
    124124                return false;
    125125            }
    126 
    127 # if (0)
    128                 int nap = 0;
    129                 if (!psphotMagnitudes_Unthreaded (&nap, cells->data[j], psf, binning, backModel, backStdev, photMode, maskVal)) {
    130                     psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    131                     return false;
    132                 }
    133                 Nap += nap;
    134 # endif
    135126        }
    136127
     
    186177        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal);
    187178
    188         status = pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
     179        status = pmSourceMagnitudes (source, psf, photMode, maskVal, markVal);
    189180        if (status && isfinite(source->apMag)) Nap ++;
    190181
     
    268259            psArrayAdd(job->args, 1, cells->data[j]); // sources
    269260            PS_ARRAY_ADD_SCALAR(job->args, maskVal,  PS_TYPE_IMAGE_MASK);
     261            PS_ARRAY_ADD_SCALAR(job->args, markVal,  PS_TYPE_IMAGE_MASK);
    270262
    271263            if (!psThreadJobAddPending(job)) {
     
    304296    psArray *sources                = job->args->data[0];
    305297    psImageMaskType maskVal         = PS_SCALAR_VALUE(job->args->data[1],PS_TYPE_IMAGE_MASK_DATA);
     298    psImageMaskType markVal         = PS_SCALAR_VALUE(job->args->data[2],PS_TYPE_IMAGE_MASK_DATA);
    306299
    307300    for (int i = 0; i < sources->n; i++) {
     
    312305        if (model == NULL) {
    313306          psTrace ("psphot", 3, "fail mag : no valid model");
    314           source->pixWeight = NAN;
     307          source->pixWeightNotBad = NAN;
     308          source->pixWeightNotPoor = NAN;
    315309          continue;
    316310        }
    317311
    318         status = pmSourcePixelWeight (&source->pixWeight, model, source->maskObj, maskVal);
     312        status = pmSourcePixelWeight (&source->pixWeightNotBad, &source->pixWeightNotPoor, model, source->maskObj, maskVal, markVal);
    319313        if (!status) {
    320314          psTrace ("psphot", 3, "fail to measure pixel weight");
    321           source->pixWeight = NAN;
     315          source->pixWeightNotBad = NAN;
     316          source->pixWeightNotPoor = NAN;
    322317          continue;
    323318        }
  • trunk/psphot/src/psphotModelWithPSF.c

    r21366 r29004  
    7373
    7474    // iterate until the tolerance is reached, or give up
    75     while ((min->iter < min->maxIter) && ((min->lastDelta > min->tol) || !isfinite(min->lastDelta))) {
     75    while ((min->iter < min->maxIter) && ((min->lastDelta > min->minTol) || !isfinite(min->lastDelta))) {
    7676        psTrace("psphot", 5, "Iteration number %d.  (max iterations is %d).\n", min->iter, min->maxIter);
    77         psTrace("psphot", 5, "Last delta is %f.  Min->tol is %f.\n", min->lastDelta, min->tol);
     77        psTrace("psphot", 5, "Last delta is %f.  Min->minTol is %f.\n", min->lastDelta, min->minTol);
    7878
    7979
     
    166166    psFree(pcm);
    167167
    168     if (min->iter == min->maxIter) {
    169         psTrace("psphot", 3, "---- end (false) ----\n");
    170         return(false);
    171     }
    172 
    173     psTrace("psphot", 3, "---- end (true) ----\n");
    174     return(true);
     168    // if the last improvement was at least as good as maxTol, accept the fit:
     169    if (min->lastDelta <= min->maxTol) {
     170        psTrace("psphot", 6, "---- end (true) ----\n");
     171        return(true);
     172    }
     173    psTrace("psphot", 6, "---- end (false) ----\n");
     174    return(false);
    175175}
    176176
  • trunk/psphot/src/psphotPSFConvModel.c

    r26894 r29004  
    44// save as static values so they may be set externally
    55static psF32 PM_SOURCE_FIT_MODEL_NUM_ITERATIONS = 15;
    6 static psF32 PM_SOURCE_FIT_MODEL_TOLERANCE = 0.1;
     6static psF32 PM_SOURCE_FIT_MODEL_MIN_TOL = 0.1;
     7static psF32 PM_SOURCE_FIT_MODEL_MAX_TOL = 2.0;
    78
    89// input source has both modelPSF and modelEXT.  on successful exit, we set the
    910// modelConv to contain the fitted parameters, and the modelFlux to contain the
    1011// convolved model image.
    11 pmModel *psphotPSFConvModel (pmReadout *readout, pmSource *source, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     12
     13// XXX need to generalize this -- number of fitted parameters must be flexible based on the fitOptions
     14
     15pmModel *psphotPSFConvModel (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
    1216   
    1317    // maskVal is used to test for rejected pixels, and must include markVal
     
    9094
    9195    // set up the minimization process
    92     psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_TOLERANCE);
     96    psMinimization *myMin = psMinimizationAlloc (PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, PM_SOURCE_FIT_MODEL_MIN_TOL, PM_SOURCE_FIT_MODEL_MAX_TOL);
    9397
    9498    psImage *covar = psImageAlloc (params->n, params->n, PS_TYPE_F32);
  • trunk/psphot/src/psphotPetrosianVisual.c

    r27819 r29004  
    11# include "psphotInternal.h"
    2 # define FORCE_VISUAL 0
    32
    43// this function displays representative images as the psphot analysis progresses:
     
    5453    Graphdata graphdata;
    5554
    56     // return true;
    57     if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
     55    if (!pmVisualTestLevel("psphot.petro.byangle", 2)) return true;
    5856
    5957    if (kapa2 == -1) {
     
    10199    Graphdata graphdata;
    102100
    103     // return true;
    104     if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
     101    if (!pmVisualTestLevel("psphot.petro.radii", 2)) return true;
    105102
    106103    if (kapa == -1) {
     
    173170    KapaSection section;
    174171
    175     if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
     172    if (!pmVisualTestLevel("psphot.petro.stats", 2)) return true;
    176173
    177174    if (kapa2 == -1) {
     
    311308    Graphdata graphdata;
    312309
    313     if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
     310    if (!pmVisualTestLevel("psphot.petro.ellipse", 2)) return true;
    314311
    315312    if (kapa == -1) {
  • trunk/psphot/src/psphotRadiusChecks.c

    r28418 r29004  
    88                                        // and a per-object radius is calculated)
    99
    10 bool psphotInitRadiusPSF(const psMetadata *recipe, const psMetadata *analysis, const pmModelType type) {
     10bool psphotInitRadiusPSF(psMetadata *recipe, pmReadout *readout) {
    1111
    1212    bool status = true;
     
    1515    PSF_FIT_PADDING = psMetadataLookupF32(&status, recipe, "PSF_FIT_PADDING");
    1616
    17     PSF_FIT_RADIUS =  psMetadataLookupF32(&status, analysis, "PSF_FIT_RADIUS");
     17    PSF_FIT_RADIUS =  psMetadataLookupF32(&status, readout->analysis, "PSF_FIT_RADIUS");
    1818    if (!status) {
    1919        PSF_FIT_RADIUS = psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS");
    2020    }
    2121
    22     PSF_APERTURE =  psMetadataLookupF32(&status, analysis, "PSF_APERTURE");
     22    PSF_APERTURE =  psMetadataLookupF32(&status, readout->analysis, "PSF_APERTURE");
    2323    if (!status) {
    2424        PSF_APERTURE =  psMetadataLookupF32(&status, recipe, "PSF_APERTURE");
     
    2828
    2929    if (PSF_FIT_RADIUS == 0.0) {
    30         float gaussSigma = psMetadataLookupF32(&status, analysis, "MOMENTS_GAUSS_SIGMA");
     30        float gaussSigma = psMetadataLookupF32(&status, readout->analysis, "MOMENTS_GAUSS_SIGMA");
    3131        if (!status) {
    3232            gaussSigma = psMetadataLookupF32(&status, recipe, "MOMENTS_GAUSS_SIGMA");
     
    3737
    3838    if (PSF_APERTURE == 0.0) {
    39         float gaussSigma = psMetadataLookupF32(&status, analysis, "MOMENTS_GAUSS_SIGMA");
     39        float gaussSigma = psMetadataLookupF32(&status, readout->analysis, "MOMENTS_GAUSS_SIGMA");
    4040        if (!status) {
    4141            gaussSigma = psMetadataLookupF32(&status, recipe, "MOMENTS_GAUSS_SIGMA");
     
    122122}
    123123
     124static float EXT_FIT_SKY_SIG;
    124125static float EXT_FIT_NSIGMA;
    125126static float EXT_FIT_PADDING;
    126127static float EXT_FIT_MAX_RADIUS;
    127128
    128 bool psphotInitRadiusEXT (psMetadata *recipe, pmModelType type) {
     129bool psphotInitRadiusEXT (psMetadata *recipe, pmReadout *readout) {
    129130
    130131    bool status;
     
    134135    EXT_FIT_MAX_RADIUS = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MAX_RADIUS");
    135136
     137    float skyMean  = psMetadataLookupF32 (&status, readout->analysis, "SKY_MEAN");
     138    float skyStdev = psMetadataLookupF32 (&status, readout->analysis, "SKY_STDEV");
     139
     140    fprintf (stderr, "sky: %f +/- %f\n", skyMean, skyStdev);
     141
     142    EXT_FIT_SKY_SIG = skyStdev;
     143
    136144    return true;
    137145}
    138146
    139147// call this function whenever you (re)-define the EXT model
    140 float psphotSetRadiusEXT (pmReadout *readout, pmSource *source, psImageMaskType markVal) {
     148bool psphotSetRadiusFootprint (float *radius, pmReadout *readout, pmSource *source, psImageMaskType markVal, float factor) {
    141149
    142150    psAssert (source, "source not defined??");
     
    146154
    147155    // set the radius based on the footprint:
    148     if (!peak->footprint) goto escape;
     156    if (!peak->footprint) return false;
    149157    pmFootprint *footprint = peak->footprint;
    150     if (!footprint->spans) goto escape;
    151     if (footprint->spans->n < 1) goto escape;
     158    if (!footprint->spans) return false;
     159    if (footprint->spans->n < 1) return false;
    152160
    153161    // find the max radius
    154     float radius = 0.0;
     162    float rawRadius = 0.0;
    155163    for (int j = 0; j < footprint->spans->n; j++) {
    156164        pmSpan *span = footprint->spans->data[j];
     
    160168        float dX1 = span->x1 - peak->xf;
    161169
    162         radius = PS_MAX (radius, hypot(dY, dX0));
    163         radius = PS_MAX (radius, hypot(dY, dX1));
    164     }
    165 
    166     radius += EXT_FIT_PADDING;
    167     if (isnan(radius)) psAbort("error in radius");
    168 
    169     radius = PS_MIN (radius, EXT_FIT_MAX_RADIUS);
     170        rawRadius = PS_MAX (rawRadius, hypot(dY, dX0));
     171        rawRadius = PS_MAX (rawRadius, hypot(dY, dX1));
     172    }
     173    if (isnan(rawRadius)) return false;
     174    rawRadius = PS_MIN (factor*rawRadius + EXT_FIT_PADDING, EXT_FIT_MAX_RADIUS);
    170175
    171176    // redefine the pixels if needed
    172     pmSourceRedefinePixels (source, readout, peak->xf, peak->yf, radius);
    173 
    174     // set the mask to flag the excluded pixels
    175     psImageKeepCircle (source->maskObj, peak->xf, peak->yf, radius, "OR", markVal);
    176     return radius;
    177 
    178 escape:
    179     return NAN;
    180     // bool result = psphotCheckRadiusEXT (readout, source, model, markVal);
    181     // return result;
     177    pmSourceRedefinePixels (source, readout, peak->xf, peak->yf, rawRadius);
     178
     179    // set the mask to flag the excluded pixels
     180    psImageKeepCircle (source->maskObj, peak->xf, peak->yf, rawRadius, "OR", markVal);
     181
     182    *radius = rawRadius;
     183    return true;
    182184}
    183185
    184186// alternative EXT radius based on model guess (for use without footprints)
    185 bool psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal) {
    186 
    187     psAbort ("do not use this function");
     187bool psphotSetRadiusModel (pmModel *model, pmReadout *readout, pmSource *source, psImageMaskType markVal, bool deep) {
    188188
    189189    psF32 *PAR = model->params->data.F32;
     
    193193
    194194    // set the fit radius based on the object flux limit and the model
    195     float rawRadius = model->modelRadius (model->params, EXT_FIT_NSIGMA*moments->dSky);
    196 
    197     model->fitRadius = rawRadius + EXT_FIT_PADDING;
    198     if (isnan(model->fitRadius)) psAbort("error in radius");
     195    float flux = deep ? EXT_FIT_NSIGMA*EXT_FIT_SKY_SIG : 0.1 * model->params->data.F32[PM_PAR_I0];
     196
     197    float rawRadius = model->modelRadius (model->params, flux);
     198    if (isnan(rawRadius)) return false;
     199
     200    rawRadius = PS_MIN (rawRadius + EXT_FIT_PADDING, EXT_FIT_MAX_RADIUS);
     201    model->fitRadius = rawRadius;
    199202
    200203    // redefine the pixels if needed
    201     bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius);
     204    pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius);
    202205
    203206    // set the mask to flag the excluded pixels
    204207    psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius, "OR", markVal);
    205     return status;
    206 }
     208    return true;
     209}
  • trunk/psphot/src/psphotReadout.c

    r28398 r29004  
    5353    }
    5454
    55     // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are determined and saved on
    56     // readout->analysis XXX this function currently only works with a single PSPHOT.INPUT
     55    // load the psf model, if suppled.  FWHM_MAJ,FWHM_MIN,etc are determined and saved on
     56    // readout->analysis. XXX Note: this function currently only works with a single
     57    // PSPHOT.INPUT
    5758    if (!psphotLoadPSF (config, view)) { // ??? need to supply 2 ?
    5859        psError (PSPHOT_ERR_UNKNOWN, false, "error loading psf model");
  • trunk/psphot/src/psphotSetThreads.c

    r26894 r29004  
    1515    psFree(task);
    1616
    17     task = psThreadTaskAlloc("PSPHOT_PSF_WEIGHTS", 2);
     17    task = psThreadTaskAlloc("PSPHOT_PSF_WEIGHTS", 3);
    1818    task->function = &psphotPSFWeights_Threaded;
    1919    psThreadTaskAdd(task);
     
    3030    psFree(task);
    3131
    32     task = psThreadTaskAlloc("PSPHOT_BLEND_FIT", 9);
     32    task = psThreadTaskAlloc("PSPHOT_BLEND_FIT", 10);
    3333    task->function = &psphotBlendFit_Threaded;
     34    psThreadTaskAdd(task);
     35    psFree(task);
     36
     37    task = psThreadTaskAlloc("PSPHOT_EXTENDED_FIT", 12);
     38    task->function = &psphotExtendedSourceFits_Threaded;
    3439    psThreadTaskAdd(task);
    3540    psFree(task);
  • trunk/psphot/src/psphotSignificanceImage.c

    r28667 r29004  
    9797                smooth_im->data.F32[j][i] = 0.0;
    9898            } else {
    99                 smooth_im->data.F32[j][i] = factor * PS_SQR(value) / smooth_wt->data.F32[j][i];
     99                float v2 = value + PS_SQR(value/1000.0);
     100                smooth_im->data.F32[j][i] = factor * PS_SQR(v2) / smooth_wt->data.F32[j][i];
    100101            }
    101102        }
  • trunk/psphot/src/psphotSourceFits.c

    r26894 r29004  
    22
    33// given a source with an existing modelPSF, attempt a full PSF fit, subtract if successful
    4 // XXX this function does not call pmSourceFitModelInit : fix this?
    54
    65static int NfitPSF = 0;
     
    87static int NfitDBL = 0;
    98static int NfitEXT = 0;
     9static int NfitPCM = 0;
    1010
    1111bool psphotFitInit (int nThreads) {
     
    1818
    1919    psLogMsg ("psphot.pspsf", PS_LOG_INFO, "fitted %5d psf, %5d blend, %5d ext, %5d dbl : %6.2f sec\n",
    20              NfitPSF, NfitBlend, NfitEXT, NfitDBL, psTimerMark ("psphot.fits"));
    21     return true;
    22 }
    23 
    24 bool psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal) {
     20              NfitPSF, NfitBlend, NfitEXT, NfitDBL, psTimerMark ("psphot.fits"));
     21    return true;
     22}
     23
     24bool psphotFitBlend (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
    2525
    2626    float x, y, dR;
     27
     28    pmSourceFitOptions options = *fitOptions;
    2729
    2830    // maskVal is used to test for rejected pixels, and must include markVal
     
    3133    // if this source is not a possible blend, just fit as PSF
    3234    if ((source->blends == NULL) || (source->mode & PM_SOURCE_MODE_SATSTAR)) {
    33         bool status = psphotFitPSF (readout, source, psf, maskVal, markVal);
     35        bool status = psphotFitPSF (readout, source, psf, fitOptions, maskVal, markVal);
    3436        return status;
    3537    }
     
    9193
    9294    // fit PSF model
    93     pmSourceFitSet (source, modelSet, PM_SOURCE_FIT_PSF, maskVal);
     95    options.mode = PM_SOURCE_FIT_PSF;
     96    pmSourceFitSet (source, modelSet, &options, maskVal);
    9497
    9598    // clear the circular mask
     
    154157}
    155158
    156 bool psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal) {
     159bool psphotFitPSF (pmReadout *readout, pmSource *source, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
    157160
    158161    double chiTrend;
     162    pmSourceFitOptions options = *fitOptions;
    159163
    160164    // maskVal is used to test for rejected pixels, and must include markVal
     
    171175
    172176    // fit PSF model (set/unset the pixel mask)
    173     pmSourceFitModel (source, PSF, PM_SOURCE_FIT_PSF, maskVal);
     177    options.mode = PM_SOURCE_FIT_PSF;
     178    pmSourceFitModel (source, PSF, &options, maskVal);
    174179
    175180    if (!isfinite(PSF->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
     
    199204}
    200205
     206// save a local, static copy of the EXT model type so we don't have to lookup for each object
    201207static pmModelType modelTypeEXT;
    202208
    203 bool psphotInitLimitsEXT (psMetadata *recipe) {
     209bool psphotInitLimitsEXT (psMetadata *recipe, pmReadout *readout) {
    204210
    205211    bool status;
     
    208214    char *modelNameEXT = psMetadataLookupStr (&status, recipe, "EXT_MODEL");
    209215    modelTypeEXT = pmModelClassGetType (modelNameEXT);
    210     psphotInitRadiusEXT (recipe, modelTypeEXT);
    211 
    212     return true;
    213 }
    214 
    215 bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *newSources, pmPSF *psf, psImageMaskType maskVal, psImageMaskType markVal) {
    216 
     216
     217    psphotInitRadiusEXT (recipe, readout);
     218
     219    return true;
     220}
     221
     222bool psphotFitBlob (pmReadout *readout, pmSource *source, psArray *newSources, pmPSF *psf, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
     223
     224    float radius;
    217225    bool okEXT, okDBL;
    218226    float chiEXT, chiDBL;
     
    222230    pmModel *EXT = NULL;
    223231    psArray *DBL = NULL;
     232    pmMoments psfMoments;
    224233
    225234    // skip the source if we don't think it is extended
     235    // XXX are these robust, or do we have better info from the source-size analysis??
    226236    if (source->type == PM_SOURCE_TYPE_UNKNOWN) return false;
    227237    if (source->type == PM_SOURCE_TYPE_DEFECT) return false;
     
    229239
    230240    // set the radius based on the footprint (also sets the mask pixels)
    231     float radius = psphotSetRadiusEXT (readout, source, markVal);
     241    if (!psphotSetRadiusFootprint(&radius, readout, source, markVal, 1.0)) return false;
    232242
    233243    // XXX note that this changes the source moments that are published...
     244    // XXX all published moments should use the same measurement
    234245    // recalculate the source moments using the larger extended-source moments radius
    235246    // at this stage, skip Gaussian windowing, and do not clip pixels by S/N
    236247    // this uses the footprint to judge both radius and aperture?
    237     if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) return false;
     248    // XXX save the psf-based moments for output
     249    psfMoments = *source->moments;
     250    if (!pmSourceMoments (source, radius, 0.0, 0.5, maskVal)) {
     251      *source->moments = psfMoments;
     252      return false;
     253    }
    238254
    239255    psTrace ("psphot", 5, "trying blob...\n");
     
    244260    // this temporary source is used as a place-holder by the psphotEval functions below
    245261    tmpSrc = pmSourceAlloc ();
    246 
    247     // XXX need to handle failures better here
    248     EXT = psphotFitEXT (readout, source, modelTypeEXT, maskVal, markVal);
    249     if (!EXT) goto escape;
    250     if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape;
    251 
    252     okEXT = psphotEvalEXT (tmpSrc, EXT);
    253     chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN;
    254 
    255     // DBL will always be defined, but DBL->data[n] might not
    256     DBL = psphotFitDBL (readout, source, maskVal, markVal);
    257     if (!DBL) goto escape;
    258     if (!DBL->n) goto escape;
    259 
    260     okDBL  = psphotEvalDBL (tmpSrc, DBL->data[0]);
    261     okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]);
    262     // XXX should I keep / save the flags set in the eval functions?
     262    {
     263        // DBL will always be defined, but DBL->data[n] might not
     264        DBL = psphotFitDBL (readout, source, fitOptions, maskVal, markVal);
     265        if (!DBL) goto escape;
     266        if (!DBL->n) goto escape;
     267
     268        okDBL  = psphotEvalDBL (tmpSrc, DBL->data[0]);
     269        okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]);
     270        // XXX should I keep / save the flags set in the eval functions?
     271
     272        // correct first model chisqs for flux trend
     273        chiDBL = NAN;
     274        ONE = DBL->data[0];
     275        if (ONE) {
     276            if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
     277            chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
     278            ONE->chisqNorm = ONE->chisq / chiTrend;
     279            chiDBL = ONE->chisq / ONE->nDOF; // save chisq for double-star/galaxy comparison
     280            ONE->fitRadius = radius;
     281        }
     282
     283        // correct second model chisqs for flux trend
     284        ONE = DBL->data[1];
     285        if (ONE) {
     286            if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
     287            chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
     288            ONE->chisqNorm = ONE->chisq / chiTrend;
     289            ONE->fitRadius = radius;
     290        }
     291    }
     292
     293    {
     294        // XXX need to handle failures better here
     295        EXT = psphotFitEXT (readout, source, fitOptions, modelTypeEXT, maskVal, markVal);
     296        if (!EXT) goto escape;
     297        if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape;
     298
     299        okEXT = psphotEvalEXT (tmpSrc, EXT);
     300        chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN;
     301    }
    263302
    264303    // clear the circular mask
    265304    psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
    266 
    267     // correct first model chisqs for flux trend
    268     chiDBL = NAN;
    269     ONE = DBL->data[0];
    270     if (ONE) {
    271         if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
    272       chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
    273       ONE->chisqNorm = ONE->chisq / chiTrend;
    274       chiDBL = ONE->chisq / ONE->nDOF; // save chisq for double-star/galaxy comparison
    275     }
    276 
    277     // correct second model chisqs for flux trend
    278     ONE = DBL->data[1];
    279     if (ONE) {
    280         if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
    281       chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]);
    282       ONE->chisqNorm = ONE->chisq / chiTrend;
    283     }
    284305
    285306    psFree (tmpSrc);
     
    298319
    299320    // both models failed; reject them both
    300     // XXX -- change type flags to psf in this case and keep original moments?
     321    // XXX -- change type flags to psf in this case, and make sure we subtract it?
     322    // reset the psf moments
     323    *source->moments = psfMoments;
     324
    301325    psFree (EXT);
    302326    psFree (DBL);
     
    308332
    309333    // save new model
     334    // XXX save the correct radius...
    310335    source->modelEXT = EXT;
    311     source->modelEXT->fitRadius = radius;
    312336    source->type = PM_SOURCE_TYPE_EXTENDED;
    313337    source->mode |= PM_SOURCE_MODE_EXTMODEL;
     
    327351# endif
    328352
     353    // reset the psf moments
     354    *source->moments = psfMoments;
    329355    return true;
    330356
     
    337363    source->modelPSF = psMemIncrRefCounter (DBL->data[0]);
    338364    source->mode     |= PM_SOURCE_MODE_PAIR;
    339     source->modelPSF->fitRadius = radius;
    340365
    341366    // copy most data from the primary source (modelEXT, blends stay NULL)
    342     pmSource *newSrc = pmSourceCopy (source);
     367    pmSource *newSrc = pmSourceCopyData (source);
    343368    newSrc->modelPSF = psMemIncrRefCounter (DBL->data[1]);
    344     newSrc->modelPSF->fitRadius = radius;
    345369
    346370    // build cached models and subtract
     
    365389# endif
    366390
     391    // reset the (original) psf moments
     392    *source->moments = psfMoments;
     393    *newSrc->moments = psfMoments;
     394
    367395    psArrayAdd (newSources, 100, newSrc);
    368396    psFree (newSrc);
     
    371399
    372400escape:
     401    // reset the psf moments
     402    *source->moments = psfMoments;
    373403    psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
    374404    psFree (tmpSrc);
     
    379409
    380410// fit a double PSF source to an extended blob
    381 psArray *psphotFitDBL (pmReadout *readout, pmSource *source, psImageMaskType maskVal, psImageMaskType markVal) {
     411psArray *psphotFitDBL (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
    382412
    383413    float dx, dy;
     
    387417    psEllipseMoments moments;
    388418    psArray *modelSet;
     419
     420    pmSourceFitOptions options = *fitOptions;
    389421
    390422    NfitDBL ++;
     
    403435    axes = psEllipseMomentsToAxes (moments, 20.0);
    404436
     437    if (isnan(axes.major)) return NULL;
     438    if (isnan(axes.minor)) return NULL;
     439    if (isnan(axes.theta)) return NULL;
     440
    405441    // XXX this is really arbitrary: 4 pixel separation?
    406442    dx = 2 * cos (axes.theta);
     
    426462
    427463    // fit PSF model (set/unset the pixel mask)
    428     pmSourceFitSet (source, modelSet, PM_SOURCE_FIT_PSF, maskVal);
     464    options.mode = PM_SOURCE_FIT_PSF;
     465    pmSourceFitSet (source, modelSet, &options, maskVal);
    429466    return (modelSet);
    430467}
    431468
    432 pmModel *psphotFitEXT (pmReadout *readout, pmSource *source, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal) {
     469pmModel *psphotFitEXT (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal) {
     470
     471    if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) {
     472        psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
     473    }
     474
     475    pmSourceFitOptions options = *fitOptions;
    433476
    434477    NfitEXT ++;
     
    438481
    439482    // use the source moments, etc to guess basic model parameters
    440     pmModel *EXT = pmSourceModelGuess (source, modelType);
    441     if (!EXT) {
     483    pmModel *model = pmSourceModelGuess (source, modelType);
     484    if (!model) {
    442485        psTrace ("psphot", 5, "failed to generate a model for source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
    443486        return NULL;
    444487    }
    445488
     489    // for sersic models, use a grid search to choose an index, then float the params there
     490    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
     491        // for the test fits, use a somewhat smaller radius
     492        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     493        psphotFitSersicIndex (model, readout, source, fitOptions, maskVal, markVal);
     494    }
     495
     496    if (!psphotSetRadiusModel (model, readout, source, markVal, true)) {
     497        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 1.0);
     498    }
     499
     500    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
     501        options.mode = PM_SOURCE_FIT_NO_INDEX;
     502    } else {
     503        options.mode = PM_SOURCE_FIT_EXT;
     504    }
     505
     506    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
     507    pmSourceFitModel (source, model, &options, maskVal);
     508    fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     509
     510    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0);
     511    return (model);
     512}
     513
     514pmModel *psphotFitPCM (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     515
    446516    if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) {
    447517        psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
    448518    }
    449519
     520    pmSourceFitOptions options = *fitOptions;
     521
     522    NfitPCM ++;
     523
     524    // maskVal is used to test for rejected pixels, and must include markVal
     525    maskVal |= markVal;
     526
     527    // allocate the model
     528    pmModel *model = pmModelAlloc(modelType);
     529    if (!model) {
     530        return NULL;
     531    }
     532
     533    pmPCMdata *pcm = pmPCMinit (source, &options, model, maskVal, psfSize);
     534    if (!pcm) {
     535        psTrace ("psphot", 5, "failed to generate a model for source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
     536        model->flags |= PM_MODEL_STATUS_BADARGS; // XXX this is probably already set in pmPCMinit
     537        return model;
     538    }
     539
     540    // use the source moments, etc to guess basic model parameters
     541    if (!pmSourceModelGuessPCM (pcm, source, maskVal, markVal)) {
     542        psFree (pcm);
     543        model->flags |= PM_MODEL_STATUS_BADARGS;
     544        return model;
     545    }
     546
     547    // for sersic models, use a grid search to choose an index, then float the params there
     548    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
     549        // for the test fits, use a somewhat smaller radius
     550        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     551
     552        if (!psphotFitSersicIndexPCM (pcm, readout, source, fitOptions, maskVal, markVal, psfSize)) {
     553            model->flags |= PM_MODEL_STATUS_BADARGS;
     554            return model;
     555        }
     556    }
     557
     558    if (!psphotSetRadiusModel (model, readout, source, markVal, true)) {
     559        psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 1.0);
     560    }
     561
     562    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
     563        options.mode = PM_SOURCE_FIT_NO_INDEX;
     564    } else {
     565        options.mode = PM_SOURCE_FIT_EXT;
     566    }
     567    // update the pcm elements if we have changed the circumstance (options.mode or source->pixels)
     568    pmPCMupdate(pcm, source, &options, model);
     569
     570    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
     571    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     572    fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     573
     574    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0);
     575    psFree (pcm);
     576
     577    return model;
     578}
     579
     580// note that these should be 1/2n of the standard sersic index
     581float indexGuess[] = {0.5, 0.33, 0.25, 0.167, 0.125, 0.083};
     582# define N_INDEX_GUESS 6
     583
     584// A sersic model is very sensitive to the index.  attempt to find the index first by grid search in just the index
     585// for a sersic model, attempt to fit just the index and normalization with a modest number of iterations
     586bool psphotFitSersicIndex (pmModel *model, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal) {
     587
     588    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     589
     590    pmSourceFitOptions options = *fitOptions;
     591   
    450592    // fit EXT (not PSF) model (set/unset the pixel mask)
    451     pmSourceFitModel (source, EXT, PM_SOURCE_FIT_EXT, maskVal);
    452     return (EXT);
    453 }
     593    options.mode = PM_SOURCE_FIT_NO_INDEX;
     594    options.nIter = 4;
     595
     596    int iMin = -1;
     597    float xMin = NAN;
     598    float chiSquare[N_INDEX_GUESS];
     599
     600    for (int i = 0; i < N_INDEX_GUESS; i++) {
     601        model->params->data.F32[PM_PAR_7] = indexGuess[i];
     602
     603        if (!model->modelGuess(model, source)) {
     604            model->flags |= PM_MODEL_STATUS_BADARGS;
     605            return false;
     606        }
     607
     608        // each time we change the model guess, we need to adjust the radius
     609        // XXX this did not work : we do not need such a large radius -- just uses moments-based radius
     610        if (false && !psphotSetRadiusModel (model, readout, source, markVal, false)) {
     611            psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     612        }
     613       
     614        pmSourceFitModel (source, model, &options, maskVal);
     615        fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     616
     617        chiSquare[i] = model->chisqNorm;
     618        if (i == 0) {
     619            xMin = chiSquare[i];
     620            iMin = i;
     621        } else {
     622            if (chiSquare[i] < xMin) {
     623                xMin = chiSquare[i];
     624                iMin = i;
     625            }
     626        }
     627    }
     628    assert (iMin >= 0);
     629
     630    model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it
     631    model->params->data.F32[PM_PAR_7] = indexGuess[iMin];
     632    model->modelGuess(model, source);
     633
     634    // each time we change the model guess, we need to adjust the radius
     635    // if (!psphotSetRadiusModel (model, readout, source, markVal, true)) {
     636    //  psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal);
     637    // }
     638
     639    return true;
     640}
     641
     642// A sersic model is very sensitive to the index.  attempt to find the index first by grid search in just the index
     643// for a sersic model, attempt to fit just the index and normalization with a modest number of iterations
     644bool psphotFitSersicIndexPCM (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     645
     646    pmModel *model = pcm->modelConv;
     647
     648    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     649
     650    pmSourceFitOptions options = *fitOptions;
     651   
     652    // fit EXT (not PSF) model (set/unset the pixel mask)
     653    options.mode = PM_SOURCE_FIT_NO_INDEX;
     654    options.nIter = 4;
     655
     656    // update the pcm elements if we have changed the circumstance (here, options.mode)
     657    pmPCMupdate(pcm, source, &options, model);
     658
     659    int iMin = -1;
     660    float xMin = NAN;
     661    float chiSquare[N_INDEX_GUESS];
     662
     663    for (int i = 0; i < N_INDEX_GUESS; i++) {
     664        model->params->data.F32[PM_PAR_7] = indexGuess[i];
     665       
     666        if (!model->modelGuess(model, source)) {
     667            model->flags |= PM_MODEL_STATUS_BADARGS;
     668            return false;
     669        }
     670
     671        // each time we change the model guess, we need to adjust the radius
     672        // XXX this did not work : we do not need such a large radius -- just uses moments-based radius
     673        if (false && !psphotSetRadiusModel (model, readout, source, markVal, false)) {
     674            psphotSetRadiusFootprint(&model->fitRadius, readout, source, markVal, 0.5);
     675        }
     676       
     677        pmSourceFitModel (source, model, &options, maskVal);
     678        fprintf (stderr, "chisq: %f, nIter: %d, radius: %f, npix: %d\n", model->chisqNorm, model->nIter, model->fitRadius, model->nPix);
     679
     680        // pmSourceModelGuessPCM(pcm, source, maskVal, markVal);
     681        // pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     682
     683        chiSquare[i] = model->chisq;
     684        if (i == 0) {
     685            xMin = chiSquare[i];
     686            iMin = i;
     687        } else {
     688            if (chiSquare[i] < xMin) {
     689                xMin = chiSquare[i];
     690                iMin = i;
     691            }
     692        }
     693    }
     694    assert (iMin >= 0);
     695   
     696    model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it
     697    model->params->data.F32[PM_PAR_7] = indexGuess[iMin];
     698
     699    pmSourceModelGuessPCM(pcm, source, maskVal, markVal);
     700
     701    return true;
     702}
  • trunk/psphot/src/psphotSourceSize.c

    r28013 r29004  
    11# include "psphotInternal.h"
    22# include <gsl/gsl_sf_gamma.h>
     3
     4# define KRON 1
    35
    46typedef struct {
     
    168170    psVector *ApErr = psVectorAllocEmpty (100, PS_TYPE_F32);
    169171
     172    psImageMaskType markVal = options->markVal;
    170173    psImageMaskType maskVal = options->maskVal | options->markVal;
    171174
     
    189192
    190193        // XXX can we test if psfMag is set and calculate only if needed?
    191         pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
     194        pmSourceMagnitudes (source, psf, photMode, maskVal, markVal);
    192195
    193196        // clear the mask bit
     
    197200        pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal);
    198201
     202        // XXX test: switch to kron flux
     203# if (KRON)
     204        float apMag = -2.5*log10(source->moments->KronFlux);
     205# else
    199206        float apMag = -2.5*log10(source->moments->Sum);
     207# endif
    200208        float dMag = source->psfMag - apMag;
    201209
     
    288296    pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_WEIGHT;
    289297
     298    psImageMaskType markVal = options->markVal;
    290299    psImageMaskType maskVal = options->maskVal | options->markVal;
    291300
     
    335344
    336345        // XXX can we test if psfMag is set and calculate only if needed?
    337         pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
     346        pmSourceMagnitudes (source, psf, photMode, maskVal, markVal);
    338347
    339348        // clear the mask bit
     
    343352        pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal);
    344353
     354# if (KRON)
     355        float apMag = -2.5*log10(source->moments->KronFlux);
     356# else
    345357        float apMag = -2.5*log10(source->moments->Sum);
     358# endif
    346359        float dMag = source->psfMag - apMag;
    347360
    348361        // set nSigma to include both systematic and poisson error terms
    349362        // XXX the 'poisson error' contribution for size is probably wrong...
    350         float nSigmaMAG = (dMag - options->ApResid) / hypot(source->errMag, options->ApSysErr);
     363        // XXX add in a hard floor on the Ap Sys Err (to be a bit generous)
     364        float nSigmaMAG = (dMag - options->ApResid) / hypot(source->errMag, hypot(options->ApSysErr, 0.025));
    351365        float nSigmaMXX = (Mxx - psfClump->X) / hypot(psfClump->dX, psfClump->X*psfClump->X*source->errMag);
    352366        float nSigmaMYY = (Myy - psfClump->Y) / hypot(psfClump->dY, psfClump->Y*psfClump->Y*source->errMag);
    353367
    354         // partially-masked sources are more likely to be mis-measured PSFs
     368        fprintf (stderr, "%f %f : Mxx: %f, Myy: %f, dx: %f, dy: %f, psfMag: %f, apMag: %f, dMag: %f, errMag: %f, nSigmaMag: %f, nSigmaMxx: %f, nSigmaMyy: %f\n",
     369                 source->peak->xf, source->peak->yf, Mxx, Myy, source->peak->xf - source->moments->Mx, source->peak->yf - source->moments->My,
     370                 source->psfMag, apMag, dMag, source->errMag, nSigmaMAG, nSigmaMXX, nSigmaMYY);
     371
     372        // XXX double check on ths stuff!! partially-masked sources are more likely to be mis-measured PSFs
    355373        float sizeBias = 1.0;
    356         if (source->pixWeight < 0.9) {
     374        if (source->pixWeightNotBad < 0.9) {
     375            sizeBias = 3.0;
     376        }
     377        if (source->pixWeightNotPoor < 0.9) {
    357378            sizeBias = 3.0;
    358379        }
     
    389410        if (isCR) {
    390411            psTrace("psphotSourceClassRegion.CR",4,"CLASS: %g %g %f\t%g %g  %g %g  %g %g\t%g %g\t%g CR\t%g %g\n",
    391                     source->peak->xf,source->peak->yf,source->pixWeight,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG,
     412                    source->peak->xf,source->peak->yf,source->pixWeightNotBad,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG,
    392413                    options->nSigmaApResid,sizeBias*options->nSigmaMoments);
    393414            source->mode |= PM_SOURCE_MODE_DEFECT;
  • trunk/psphot/src/psphotSourceStats.c

    r28419 r29004  
    11# include "psphotInternal.h"
     2void pmSourceMomentsSetVerbose(bool state);
    23
    34// convert detections to sources and measure their basic properties (moments, local sky, sky
     
    369370    maskVal |= markVal;
    370371
     372    // XXX test : pmSourceMomentsSetVerbose(true);
     373
    371374    // threaded measurement of the sources moments
    372375    int Nfail = 0;
     
    408411        // measure basic source moments (no S/N clipping on input pixels)
    409412        status = pmSourceMoments (source, RADIUS, SIGMA, 0.0, maskVal);
     413        // XXX moments / aperture test:
     414        if (0) {
     415            // clear the mask bit and set the circular mask pixels
     416            psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
     417            psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, 4.0*source->moments->Mrf, "OR", markVal);
     418           
     419            float apMag = NAN;
     420            pmSourcePhotometryAper (&apMag, NULL, source->pixels, source->maskObj, maskVal);
     421            fprintf (stderr, "apMag: %f, kronMag: %f\n", apMag, -2.5*log10(source->moments->KronFlux));
     422
     423            // clear the mask bit
     424            psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
     425        }           
    410426        if (status) {
    411427            Nmoments ++;
     
    502518        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX);
    503519        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
    504         psphotVisualPlotMoments (recipe, analysis, sources);
     520        if (pmVisualTestLevel("psphot.moments.full", 2)) {
     521            psphotVisualPlotMoments (recipe, analysis, sources);
     522        }
    505523#endif
    506524
  • trunk/psphot/src/psphotVisual.c

    r28128 r29004  
    6666    int myKapa = psphotKapaChannel (channel);
    6767    if (!(strcasecmp (overlay, "all"))) {
    68       KiiEraseOverlay (myKapa, "red");
    69       KiiEraseOverlay (myKapa, "green");
    70       KiiEraseOverlay (myKapa, "blue");
    71       KiiEraseOverlay (myKapa, "yellow");
    72       return true;
     68        KiiEraseOverlay (myKapa, "red");
     69        KiiEraseOverlay (myKapa, "green");
     70        KiiEraseOverlay (myKapa, "blue");
     71        KiiEraseOverlay (myKapa, "yellow");
     72        return true;
    7373    }
    7474    KiiEraseOverlay (myKapa, overlay);
     
    182182bool psphotVisualShowImage (pmReadout *readout) {
    183183
    184     if (!pmVisualIsVisual()) return true;
     184    if (!pmVisualTestLevel("psphot.image", 1)) return true;
    185185
    186186    int kapa = psphotKapaChannel (1);
     
    199199    pmReadout *backgnd;
    200200
    201     if (!DEBUG && !pmVisualIsVisual()) return true;
     201    if (!pmVisualTestLevel("psphot.image.backgnd", 2)) return true;
    202202
    203203    int kapa = psphotKapaChannel (1);
     
    208208
    209209    if (file->mode == PM_FPA_MODE_INTERNAL) {
    210         backgnd = file->readout;
     210        backgnd = file->readout;
    211211    } else {
    212         backgnd = pmFPAviewThisReadout (view, file->fpa);
     212        backgnd = pmFPAviewThisReadout (view, file->fpa);
    213213    }
    214214
     
    222222bool psphotVisualShowSignificance (psImage *image, float min, float max) {
    223223
    224     if (!DEBUG && !pmVisualIsVisual()) return true;
     224    if (!pmVisualTestLevel("psphot.image.signif", 2)) return true;
    225225
    226226    int kapa = psphotKapaChannel (1);
     
    233233}
    234234
     235bool psphotVisualShowLogSignificance (psImage *image, float min, float max) {
     236
     237    if (!pmVisualTestLevel("psphot.image.logsignif", 3)) return true;
     238
     239    int kapa = psphotKapaChannel (1);
     240    if (kapa == -1) return false;
     241
     242    psImage *lsig = (psImage *) psUnaryOp (NULL, image, "log");
     243    psphotVisualRangeImage (kapa, lsig, "log-signif", 2, min, max);
     244    psFree (lsig);
     245
     246    pmVisualAskUser(NULL);
     247    return true;
     248}
     249
     250// XXX : requires psphotVisualShowImage
    235251bool psphotVisualShowPeaks (pmDetections *detections) {
    236252
     
    238254    KiiOverlay *overlay;
    239255
    240     if (!DEBUG && !pmVisualIsVisual()) return true;
     256    if (!pmVisualTestLevel("psphot.objects.peaks", 1)) return true;
    241257
    242258    int kapa = psphotKapaChannel (1);
     
    252268    for (int i = 0; i < peaks->n; i++) {
    253269
    254         pmPeak *peak = peaks->data[i];
    255         if (peak == NULL) continue;
    256 
    257         overlay[Noverlay].type = KII_OVERLAY_BOX;
    258         overlay[Noverlay].x = peak->xf;
    259         overlay[Noverlay].y = peak->yf;
    260         overlay[Noverlay].dx = 2.0;
    261         overlay[Noverlay].dy = 2.0;
    262         overlay[Noverlay].angle = 0.0;
    263         overlay[Noverlay].text = NULL;
    264         Noverlay ++;
     270        pmPeak *peak = peaks->data[i];
     271        if (peak == NULL) continue;
     272
     273        overlay[Noverlay].type = KII_OVERLAY_BOX;
     274        overlay[Noverlay].x = peak->xf;
     275        overlay[Noverlay].y = peak->yf;
     276        overlay[Noverlay].dx = 2.0;
     277        overlay[Noverlay].dy = 2.0;
     278        overlay[Noverlay].angle = 0.0;
     279        overlay[Noverlay].text = NULL;
     280        Noverlay ++;
    265281    }
    266282
     
    272288}
    273289
     290// XXX : requires psphotVisualShowImage
    274291bool psphotVisualShowFootprints (pmDetections *detections) {
    275292
     
    277294    KiiOverlay *overlay;
    278295
    279     if (!DEBUG && !pmVisualIsVisual()) return true;
     296    if (!pmVisualTestLevel("psphot.objects.footprints", 3)) return true;
    280297
    281298    int kapa = psphotKapaChannel (1);
     
    292309    for (int i = 0; i < footprints->n; i++) {
    293310
    294         pmSpan *span = NULL;
    295 
    296         pmFootprint *footprint = footprints->data[i];
    297         if (footprint == NULL) continue;
    298         if (footprint->spans == NULL) continue;
    299         if (footprint->spans->n < 1) continue;
    300 
    301         // draw the top
    302         // XXX need to allow top (and bottom) to have more than one span
    303         span = footprint->spans->data[0];
    304         overlay[Noverlay].type = KII_OVERLAY_LINE;
    305         overlay[Noverlay].x = span->x0;
    306         overlay[Noverlay].y = span->y;
    307         overlay[Noverlay].dx = span->x1 - span->x0;
    308         overlay[Noverlay].dy = 0;
    309         overlay[Noverlay].angle = 0.0;
    310         overlay[Noverlay].text = NULL;
    311         Noverlay ++;
    312         CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    313 
    314         int ys = span->y;
    315         int x0s = span->x0;
    316         int x1s = span->x1;
    317 
    318         // draw the outer span edges
    319         for (int j = 1; j < footprint->spans->n; j++) {
    320             pmSpan *span1 = footprint->spans->data[j];
    321 
    322             int ye = span1->y;
    323             int x0e = span1->x0;
    324             int x1e = span1->x1;
    325 
    326             // we cannot have two discontinuous spans on the top or bottom, right? (no, probably not right)
    327             // find all of the spans in this row and generate x0e, x01:
    328             for (int k = j + 1; k < footprint->spans->n; k++) {
    329                 pmSpan *span2 = footprint->spans->data[k];
    330                 if (span2->y > span1->y) break;
    331                 x0e = PS_MIN (x0e, span2->x0);
    332                 x1e = PS_MAX (x1e, span2->x1);
    333                 j++;
    334             }
    335 
    336             overlay[Noverlay].type = KII_OVERLAY_LINE;
    337             overlay[Noverlay].x = x0s;
    338             overlay[Noverlay].y = ys;
    339             overlay[Noverlay].dx = x0e - x0s;
    340             overlay[Noverlay].dy = ye - ys;
    341             overlay[Noverlay].angle = 0.0;
    342             overlay[Noverlay].text = NULL;
    343             Noverlay ++;
    344             CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    345 
    346             overlay[Noverlay].type = KII_OVERLAY_LINE;
    347             overlay[Noverlay].x = x1s;
    348             overlay[Noverlay].y = ys;
    349             overlay[Noverlay].dx = x1e - x1s;
    350             overlay[Noverlay].dy = ye - ys;
    351             overlay[Noverlay].angle = 0.0;
    352             overlay[Noverlay].text = NULL;
    353             Noverlay ++;
    354             CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    355 
    356             ys = ye;
    357             x0s = x0e;
    358             x1s = x1e;
    359         }
    360 
    361         // draw the bottom
    362         span = footprint->spans->data[footprint->spans->n - 1];
    363         overlay[Noverlay].type = KII_OVERLAY_LINE;
    364         overlay[Noverlay].x = span->x0;
    365         overlay[Noverlay].y = span->y;
    366         overlay[Noverlay].dx = span->x1 - span->x0;
    367         overlay[Noverlay].dy = 0;
    368         overlay[Noverlay].angle = 0.0;
    369         overlay[Noverlay].text = NULL;
    370         Noverlay ++;
    371         CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     311        pmSpan *span = NULL;
     312
     313        pmFootprint *footprint = footprints->data[i];
     314        if (footprint == NULL) continue;
     315        if (footprint->spans == NULL) continue;
     316        if (footprint->spans->n < 1) continue;
     317
     318        // draw the top
     319        // XXX need to allow top (and bottom) to have more than one span
     320        span = footprint->spans->data[0];
     321        overlay[Noverlay].type = KII_OVERLAY_LINE;
     322        overlay[Noverlay].x = span->x0;
     323        overlay[Noverlay].y = span->y;
     324        overlay[Noverlay].dx = span->x1 - span->x0;
     325        overlay[Noverlay].dy = 0;
     326        overlay[Noverlay].angle = 0.0;
     327        overlay[Noverlay].text = NULL;
     328        Noverlay ++;
     329        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     330
     331        int ys = span->y;
     332        int x0s = span->x0;
     333        int x1s = span->x1;
     334
     335        // draw the outer span edges
     336        for (int j = 1; j < footprint->spans->n; j++) {
     337            pmSpan *span1 = footprint->spans->data[j];
     338
     339            int ye = span1->y;
     340            int x0e = span1->x0;
     341            int x1e = span1->x1;
     342
     343            // we cannot have two discontinuous spans on the top or bottom, right? (no, probably not right)
     344            // find all of the spans in this row and generate x0e, x01:
     345            for (int k = j + 1; k < footprint->spans->n; k++) {
     346                pmSpan *span2 = footprint->spans->data[k];
     347                if (span2->y > span1->y) break;
     348                x0e = PS_MIN (x0e, span2->x0);
     349                x1e = PS_MAX (x1e, span2->x1);
     350                j++;
     351            }
     352
     353            overlay[Noverlay].type = KII_OVERLAY_LINE;
     354            overlay[Noverlay].x = x0s;
     355            overlay[Noverlay].y = ys;
     356            overlay[Noverlay].dx = x0e - x0s;
     357            overlay[Noverlay].dy = ye - ys;
     358            overlay[Noverlay].angle = 0.0;
     359            overlay[Noverlay].text = NULL;
     360            Noverlay ++;
     361            CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     362
     363            overlay[Noverlay].type = KII_OVERLAY_LINE;
     364            overlay[Noverlay].x = x1s;
     365            overlay[Noverlay].y = ys;
     366            overlay[Noverlay].dx = x1e - x1s;
     367            overlay[Noverlay].dy = ye - ys;
     368            overlay[Noverlay].angle = 0.0;
     369            overlay[Noverlay].text = NULL;
     370            Noverlay ++;
     371            CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     372
     373            ys = ye;
     374            x0s = x0e;
     375            x1s = x1e;
     376        }
     377
     378        // draw the bottom
     379        span = footprint->spans->data[footprint->spans->n - 1];
     380        overlay[Noverlay].type = KII_OVERLAY_LINE;
     381        overlay[Noverlay].x = span->x0;
     382        overlay[Noverlay].y = span->y;
     383        overlay[Noverlay].dx = span->x1 - span->x0;
     384        overlay[Noverlay].dy = 0;
     385        overlay[Noverlay].angle = 0.0;
     386        overlay[Noverlay].text = NULL;
     387        Noverlay ++;
     388        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    372389    }
    373390
     
    379396}
    380397
     398// XXX : requires psphotVisualShowImage
    381399bool psphotVisualShowMoments (psArray *sources) {
    382400
     
    387405    psEllipseAxes axes;
    388406
    389     if (!DEBUG && !pmVisualIsVisual()) return true;
     407    if (!pmVisualTestLevel("psphot.objects.moments", 2)) return true;
    390408
    391409    int kapa = psphotKapaChannel (1);
     
    401419    for (int i = 0; i < sources->n; i++) {
    402420
    403         pmSource *source = sources->data[i];
    404         if (source == NULL) continue;
    405 
    406         pmMoments *moments = source->moments;
    407         if (moments == NULL) continue;
    408 
    409         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    410         overlay[Noverlay].x = moments->Mx;
    411         overlay[Noverlay].y = moments->My;
    412 
    413         emoments.x2 = moments->Mxx;
    414         emoments.xy = moments->Mxy;
    415         emoments.y2 = moments->Myy;
    416 
    417         axes = psEllipseMomentsToAxes (emoments, 20.0);
    418 
    419         overlay[Noverlay].dx = 2.0*axes.major;
    420         overlay[Noverlay].dy = 2.0*axes.minor;
    421 
    422         overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
    423 
    424         overlay[Noverlay].text = NULL;
    425         Noverlay ++;
     421        pmSource *source = sources->data[i];
     422        if (source == NULL) continue;
     423
     424        pmMoments *moments = source->moments;
     425        if (moments == NULL) continue;
     426
     427        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     428        overlay[Noverlay].x = moments->Mx;
     429        overlay[Noverlay].y = moments->My;
     430
     431        emoments.x2 = moments->Mxx;
     432        emoments.xy = moments->Mxy;
     433        emoments.y2 = moments->Myy;
     434
     435        axes = psEllipseMomentsToAxes (emoments, 20.0);
     436
     437        overlay[Noverlay].dx = 2.0*axes.major;
     438        overlay[Noverlay].dy = 2.0*axes.minor;
     439
     440        overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
     441
     442        overlay[Noverlay].text = NULL;
     443        Noverlay ++;
    426444    }
    427445
     
    439457    KapaSection section;
    440458
    441     if (!DEBUG && !pmVisualIsVisual()) return true;
     459    if (!pmVisualTestLevel("psphot.moments", 1)) return true;
    442460
    443461    int myKapa = psphotKapaChannel (2);
     
    456474    float Ymin = 1000.0, Ymax = 0.0;
    457475    {
    458         int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    459         for (int n = 0; n < nRegions; n++) {
    460 
    461             char regionName[64];
    462             snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
    463             psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
    464 
    465             float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
    466             float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
    467             float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
    468             float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
    469 
    470             float X0 = psfX - 4.0*psfdX;
    471             float X1 = psfX + 4.0*psfdX;
    472             float Y0 = psfY - 4.0*psfdY;
    473             float Y1 = psfY + 4.0*psfdY;
    474 
    475             if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
    476             if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
    477             if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
    478             if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
    479         }
     476        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     477        for (int n = 0; n < nRegions; n++) {
     478
     479            char regionName[64];
     480            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     481            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     482
     483            float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     484            float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     485            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     486            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     487
     488            float X0 = psfX - 4.0*psfdX;
     489            float X1 = psfX + 4.0*psfdX;
     490            float Y0 = psfY - 4.0*psfdY;
     491            float Y1 = psfY + 4.0*psfdY;
     492
     493            if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
     494            if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
     495            if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
     496            if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
     497        }
    480498    }
    481499    Xmin = PS_MAX(Xmin, -0.1);
     
    498516    int nF = 0;
    499517    for (int i = 0; i < sources->n; i++) {
    500         pmSource *source = sources->data[i];
    501         if (source->moments == NULL)
    502             continue;
    503 
    504         xFaint->data.F32[nF] = source->moments->Mxx;
    505         yFaint->data.F32[nF] = source->moments->Myy;
    506         mFaint->data.F32[nF] = -2.5*log10(source->moments->Sum);
    507         nF++;
    508 
    509         // XXX make this a user-defined cutoff
    510         if (source->moments->SN < SN_LIM)
    511             continue;
    512 
    513         xBright->data.F32[nB] = source->moments->Mxx;
    514         yBright->data.F32[nB] = source->moments->Myy;
    515         mBright->data.F32[nB] = -2.5*log10(source->moments->Sum);
    516         nB++;
     518        pmSource *source = sources->data[i];
     519        if (source->moments == NULL)
     520            continue;
     521
     522        xFaint->data.F32[nF] = source->moments->Mxx;
     523        yFaint->data.F32[nF] = source->moments->Myy;
     524        mFaint->data.F32[nF] = -2.5*log10(source->moments->Sum);
     525        nF++;
     526
     527        // XXX make this a user-defined cutoff
     528        if (source->moments->SN < SN_LIM)
     529            continue;
     530
     531        xBright->data.F32[nB] = source->moments->Mxx;
     532        yBright->data.F32[nB] = source->moments->Myy;
     533        mBright->data.F32[nB] = -2.5*log10(source->moments->Sum);
     534        nB++;
    517535    }
    518536    xFaint->n = nF;
     
    652670    // draw N circles to outline the clumps
    653671    {
    654         KapaSelectSection (myKapa, "MxxMyy");
    655 
    656         // draw a circle centered on psfX,Y with size of the psf limit
    657         psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
    658         psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
    659 
    660         int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    661         float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
    662 
    663         graphdata.color = KapaColorByName ("blue");
    664         graphdata.style = 0;
    665 
    666         graphdata.xmin = Xmin;
    667         graphdata.ymin = Ymin;
    668         graphdata.xmax = Xmax;
    669         graphdata.ymax = Ymax;
    670         KapaSetLimits (myKapa, &graphdata);
    671 
    672         for (int n = 0; n < nRegions; n++) {
    673 
    674             char regionName[64];
    675             snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
    676             psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
    677 
    678             float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
    679             float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
    680             float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
    681             float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
    682             float Rx = psfdX * PSF_CLUMP_NSIGMA;
    683             float Ry = psfdY * PSF_CLUMP_NSIGMA;
    684 
    685             for (int i = 0; i < xLimit->n; i++) {
    686                 xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
    687                 yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
    688             }
    689             KapaPrepPlot (myKapa, xLimit->n, &graphdata);
    690             KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
    691             KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
    692         }
    693         psFree (xLimit);
    694         psFree (yLimit);
     672        KapaSelectSection (myKapa, "MxxMyy");
     673
     674        // draw a circle centered on psfX,Y with size of the psf limit
     675        psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
     676        psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
     677
     678        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     679        float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
     680
     681        graphdata.color = KapaColorByName ("blue");
     682        graphdata.style = 0;
     683
     684        graphdata.xmin = Xmin;
     685        graphdata.ymin = Ymin;
     686        graphdata.xmax = Xmax;
     687        graphdata.ymax = Ymax;
     688        KapaSetLimits (myKapa, &graphdata);
     689
     690        for (int n = 0; n < nRegions; n++) {
     691
     692            char regionName[64];
     693            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     694            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     695
     696            float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     697            float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     698            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     699            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     700            float Rx = psfdX * PSF_CLUMP_NSIGMA;
     701            float Ry = psfdY * PSF_CLUMP_NSIGMA;
     702
     703            for (int i = 0; i < xLimit->n; i++) {
     704                xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
     705                yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
     706            }
     707            KapaPrepPlot (myKapa, xLimit->n, &graphdata);
     708            KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
     709            KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
     710        }
     711        psFree (xLimit);
     712        psFree (yLimit);
    695713    }
    696714
     
    721739    for (int i = 0; i < sources->n; i++) {
    722740
    723         pmSource *source = sources->data[i];
    724         if (source == NULL) continue;
    725 
    726         if (source->type != type) continue;
    727         if (mode && !(source->mode & mode)) continue;
    728 
    729         pmMoments *moments = source->moments;
    730         if (moments == NULL) continue;
    731 
    732         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    733         overlay[Noverlay].x = moments->Mx;
    734         overlay[Noverlay].y = moments->My;
    735 
    736         emoments.x2 = moments->Mxx;
    737         emoments.y2 = moments->Myy;
    738         emoments.xy = moments->Mxy;
    739 
    740         axes = psEllipseMomentsToAxes (emoments, 20.0);
    741 
    742         overlay[Noverlay].dx = 2.0*axes.major;
    743         overlay[Noverlay].dy = 2.0*axes.minor;
    744         overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
    745         overlay[Noverlay].text = NULL;
    746         Noverlay ++;
     741        pmSource *source = sources->data[i];
     742        if (source == NULL) continue;
     743
     744        if (source->type != type) continue;
     745        if (mode && !(source->mode & mode)) continue;
     746
     747        pmMoments *moments = source->moments;
     748        if (moments == NULL) continue;
     749
     750        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     751        overlay[Noverlay].x = moments->Mx;
     752        overlay[Noverlay].y = moments->My;
     753
     754        emoments.x2 = moments->Mxx;
     755        emoments.y2 = moments->Myy;
     756        emoments.xy = moments->Mxy;
     757
     758        axes = psEllipseMomentsToAxes (emoments, 20.0);
     759
     760        overlay[Noverlay].dx = 2.0*axes.major;
     761        overlay[Noverlay].dy = 2.0*axes.minor;
     762        overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
     763        overlay[Noverlay].text = NULL;
     764        Noverlay ++;
    747765    }
    748766
     
    753771}
    754772
     773// XXX : requires psphotVisualShowImage
    755774bool psphotVisualShowRoughClass (psArray *sources) {
    756775
    757     if (!DEBUG && !pmVisualIsVisual()) return true;
     776    if (!pmVisualTestLevel("psphot.objects.size", 3)) return true;
    758777
    759778    int myKapa = psphotKapaChannel (1);
     
    776795bool psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf) {
    777796
    778     if (!DEBUG && !pmVisualIsVisual()) return true;
     797    if (!pmVisualTestLevel("psphot.psf.model", 1)) return true;
    779798
    780799    int myKapa = psphotKapaChannel (3);
     
    797816    // generate a fake model at each of the 3x3 image grid positions
    798817    for (int x = -2; x <= +2; x ++) {
    799         for (int y = -2; y <= +2; y ++) {
    800             // use the center of the center pixel of the image
    801             float xc = (int)((0.5 + 0.225*x)*readout->image->numCols) + readout->image->col0 + 0.5;
    802             float yc = (int)((0.5 + 0.225*y)*readout->image->numRows) + readout->image->row0 + 0.5;
    803 
    804             // assign the x and y coords to the image center
    805             // create an object with center intensity of 1000
    806             modelRef->params->data.F32[PM_PAR_SKY] = 0;
    807             modelRef->params->data.F32[PM_PAR_I0] = 1000;
    808             modelRef->params->data.F32[PM_PAR_XPOS] = xc;
    809             modelRef->params->data.F32[PM_PAR_YPOS] = yc;
    810 
    811             // create modelPSF from this model
    812             pmModel *model = pmModelFromPSF (modelRef, psf);
    813             if (!model) continue;
    814 
    815             // place the reference object in the image center
    816             // no need to mask the source here
    817             // XXX should we measure this for the analytical model only or the full model?
    818             pmModelAddWithOffset (psfMosaic, NULL, model, PM_MODEL_OP_FULL | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
    819             pmModelAddWithOffset (funMosaic, NULL, model, PM_MODEL_OP_FUNC | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
    820             pmModelAddWithOffset (resMosaic, NULL, model, PM_MODEL_OP_RES0 | PM_MODEL_OP_RES1 | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
    821             psFree (model);
    822         }
     818        for (int y = -2; y <= +2; y ++) {
     819            // use the center of the center pixel of the image
     820            float xc = (int)((0.5 + 0.225*x)*readout->image->numCols) + readout->image->col0 + 0.5;
     821            float yc = (int)((0.5 + 0.225*y)*readout->image->numRows) + readout->image->row0 + 0.5;
     822
     823            // assign the x and y coords to the image center
     824            // create an object with center intensity of 1000
     825            modelRef->params->data.F32[PM_PAR_SKY] = 0;
     826            modelRef->params->data.F32[PM_PAR_I0] = 1000;
     827            modelRef->params->data.F32[PM_PAR_XPOS] = xc;
     828            modelRef->params->data.F32[PM_PAR_YPOS] = yc;
     829
     830            // create modelPSF from this model
     831            pmModel *model = pmModelFromPSF (modelRef, psf);
     832            if (!model) continue;
     833
     834            // place the reference object in the image center
     835            // no need to mask the source here
     836            // XXX should we measure this for the analytical model only or the full model?
     837            pmModelAddWithOffset (psfMosaic, NULL, model, PM_MODEL_OP_FULL | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
     838            pmModelAddWithOffset (funMosaic, NULL, model, PM_MODEL_OP_FUNC | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
     839            pmModelAddWithOffset (resMosaic, NULL, model, PM_MODEL_OP_RES0 | PM_MODEL_OP_RES1 | PM_MODEL_OP_CENTER, 0, x*DX, y*DY);
     840            psFree (model);
     841        }
    823842    }
    824843
     
    842861    bool status;
    843862
    844     if (!DEBUG && !pmVisualIsVisual()) return true;
     863    if (!pmVisualTestLevel("psphot.psf.stars", 2)) return true;
    845864
    846865    int myKapa = psphotKapaChannel (3);
     
    871890    for (int i = 0; i < sources->n; i++) {
    872891
    873         pmSource *source = sources->data[i];
    874 
    875         bool keep = false;
    876         keep |= (source->mode & PM_SOURCE_MODE_PSFSTAR);
    877         if (!keep) continue;
    878 
    879         // how does this subimage get placed into the output image?
    880         // DX = source->pixels->numCols
    881         // DY = source->pixels->numRows
    882 
    883         if (dX + DX > NX) {
    884             // too wide for the rest of this row
    885             if (dX == 0) {
    886                 // alone on this row
    887                 NY += DY;
    888                 dX = 0;
    889                 dY = 0;
    890             } else {
    891                 // start the next row
    892                 NY += dY;
    893                 dX = DX;
    894                 dY = DY;
    895             }
    896         } else {
    897             // extend this row
    898             dX += DX;
    899             dY = PS_MAX (dY, DY);
    900         }
     892        pmSource *source = sources->data[i];
     893
     894        bool keep = false;
     895        keep |= (source->mode & PM_SOURCE_MODE_PSFSTAR);
     896        if (!keep) continue;
     897
     898        // how does this subimage get placed into the output image?
     899        // DX = source->pixels->numCols
     900        // DY = source->pixels->numRows
     901
     902        if (dX + DX > NX) {
     903            // too wide for the rest of this row
     904            if (dX == 0) {
     905                // alone on this row
     906                NY += DY;
     907                dX = 0;
     908                dY = 0;
     909            } else {
     910                // start the next row
     911                NY += dY;
     912                dX = DX;
     913                dY = DY;
     914            }
     915        } else {
     916            // extend this row
     917            dX += DX;
     918            dY = PS_MAX (dY, DY);
     919        }
    901920    }
    902921    NY += DY;
     
    918937    for (int i = 0; i < sources->n; i++) {
    919938
    920         pmSource *source = sources->data[i];
    921 
    922         bool keep = false;
    923         if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
    924             nPSF ++;
    925             keep = true;
    926         }
    927         if (!keep) continue;
    928 
    929         if (Xo + DX > NX) {
    930             // too wide for the rest of this row
    931             if (Xo == 0) {
    932                 // place source alone on this row
    933                 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    934                 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    935                 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
    936 
    937                 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    938                 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
    939 
    940                 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    941 
    942                 Yo += DY;
    943                 Xo = 0;
    944                 dY = 0;
    945             } else {
    946                 // start the next row
    947                 Yo += dY;
    948                 Xo = 0;
    949 
    950                 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    951                 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    952                 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
    953 
    954                 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    955                 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
    956 
    957                 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    958 
    959                 Xo = DX;
    960                 dY = DY;
    961             }
    962         } else {
    963             // extend this row
    964             bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    965             if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    966             psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
    967 
    968             pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    969             psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
    970             if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    971 
    972             Xo += DX;
    973             dY = PS_MAX (dY, DY);
    974         }
     939        pmSource *source = sources->data[i];
     940
     941        bool keep = false;
     942        if (source->mode & PM_SOURCE_MODE_PSFSTAR) {
     943            nPSF ++;
     944            keep = true;
     945        }
     946        if (!keep) continue;
     947
     948        if (Xo + DX > NX) {
     949            // too wide for the rest of this row
     950            if (Xo == 0) {
     951                // place source alone on this row
     952                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     953                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     954                psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
     955
     956                pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     957                psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
     958
     959                if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     960
     961                Yo += DY;
     962                Xo = 0;
     963                dY = 0;
     964            } else {
     965                // start the next row
     966                Yo += dY;
     967                Xo = 0;
     968
     969                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     970                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     971                psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
     972
     973                pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     974                psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
     975
     976                if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     977
     978                Xo = DX;
     979                dY = DY;
     980            }
     981        } else {
     982            // extend this row
     983            bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     984            if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     985            psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true);
     986
     987            pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     988            psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true);
     989            if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     990
     991            Xo += DX;
     992            dY = PS_MAX (dY, DY);
     993        }
    975994    }
    976995
     
    9941013    bool status;
    9951014
    996     if (!DEBUG && !pmVisualIsVisual()) return true;
     1015    if (!pmVisualTestLevel("psphot.psf.sat", 3)) return true;
    9971016
    9981017    int myKapa = psphotKapaChannel (3);
     
    10231042    for (int i = 0; i < sources->n; i++) {
    10241043
    1025         pmSource *source = sources->data[i];
    1026 
    1027         // only show "real" saturated stars (not defects)
    1028         if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
    1029         if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
    1030 
    1031         // how does this subimage get placed into the output image?
    1032         // DX = source->pixels->numCols
    1033         // DY = source->pixels->numRows
    1034 
    1035         if (dX + DX > NX) {
    1036             // too wide for the rest of this row
    1037             if (dX == 0) {
    1038                 // alone on this row
    1039                 NY += DY;
    1040                 dX = 0;
    1041                 dY = 0;
    1042             } else {
    1043                 // start the next row
    1044                 NY += dY;
    1045                 dX = DX;
    1046                 dY = DY;
    1047             }
    1048         } else {
    1049             // extend this row
    1050             dX += DX;
    1051             dY = PS_MAX (dY, DY);
    1052         }
     1044        pmSource *source = sources->data[i];
     1045
     1046        // only show "real" saturated stars (not defects)
     1047        if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
     1048        if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
     1049
     1050        // how does this subimage get placed into the output image?
     1051        // DX = source->pixels->numCols
     1052        // DY = source->pixels->numRows
     1053
     1054        if (dX + DX > NX) {
     1055            // too wide for the rest of this row
     1056            if (dX == 0) {
     1057                // alone on this row
     1058                NY += DY;
     1059                dX = 0;
     1060                dY = 0;
     1061            } else {
     1062                // start the next row
     1063                NY += dY;
     1064                dX = DX;
     1065                dY = DY;
     1066            }
     1067        } else {
     1068            // extend this row
     1069            dX += DX;
     1070            dY = PS_MAX (dY, DY);
     1071        }
    10531072    }
    10541073    NY += DY;
     
    10681087    for (int i = 0; i < sources->n; i++) {
    10691088
    1070         pmSource *source = sources->data[i];
    1071 
    1072         // only show "real" saturated stars (not defects)
    1073         if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
    1074         if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
    1075         nSAT ++;
    1076 
    1077         if (Xo + DX > NX) {
    1078             // too wide for the rest of this row
    1079             if (Xo == 0) {
    1080                 // place source alone on this row
    1081                 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    1082                 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    1083                 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
    1084                 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    1085 
    1086                 Yo += DY;
    1087                 Xo = 0;
    1088                 dY = 0;
    1089             } else {
    1090                 // start the next row
    1091                 Yo += dY;
    1092                 Xo = 0;
    1093 
    1094                 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    1095                 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    1096                 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
    1097                 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    1098 
    1099                 Xo = DX;
    1100                 dY = DY;
    1101             }
    1102         } else {
    1103             // extend this row
    1104             bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    1105             if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    1106             psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
    1107             if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    1108 
    1109             Xo += DX;
    1110             dY = PS_MAX (dY, DY);
    1111         }
     1089        pmSource *source = sources->data[i];
     1090
     1091        // only show "real" saturated stars (not defects)
     1092        if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;;
     1093        if (source->mode & PM_SOURCE_MODE_DEFECT) continue;;
     1094        nSAT ++;
     1095
     1096        if (Xo + DX > NX) {
     1097            // too wide for the rest of this row
     1098            if (Xo == 0) {
     1099                // place source alone on this row
     1100                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     1101                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     1102                psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
     1103                if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     1104
     1105                Yo += DY;
     1106                Xo = 0;
     1107                dY = 0;
     1108            } else {
     1109                // start the next row
     1110                Yo += dY;
     1111                Xo = 0;
     1112
     1113                bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     1114                if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     1115                psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
     1116                if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     1117
     1118                Xo = DX;
     1119                dY = DY;
     1120            }
     1121        } else {
     1122            // extend this row
     1123            bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
     1124            if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
     1125            psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false);
     1126            if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     1127
     1128            Xo += DX;
     1129            dY = PS_MAX (dY, DY);
     1130        }
    11121131    }
    11131132
     
    11511170    float Yo = source->modelPSF->params->data.F32[PM_PAR_YPOS] - source->pixels->row0;
    11521171    for (int iy = 0; iy < source->pixels->numRows; iy++) {
    1153         for (int ix = 0; ix < source->pixels->numCols; ix++) {
    1154             if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
    1155                 rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
    1156                 // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ;
    1157                 Rb->data.F32[nb] = log10(rb->data.F32[nb]);
    1158                 fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]);
    1159                 nb++;
    1160             } else {
    1161                 rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
    1162                 // rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ;
    1163                 Rg->data.F32[ng] = log10(rg->data.F32[ng]);
    1164                 fg->data.F32[ng] = log10(source->pixels->data.F32[iy][ix]);
    1165                 ng++;
    1166             }
    1167         }
     1172        for (int ix = 0; ix < source->pixels->numCols; ix++) {
     1173            if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
     1174                rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
     1175                // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ;
     1176                Rb->data.F32[nb] = log10(rb->data.F32[nb]);
     1177                fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]);
     1178                nb++;
     1179            } else {
     1180                rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;
     1181                // rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ;
     1182                Rg->data.F32[ng] = log10(rg->data.F32[ng]);
     1183                fg->data.F32[ng] = log10(source->pixels->data.F32[iy][ix]);
     1184                ng++;
     1185            }
     1186        }
    11681187    }
    11691188
     
    13581377    KapaSection section;  // put the positive profile in one and the residuals in another?
    13591378
    1360     if (!DEBUG && !pmVisualIsVisual()) return true;
     1379    if (!pmVisualTestLevel("psphot.profiles", 3)) return true;
    13611380
    13621381    int myKapa = psphotKapaChannel (2);
     
    13941413    for (int i = 0; i < sources->n; i++) {
    13951414
    1396         pmSource *source = sources->data[i];
    1397         if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
    1398 
    1399         psphotVisualPlotRadialProfile (myKapa, source, maskVal);
    1400 
    1401         // pause and wait for user input:
    1402         // continue, save (provide name), ??
    1403         char key[10];
    1404         fprintf (stdout, "[e]rase and continue? [o]verplot and continue? [s]kip rest of stars? : ");
    1405         if (!fgets(key, 8, stdin)) {
    1406             psWarning("Unable to read option");
    1407         }
    1408         if (key[0] == 'e') {
    1409             KapaClearPlots (myKapa);
    1410         }
    1411         if (key[0] == 's') {
    1412             break;
    1413         }
     1415        pmSource *source = sources->data[i];
     1416        if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
     1417
     1418        psphotVisualPlotRadialProfile (myKapa, source, maskVal);
     1419
     1420        // pause and wait for user input:
     1421        // continue, save (provide name), ??
     1422        char key[10];
     1423        fprintf (stdout, "[e]rase and continue? [o]verplot and continue? [s]kip rest of stars? : ");
     1424        if (!fgets(key, 8, stdin)) {
     1425            psWarning("Unable to read option");
     1426        }
     1427        if (key[0] == 'e') {
     1428            KapaClearPlots (myKapa);
     1429        }
     1430        if (key[0] == 's') {
     1431            break;
     1432        }
    14141433    }
    14151434
     
    14291448    return true;
    14301449
    1431     if (!DEBUG && !pmVisualIsVisual()) return true;
     1450    if (!pmVisualTestLevel("psphot.objects.flags", 3)) return true;
    14321451
    14331452    int myKapa = psphotKapaChannel (1);
     
    14451464    for (int i = 0; i < sources->n; i++) {
    14461465
    1447         float Xo, Yo, Rmaj, Rmin, cs, sn;
    1448 
    1449         pmSource *source = sources->data[i];
    1450         if (source == NULL) continue;
    1451 
    1452         pmMoments *moments = source->moments;
    1453         if (0) {
    1454             emoments.x2 = moments->Mxx;
    1455             emoments.y2 = moments->Myy;
    1456             emoments.xy = moments->Mxy;
    1457             Xo = moments->Mx;
    1458             Yo = moments->My;
    1459 
    1460             axes = psEllipseMomentsToAxes (emoments, 20.0);
    1461             Rmaj = 2.0*axes.major;
    1462             Rmin = 2.0*axes.minor;
    1463             cs = cos(axes.theta);
    1464             sn = sin(axes.theta);
    1465         } else {
    1466             Rmaj = Rmin = 5.0;
    1467             cs = 1.0;
    1468             sn = 0.0;
    1469             Xo = source->peak->xf;
    1470             Yo = source->peak->yf;
    1471         }
    1472 
    1473         unsigned short int flagMask = 0x01;
    1474         for (int j = 0; j < 8; j++) {
    1475             if (source->mode & flagMask) {
    1476                 overlayE[NoverlayE].type = KII_OVERLAY_LINE;
    1477                 overlayE[NoverlayE].x = Xo;
    1478                 overlayE[NoverlayE].y = Yo;
    1479 
    1480                 float phi = j*M_PI/4.0;
    1481                 overlayE[NoverlayE].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
    1482                 overlayE[NoverlayE].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
    1483                 overlayE[NoverlayE].angle = 0;
    1484                 overlayE[NoverlayE].text = NULL;
    1485                 NoverlayE ++;
    1486                 CHECK_REALLOCATE (overlayE, KiiOverlay, NOVERLAYE, NoverlayE, 100);
    1487             }
    1488             flagMask <<= 1;
    1489 
    1490             if (source->mode & flagMask) {
    1491                 overlayO[NoverlayO].type = KII_OVERLAY_LINE;
    1492                 overlayO[NoverlayO].x = Xo + 1;
    1493                 overlayO[NoverlayO].y = Yo;
    1494 
    1495                 float phi = j*M_PI/4.0;
    1496                 overlayO[NoverlayO].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
    1497                 overlayO[NoverlayO].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
    1498                 overlayO[NoverlayO].angle = 0;
    1499                 overlayO[NoverlayO].text = NULL;
    1500                 NoverlayO ++;
    1501                 CHECK_REALLOCATE (overlayO, KiiOverlay, NOVERLAYO, NoverlayO, 100);
    1502             }
    1503             flagMask <<= 1;
    1504         }
     1466        float Xo, Yo, Rmaj, Rmin, cs, sn;
     1467
     1468        pmSource *source = sources->data[i];
     1469        if (source == NULL) continue;
     1470
     1471        pmMoments *moments = source->moments;
     1472        if (0) {
     1473            emoments.x2 = moments->Mxx;
     1474            emoments.y2 = moments->Myy;
     1475            emoments.xy = moments->Mxy;
     1476            Xo = moments->Mx;
     1477            Yo = moments->My;
     1478
     1479            axes = psEllipseMomentsToAxes (emoments, 20.0);
     1480            Rmaj = 2.0*axes.major;
     1481            Rmin = 2.0*axes.minor;
     1482            cs = cos(axes.theta);
     1483            sn = sin(axes.theta);
     1484        } else {
     1485            Rmaj = Rmin = 5.0;
     1486            cs = 1.0;
     1487            sn = 0.0;
     1488            Xo = source->peak->xf;
     1489            Yo = source->peak->yf;
     1490        }
     1491
     1492        unsigned short int flagMask = 0x01;
     1493        for (int j = 0; j < 8; j++) {
     1494            if (source->mode & flagMask) {
     1495                overlayE[NoverlayE].type = KII_OVERLAY_LINE;
     1496                overlayE[NoverlayE].x = Xo;
     1497                overlayE[NoverlayE].y = Yo;
     1498
     1499                float phi = j*M_PI/4.0;
     1500                overlayE[NoverlayE].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
     1501                overlayE[NoverlayE].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
     1502                overlayE[NoverlayE].angle = 0;
     1503                overlayE[NoverlayE].text = NULL;
     1504                NoverlayE ++;
     1505                CHECK_REALLOCATE (overlayE, KiiOverlay, NOVERLAYE, NoverlayE, 100);
     1506            }
     1507            flagMask <<= 1;
     1508
     1509            if (source->mode & flagMask) {
     1510                overlayO[NoverlayO].type = KII_OVERLAY_LINE;
     1511                overlayO[NoverlayO].x = Xo + 1;
     1512                overlayO[NoverlayO].y = Yo;
     1513
     1514                float phi = j*M_PI/4.0;
     1515                overlayO[NoverlayO].dx = +Rmaj*cos(phi)*cs - Rmin*sin(phi)*sn;
     1516                overlayO[NoverlayO].dy = +Rmaj*cos(phi)*sn + Rmin*sin(phi)*cs;
     1517                overlayO[NoverlayO].angle = 0;
     1518                overlayO[NoverlayO].text = NULL;
     1519                NoverlayO ++;
     1520                CHECK_REALLOCATE (overlayO, KiiOverlay, NOVERLAYO, NoverlayO, 100);
     1521            }
     1522            flagMask <<= 1;
     1523        }
    15051524    }
    15061525
     
    15311550    for (int i = 0; i < sources->n; i++) {
    15321551
    1533         pmSource *source = sources->data[i];
    1534         if (source == NULL) continue;
    1535 
    1536         if (mode) {
    1537             if (keep) {
    1538                 if (!(source->mode & mode)) continue;
    1539             } else {
    1540                 if (source->mode & mode) continue;
    1541             }
    1542         }
    1543 
    1544         pmMoments *moments = source->moments;
    1545         if (moments == NULL) continue;
    1546 
    1547         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    1548         overlay[Noverlay].x = moments->Mx;
    1549         overlay[Noverlay].y = moments->My;
    1550 
    1551         emoments.x2 = moments->Mxx;
    1552         emoments.y2 = moments->Myy;
    1553         emoments.xy = moments->Mxy;
    1554 
    1555         axes = psEllipseMomentsToAxes (emoments, 20.0);
    1556 
    1557         overlay[Noverlay].dx = scale*2.0*axes.major;
    1558         overlay[Noverlay].dy = scale*2.0*axes.minor;
    1559         overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
    1560         overlay[Noverlay].text = NULL;
    1561         Noverlay ++;
     1552        pmSource *source = sources->data[i];
     1553        if (source == NULL) continue;
     1554
     1555        if (mode) {
     1556            if (keep) {
     1557                if (!(source->mode & mode)) continue;
     1558            } else {
     1559                if (source->mode & mode) continue;
     1560            }
     1561        }
     1562
     1563        pmMoments *moments = source->moments;
     1564        if (moments == NULL) continue;
     1565
     1566        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     1567        overlay[Noverlay].x = moments->Mx;
     1568        overlay[Noverlay].y = moments->My;
     1569
     1570        emoments.x2 = moments->Mxx;
     1571        emoments.y2 = moments->Myy;
     1572        emoments.xy = moments->Mxy;
     1573
     1574        axes = psEllipseMomentsToAxes (emoments, 20.0);
     1575
     1576        overlay[Noverlay].dx = scale*2.0*axes.major;
     1577        overlay[Noverlay].dy = scale*2.0*axes.minor;
     1578        overlay[Noverlay].angle = axes.theta * PS_DEG_RAD;
     1579        overlay[Noverlay].text = NULL;
     1580        Noverlay ++;
    15621581    }
    15631582
     
    15701589bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources) {
    15711590
    1572     if (!DEBUG && !pmVisualIsVisual()) return true;
     1591    if (!pmVisualTestLevel("psphot.objects.size", 2)) return true;
    15731592
    15741593    int myKapa = psphotKapaChannel (1);
     
    15971616    KapaSection section;
    15981617
    1599     if (!DEBUG && !pmVisualIsVisual()) return true;
     1618    if (!pmVisualTestLevel("psphot.size", 2)) return true;
    16001619
    16011620    int myKapa = psphotKapaChannel (2);
     
    16121631    float Ymin = 1000.0, Ymax = 0.0;
    16131632    {
    1614         int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    1615         for (int n = 0; n < nRegions; n++) {
    1616 
    1617             char regionName[64];
    1618             snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
    1619             psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
    1620 
    1621             float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
    1622             float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
    1623             float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
    1624             float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
    1625 
    1626             float X0 = psfX - 10.0*psfdX;
    1627             float X1 = psfX + 10.0*psfdX;
    1628             float Y0 = psfY - 10.0*psfdY;
    1629             float Y1 = psfY + 10.0*psfdY;
    1630 
    1631             if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
    1632             if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
    1633             if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
    1634             if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
    1635         }
     1633        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     1634        for (int n = 0; n < nRegions; n++) {
     1635
     1636            char regionName[64];
     1637            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     1638            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     1639
     1640            float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     1641            float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     1642            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     1643            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     1644
     1645            float X0 = psfX - 10.0*psfdX;
     1646            float X1 = psfX + 10.0*psfdX;
     1647            float Y0 = psfY - 10.0*psfdY;
     1648            float Y1 = psfY + 10.0*psfdY;
     1649
     1650            if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); }
     1651            if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); }
     1652            if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); }
     1653            if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); }
     1654        }
    16361655    }
    16371656    Xmin = PS_MAX(Xmin, -0.1);
     
    16771696    int nCR  = 0;
    16781697    for (int i = 0; i < sources->n; i++) {
    1679         pmSource *source = sources->data[i];
    1680         if (source->moments == NULL) continue;
     1698        pmSource *source = sources->data[i];
     1699        if (source->moments == NULL) continue;
    16811700
    16821701        // only plot the measured sources...
    1683         if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)) continue;
    1684 
    1685         if (source->mode & PM_SOURCE_MODE_CR_LIMIT) {
    1686             xCR->data.F32[nCR] = source->moments->Mxx;
    1687             yCR->data.F32[nCR] = source->moments->Myy;
    1688             mCR->data.F32[nCR] = -2.5*log10(source->moments->Sum);
    1689             sCR->data.F32[nCR] = source->extNsigma;
    1690             nCR++;
    1691         }
    1692         if (source->mode & PM_SOURCE_MODE_SATSTAR) {
    1693             xSAT->data.F32[nSAT] = source->moments->Mxx;
    1694             ySAT->data.F32[nSAT] = source->moments->Myy;
    1695             mSAT->data.F32[nSAT] = -2.5*log10(source->moments->Sum);
    1696             sSAT->data.F32[nSAT] = source->extNsigma;
    1697             nSAT++;
    1698         }
    1699         if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    1700             xEXT->data.F32[nEXT] = source->moments->Mxx;
    1701             yEXT->data.F32[nEXT] = source->moments->Myy;
    1702             mEXT->data.F32[nEXT] = -2.5*log10(source->moments->Sum);
    1703             sEXT->data.F32[nEXT] = source->extNsigma;
    1704             nEXT++;
    1705             continue;
    1706         }
    1707         if (source->mode & PM_SOURCE_MODE_DEFECT) {
    1708             xDEF->data.F32[nDEF] = source->moments->Mxx;
    1709             yDEF->data.F32[nDEF] = source->moments->Myy;
    1710             mDEF->data.F32[nDEF] = -2.5*log10(source->moments->Sum);
    1711             sDEF->data.F32[nDEF] = source->extNsigma;
    1712             nDEF++;
    1713             continue;
    1714         }
    1715         if (source->errMag > 0.1) {
    1716             xLOW->data.F32[nLOW] = source->moments->Mxx;
    1717             yLOW->data.F32[nLOW] = source->moments->Myy;
    1718             mLOW->data.F32[nLOW] = -2.5*log10(source->moments->Sum);
    1719             sLOW->data.F32[nLOW] = source->extNsigma;
    1720             nLOW++;
    1721             continue;
    1722         }
    1723         xPSF->data.F32[nPSF] = source->moments->Mxx;
    1724         yPSF->data.F32[nPSF] = source->moments->Myy;
    1725         mPSF->data.F32[nPSF] = -2.5*log10(source->moments->Sum);
    1726         sPSF->data.F32[nPSF] = source->extNsigma;
    1727         nPSF++;
     1702        if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)) continue;
     1703
     1704        if (source->mode & PM_SOURCE_MODE_CR_LIMIT) {
     1705            xCR->data.F32[nCR] = source->moments->Mxx;
     1706            yCR->data.F32[nCR] = source->moments->Myy;
     1707            mCR->data.F32[nCR] = -2.5*log10(source->moments->Sum);
     1708            sCR->data.F32[nCR] = source->extNsigma;
     1709            nCR++;
     1710        }
     1711        if (source->mode & PM_SOURCE_MODE_SATSTAR) {
     1712            xSAT->data.F32[nSAT] = source->moments->Mxx;
     1713            ySAT->data.F32[nSAT] = source->moments->Myy;
     1714            mSAT->data.F32[nSAT] = -2.5*log10(source->moments->Sum);
     1715            sSAT->data.F32[nSAT] = source->extNsigma;
     1716            nSAT++;
     1717        }
     1718        if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
     1719            xEXT->data.F32[nEXT] = source->moments->Mxx;
     1720            yEXT->data.F32[nEXT] = source->moments->Myy;
     1721            mEXT->data.F32[nEXT] = -2.5*log10(source->moments->Sum);
     1722            sEXT->data.F32[nEXT] = source->extNsigma;
     1723            nEXT++;
     1724            continue;
     1725        }
     1726        if (source->mode & PM_SOURCE_MODE_DEFECT) {
     1727            xDEF->data.F32[nDEF] = source->moments->Mxx;
     1728            yDEF->data.F32[nDEF] = source->moments->Myy;
     1729            mDEF->data.F32[nDEF] = -2.5*log10(source->moments->Sum);
     1730            sDEF->data.F32[nDEF] = source->extNsigma;
     1731            nDEF++;
     1732            continue;
     1733        }
     1734        if (source->errMag > 0.1) {
     1735            xLOW->data.F32[nLOW] = source->moments->Mxx;
     1736            yLOW->data.F32[nLOW] = source->moments->Myy;
     1737            mLOW->data.F32[nLOW] = -2.5*log10(source->moments->Sum);
     1738            sLOW->data.F32[nLOW] = source->extNsigma;
     1739            nLOW++;
     1740            continue;
     1741        }
     1742        xPSF->data.F32[nPSF] = source->moments->Mxx;
     1743        yPSF->data.F32[nPSF] = source->moments->Myy;
     1744        mPSF->data.F32[nPSF] = -2.5*log10(source->moments->Sum);
     1745        sPSF->data.F32[nPSF] = source->extNsigma;
     1746        nPSF++;
    17281747    }
    17291748
     
    20292048    // draw N circles to outline the clumps
    20302049    {
    2031         KapaSelectSection (myKapa, "MxxMyy");
    2032 
    2033         // draw a circle centered on psfX,Y with size of the psf limit
    2034         psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
    2035         psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
    2036 
    2037         int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    2038         float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
    2039 
    2040         graphdata.color = KapaColorByName ("blue");
    2041         graphdata.style = 0;
    2042 
    2043         graphdata.xmin = Xmin;
    2044         graphdata.ymin = Ymin;
    2045         graphdata.xmax = Xmax;
    2046         graphdata.ymax = Ymax;
    2047         KapaSetLimits (myKapa, &graphdata);
    2048 
    2049         for (int n = 0; n < nRegions; n++) {
    2050 
    2051             char regionName[64];
    2052             snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
    2053             psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
    2054 
    2055             float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
    2056             float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
    2057             float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
    2058             float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
    2059             float Rx = psfdX * PSF_CLUMP_NSIGMA;
    2060             float Ry = psfdY * PSF_CLUMP_NSIGMA;
    2061 
    2062             for (int i = 0; i < xLimit->n; i++) {
    2063                 xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
    2064                 yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
    2065             }
    2066             KapaPrepPlot (myKapa, xLimit->n, &graphdata);
    2067             KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
    2068             KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
    2069         }
    2070         psFree (xLimit);
    2071         psFree (yLimit);
     2050        KapaSelectSection (myKapa, "MxxMyy");
     2051
     2052        // draw a circle centered on psfX,Y with size of the psf limit
     2053        psVector *xLimit  = psVectorAlloc (120, PS_TYPE_F32);
     2054        psVector *yLimit  = psVectorAlloc (120, PS_TYPE_F32);
     2055
     2056        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
     2057        float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
     2058
     2059        graphdata.color = KapaColorByName ("blue");
     2060        graphdata.style = 0;
     2061
     2062        graphdata.xmin = Xmin;
     2063        graphdata.ymin = Ymin;
     2064        graphdata.xmax = Xmax;
     2065        graphdata.ymax = Ymax;
     2066        KapaSetLimits (myKapa, &graphdata);
     2067
     2068        for (int n = 0; n < nRegions; n++) {
     2069
     2070            char regionName[64];
     2071            snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n);
     2072            psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
     2073
     2074            float psfX  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");
     2075            float psfY  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");
     2076            float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");
     2077            float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");
     2078            float Rx = psfdX * PSF_CLUMP_NSIGMA;
     2079            float Ry = psfdY * PSF_CLUMP_NSIGMA;
     2080
     2081            for (int i = 0; i < xLimit->n; i++) {
     2082                xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX;
     2083                yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY;
     2084            }
     2085            KapaPrepPlot (myKapa, xLimit->n, &graphdata);
     2086            KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x");
     2087            KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y");
     2088        }
     2089        psFree (xLimit);
     2090        psFree (yLimit);
    20722091    }
    20732092
     
    21082127bool psphotVisualShowResidualImage (pmReadout *readout) {
    21092128
    2110     if (!DEBUG && !pmVisualIsVisual()) return true;
     2129    if (!pmVisualTestLevel("psphot.image.resid", 2)) return true;
    21112130
    21122131    int myKapa = psphotKapaChannel (1);
     
    21242143    float lineX[2], lineY[2];
    21252144
    2126     if (!DEBUG && !pmVisualIsVisual()) return true;
     2145    if (!pmVisualTestLevel("psphot.apresid", 1)) return true;
    21272146
    21282147    int myKapa = psphotKapaChannel (2);
     
    21442163    int n = 0;
    21452164    for (int i = 0; i < sources->n; i++) {
    2146         pmSource *source = sources->data[i];
    2147         if (!source) continue;
    2148         if (source->type != PM_SOURCE_TYPE_STAR) continue;
    2149         if (!isfinite (source->apMag)) continue;
    2150         if (!isfinite (source->psfMag)) continue;
    2151 
    2152         x->data.F32[n] = source->psfMag;
    2153         y->data.F32[n] = source->apMag - source->psfMag;
    2154         dy->data.F32[n] = source->errMag;
    2155         graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
    2156         graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
    2157         graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
    2158         graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
    2159 
    2160         n++;
     2165        pmSource *source = sources->data[i];
     2166        if (!source) continue;
     2167        if (source->type != PM_SOURCE_TYPE_STAR) continue;
     2168        if (!isfinite (source->apMag)) continue;
     2169        if (!isfinite (source->psfMag)) continue;
     2170
     2171        x->data.F32[n] = source->psfMag;
     2172        y->data.F32[n] = source->apMag - source->psfMag;
     2173        dy->data.F32[n] = source->errMag;
     2174        graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
     2175        graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
     2176        graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
     2177        graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
     2178
     2179        n++;
    21612180    }
    21622181    x->n = y->n = dy->n = n;
     
    22422261    Graphdata graphdata;
    22432262
    2244     if (!DEBUG && !pmVisualIsVisual()) return true;
     2263    if (!pmVisualTestLevel("psphot.chisq", 1)) return true;
    22452264
    22462265    int myKapa = psphotKapaChannel (2);
     
    22632282    int n = 0;
    22642283    for (int i = 0; i < sources->n; i++) {
    2265         pmSource *source = sources->data[i];
    2266         if (!source) continue;
    2267         if (source->type != PM_SOURCE_TYPE_STAR) continue;
    2268         if (!source->moments) continue;
    2269         if (!isfinite(source->moments->Sum)) continue;
    2270         if (!source->modelPSF) continue;
    2271         if (!isfinite(source->modelPSF->chisq)) continue;
    2272 
    2273         x->data.F32[n] = -2.5*log10(source->moments->Sum);
    2274         y->data.F32[n] = source->modelPSF->chisq / source->modelPSF->nDOF;
    2275         graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
    2276         graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
    2277         graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
    2278         graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
    2279 
    2280         fprintf (f, "%d %d %f %f\n", i, n, x->data.F32[n], y->data.F32[n]);
    2281 
    2282         n++;
     2284        pmSource *source = sources->data[i];
     2285        if (!source) continue;
     2286        if (source->type != PM_SOURCE_TYPE_STAR) continue;
     2287        if (!source->moments) continue;
     2288        if (!isfinite(source->moments->Sum)) continue;
     2289        if (!source->modelPSF) continue;
     2290        if (!isfinite(source->modelPSF->chisq)) continue;
     2291
     2292        x->data.F32[n] = -2.5*log10(source->moments->Sum);
     2293        y->data.F32[n] = source->modelPSF->chisq / source->modelPSF->nDOF;
     2294        graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
     2295        graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
     2296        graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
     2297        graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
     2298
     2299        fprintf (f, "%d %d %f %f\n", i, n, x->data.F32[n], y->data.F32[n]);
     2300
     2301        n++;
    22832302    }
    22842303    x->n = y->n = n;
     
    23262345    KiiOverlay *overlay;
    23272346
    2328     if (!DEBUG && !pmVisualIsVisual()) return true;
     2347    if (!pmVisualTestLevel("psphot.objects.petro", 2)) return true;
    23292348
    23302349    int kapa = psphotKapaChannel (1);
     
    23362355
    23372356    for (int i = 0; i < sources->n; i++) {
    2338         pmSource *source = sources->data[i];
    2339 
    2340         if (!source) continue;
    2341         if (!source->extpars) continue;
    2342         if (!source->extpars->petProfile) continue;
    2343 
    2344         float petrosianRadius = source->extpars->petrosianRadius;
     2357        pmSource *source = sources->data[i];
     2358
     2359        if (!source) continue;
     2360        if (!source->extpars) continue;
     2361        if (!source->extpars->petProfile) continue;
     2362
     2363        float petrosianRadius = source->extpars->petrosianRadius;
    23452364        psEllipseAxes *axes = &source->extpars->axes;
    23462365
    2347         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    2348         overlay[Noverlay].x = source->peak->xf;
    2349         overlay[Noverlay].y = source->peak->yf;
    2350         overlay[Noverlay].dx = 1.0*petrosianRadius;
    2351         overlay[Noverlay].dy = 1.0*petrosianRadius*axes->minor/axes->major;
    2352         overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
    2353         overlay[Noverlay].text = NULL;
    2354         Noverlay ++;
    2355         CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    2356 
    2357         // overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    2358         // overlay[Noverlay].x = source->peak->xf;
    2359         // overlay[Noverlay].y = source->peak->yf;
    2360         // overlay[Noverlay].dx = 2.0*petrosianRadius;
    2361         // overlay[Noverlay].dy = 2.0*petrosianRadius*axes->minor/axes->major;
    2362         // overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
    2363         // overlay[Noverlay].text = NULL;
    2364         // Noverlay ++;
    2365         // CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     2366        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     2367        overlay[Noverlay].x = source->peak->xf;
     2368        overlay[Noverlay].y = source->peak->yf;
     2369        overlay[Noverlay].dx = 1.0*petrosianRadius;
     2370        overlay[Noverlay].dy = 1.0*petrosianRadius*axes->minor/axes->major;
     2371        overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
     2372        overlay[Noverlay].text = NULL;
     2373        Noverlay ++;
     2374        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     2375
     2376        // overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     2377        // overlay[Noverlay].x = source->peak->xf;
     2378        // overlay[Noverlay].y = source->peak->yf;
     2379        // overlay[Noverlay].dx = 2.0*petrosianRadius;
     2380        // overlay[Noverlay].dy = 2.0*petrosianRadius*axes->minor/axes->major;
     2381        // overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
     2382        // overlay[Noverlay].text = NULL;
     2383        // Noverlay ++;
     2384        // CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    23662385    }
    23672386
Note: See TracChangeset for help on using the changeset viewer.