IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 17, 2014, 12:30:45 PM (12 years ago)
Author:
eugene
Message:

merge changes (from past YEAR) into trunk

Location:
branches/eam_branches/ipp-ops-20130712/psphot
Files:
40 edited
14 copied

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-ops-20130712/psphot

    • Property svn:mergeinfo deleted
  • branches/eam_branches/ipp-ops-20130712/psphot/src

    • Property svn:ignore
      •  

        old new  
        2424psphotModelTest
        2525psphotMinimal
         26psphotFullForce
         27psmakecff
         28psphotFullForceSummary
    • Property svn:mergeinfo deleted
  • branches/eam_branches/ipp-ops-20130712/psphot/src/Makefile.am

    r34317 r37066  
    2525libpsphot_la_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
    2626
    27 bin_PROGRAMS = psphot psphotForced psphotMinimal psphotMakePSF psphotStack psphotModelTest
     27bin_PROGRAMS = psphot psphotForced psphotFullForce psphotFullForceSummary psphotMinimal psphotMakePSF psphotStack psphotModelTest psmakecff
    2828# bin_PROGRAMS = psphotPetrosianStudy psphotTest psphotMomentsStudy
    2929
     
    3636psphotForced_LDADD = libpsphot.la
    3737
     38psphotFullForce_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     39psphotFullForce_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     40psphotFullForce_LDADD = libpsphot.la
     41
     42psphotFullForceSummary_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     43psphotFullForceSummary_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     44psphotFullForceSummary_LDADD = libpsphot.la
     45
    3846psphotMinimal_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
    3947psphotMinimal_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     
    5159psphotModelTest_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
    5260psphotModelTest_LDADD = libpsphot.la
     61
     62psmakecff_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     63psmakecff_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     64psmakecff_LDADD = libpsphot.la
     65
    5366
    5467# psphotMomentsStudy_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     
    8194        psphotMosaicChip.c         \
    8295        psphotCleanup.c
     96
     97# generalized forced photometry (including Kron, Petro, and Models) of specified positions given a specified psf
     98psphotFullForce_SOURCES = \
     99        psphotFullForce.c             \
     100        psphotFullForceArguments.c    \
     101        psphotParseCamera.c        \
     102        psphotImageLoop.c          \
     103        psphotMosaicChip.c         \
     104        psphotCleanup.c
     105
     106# combine full force results from several inputs
     107psphotFullForceSummary_SOURCES = \
     108        psphotFullForceSummary.c \
     109        psphotFullForceSummaryReadout.c
    83110
    84111# forced photometry of specified positions given a specified psf
     
    129156        psphotCleanup.c
    130157
     158# a program that takes a cmf file and makes a cff file (input file for psphotFullForce
     159psmakecff_SOURCES = \
     160        psmakecff.c
     161
    131162# psphotTest_SOURCES = \
    132163#         psphotTest.c
     
    155186        psphotReadoutMinimal.c         \
    156187        psphotForcedReadout.c          \
     188        psphotFullForceReadout.c       \
     189        psphotFullForce.SourceStats.c \
    157190        psphotMakePSFReadout.c         \
    158191        psphotModelBackground.c        \
     
    175208        psphotMakeGrowthCurve.c        \
    176209        psphotMagnitudes.c             \
     210        psphotLensing.c        \
    177211        psphotSetMaskBits.c            \
    178212        psphotSkyReplace.c             \
     
    181215        psphotSourceFits.c             \
    182216        psphotRadiusChecks.c           \
     217        psphotChooseAnalysisOptions.c  \
    183218        psphotOutput.c                 \
    184219        psphotFakeSources.c            \
     
    198233        psphotRadialPlot.c             \
    199234        psphotKronIterate.c            \
     235        psphotKronFlux.c            \
     236        psphotPetroFlux.c            \
     237        psphotGalaxyShape.c            \
    200238        psphotRadialProfileWings.c     \
    201239        psphotDeblendSatstars.c        \
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphot.h

    r35769 r37066  
    1818    PSPHOT_SINGLE,
    1919    PSPHOT_FORCED,
     20    PSPHOT_FULL_FORCE,
    2021    PSPHOT_MAKE_PSF,
    2122    PSPHOT_MODEL_TEST,
     
    8182bool            psphotSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe, bool setWindow);
    8283
     84bool            psphotFullForceSourceStats (pmConfig *config, const pmFPAview *view, const char *filerule, bool setWindow);
     85bool            psphotFullForceSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe, bool setWindow);
     86
    8387bool            psphotDeblendSatstars (pmConfig *config, const pmFPAview *view, const char *filerule);
    8488bool            psphotDeblendSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     
    122126bool            psphotAddOrSubNoise_Threaded (psThreadJob *job);
    123127
     128bool            psphotChooseAnalysisOptions (pmConfig *config, const pmFPAview *view, const char *filerule);
     129bool            psphotChooseAnalysisOptionsReadout(pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     130bool            psphotChooseAnalysisOptionsByObject(pmConfig *config, const pmFPAview *view, const char *filerule, psArray *objects);
     131
    124132bool            psphotExtendedSourceAnalysis (pmConfig *config, const pmFPAview *view, const char *filerule);
    125133bool            psphotExtendedSourceAnalysisReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     
    136144bool            psphotMagnitudesReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, pmReadout *readout, psArray *sources, pmPSF *psf);
    137145bool            psphotMagnitudes_Threaded (psThreadJob *job);
     146
     147bool            psphotLensing (pmConfig *config, const pmFPAview *view, const char *filerule);
     148bool            psphotLensingReadout(pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     149bool            psphotLensingPSFtrendsReadout(pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
    138150
    139151bool            psphotEfficiency (pmConfig *config, const pmFPAview *view, const char *filerule);
     
    341353bool psphotForcedReadout(pmConfig *config, const pmFPAview *view, const char *filerule);
    342354
     355pmConfig *psphotFullForceArguments(int argc, char **argv);
     356bool psphotFullForceReadout(pmConfig *config, const pmFPAview *view, const char *filerule);
     357
    343358pmConfig *psphotMinimalArguments(int argc, char **argv);
    344359bool psphotReadoutMinimal(pmConfig *config, const pmFPAview *view, const char *filerule);
     
    349364pmConfig *psphotModelTestArguments(int argc, char **argv);
    350365bool psphotModelTestReadout(pmConfig *config, const pmFPAview *view, const char *filerule);
     366
     367bool psphotFullForceSummaryReadout (pmConfig * config, const pmFPAview *view);
    351368
    352369int psphotFileruleCount(const pmConfig *config, const char *filerule);
     
    414431} psphotStackOptions;
    415432
     433typedef struct {
     434    float   Q;
     435    float   NSigma;
     436    float   clampSN;
     437    int     extModelType;
     438} psphotGalaxyShapeOptions;
     439
    416440/*** psphotStackMatchPSF prototypes ***/
    417441bool psphotStackMatchPSFs (pmConfig *config, const pmFPAview *view);
     
    475499bool psphotSourceChildren (pmConfig *config, const pmFPAview *view, const char *ruleOut, const char *ruleSrc);
    476500bool psphotSourceChildrenReadout (pmConfig *config, const pmFPAview *view, const char *ruleOut, const char *ruleSrc, int index);
    477 psArray *psphotSourceChildrenByObject (pmConfig *config, const pmFPAview *view, const char *filerule, psArray *objectsSrc);
     501psArray *psphotSourceChildrenByObject (pmConfig *config, const pmFPAview *view, const char *filerule, psArray *objectsSrc, bool sourcesSubtracted);
    478502
    479503bool psphotSourceParents (pmConfig *config, const pmFPAview *view, const char *ruleOut, const char *ruleSrc);
     
    496520bool psphotKronIterateReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, const char * filerule, pmReadout *readout, psArray *sources, pmPSF *psf, int index, int pass);
    497521bool psphotKronIterate_Threaded (psThreadJob *job);
     522
     523bool psphotKronFlux (pmConfig *config, const pmFPAview *view, const char *filerule);
     524bool psphotKronFluxReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, const char *filerule, pmReadout *readout, psArray *sources);
     525bool psphotKronFlux_Threaded (psThreadJob *job);
     526bool psphotKronFluxSource (pmSource *source, psImageMaskType maskVal);
     527
     528bool psphotPetroFlux (pmConfig *config, const pmFPAview *view, const char *filerule);
     529bool psphotPetroFluxReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, const char * filerule, pmReadout *readout, psArray *sources);
     530bool psphotPetroFlux_Threaded (psThreadJob *job);
     531bool psphotPetroFluxSource (pmSource *source, psImageMaskType maskVal);
     532
     533bool psphotGalaxyShape (pmConfig *config, const pmFPAview *view, const char *filerule);
     534bool psphotGalaxyShapeReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, const char * filerule, pmReadout *readout, psArray *sources, pmPSF *psf);
     535bool psphotGalaxyShape_Threaded (psThreadJob *job);
     536bool psphotGalaxyShapeGrid (pmSource *source, pmSourceFitOptions *fitOptions, psphotGalaxyShapeOptions *opt, psImageMaskType maskVal, int psfSize);
     537bool psphotGalaxyShapeSource (pmPCMdata *pcm, pmSource *source, pmSourceGalaxyFits *galaxyFits, psImageMaskType maskVal, int psfSize, bool saveResults);
     538psphotGalaxyShapeOptions *psphotGalaxyShapeOptionsAlloc();
     539bool psphotGalaxyShapeOptionsSet(pmSource *source, pmSourceGalaxyFits *galaxyFits, psphotGalaxyShapeOptions *defaultOptions);
    498540
    499541bool psphotRadialProfileWings (pmConfig *config, const pmFPAview *view, const char *filerule);
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotApResid.c

    r34404 r37066  
    214214
    215215        // XXX make this user-configurable?
    216         if (source->psfMagErr > 0.01) continue;
     216        if (source->psfMagErr > 0.03) continue;
    217217
    218218        // aperture residual for this source
     
    267267
    268268    // set the max order (0 = constant) which the number of psf stars can support:
    269     // rule of thumb: require 3 stars per 'cell' (order+1)^2
     269    // we require only 3 stars for n = 0, increase stars / cell for higher order
    270270    int MaxOrderForStars = 0;
    271     if (Npsf >= 12) MaxOrderForStars = 1; // 4 cells
    272     if (Npsf >= 27) MaxOrderForStars = 2; // 9 cells
    273     if (Npsf >= 48) MaxOrderForStars = 3; // 16 cells
    274     if (Npsf >  75) MaxOrderForStars = 4; // 25 cells
     271    if (Npsf >=  16) MaxOrderForStars = 1; // 4 cells
     272    if (Npsf >=  54) MaxOrderForStars = 2; // 9 cells
     273    if (Npsf >= 128) MaxOrderForStars = 3; // 16 cells
     274    if (Npsf >= 300) MaxOrderForStars = 4; // 25 cells
     275    if (Npsf >  576) MaxOrderForStars = 5; // 36 cells
    275276
    276277    pmTrend2DMode mode = PM_TREND_MAP;
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotArguments.c

    r33690 r37066  
    217217    pmConfigFileSetsMD (config->arguments, &argc, argv, "PSPHOT.PSF", "-psf",      "-psflist");
    218218    pmConfigFileSetsMD (config->arguments, &argc, argv, "SRC",        "-src",      "-srclist");
     219    // XXX allow this format? pmConfigFileSetsMD (config->arguments, &argc, argv, "FORCE",      "-force",    "-forcelist");
    219220    pmConfigFileSetsMD (config->arguments, &argc, argv, "EXPNUM",     "-expnum",   "-expnumlist");
    220221
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotBlendFit.c

    r35769 r37066  
    273273        pmSource *source = sources->data[i];
    274274
    275         int TEST_ON = false;
    276 # if (0)
     275# if (PS_TRACE_ON)
    277276# define TEST_X 653
    278277# define TEST_Y 466
    279         if ((fabs(source->peak->xf - TEST_X) < 5) && (fabs(source->peak->yf - TEST_Y) < 5)) {
     278# define TESTING 1
     279        int TEST_ON = false;
     280        if (TESTING && (fabs(source->peak->xf - TEST_X) < 5) && (fabs(source->peak->yf - TEST_Y) < 5)) {
    280281            fprintf (stderr, "test object\n");
    281282            psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
     
    342343        if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    343344            if (psphotFitBlob (readout, source, newSources, psf, fitOptions, maskVal, markVal)) {
     345# if (PS_TRACE_ON)
    344346                if (TEST_ON) {
    345347                    psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0);
    346348                }
     349# endif
    347350                psTrace ("psphot", 5, "source at %7.1f, %7.1f is ext", source->peak->xf, source->peak->yf);
    348351                Next ++;
     
    351354        } else {
    352355            if (psphotFitBlend (readout, source, psf, fitOptions, maskVal, markVal)) {
     356# if (PS_TRACE_ON)
    353357                if (TEST_ON) {
    354358                    psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0);
    355359                }
     360# endif
    356361                source->type = PM_SOURCE_TYPE_STAR;
    357362                psTrace ("psphot", 5, "source at %7.1f, %7.1f is psf", source->peak->xf, source->peak->yf);
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotChoosePSF.c

    r35769 r37066  
    399399    char *modelName = pmModelClassGetName (psf->type);
    400400    psLogMsg ("psphot.pspsf", PS_LOG_WARN, "select psf model: %f sec\n", psTimerMark ("psphot.choose.psf"));
    401     psLogMsg ("psphot.pspsf", PS_LOG_INFO, "psf model %s, ApResid: %f +/- %f\n", modelName, psf->ApResid, psf->dApResid);
     401    psLogMsg ("psphot.pspsf", PS_LOG_INFO, "psf model %s, ApResid: %f +/- %f (%d x %d model)\n", modelName, psf->ApResid, psf->dApResid, psf->trendNx, psf->trendNy);
    402402
    403403    psFree (options);
     
    448448
    449449            // get the model full-width at half-max
    450             float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5);
     450            float FWHM_MAJOR = 2*modelPSF->class->modelRadius (modelPSF->params, 0.5);
    451451
    452452            // XXX make sure this is consistent with the re-definition of PM_PAR_SXX
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotCleanup.c

    r34086 r37066  
    2222    pmVisualCleanup ();
    2323    psLibFinalize();
     24#if (PS_TRACE_ON)
     25    // don't display memory leaks unless trace is on.
    2426    // fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, NULL, false), "psphot");
    2527    fprintf (stderr, "found %d leaks at %s\n", psMemCheckLeaks (0, NULL, stdout, false), "psphot");
     28#endif
    2629    return;
    2730}
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotDeblendSatstars.c

    r34708 r37066  
    128128    // int display = psphotKapaChannel (1);
    129129    // psphotVisualScaleImage (display, (psImage *) source->pixels->parent, NULL, "image", 1.0, 0);
     130
     131    int Nsatstar = 0;
    130132
    131133    // examine sources in decreasing SN order
     
    179181        source->mode2 |= PM_SOURCE_MODE2_SATSTAR_PROFILE; // and we have in fact subtracted the profile
    180182
     183        Nsatstar ++;
     184
    181185        // XXX visualize, model, and subtract
    182186        // if (!psphotVisualRadialProfileSatstar (source, maskVal)) {
     
    192196    psFree (index);
    193197
    194     psLogMsg ("psphot", PS_LOG_INFO, "deblend satstar: %f sec\n", psTimerMark ("psphot.deblend.sat"));
     198    psLogMsg ("psphot", PS_LOG_INFO, "deblend %d satstars: %f sec\n", Nsatstar, psTimerMark ("psphot.deblend.sat"));
    195199    return true;
    196200}
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotDefineFiles.c

    r34528 r37066  
    150150    }
    151151
     152    if (psMetadataLookupPtr(NULL, config->arguments, "FORCE")) {
     153        if (!pmFPAfileDefineFromArgs (&status, config, "PSPHOT.INPUT.CFF", "FORCE")) {
     154            psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.INPUT.CFF");
     155            return status;
     156        }
     157    }
     158
    152159    if (psMetadataLookupPtr(NULL, config->arguments, "SRCTEXT")) {
    153160        // XXX cannot use pmFPAfileDefineFromArgs: this is explicitly a FITS-based I/O function
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotEfficiency.c

    r34353 r37066  
    7171                continue;
    7272            }
    73             float flux = normModel->modelFlux(normModel->params); // Total flux for peak of 1.0
     73            float flux = normModel->class->modelFlux(normModel->params); // Total flux for peak of 1.0
    7474            psFree(normModel);
    7575            if (!isfinite(flux)) {
     
    424424                    continue;
    425425                }
    426                 float sourceRadius = PS_MAX(radius, model->modelRadius(model->params, minFlux)); // Radius for source
     426                float sourceRadius = PS_MAX(radius, model->class->modelRadius(model->params, minFlux)); // Radius for source
    427427                psFree(model);
    428428                if (!isfinite(sourceRadius)) {
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotEllipticalContour.c

    r32348 r37066  
    6464        psFree (y);
    6565        psFree (yErr);
     66        source->mode2 |= PM_SOURCE_MODE2_ECONTOUR_FEW_PTS;
    6667        return false;
    6768    }
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotEvalFLT.c

    r17396 r37066  
    5353    }
    5454
    55     keep = model->modelFitStatus(model);
     55    keep = model->class->modelFitStatus(model);
    5656    if (keep) return true;
    5757
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotExtendedSourceAnalysis.c

    r34404 r37066  
    11# include "psphotInternal.h"
    2 
    3 // measure the elliptical radial profile and use this to measure the petrosian parameters for the sources
     2void psphotRadialProfileShowSkips ();
     3
     4// measure the petrosian parameters for the sources
    45
    56// for now, let's store the detections on the readout->analysis for each readout
     
    1516    psAssert (recipe, "missing recipe?");
    1617
    17     // perform full non-linear fits / extended source analysis?
    18     if (!psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANALYSIS")) {
     18    bool doPetrosian = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
     19    bool doAnnuli    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
     20
     21    // measure petrosians?
     22    if (!doPetrosian && !doAnnuli) {
    1923        psLogMsg ("psphot", PS_LOG_INFO, "skipping extended source measurements\n");
    2024        return true;
     
    3337}
    3438
     39/*** for the moment, this test code : it is not thread safe ***/
     40int    Nall = 0;
     41int  Nskip1 = 0;
     42int  Nskip2 = 0;
     43int  Nskip3 = 0;
     44int  Nskip4 = 0;
     45int  Nskip5 = 0;
     46int  Nskip6 = 0;
     47
     48# define SKIP(VALUE) { VALUE++; continue; }
     49
    3550// aperture-like measurements for extended sources
    3651bool psphotExtendedSourceAnalysisReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe) {
     
    110125
    111126// set this to 0 to run without threading
    112 # if (1)           
     127# if (0)           
    113128            if (!psThreadJobAddPending(job)) {
    114129                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     
    164179    psLogMsg ("psphot", PS_LOG_INFO, "  %d annuli\n", Nannuli);
    165180
     181# if (PS_TRACE_ON)
     182    fprintf (stderr, "ext analysis skipped @ 1  : %d\n", Nskip1);
     183    fprintf (stderr, "ext analysis skipped @ 2  : %d\n", Nskip2);
     184    fprintf (stderr, "ext analysis skipped @ 3  : %d\n", Nskip3);
     185    fprintf (stderr, "ext analysis skipped @ 4  : %d\n", Nskip4);
     186    fprintf (stderr, "ext analysis skipped @ 5  : %d\n", Nskip5);
     187    fprintf (stderr, "ext analysis skipped @ 6  : %d\n", Nskip6);
     188#endif
     189
     190    psphotRadialProfileShowSkips ();
     191
    166192    psphotVisualShowResidualImage (readout, false);
    167193
    168     bool doPetrosian    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
    169     if (doPetrosian) {
    170         psphotVisualShowPetrosians (sources);
    171     }
     194    psphotVisualShowPetrosians (sources);
    172195
    173196    return true;
     
    190213    float skynoise          = PS_SCALAR_VALUE(job->args->data[4],F32);
    191214
    192     // S/N limit to perform full non-linear fits
    193     float SN_LIM = psMetadataLookupF32 (&status, recipe, "EXTENDED_SOURCE_SN_LIM");
    194 
    195     // which extended source analyses should we perform?
    196215    bool doPetrosian    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
    197     bool doAnnuli       = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
    198     bool doPetroStars   = psMetadataLookupBool (&status, recipe, "PETROSIAN_FOR_STARS");
    199216
    200217    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     
    207224        pmSource *source = sources->data[i];
    208225
    209         // if we have checked the source validity on the basis of the object set, then
    210         // we either skip these tests below or we skip the source completely
    211         if (source->tmpFlags & PM_SOURCE_TMPF_PETRO_SKIP) continue;
    212         if (source->tmpFlags & PM_SOURCE_TMPF_PETRO_KEEP) goto keepSource;
    213 
    214         // skip PSF-like and non-astronomical objects
    215         if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
    216         if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
    217         if (source->mode & PM_SOURCE_MODE_DEFECT) continue;
    218         if (source->mode & PM_SOURCE_MODE_SATSTAR) continue;
    219 
    220         // skip saturated stars modeled with a radial profile
    221         if (source->mode2 & PM_SOURCE_MODE2_SATSTAR_PROFILE) continue;
    222 
    223         // optionally allow non-extended objects to get petrosians as well
    224         if (!doPetroStars) {
    225             if (!(source->mode & PM_SOURCE_MODE_EXT_LIMIT)) continue;
    226             if (source->type == PM_SOURCE_TYPE_STAR) continue;
    227         }
    228 
    229         // limit selection to some SN limit
    230         // assert (source->peak); // how can a source not have a peak?
    231         // limit selection to some SN limit
    232         bool skipSource = false;
    233         if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    234             skipSource = (source->moments->KronFlux < SN_LIM * source->moments->KronFluxErr);
    235         } else {
    236             skipSource = (sqrt(source->peak->detValue) < SN_LIM);
    237         }
    238         if (skipSource) continue;
    239 
    240         // limit selection by analysis region (this automatically apply
    241         if (source->peak->x < region->x0) continue;
    242         if (source->peak->y < region->y0) continue;
    243         if (source->peak->x > region->x1) continue;
    244         if (source->peak->y > region->y1) continue;
    245 
    246     keepSource:
     226        Nall ++;
     227
     228        // rules for measuring petrosian parameters for specific objects are set in
     229        // psphotChooseAnalysisOptions.c
     230        if (!(source->tmpFlags & PM_SOURCE_TMPF_PETRO)) SKIP (Nskip1);
     231
     232        // limit selection by analysis region (XXX move this into psphotChooseAnalysisOption?)
     233        if (source->peak->x < region->x0) SKIP (Nskip2);
     234        if (source->peak->y < region->y0) SKIP (Nskip3);
     235        if (source->peak->x > region->x1) SKIP (Nskip4);
     236        if (source->peak->y > region->y1) SKIP (Nskip5);
    247237
    248238        // replace object in image
     
    259249        pmSourceRedefinePixels (source, readout, source->peak->xf, source->peak->yf, 1.5*radius);
    260250
    261         // if we request any of these measurements, we require the radial profile
    262         if (doPetrosian || doAnnuli) {
    263             if (!psphotRadialProfile (source, recipe, skynoise, maskVal)) {
    264                 // all measurements below require the radial profile; skip them all
    265                 // re-subtract the object, leave local sky
    266                 psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    267                 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    268                 continue;
    269             }
    270             Nannuli ++;
    271             source->mode |= PM_SOURCE_MODE_RADIAL_FLUX;
    272         }
     251        // measure the radial profile
     252        if (!psphotRadialProfile (source, recipe, skynoise, maskVal)) {
     253          // re-subtract the object, leave local sky
     254          psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
     255          pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     256          SKIP (Nskip6);
     257        }
     258
     259        Nannuli ++;
     260        source->mode |= PM_SOURCE_MODE_RADIAL_FLUX;
    273261
    274262        // Petrosian Mags
    275263        if (doPetrosian) {
    276             if (!psphotPetrosian (source, recipe, skynoise, maskVal)) {
    277                 psTrace ("psphot", 5, "FAILED petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    278             } else {
    279                 psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    280                 Npetro ++;
    281                 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS;
    282             }
     264          if (!psphotPetrosian (source, recipe, skynoise, maskVal)) {
     265            psTrace ("psphot", 5, "FAILED petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
     266          } else {
     267            psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
     268            Npetro ++;
     269            source->mode |= PM_SOURCE_MODE_EXTENDED_STATS;
     270          }
    283271        }
    284272
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotExtendedSourceFits.c

    r35769 r37066  
    111111    }
    112112
     113    float fitNsigmaConv = psMetadataLookupF32 (&status, recipe, "EXT_FIT_NSIGMA_CONV"); // number of sigma for the convolution
     114    if (!status || !isfinite(fitNsigmaConv) || fitNsigmaConv <= 0) {
     115        fitNsigmaConv = 5.0;
     116    }
     117
    113118    bool chisqConvergence = psMetadataLookupBool (&status, recipe, "LMM_FIT_CHISQ_CONVERGENCE"); // Fit tolerance
    114119    if (!status) {
     
    123128    }
    124129
     130    // perform full extended source non-linear fits?
     131    bool isInteractive = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_FITS_INTERACTIVE");
     132    if (!status) isInteractive = false;
     133
    125134    // Define source fitting parameters for extended source fits
    126135    pmSourceFitOptions *fitOptions = pmSourceFitOptionsAlloc();
    127     fitOptions->mode           = PM_SOURCE_FIT_EXT;
     136    fitOptions->mode           = PM_SOURCE_FIT_EXT_AND_SKY;
    128137    fitOptions->saveCovariance = true;  // XXX make this a user option?
    129138    fitOptions->covarFactor    = psImageCovarianceFactorForAperture(readout->covariance, 10.0); // Covariance matrix
     
    131140    fitOptions->minTol         = fitMinTol;
    132141    fitOptions->maxTol         = fitMaxTol;
     142    fitOptions->nsigma         = fitNsigmaConv;
    133143
    134144    fitOptions->gainFactorMode   = gainFactorMode;
    135145    fitOptions->chisqConvergence = chisqConvergence;
     146    fitOptions->isInteractive    = isInteractive;
     147
     148    // use poissonian errors or local-sky errors
     149    fitOptions->poissonErrors = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_FITS_POISSON");
     150    if (!status) fitOptions->poissonErrors = true;
    136151
    137152    // maskVal is used to test for rejected pixels, and must include markVal
     
    278293            psArrayAdd(job->args, 1, cells->data[j]); // sources
    279294            psArrayAdd(job->args, 1, models);
     295
    280296            // Allocate a metadata iterator here because psMetadataIteratorAlloc/Free are not thread safe
    281297            psMetadataIterator *iter = psMetadataIteratorAlloc (models, PS_LIST_HEAD, NULL);
     
    296312            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfail
    297313
    298 // set this to 0 to run without threading
    299 # if (1)           
    300             if (!psThreadJobAddPending(job)) {
    301                 psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    302                 psFree(AnalysisRegion);
    303                 psFree (fitOptions);
    304                 psFree (models);
    305                 psphotSersicModelClassCleanup();
    306                 return false;
    307             }
    308 # else
    309             if (!psphotExtendedSourceFits_Threaded(job)) {
    310                 psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    311                 psFree(AnalysisRegion);
    312                 psFree (fitOptions);
    313                 psFree (models);
    314                 psphotSersicModelClassCleanup();
    315                 return false;
     314// XXX TEST
     315            if (!isInteractive) {
     316                if (!psThreadJobAddPending(job)) {
     317                    psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     318                    psFree(AnalysisRegion);
     319                    psFree (fitOptions);
     320                    psFree (models);
     321                    psphotSersicModelClassCleanup();
     322                    return false;
     323                }
     324            } else {
     325                // run without threading
     326                if (!psphotExtendedSourceFits_Threaded(job)) {
     327                    psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     328                    psFree(AnalysisRegion);
     329                    psFree (fitOptions);
     330                    psFree (models);
     331                    psphotSersicModelClassCleanup();
     332                    return false;
     333                }
     334                psScalar *scalar = NULL;
     335                scalar = job->args->data[9];
     336                Next += scalar->data.S32;
     337                scalar = job->args->data[10];
     338                Nconvolve += scalar->data.S32;
     339                scalar = job->args->data[11];
     340                NconvolvePass += scalar->data.S32;
     341                scalar = job->args->data[12];
     342                Nplain += scalar->data.S32;
     343                scalar = job->args->data[13];
     344                NplainPass += scalar->data.S32;
     345                scalar = job->args->data[14];
     346                Nfaint += scalar->data.S32;
     347                scalar = job->args->data[15];
     348                Nfail += scalar->data.S32;
     349                psFree(job->args->data[3]); // iterator allocated above
     350                psFree(job);
    316351            }
    317             psScalar *scalar = NULL;
    318             scalar = job->args->data[9];
    319             Next += scalar->data.S32;
    320             scalar = job->args->data[10];
    321             Nconvolve += scalar->data.S32;
    322             scalar = job->args->data[11];
    323             NconvolvePass += scalar->data.S32;
    324             scalar = job->args->data[12];
    325             Nplain += scalar->data.S32;
    326             scalar = job->args->data[13];
    327             NplainPass += scalar->data.S32;
    328             scalar = job->args->data[14];
    329             Nfaint += scalar->data.S32;
    330             scalar = job->args->data[15];
    331             Nfail += scalar->data.S32;
    332             psFree(job->args->data[3]); // iterator allocated above
    333             psFree(job);
    334 # endif
    335352        }
    336353
     
    418435    // psTraceSetLevel ("psLib.math.psMinimizeLMChi2_Alt", 5);
    419436
     437    pmModelStatus badModel = PM_MODEL_STATUS_NONE;
     438    badModel |= PM_MODEL_STATUS_BADARGS;
     439    badModel |= PM_MODEL_STATUS_OFFIMAGE;
     440    badModel |= PM_MODEL_STATUS_NAN_CHISQ;
     441    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GUESS;
     442    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GRID;
     443    badModel |= PM_MODEL_PCM_FAIL_GUESS;
     444
    420445    // choose the sources of interest
    421446    for (int i = 0; i < sources->n; i++) {
     
    423448        pmSource *source = sources->data[i];
    424449
    425         // skip PSF-like and non-astronomical objects
    426         if (!(source->mode & PM_SOURCE_MODE_EXT_LIMIT)) continue;
    427         if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
    428         if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
    429 
    430         // skip saturated stars modeled with a radial profile
    431         if (source->mode2 & PM_SOURCE_MODE2_SATSTAR_PROFILE) continue;
    432 
    433         // XXX this should use peak?
     450        // rules for measuring petrosian parameters for specific objects are set in
     451        // psphotChooseAnalysisOptions.c
     452        if (!(source->tmpFlags & PM_SOURCE_TMPF_EXT_FIT)) continue;
     453
     454        // limit selection by analysis region (XXX move this into psphotChooseAnalysisOption?)
    434455        if (source->peak->x < region->x0) continue;
    435456        if (source->peak->y < region->y0) continue;
    436457        if (source->peak->x > region->x1) continue;
    437458        if (source->peak->y > region->y1) continue;
    438 
    439 
    440         // XXX for a test, just do the obvious trail
    441         // XXX if (source->peak->xf < 1100) continue;
    442         // XXX if (source->peak->xf > 1400) continue;
    443         // XXX if (source->peak->yf >  245) continue;
    444459
    445460        // replace object in image
     
    452467        psphotSetRadiusMomentsExact(&fitRadius, &windowRadius, readout, source, markVal); // NOTE : 6 allocs
    453468
    454         // XXX WATCH OUT HERE!!
    455         // fitRadius = 30;
    456 
    457469        // UPDATE : we have changed the moments calculation.  There is now an iteration within
    458470        // psphotKronMasked to determine moments appropriate for a larger object.  The values
     
    464476            source->modelFits = psArrayAllocEmpty (models->list->n);
    465477        }
     478
     479# ifdef TEST_OBJECT
     480        bool testObject = false;
     481        testObject |= ((fabs(source->peak->xf -  179) < 5) && (fabs(source->peak->yf - 1138) < 5));
     482        if (testObject) {
     483            fprintf (stderr, "test object @ %f, %f\n", source->peak->xf, source->peak->yf);
     484            psTraceSetLevel ("psModules.objects.pmPCM_MinimizeChisq", 5);
     485            psTraceSetLevel ("psphot.psphotExtendedSourceFits_Threaded", 5);
     486        }
     487# endif
    466488
    467489        // loop here over the models chosen for each source (exclude by S/N)
     
    479501          assert (status);
    480502
    481           // limit selection to some SN limit
    482           bool skipSource = false;
    483           if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    484               skipSource = (source->moments->KronFlux < FIT_SN_LIM * source->moments->KronFluxErr);
    485           } else {
    486               skipSource = (sqrt(source->peak->detValue) < FIT_SN_LIM);
    487           }
    488           if (skipSource) {
     503          // limit selection to some SN limit for specific models (this value only applies if > EXTENDED_SOURCE_SN_LIM)
     504          if (isfinite(FIT_SN_LIM)) {
     505            if (source->moments->KronFlux < FIT_SN_LIM * source->moments->KronFluxErr) {
    489506              Nfaint ++;
    490507              continue;
     508            }
    491509          }
     510
     511          source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_RUN;
    492512
    493513          // check on the model type
     
    507527                  psTrace ("psphot", 5, "failed to fit psf-conv model for object at %f, %f", source->moments->Mx, source->moments->My);
    508528                  Nfail ++;
     529                  source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_FAIL;
    509530                  continue;
    510531              }
     
    512533                       source->moments->Mx, source->moments->My, pmModelClassGetName (modelFit->type), modelFit->chisq, modelFit->nPix, modelFit->nIter);
    513534              Nconvolve ++;
    514               if (!(modelFit->flags & (PM_MODEL_STATUS_BADARGS | PM_MODEL_STATUS_NONCONVERGE | PM_MODEL_STATUS_OFFIMAGE))) {
     535              if (!(modelFit->flags & badModel)) {
    515536                  NconvolvePass ++;
    516537                  source->mode |= PM_SOURCE_MODE_EXTENDED_FIT;
     
    526547                      Nfail ++;
    527548                      doneFits = true;
     549                      source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_FAIL;
    528550                      continue;
    529551                  }
    530552                  psTrace ("psphot", 4, "fit plain model for %f, %f : %s chisq = %f (npix: %d, niter: %d)\n", source->moments->Mx, source->moments->My, pmModelClassGetName (modelFit->type), modelFit->chisq, modelFit->nPix, modelFit->nIter);
    531553                  Nplain ++;
    532                   if (!(modelFit->flags & (PM_MODEL_STATUS_BADARGS | PM_MODEL_STATUS_NONCONVERGE | PM_MODEL_STATUS_OFFIMAGE))) {
     554                  if (!(modelFit->flags & badModel)) {
    533555                      NplainPass ++;
    534556                      source->mode |= PM_SOURCE_MODE_EXTENDED_FIT;
     
    544566                      float Ymax = PAR[PM_PAR_YPOS] + 0.5*PAR[PM_PAR_LENGTH]*cos(PAR[PM_PAR_THETA]);
    545567
    546                       if (false && (source->peak->xf > 1100) &&
    547                           (source->peak->xf < 1400) &&
    548                           (source->peak->yf < 245)) {
     568                      if ((fabs(source->peak->xf - 2572) < 20) && (fabs(source->peak->yf - 5874) < 20)) {
    549569                          fprintf (stderr, "src vs fit : %d %d - %d %d | %f %f - %f %f\n",
    550570                                   source->pixels->col0, source->pixels->row0,
     
    556576                          fprintf (stderr, "update window : %f %f : %f -> %f\n", source->peak->xf, source->peak->yf, fitRadius, 2*fitRadius);
    557577                          psphotSetWindowTrail (&fitRadius, &windowRadius, readout, source, markVal, fitRadius*2.0);
     578                          source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_RETRY;
    558579                      }
    559580                  }
    560581              }
    561582          }
    562           // XXX really need to do this in a cleaner way:
    563           if (!modelFit) continue;
     583          psAssert (modelFit, "modelFit not set?");
    564584
    565585          // test for fit quality / result
     
    570590        }
    571591
     592        // we are allowed to fit both stars and non-stars here -- if we have fitted
     593        // something which we think is a star, we should use that model to subtract the
     594        // object from the image.
     595        if (source->type == PM_SOURCE_TYPE_STAR) {
     596          // ensure the modelPSF is cached
     597          pmSourceCacheModel (source, maskVal);
     598          pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     599          continue;
     600        }
     601
    572602        // evaluate the relative quality of the models, choose one
     603        // the PSF model might be the best fit : allow it to succeed
    573604        float minChisq = NAN;
    574605        int minModel = -1;
     
    576607            pmModel *model = source->modelFits->data[i];
    577608
     609            // skip the really bad fits
    578610            if (!(model->flags & PM_MODEL_STATUS_FITTED)) continue;
    579 
    580             if (model->flags & (PM_MODEL_STATUS_BADARGS)) continue;
    581             if (model->flags & (PM_MODEL_STATUS_NONCONVERGE)) continue;
    582             if (model->flags & (PM_MODEL_STATUS_OFFIMAGE)) continue;
     611            if (model->flags & badModel) continue;
     612
     613            // if (model->flags & (PM_MODEL_STATUS_NONCONVERGE)) continue;
    583614
    584615            if ((minModel < 0) || (model->chisq < minChisq)) {
     
    598629          pmSourceCacheModel (source, maskVal);
    599630
     631# if (PS_TRACE_ON)
     632          pmModel *model = source->modelFits->data[0];
     633          int flags = 0xffffffff;
     634          if (model) {
     635            flags = model->flags;
     636          }
     637          fprintf (stderr, "failed to fit extended source model to object %d @ %f, %f (%x)\n", source->id, source->moments->Mx, source->moments->My, flags);
     638#endif
    600639          pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    601640
     641          source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_NONE;
    602642          continue;
    603643        }
     
    615655        // cache the model flux
    616656        if (source->modelEXT->isPCM) {
    617             pmPCMCacheModel (source, maskVal, psfSize);
     657            // fprintf (stderr, "subtract PCM extended source model for object %d @ %f, %f\n", source->id, source->moments->Mx, source->moments->My);
     658            pmPCMCacheModel (source, maskVal, psfSize, fitOptions->nsigma);
    618659        } else {
     660            // fprintf (stderr, "subtract non-PCM extended source model for object %d @ %f, %f\n", source->id, source->moments->Mx, source->moments->My);
    619661            pmSourceCacheModel (source, maskVal);
    620662        }
     663        source->modelEXT->flags |= PM_MODEL_BEST_FIT;
    621664
    622665        // subtract the best fit from the object, leave local sky
     
    625668        psTrace ("psphot", 4, "best ext model for %f, %f : %s chisq = %f\n", source->moments->Mx, source->moments->My, pmModelClassGetName (source->modelEXT->type), source->modelEXT->chisq);
    626669        psTrace ("psphot", 5, "extended source model for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
     670
     671# ifdef TEST_OBJECT
     672        if (testObject) {
     673            psTraceSetLevel ("psModules.objects.pmPCM_MinimizeChisq", 0);
     674            psTraceSetLevel ("psphot.psphotExtendedSourceFits_Threaded", 0);
     675        }
     676# endif
    627677    }
    628678
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotImageLoop.c

    r34258 r37066  
    132132                    }
    133133                    break;
     134                  case PSPHOT_FULL_FORCE:
     135                    if (!psphotFullForceReadout (config, view, "PSPHOT.INPUT")) {
     136                        psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
     137                        psFree (view);
     138                        return false;
     139                    }
     140                    break;
    134141                  case PSPHOT_MAKE_PSF:
    135142                    if (!psphotMakePSFReadout (config, view, "PSPHOT.INPUT")) {
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotKronIterate.c

    r35769 r37066  
    166166    }
    167167
     168# if (PS_TRACE_ON)
    168169    fprintf (stderr, "--- starting KRON ---\n");
     170#endif
    169171
    170172    // We measure the Kron Radius on a smoothed copy of the readout image
     
    530532            source->moments->KronFlux  = NAN;
    531533            source->moments->KronFluxErr  = NAN;
     534            source->moments->KronFinner = NAN;
     535            source->moments->KronFouter = NAN;
    532536            return false;
    533537        }
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotLoadPSF.c

    r29936 r37066  
    11# include "psphotInternal.h"
     2
     3// PSPHOT.PSF.LOAD vs input file -- see note at top
     4bool psphotLoadPSF (pmConfig *config, const pmFPAview *view, const char *filerule) {
     5
     6    int num = psphotFileruleCount(config, filerule);
     7
     8    // loop over the available readouts
     9    for (int i = 0; i < num; i++) {
     10
     11        // Generate the mask and weight images, including the user-defined analysis region of interest
     12        if (!psphotLoadPSFReadout (config, view, filerule, "PSPHOT.PSF.LOAD", i)) {
     13            psError (PSPHOT_ERR_CONFIG, false, "failed to load PSF model for PSPHOT.PSF.LOAD entry %d", i);
     14            return false;
     15        }
     16    }
     17    return true;
     18}
    219
    320// NOTE : pmPSF_IO.c functions must load the psf model onto the chip->analysis metadata because
     
    5875    return true;
    5976}
    60 
    61 // PSPHOT.PSF.LOAD vs input file -- see note at top
    62 bool psphotLoadPSF (pmConfig *config, const pmFPAview *view, const char *filerule) {
    63 
    64     int num = psphotFileruleCount(config, filerule);
    65 
    66     // loop over the available readouts
    67     for (int i = 0; i < num; i++) {
    68 
    69         // Generate the mask and weight images, including the user-defined analysis region of interest
    70         if (!psphotLoadPSFReadout (config, view, filerule, "PSPHOT.PSF.LOAD", i)) {
    71             psError (PSPHOT_ERR_CONFIG, false, "failed to load PSF model for PSPHOT.PSF.LOAD entry %d", i);
    72             return false;
    73         }
    74     }
    75     return true;
    76 }
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotLoadSRCTEXT.c

    r32348 r37066  
    7373            dPAR[PM_PAR_I0]   = 0.0;
    7474
    75             pmPSF_AxesToModel (PAR, axes, modelType);
     75            pmPSF_AxesToModel (PAR, axes, model->class->useReff);
    7676
    7777            float peakFlux    = 1.0;
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotMakeFluxScale.c

    r30624 r37066  
    3838            } else {
    3939                // measure the fitMag for this model
    40                 fitSum = model->modelFlux (model->params);
     40                fitSum = model->class->modelFlux (model->params);
    4141            }
    4242            if (fitSum < 1.e-6) continue;
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotMergeSources.c

    r34266 r37066  
    3939    psAssert (newSources, "missing sources?");
    4040
    41     // XXX TEST:
    42     if (detections->allSources) {
    43         psphotMaskCosmicRayFootprintCheck(detections->allSources);
    44     }
    45     if (detections->newSources) {
    46         psphotMaskCosmicRayFootprintCheck(detections->newSources);
    47     }
    48 
    4941    if (!detections->allSources) {
    5042        detections->allSources = psArrayAllocEmpty(newSources->n);
     
    6557// Merge the externally supplied sources with the existing sources.  Mark them as having mode
    6658// PM_SOURCE_MODE_EXTERNAL.
     59
     60// XXX this function needs to be updated slightly for psphotFullForce:
     61// * load the additional parameters to guide the new concepts
    6762
    6863// XXX This function needs to be updated to loop over set of input files.  At the moment, we
     
    7368    bool status;
    7469    pmDetections *extCMF = NULL;
     70    pmDetections *extCFF = NULL;
    7571    psArray *extSourcesTXT = NULL;
    7672    int index = 0;
     
    10298    {
    10399        pmReadout *readoutCMF = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT.CMF");
    104         if (!readoutCMF) goto loadTXT;
     100        if (!readoutCMF) goto loadCFF;
    105101
    106102        extCMF = psMetadataLookupPtr (NULL, readoutCMF->analysis, "PSPHOT.DETECTIONS");
     
    125121    }
    126122
     123loadCFF:
     124    // load data from input CFF file:
     125    {
     126        pmReadout *readoutCFF = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT.CFF");
     127        if (!readoutCFF) goto loadTXT;
     128
     129        extCFF = psMetadataLookupPtr (NULL, readoutCFF->analysis, "PSPHOT.DETECTIONS");
     130        if (extCFF) {
     131            psF32 exptime = psMetadataLookupF32(NULL, readout->parent->concepts, "CELL.EXPOSURE");
     132            for (int i = 0; i < extCFF->allSources->n; i++) {
     133                pmSource *source = extCFF->allSources->data[i];
     134
     135                // setting this bit not only tracks the inputs, it makes pmSourceMoments
     136                // keep the Mx,My values for the centroid. 
     137                source->mode |= PM_SOURCE_MODE_EXTERNAL;
     138
     139                // source->peak->detValue,rawFlux,smoothFlux all set to input flux value which is scaled
     140                // to 1 second exposure time. Scale to this image's exposure.
     141                source->peak->rawFlux    *= exptime;
     142                source->peak->smoothFlux *= exptime;
     143                source->peak->detValue   *= exptime;
     144                // source->peak->xf,yf, moments->Mx,My all set to input position
     145
     146                // drop the loaded source modelPSF
     147                psFree (source->modelPSF);
     148                source->modelPSF = NULL;
     149                source->imageID = index;
     150
     151                psArrayAdd (detections->newSources, 100, source);
     152            }
     153        }
     154    }
     155
    127156loadTXT:
    128157
     
    157186    psFree (detections);
    158187
    159     if (!extCMF && !extSourcesTXT) {
     188    if (!(extCMF || extCFF || extSourcesTXT)) {
    160189        psLogMsg ("psphot", 3, "no external sources for this readout");
    161190        return true;
     
    163192
    164193    int nCMF = extCMF        ? extCMF->allSources->n        : 0;
    165     int nTXT = extSourcesTXT ? extSourcesTXT->n : 0;
    166 
    167     psLogMsg ("psphot", 3, "%d external sources (%d cmf, %d text) merged to yield %ld total sources",
    168               nCMF + nTXT, nCMF, nTXT, sources->n);
     194    int nCFF = extCFF        ? extCFF->allSources->n        : 0;
     195    int nTXT = extSourcesTXT ? extSourcesTXT->n             : 0;
     196
     197    psLogMsg ("psphot", 3, "%d external sources (%d cmf, %d cff, %d text) merged to yield %ld total sources",
     198              nCMF + nCFF + nTXT, nCMF, nCFF, nTXT, sources->n);
    169199    return true;
    170200}
     
    812842// array containing the child sources.  XXX currently, this is only used by psphotStackReadout
    813843// (sources go on allSources so that psphotChoosePSF can be called repeatedly)
    814 psArray *psphotSourceChildrenByObject (pmConfig *config, const pmFPAview *view, const char *filerule, psArray *objectsSrc) {
     844psArray *psphotSourceChildrenByObject (pmConfig *config, const pmFPAview *view, const char *filerule, psArray *objectsSrc, bool sourcesSubtracted) {
    815845
    816846    bool status;
     
    919949            // child sources have not been subtracted in this image, but this flag may be raised if
    920950            // they were subtracted in the parent's image
    921             sourceOut->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;
     951            // XXX NOTE : in the pre-20130914 version of psphotStack, we carried a copy of the pixels
     952            // generated before the subtraction took place (and then we smoothed to match the desired PSF). 
     953            // in the new version, we copy the image after subtraction; we need to distinguish these cases
     954            if (!sourcesSubtracted) {
     955                sourceOut->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;
     956            }
    922957
    923958            // set the output detections:
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotModelTestReadout.c

    r35769 r37066  
    125125
    126126            // get the source moments
    127             status = pmSourceMoments (source, radius, 0.25*radius, 0.0, MIN_KRON_RADIUS, maskVal);
     127          status = pmSourceMoments (source, radius, 0.25*radius, 0.0, MIN_KRON_RADIUS, maskVal);
    128128            if (!status) psAbort("psSourceMoments error");
    129129
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotPetrosianRadialBins.c

    r31154 r37066  
    3636    pmSourceRadialProfile *profile = source->extpars->petProfile;
    3737
    38     float skyModelErrorSQ = PS_SQR(skynoise);
     38    // float skyModelErrorSQ = PS_SQR(skynoise);
    3939
    4040    int nMax = radiusMax;
     
    133133        if (radius->data.F32[i] > Rmax) {
    134134            // calculate the value for the nOut bin
    135             float value, dvalue;
     135            float value; // , dvalue;
    136136            if (values->n > 0) {
    137137                psVectorStats (stats, values, NULL, NULL, 0);
    138138                value = stats->robustMedian;
    139                 dvalue = stats->robustStdev;
     139                // dvalue = stats->robustStdev;
    140140            } else {
    141141                value = NAN;
    142                 dvalue = NAN;
     142                // dvalue = NAN;
    143143            }
    144144
    145145            binSB->data.F32[nOut] = value;
    146             binSBstdev->data.F32[nOut] = sqrt(PS_SQR(dvalue) / values->n + skyModelErrorSQ);
     146            // binSBstdev->data.F32[nOut] = sqrt(PS_SQR(dvalue) / values->n + skyModelErrorSQ);
     147            binSBstdev->data.F32[nOut] = skynoise / sqrt(values->n);
    147148            binFill->data.F32[nOut] = values->n / binArea->data.F32[nOut];
    148149
     
    185186        psFree(values);
    186187        psFree(stats);
     188        source->mode2 |= PM_SOURCE_MODE2_RADBIN_NAN_CENTER;
    187189        return true;
    188190    }
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotPetrosianStats.c

    r34086 r37066  
    66// generate the Petrosian radius and flux from the mean surface brightness (r_i)
    77
     8float InterpolateValuesQuadratic (float *Xin, float *Yin, float X);
    89float InterpolateValues     (float X0, float Y0, float X1, float Y1, float X);
    910float InterpolateValuesErrX (float X0, float Y0, float X1, float Y1, float X, float dX0, float dX1);
     
    2021    if (!profile->binSB) {
    2122        psLogMsg ("psphot", PS_LOG_DETAIL, "no petrosian profile, skipping source %f, %f", source->peak->xf, source->peak->yf);
     23        source->mode2 |= PM_SOURCE_MODE2_PETRO_NO_PROFILE;
    2224        return true;
    2325    }
     
    5355    float dFsum2 = 0.0;
    5456
    55     float nSigma = 3.0;
     57    float nSigma = 2.0;
    5658    int lowestSignificantRadius = 0;
    5759    float lowestSignificantRatio = 1.0;
     
    117119                petRadius    = InterpolateValues     (1.0, 0.0, petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO);
    118120                petRadiusErr = InterpolateValuesErrX (1.0, 0.0, petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO, 0.0, petRatioErr->data.F32[nOut]);
    119             } else {
    120                 petRadius    = InterpolateValues     (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO);
    121                 petRadiusErr = InterpolateValuesErrX (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO, petRatioErr->data.F32[nOut-1], petRatioErr->data.F32[nOut]);
     121                source->mode2 |= PM_SOURCE_MODE2_PETRO_RATIO_ZEROBIN;
     122            } else {
     123              // petRadius    = InterpolateValues     (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO);
     124              if (nOut > 1) {
     125                petRadius    = InterpolateValuesQuadratic (&petRatio->data.F32[nOut-2], &refRadius->data.F32[nOut-2],   PETROSIAN_RATIO);
     126              } else {
     127                petRadius    = InterpolateValuesQuadratic (&petRatio->data.F32[nOut-3], &refRadius->data.F32[nOut-3], PETROSIAN_RATIO);
     128              }
     129# if (PS_TRACE_ON)
     130              float petRadiusLinear = InterpolateValues     (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO);
     131              if (fabs(petRadius - petRadiusLinear) > fabs(refRadius->data.F32[nOut] - refRadius->data.F32[nOut-1])) {
     132                fprintf (stderr, "big difference : %f vs %f\n", petRadius, petRadiusLinear);
     133              }
     134#endif
     135              petRadiusErr = InterpolateValuesErrX (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO, petRatioErr->data.F32[nOut-1], petRatioErr->data.F32[nOut]);
    122136            }
    123137            above = false;
     
    148162            fprintf (stderr, "nan pet radius\n");
    149163        }
     164        source->mode2 |= PM_SOURCE_MODE2_PETRO_INSIG_RATIO;
    150165    }
    151166
     
    180195    bool found50 = false;
    181196    bool found90 = false;
     197
    182198    // XXX use bisection to do this faster:
    183199    for (int i = 0; !(found50 && found90) && i < refRadius->n; i++) {
     
    235251}
    236252
     253// Lagrange's form of the interpolating polynomial...
     254float InterpolateValuesQuadratic (float *Xin, float *Yin, float X) {
     255
     256  float dx01 = Xin[0] - Xin[1];
     257  float dx02 = Xin[0] - Xin[2];
     258  float dx12 = Xin[1] - Xin[2];
     259
     260  float dx0  = X - Xin[0];
     261  float dx1  = X - Xin[1];
     262  float dx2  = X - Xin[2];
     263
     264  float y0 = Yin[0]*dx1*dx2/(dx01*dx02);
     265  float y1 = Yin[1]*dx0*dx2/(dx01*dx12); // need - sign
     266  float y2 = Yin[2]*dx0*dx1/(dx02*dx12);
     267
     268  float Y = y0 - y1 + y2;
     269  return Y;
     270}
     271
    237272float InterpolateValues (float X0, float Y0, float X1, float Y1, float X) {
    238273    float dydx = (Y1 - Y0) / (X1 - X0);
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotRadialBins.c

    r34226 r37066  
    4444    psVector *radMin = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER");
    4545    psVector *radMax = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER");
    46     if (!radMin || !radMin->n) {
    47         psError (PSPHOT_ERR_CONFIG, true, "error in definition of annular bins (radMin missing or empty)");
    48         return false;
    49     }
    50     if (!radMax || !radMax->n) {
    51         psError (PSPHOT_ERR_CONFIG, true, "error in definition of annular bins (radMax missing or empty)");
    52         return false;
    53     }
     46    psAssert (radMin, "RADIAL.ANNULAR.BINS.LOWER is missing from recipe");
     47    psAssert (radMin->n, "RADIAL.ANNULAR.BINS.LOWER is empty in recipe");
     48    psAssert (radMax, "RADIAL.ANNULAR.BINS.UPPER is missing from recipe");
     49    psAssert (radMax->n, "RADIAL.ANNULAR.BINS.UPPER is empty in recipe");
    5450
    5551    psVector *binSB      = psVectorAllocEmpty(radMin->n, PS_TYPE_F32); // surface brightness of radial bin
     
    161157        psFree(values);
    162158        psFree(stats);
     159        source->mode2 |= PM_SOURCE_MODE2_RADBIN_NAN_CENTER;
    163160        return true;
    164161    }
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotRadialProfile.c

    r32348 r37066  
    11# include "psphotInternal.h"
     2
     3static int Nskip1 = 0;
     4static int Nskip2 = 0;
     5static int Nskip3 = 0;
     6static int Nskip4 = 0;
     7static int Nskip5 = 0;
     8
     9# define SKIP(VALUE) { VALUE++; return false; }
    210
    311bool psphotRadialProfile (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal) {
     
    2331    if (!psphotRadialProfilesByAngles (source, Nsec, Rmax)) {
    2432        psError (PS_ERR_UNKNOWN, false, "failed to measure radial profile for petrosian");
    25         return false;
     33        SKIP (Nskip1);
    2634    }
    2735    // allocate: extpars->radFlux->radii,fluxes,theta
     
    3240    if (!psphotRadiiFromProfiles (source, fluxMin, fluxMax)) {
    3341        psError (PS_ERR_UNKNOWN, false, "failed to measure isophotal radii from profiles");
    34         return false;
     42        SKIP (Nskip2);
    3543    }
    3644    // allocate : extpars->radFlux->isophotalRadii (use profile->radii,fluxes)
     
    4048    if (!psphotEllipticalContour (source)) {
    4149        // psLogMsg ("psphot", 3, "failed to measure elliptical contour");
    42         return false;
     50        SKIP (Nskip3);
    4351    }
    4452    // use extpars->radFlux->isophotalRadii,theta (result in extpars->axes)
     
    4856    if (!psphotEllipticalProfile (source, RAW_RADIUS)) {
    4957        psError (PS_ERR_UNKNOWN, false, "failed to generate elliptical profile");
    50         return false;
     58        SKIP (Nskip4);
    5159    }
    5260    // allocate extpars->ellipticalFlux->radiusElliptical,fluxElliptical (use axes to scale raw pixels)
     
    5563    if (!psphotRadialBins (recipe, source, Rmax, skynoise)) {
    5664        psError (PS_ERR_UNKNOWN, false, "failed to generate radial bins");
    57         return false;
     65        SKIP (Nskip5);
    5866    }
    5967    // allocate extpars->radProfile->binSB, binSBstdv, binSum, binFill, radialBins, area (small lengths)
     
    6270    return true;
    6371}
     72
     73void psphotRadialProfileShowSkips () {
     74# if (PS_TRACE_ON)
     75  fprintf (stderr, "radial profile skipped @ 1  : %d\n", Nskip1);
     76  fprintf (stderr, "radial profile skipped @ 2  : %d\n", Nskip2);
     77  fprintf (stderr, "radial profile skipped @ 3  : %d\n", Nskip3);
     78  fprintf (stderr, "radial profile skipped @ 4  : %d\n", Nskip4);
     79  fprintf (stderr, "radial profile skipped @ 5  : %d\n", Nskip5);
     80#endif
     81}
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotRadiusChecks.c

    r32348 r37066  
    6060    if (radiusFit <= 0) {               // use fixed radius
    6161        if (moments == NULL) {
    62             radiusFit = model->modelRadius(model->params, PSF_FIT_NSIGMA*moments->dSky);
     62            radiusFit = model->class->modelRadius(model->params, PSF_FIT_NSIGMA*moments->dSky);
    6363        } else {
    64             radiusFit = model->modelRadius(model->params, 1.0);
     64            radiusFit = model->class->modelRadius(model->params, 1.0);
    6565        }
    6666        model->fitRadius = (RADIUS_TYPE)(radiusFit + PSF_FIT_PADDING);
     
    9595    if (radiusFit <= 0) {               // use fixed radius
    9696        if (moments == NULL) {
    97             radiusFit = model->modelRadius(model->params, PSF_FIT_NSIGMA*moments->dSky);
     97            radiusFit = model->class->modelRadius(model->params, PSF_FIT_NSIGMA*moments->dSky);
    9898        } else {
    99             radiusFit = model->modelRadius(model->params, 1.0);
     99            radiusFit = model->class->modelRadius(model->params, 1.0);
    100100        }
    101101        model->fitRadius = (RADIUS_TYPE)(radiusFit + PSF_FIT_PADDING);
     
    171171# undef MIN_WINDOW
    172172
     173// XXX EAM : 20130724 : for a test, double the window size parameters
     174// # define MIN_WINDOW 10.0
     175// # define SCALE1 7.0
    173176# define MIN_WINDOW 5.0
    174 # define SCALE1 5.0
     177# define SCALE1 3.0
    175178# define PAD_WINDOW 3.0
    176179
     
    291294    float flux = deep ? EXT_FIT_NSIGMA*EXT_FIT_SKY_SIG : 0.1 * model->params->data.F32[PM_PAR_I0];
    292295
    293     float rawRadius = model->modelRadius (model->params, flux);
     296    float rawRadius = model->class->modelRadius (model->params, flux);
    294297    if (isnan(rawRadius)) return false;
    295298
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotReadout.c

    r34418 r37066  
    316316    psphotSourceSize (config, view, filerule, false); // pass 2 (detections->allSources)
    317317
     318    // XXX currently we are doing both the analysis of the size and the assessment of "fit ext"
     319    // in source size.  this overloads the bit MODE_EXT_LIMIT to mean "fit ext" not just
     320    // "bigger than a PSF"
     321
     322    // decide which source(s) are to be fitted with the extended source analysis code.
     323    psphotChooseAnalysisOptions (config, view, filerule);
     324
    318325    psphotExtendedSourceAnalysis (config, view, filerule); // pass 1 (detections->allSources)
    319326    psphotExtendedSourceFits (config, view, filerule); // pass 1 (detections->allSources)
     
    333340    // calculate source magnitudes
    334341    if (!psphotMagnitudes(config, view, filerule)) { // pass 1 (detections->allSources)
    335       psErrorStackPrint(stderr, "Unable to do magnitudes.");
     342        psErrorStackPrint(stderr, "Unable to do magnitudes.");
    336343        psErrorClear();
    337344    }
     345
     346    // calculate lensing parameters
     347    if (!psphotLensing(config, view, filerule)) {
     348        psErrorStackPrint(stderr, "Unable to do lensing parameters.");
     349        psErrorClear();
     350    }
     351
    338352    if (!psphotEfficiency(config, view, filerule)) { // pass 1
    339353        psErrorStackPrint(stderr, "Unable to determine detection efficiencies from fake sources");
     
    346360    // replace background in residual image
    347361    if (!psphotSkyReplace (config, view, filerule)) { // pass 1
    348       psErrorStackPrint(stderr, "Unable to replace sky");
    349       psErrorClear();
     362        psErrorStackPrint(stderr, "Unable to replace sky");
     363        psErrorClear();
    350364    }
    351365
    352366    // drop the references to the image pixels held by each source
    353367    if (!psphotSourceFreePixels (config, view, filerule)) { // pass 1
    354       psErrorStackPrint(stderr, "Unable to free source pixels");
    355       psErrorClear();
     368        psErrorStackPrint(stderr, "Unable to free source pixels");
     369        psErrorClear();
    356370    }
    357371
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotRoughClass.c

    r32348 r37066  
    8787    if (NX > NY) {
    8888        NXuse = ScaleForClump;
    89         NYuse = (int) (ScaleForClump * (NY / NX) + 0.5);
     89        NYuse = (int) (ScaleForClump * (NX / NY) + 0.5);
    9090    } else {
    9191        NYuse = ScaleForClump;
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotSersicModelClass.c

    r33410 r37066  
    586586            coord->data.F32[1] = (psF32) (i + source->pixels->row0);
    587587
    588             pcm->modelConvFlux->data.F32[i][j] = pcm->modelConv->modelFunc (NULL, params, coord);
     588            pcm->modelConvFlux->data.F32[i][j] = pcm->modelConv->class->modelFunc (NULL, params, coord);
    589589        }
    590590    }
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotSetThreads.c

    r35769 r37066  
    4747    psFree(task);
    4848
     49    task = psThreadTaskAlloc("PSPHOT_KRON_FLUX", 4);
     50    task->function = &psphotKronFlux_Threaded;
     51    psThreadTaskAdd(task);
     52    psFree(task);
     53
     54    task = psThreadTaskAlloc("PSPHOT_PETRO_FLUX", 4);
     55    task->function = &psphotPetroFlux_Threaded;
     56    psThreadTaskAdd(task);
     57    psFree(task);
     58
     59    task = psThreadTaskAlloc("PSPHOT_GALAXY_SHAPES", 7);
     60    task->function = &psphotGalaxyShape_Threaded;
     61    psThreadTaskAdd(task);
     62    psFree(task);
     63
    4964    task = psThreadTaskAlloc("PSPHOT_BLEND_FIT", 10);
    5065    task->function = &psphotBlendFit_Threaded;
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotSourceFits.c

    r35769 r37066  
    1919static int NfitIterPCM = 0;
    2020static int NfitPixPCM = 0;
     21
     22bool psphotPCMfitCheckSize (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize);
     23bool psphotPCMfitRetry (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, float psfSize);
    2124
    2225bool psphotFitInit (int nThreads) {
     
    559562
    560563# define TIMING 0
     564# define EXTRA_VERBOSE 0
     565
     566bool psphotSersicModelGuessPCM (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize);
     567bool psphotFitSersicShapeAndIndex (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
     568bool psphotFitSersicShapeAndIndexGrid (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
     569bool psphotFitSersicShapeAndIndexGridAuto (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
    561570
    562571pmModel *psphotFitPCM (pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, pmModelType modelType, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     
    573582    maskVal |= markVal;
    574583
    575     // allocate the model
     584    // allocate the model (this can only fail on a config error)
    576585    pmModel *model = pmModelAlloc(modelType);
    577     if (!model) {
    578         return NULL;
    579     }
    580 
    581     float t1, t2, t4, t5;
     586    psAssert (model, "invalid extended model name");
     587
     588    float t1, t2, t3, t4, t5;
     589    t1 = t2 = t3 = t4 = t5 = 0.0;
    582590    if (TIMING) { psTimerStart ("psphotFitPCM"); }
     591
     592    // if we are ever (in a given psphot implementation) going to fit a parameter, we must set the options here to include
     593    // that parameter (otherwise pmPCMupdate will fail to allocate the dmodelFlux image)
     594    // thus, if the sersic analysis below uses an index fit, need to use this EXT_AND_SKY mode for init
     595
     596    options.mode = PM_SOURCE_FIT_EXT;
     597    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
     598        options.mode = PM_SOURCE_FIT_EXT_AND_SKY;
     599    }
     600    if (modelType == pmModelClassGetType("PS_MODEL_DEV")) {
     601        options.mode = PM_SOURCE_FIT_SHAPE;
     602        options.mode = PM_SOURCE_FIT_EXT_AND_SKY;
     603    }
     604    if (modelType == pmModelClassGetType("PS_MODEL_EXP")) {
     605        options.mode = PM_SOURCE_FIT_EXT_AND_SKY;
     606    }
    583607
    584608    pmPCMdata *pcm = pmPCMinit (source, &options, model, maskVal, psfSize);
     
    594618    if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
    595619        // use the source moments, etc to guess basic model parameters
    596         if (!psphotSersicModelClassGuessPCM (pcm, source)) {
     620        if (!psphotSersicModelGuessPCM (pcm, source, maskVal, psfSize)) {
    597621            psFree (pcm);
    598             model->flags |= PM_MODEL_STATUS_BADARGS;
     622            model->flags |= PM_MODEL_SERSIC_PCM_FAIL_GUESS;
     623            return model;
     624        }
     625        if (TIMING) { t2 = psTimerMark ("psphotFitPCM"); }
     626
     627        // psphotFitSersicShapeAndIndex (pcm, readout, source, fitOptions, maskVal, markVal, psfSize);
     628        options.mode = PM_SOURCE_FIT_NO_INDEX;
     629        if (!psphotFitSersicShapeAndIndexGridAuto (pcm, readout, source, &options, maskVal, markVal, psfSize)) {
     630            psFree (pcm);
     631            model->flags |= PM_MODEL_SERSIC_PCM_FAIL_GRID;
     632            psError(PS_ERR_UNKNOWN, true, "Failed to find a index & shape");
     633            psErrorClear (); // clear the polynomial error
    599634            return model;
    600635        }
     
    603638        if (!pmSourceModelGuessPCM (pcm, source, maskVal, markVal)) {
    604639            psFree (pcm);
    605             model->flags |= PM_MODEL_STATUS_BADARGS;
     640            model->flags |= PM_MODEL_PCM_FAIL_GUESS;
    606641            return model;
    607642        }
    608643    }
    609644
    610     if (TIMING) { t2 = psTimerMark ("psphotFitPCM"); }
    611 
    612     if (modelType == pmModelClassGetType("PS_MODEL_SERSIC")) {
    613         options.mode = PM_SOURCE_FIT_NO_INDEX;
    614     } else {
    615         options.mode = PM_SOURCE_FIT_EXT;
    616     }
    617     // update the pcm elements if we have changed the circumstance (options.mode or source->pixels)
    618     pmPCMupdate(pcm, source, &options, model);
    619     if (TIMING) { t4 = psTimerMark ("psphotFitPCM"); }
     645    if (TIMING) { t3 = psTimerMark ("psphotFitPCM"); }
    620646
    621647    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
     
    623649    NfitIterPCM += pcm->modelConv->nIter;
    624650    NfitPixPCM += pcm->modelConv->nDOF;
     651    if (TIMING) { t4 = psTimerMark ("psphotFitPCM"); }
     652
     653    // XXX we might make this more efficient by setting NITER to be fairly small.  if we hit the iteration
     654    // limit, then we could do a small grid search on the size and try again from the best fit
     655
     656    if (options.isInteractive) psphotPCMfitCheckSize (pcm, source, maskVal, psfSize);
     657    // if (pcm->modelConv->nIter == fitOptions->nIter) {
     658    //  psphotPCMfitRetry (pcm, source, &options, maskVal, markVal, psfSize);
     659    // }
    625660    if (TIMING) { t5 = psTimerMark ("psphotFitPCM"); }
    626661
    627662    if (TIMING) {
    628663        int nPixBig = source->pixels->numCols * source->pixels->numRows;
    629         fprintf (stderr, "psphotFitPCM : nIter: %2d, radius: %6.1f, npix: %5d of %5d, t1: %6.4f, t2: %6.4f, t4: %6.4f, t5: %6.4f\n", model->nIter, model->fitRadius, model->nPix, nPixBig, t1, t2, t4, t5);
    630     }
    631 
    632     // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 0);
     664        fprintf (stderr, "psphotFitPCM : nIter: %2d, radius: %6.1f, npix: %5d of %5d, t1: %6.4f, t2: %6.4f, t3: %6.4f, t4: %6.4f, t5: %6.4f\n", model->nIter, model->fitRadius, model->nPix, nPixBig, t1, t2, t3, t4, t5);
     665    }
     666    if (EXTRA_VERBOSE && !TIMING) {
     667        int nPixBig = source->pixels->numCols * source->pixels->numRows;
     668        float *PAR = model->params->data.F32;
     669        fprintf (stderr, "source %d : %f - %f %f - %f %f %f - %f | nIter: %2d, radius: %6.1f, npix: %5d of %5d, chisq %f\n", source->id, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1], model->nIter, model->fitRadius, model->nPix, nPixBig, model->chisqNorm);
     670    }
     671
    633672    psFree (pcm);
    634673
     
    661700        model->params->data.F32[PM_PAR_7] = 0.5/indexGuess[i];
    662701
    663         if (!model->modelGuess(model, source, maskVal, markVal)) {
     702        if (!model->class->modelGuess(model, source, maskVal, markVal)) {
    664703            model->flags |= PM_MODEL_STATUS_BADARGS;
    665704            return false;
     
    684723    model->flags = PM_MODEL_STATUS_NONE; // do not attempt to handle failures here, let the next iteration deal with it
    685724    model->params->data.F32[PM_PAR_7] = 0.5/indexGuess[iMin];
    686     model->modelGuess(model, source, maskVal, markVal);
     725    model->class->modelGuess(model, source, maskVal, markVal);
    687726
    688727    return true;
     
    713752        model->params->data.F32[PM_PAR_7] = indexGuess[i];
    714753       
    715         if (!model->modelGuess(model, source, maskVal, markVal)) {
     754        if (!model->class->modelGuess(model, source, maskVal, markVal)) {
    716755            model->flags |= PM_MODEL_STATUS_BADARGS;
    717756            return false;
     
    748787    return true;
    749788}
     789
     790// 0.5 / n for (1.0, 1.25, 1.66, 2.0, 3.33, 4.0)
     791// float indexGuessInv[] = {0.5, 0.4, 0.3, 0.25, 0.20, 0.15, 0.125};
     792
     793// 0.5 / n for (0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0)
     794float indexGuessInv[] = {1.00, 0.50, 0.333, 0.25, 0.166, 0.125, 0.10, 0.0833};
     795float indexGuessR1q[] = {1.06, 1.19, 1.335, 1.48, 1.840, 2.290, 2.84, 3.5300};
     796# define N_INDEX_GUESS_INV 8
     797
     798// we are going to guess in fractions about the R1-based guess
     799float reffGuess[] = {0.8, 0.9, 1.0, 1.12, 1.25};
     800# define N_REFF_GUESS 5
     801
     802// A sersic model is very sensitive to the index.  attempt to find the index first by grid search in just the index
     803// for a sersic model, attempt to fit just the index and normalization with a modest number of iterations
     804bool psphotSersicModelGuessPCM (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize) {
     805
     806    // we get a reasonable guess from:
     807    // * Reff = Kron R1 / Q(index) -- Q comes from Graham & Driver
     808    // * Rmajor / Rminor & Theta from moments
     809    // * Io from total Kron flux
     810
     811    // the guesses are used to fill in PAR:
     812    psF32 *PAR = pcm->modelConv->params->data.F32;
     813
     814    // convert the moments to Major,Minor,Theta
     815    psEllipseMoments moments;
     816
     817    if (!isfinite(source->moments->Mrf)) return false;
     818    if (!isfinite(source->moments->Mxx)) return false;
     819    if (!isfinite(source->moments->Mxy)) return false;
     820    if (!isfinite(source->moments->Myy)) return false;
     821
     822    moments.x2 = source->moments->Mxx;
     823    moments.y2 = source->moments->Myy;
     824    moments.xy = source->moments->Mxy;
     825   
     826    // limit axis ratio < 20.0
     827    psEllipseAxes momentAxes = psEllipseMomentsToAxes (moments, 20.0);
     828
     829    // set the model position
     830    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     831      return false;
     832    }
     833
     834    // sky is zero (no longer fitted, but not yet deprecated)
     835    PAR[PM_PAR_SKY]  = 0.0;
     836
     837    // for the index loop, use Io = 1.0, use fitted values to determine Io
     838    PAR[PM_PAR_I0] = 1.0;
     839
     840    float xMin = NAN;
     841    float iMin = NAN;
     842    float sMin = NAN;
     843    float rMin = NAN;
     844
     845    // loop over index and Reff, keeping the ARatio and Theta constant?
     846    // loop over index guesses and find the best fit
     847    for (int j = 0; j < N_REFF_GUESS; j++) {
     848        for (int i = 0; i < N_INDEX_GUESS_INV; i++) {
     849            PAR[PM_PAR_7] = indexGuessInv[i];
     850
     851            psEllipseAxes guessAxes;
     852            guessAxes.major = reffGuess[j] * source->moments->Mrf / indexGuessR1q[i];
     853            guessAxes.minor = guessAxes.major * (momentAxes.minor / momentAxes.major);
     854            guessAxes.theta = momentAxes.theta;
     855
     856            if (!isfinite(guessAxes.major)) return false;
     857            if (!isfinite(guessAxes.minor)) return false;
     858            if (!isfinite(guessAxes.theta)) return false;
     859
     860            // convert the major,minor,theta to shape parameters for an Reff-like model
     861            pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
     862
     863            // generated the modelFlux
     864            // XXX note that this does not add sky to model
     865            pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize);
     866       
     867            float YY = 0.0;
     868            float YM = 0.0;
     869            float MM = 0.0;
     870            bool usePoisson = false;
     871
     872            for (int iy = 0; iy < source->pixels->numRows; iy++) {
     873                for (int ix = 0; ix < source->pixels->numCols; ix++) {
     874                    // skip masked points
     875                    if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
     876                        continue;
     877                    }
     878                    // skip zero-variance points
     879                    if (source->variance->data.F32[iy][ix] == 0) {
     880                        continue;
     881                    }
     882                    // skip nan value points
     883                    if (!isfinite(source->pixels->data.F32[iy][ix])) {
     884                        continue;
     885                    }
     886
     887                    float fy = source->pixels->data.F32[iy][ix];
     888                    float fm = source->modelFlux->data.F32[iy][ix];
     889                    float wt = (usePoisson) ? 1.0 / source->variance->data.F32[iy][ix] : 1.0;
     890
     891                    YY += PS_SQR(fy) * wt;
     892                    YM += fm * fy * wt;
     893                    MM += PS_SQR(fm) * wt;
     894                }
     895            }
     896
     897            float Io = YM / MM;
     898            float Chisq = YY - 2 * Io * YM + Io * Io * MM;
     899            if (isnan(xMin) || (Chisq < xMin)) {
     900                xMin = Chisq;
     901                iMin = Io;
     902                sMin = indexGuessInv[i];
     903                rMin = reffGuess[j] / indexGuessR1q[i];
     904            }
     905            if (EXTRA_VERBOSE) {
     906                fprintf (stderr, "%d | %f %f %f %f | %f %f %f %f", i, indexGuessInv[i], reffGuess[j], Io, Chisq, sMin, rMin, iMin, xMin);
     907                fprintf (stderr, "\n");
     908            }
     909        }
     910    }
     911
     912    {
     913        psEllipseAxes guessAxes;
     914        guessAxes.major = rMin * source->moments->Mrf;
     915        guessAxes.minor = guessAxes.major * (momentAxes.minor / momentAxes.major);
     916        guessAxes.theta = momentAxes.theta;
     917
     918        if (!isfinite(guessAxes.major)) return false;
     919        if (!isfinite(guessAxes.minor)) return false;
     920        if (!isfinite(guessAxes.theta)) return false;
     921
     922        // convert the major,minor,theta to shape parameters for an Reff-like model
     923        pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
     924    }
     925
     926    PAR[PM_PAR_I0] = iMin;
     927    PAR[PM_PAR_7] = sMin;
     928
     929    return true;
     930}
     931
     932// we have a set of guess parameters, do a small number of iterations fitting only SHAPE then only INDEX
     933bool psphotFitSersicShapeAndIndex (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     934
     935    pmModel *model = pcm->modelConv;
     936
     937    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     938
     939    pmSourceFitOptions options = *fitOptions;
     940   
     941    for (int i = 0; i < 3; i++) {
     942      // fit EXT (not PSF) model (set/unset the pixel mask)
     943      options.mode = PM_SOURCE_FIT_SHAPE;
     944      options.nIter = 2;
     945
     946      // update the pcm elements if we have changed the circumstance (here, options.mode)
     947      pmPCMupdate(pcm, source, &options, model);
     948     
     949      pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     950      if (EXTRA_VERBOSE) {
     951        float *PAR = model->params->data.F32;
     952        fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     953      }
     954     
     955      // fit EXT (not PSF) model (set/unset the pixel mask)
     956      options.mode = PM_SOURCE_FIT_INDEX;
     957      // options.mode = PM_SOURCE_FIT_EXT_AND_SKY;
     958      options.nIter = 30;
     959     
     960      // update the pcm elements if we have changed the circumstance (here, options.mode)
     961      pmPCMupdate(pcm, source, &options, model);
     962     
     963      pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     964      if (EXTRA_VERBOSE) {
     965        float *PAR = model->params->data.F32;
     966        fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     967      }
     968    }
     969
     970    // update the pcm elements if we have changed the circumstance (here, options.mode)
     971    pmPCMupdate(pcm, source, fitOptions, model);
     972
     973    return true;
     974}
     975
     976// we have a set of guess parameters, do a small number of iterations fitting only SHAPE then only INDEX
     977bool psphotFitSersicShapeAndIndexGridAuto (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     978
     979    pmModel *model = pcm->modelConv;
     980
     981    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     982
     983    pmSourceFitOptions options = *fitOptions;
     984   
     985    psF32 *PAR = pcm->modelConv->params->data.F32;
     986
     987    options.mode = PM_SOURCE_FIT_SHAPE;
     988    options.nIter = 7;
     989   
     990    // update the pcm elements if we have changed the circumstance (here, options.mode)
     991    pmPCMupdate(pcm, source, &options, model);
     992   
     993    // we have been provided a guess at the index (P[7]) from the list of indexGuessInv
     994
     995    // find the matching indexGuessInv
     996    int nStart = -1;
     997    for (int i = 0; i < N_INDEX_GUESS_INV; i++) {
     998        if (fabs(PAR[PM_PAR_7] - indexGuessInv[i]) < 0.01) {
     999            nStart = i;
     1000            break;
     1001        }
     1002    }
     1003    if (nStart == -1) {
     1004        fprintf (stderr, "WARNING: could not find start guess %f\n", PAR[PM_PAR_7]);
     1005        return false;
     1006    }
     1007
     1008    psVector *chi2 = psVectorAllocEmpty (16, PS_TYPE_F32);
     1009    psVector *Sidx = psVectorAllocEmpty (16, PS_TYPE_F32);
     1010
     1011    float Sm = NAN, Sp = NAN, So = NAN;
     1012    if (nStart == 0) {
     1013        Sm = indexGuessInv[nStart];
     1014        So = 0.5*(indexGuessInv[nStart + 1] + indexGuessInv[nStart]);
     1015        Sp = indexGuessInv[nStart + 1];
     1016    } else if (nStart == N_INDEX_GUESS_INV - 1) {
     1017        Sp = indexGuessInv[nStart];
     1018        So = 0.5*(indexGuessInv[nStart - 1] + indexGuessInv[nStart]);
     1019        Sm = indexGuessInv[nStart - 1];
     1020    } else {
     1021        Sm = 0.5*(indexGuessInv[nStart - 1] + indexGuessInv[nStart]);
     1022        So = indexGuessInv[nStart];
     1023        Sp = 0.5*(indexGuessInv[nStart + 1] + indexGuessInv[nStart]);
     1024    }
     1025   
     1026    PAR[PM_PAR_7] = Sm;
     1027    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1028    if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1029    psVectorAppend (Sidx, 100*PAR[PM_PAR_7]);
     1030    psVectorAppend (chi2, model->chisqNorm);
     1031
     1032    PAR[PM_PAR_7] = So;
     1033    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1034    if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1035    psVectorAppend (Sidx, 100*PAR[PM_PAR_7]);
     1036    psVectorAppend (chi2, model->chisqNorm);
     1037
     1038    PAR[PM_PAR_7] = Sp;
     1039    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1040    if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1041    psVectorAppend (Sidx, 100*PAR[PM_PAR_7]);
     1042    psVectorAppend (chi2, model->chisqNorm);
     1043
     1044    psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2);
     1045    if (!psVectorFitPolynomial1D (poly, NULL, 0, chi2, NULL, Sidx)) {
     1046        psError(PS_ERR_UNKNOWN, true, "Failed to find a good chisq parabola");
     1047        psFree (chi2);
     1048        psFree (Sidx);
     1049        psFree (poly);
     1050        return false;
     1051    }
     1052
     1053    // where is the minimum of this polynomial fit?
     1054    float Smin = -0.5 * poly->coeff[1] / poly->coeff[2] / 100.0;
     1055
     1056    // constrain Smin to be in a valid range: allow the fitted range to go a bit beyond the 3 trial points, but no further
     1057    float Smx = Sm - 0.25*(So - Sm);
     1058    float Spx = Sp + 0.25*(Sp - So);
     1059    Smin = PS_MAX(PS_MIN(Smin, Smx), Spx);
     1060    PAR[PM_PAR_7] = Smin;
     1061
     1062    // XXX I could set the error on PAR_7 here if I knew how to roughly convert these chisq values to true chisq values
     1063
     1064    // return to the original fitting mode (fitOptions)
     1065    pmPCMupdate(pcm, source, fitOptions, model);
     1066
     1067    psFree (chi2);
     1068    psFree (Sidx);
     1069    psFree (poly);
     1070
     1071    return true;
     1072}
     1073
     1074 
     1075// we have a set of guess parameters, do a small number of iterations fitting only SHAPE then only INDEX
     1076bool psphotFitSersicShapeAndIndexGridAutoScaled (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     1077
     1078    pmModel *model = pcm->modelConv;
     1079
     1080    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     1081
     1082    pmSourceFitOptions options = *fitOptions;
     1083   
     1084    psF32 *PAR = pcm->modelConv->params->data.F32;
     1085
     1086    options.mode = PM_SOURCE_FIT_SHAPE;
     1087    options.nIter = 5;
     1088   
     1089    // update the pcm elements if we have changed the circumstance (here, options.mode)
     1090    pmPCMupdate(pcm, source, &options, model);
     1091   
     1092    float parStart[8];
     1093    for (int i = 0; i < 8; i++) parStart[i] = PAR[i];
     1094
     1095    // we start with a guess at the index (P[7])
     1096
     1097    // get chisq for P[7], P[7]*1.1, P[7]*1.25 (or *0.75 depending on the result of 1.1)
     1098
     1099    psVector *chi2 = psVectorAllocEmpty (16, PS_TYPE_F32);
     1100    psVector *Sidx = psVectorAllocEmpty (16, PS_TYPE_F32);
     1101
     1102    PAR[PM_PAR_7] = parStart[7];
     1103    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1104      if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1105    psVectorAppend (Sidx, 100*PAR[PM_PAR_7]);
     1106    psVectorAppend (chi2, model->chisqNorm);
     1107
     1108    float fI = 1.1;
     1109    PAR[PM_PAR_7] = parStart[7]*fI;
     1110    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1111      if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1112    psVectorAppend (Sidx, 100*PAR[PM_PAR_7]);
     1113    psVectorAppend (chi2, model->chisqNorm);
     1114
     1115    if (chi2->data.F32[1] < chi2->data.F32[0]) {
     1116      fI = 1.3;
     1117    } else {
     1118      fI = 1.0 / 1.3;
     1119    }
     1120   
     1121    PAR[PM_PAR_7] = parStart[7]*fI;
     1122    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1123      if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1124    psVectorAppend (Sidx, 100*PAR[PM_PAR_7]);
     1125    psVectorAppend (chi2, model->chisqNorm);
     1126
     1127    // can we fit the 3 pts with a parabola?
     1128    int nTry = 0;
     1129    psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2);
     1130    while (!psVectorFitPolynomial1D (poly, NULL, 0, chi2, NULL, Sidx)) {
     1131      psErrorClear (); // clear the polynomial error
     1132      if (nTry > 4) {
     1133        psError(PS_ERR_UNKNOWN, true, "Failed to find a good chisq parabola");
     1134        psFree (chi2);
     1135        psFree (Sidx);
     1136        psFree (poly);
     1137        return false;
     1138      }
     1139      fI = (fI < 1.0) ? fI / 1.3 : fI * 1.3;
     1140      PAR[PM_PAR_7] = parStart[7]*fI;
     1141      pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1142      if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1143      psVectorAppend (Sidx, 100*PAR[PM_PAR_7]);
     1144      psVectorAppend (chi2, model->chisqNorm);
     1145      nTry ++;
     1146    }
     1147
     1148    // where is the minimum of this polynomial fit?
     1149    float Smin = -0.5 * poly->coeff[1] / poly->coeff[2] / 100.0;
     1150
     1151    // constrain Smin to be in a valid range (1.0 - 0.1, corresponding to 0.5 (Gauss) to 5.0 (slightly peakier than Dev)
     1152    Smin = PS_MAX(PS_MIN(Smin, 1.0), 0.1);
     1153    PAR[PM_PAR_7] = Smin;
     1154
     1155    // pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1156    // if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1157   
     1158    //// for (int i = 0; i < 8; i++) PAR[i] = parStart[i];
     1159    ////
     1160    //// for (float fI = 0.0; fI < 0.15; fI += 0.01) {
     1161    ////   PAR[PM_PAR_7] = parStart[7] - fI;
     1162    ////
     1163    ////   // fit EXT (not PSF) model (set/unset the pixel mask)
     1164    ////   
     1165    ////   pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1166    ////   if (TIMING) {
     1167    ////        float *PAR = model->params->data.F32;
     1168    ////        fprintf (stderr, "%d %f : %f - %f %f %f - %f\n", model->nIter, model->chisqNorm, PAR[7], PAR[4], PAR[5], PAR[6], PAR[1]);
     1169    ////   }
     1170    //// }
     1171
     1172    // return to the original fitting mode (fitOptions)
     1173    pmPCMupdate(pcm, source, fitOptions, model);
     1174
     1175    psFree (chi2);
     1176    psFree (Sidx);
     1177    psFree (poly);
     1178
     1179    return true;
     1180}
     1181
     1182 
     1183// we have a set of guess parameters, do a small number of iterations fitting only SHAPE then only INDEX
     1184bool psphotFitSersicShapeAndIndexGrid (pmPCMdata *pcm, pmReadout *readout, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
     1185
     1186    pmModel *model = pcm->modelConv;
     1187
     1188    assert (model->type == pmModelClassGetType("PS_MODEL_SERSIC"));
     1189
     1190    pmSourceFitOptions options = *fitOptions;
     1191   
     1192    psF32 *PAR = pcm->modelConv->params->data.F32;
     1193
     1194    options.mode = PM_SOURCE_FIT_SHAPE;
     1195    options.nIter = 10;
     1196   
     1197    // update the pcm elements if we have changed the circumstance (here, options.mode)
     1198    pmPCMupdate(pcm, source, &options, model);
     1199   
     1200    psVector *chi2 = psVectorAllocEmpty (16, PS_TYPE_F32);
     1201    psVector *Sidx = psVectorAllocEmpty (16, PS_TYPE_F32);
     1202
     1203    float par7[] = {0.100, 0.125, 0.150, 0.175, 0.200, 0.225, 0.250};
     1204    for (int i = 0; i < 7; i++) {
     1205      PAR[PM_PAR_7] = par7[i];
     1206      pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1207      if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1208      psVectorAppend (Sidx, PAR[PM_PAR_7]);
     1209      psVectorAppend (chi2, model->chisqNorm);
     1210    }
     1211
     1212    psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2);
     1213    if (!psVectorFitPolynomial1D (poly, NULL, 0, chi2, NULL, Sidx)) {
     1214      psError(PS_ERR_UNKNOWN, true, "Failed to find a good chisq parabola");
     1215      psFree (chi2);
     1216      psFree (Sidx);
     1217      psFree (poly);
     1218      return false;
     1219    }
     1220
     1221    // where is the minimum of this polynomial fit?
     1222    fprintf (stderr, "fit1d: %f + %f x + %f x^2\n", poly->coeff[0], poly->coeff[1], poly->coeff[2]);
     1223    float Smin = -0.5 * poly->coeff[1] / poly->coeff[2];
     1224
     1225    // constrain Smin to be in a valid range (1.0 - 0.1, corresponding to 0.5 (Gauss) to 5.0 (slightly peakier than Dev)
     1226    Smin = PS_MAX(PS_MIN(Smin, 1.0), 0.1);
     1227    PAR[PM_PAR_7] = Smin;
     1228    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1229    if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     1230   
     1231    //// for (int i = 0; i < 8; i++) PAR[i] = parStart[i];
     1232    ////
     1233    //// for (float fI = 0.0; fI < 0.15; fI += 0.01) {
     1234    ////   PAR[PM_PAR_7] = parStart[7] - fI;
     1235    ////
     1236    ////   // fit EXT (not PSF) model (set/unset the pixel mask)
     1237    ////   
     1238    ////   pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
     1239    ////   if (TIMING) {
     1240    ////        float *PAR = model->params->data.F32;
     1241    ////        fprintf (stderr, "%d %f : %f - %f %f %f - %f\n", model->nIter, model->chisqNorm, PAR[7], PAR[4], PAR[5], PAR[6], PAR[1]);
     1242    ////   }
     1243    //// }
     1244
     1245    // return to the original fitting mode (fitOptions)
     1246    pmPCMupdate(pcm, source, fitOptions, model);
     1247
     1248    psFree (chi2);
     1249    psFree (Sidx);
     1250    psFree (poly);
     1251
     1252    return true;
     1253}
     1254
     1255// # define N_REFF_CHECK 11
     1256// float drefCheck[] = {-0.02, -0.04, -0.06, 0.0, 0.85, 0.90, 0.95, 1.00, 1.05, 1.10, 1.15, 1.20, 1.25};
     1257
     1258// we have an initial fit, check to see if the current size is besst
     1259bool psphotPCMfitCheckSize (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize) {
     1260
     1261    // PAR is already at my current best guess
     1262    psF32 *PAR = pcm->modelConv->params->data.F32;
     1263
     1264    // store best guess as a shape
     1265    psEllipseAxes centerAxes;
     1266    pmModelParamsToAxes (&centerAxes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
     1267
     1268    float xMin = NAN;
     1269    float iMin = NAN;
     1270    float rMin = NAN;
     1271
     1272    // loop over Reff, keeping the ARatio and Theta constant
     1273    for (int j = -4; j <= 4; j++) {
     1274
     1275        float dref = j * 0.01;
     1276
     1277        psEllipseAxes guessAxes;
     1278        guessAxes.major = centerAxes.major + dref;
     1279        guessAxes.minor = guessAxes.major * centerAxes.minor / centerAxes.major;
     1280        guessAxes.theta = centerAxes.theta;
     1281
     1282        if (!isfinite(guessAxes.major)) return false;
     1283        if (!isfinite(guessAxes.minor)) return false;
     1284        if (!isfinite(guessAxes.theta)) return false;
     1285
     1286        // convert the major,minor,theta to shape parameters for an Reff-like model
     1287        pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
     1288
     1289        // generated the modelFlux
     1290            // XXX note that this does not add sky to model
     1291        pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize);
     1292       
     1293        float YY = 0.0;
     1294        float YM = 0.0;
     1295        float MM = 0.0;
     1296        bool usePoisson = false;
     1297
     1298        for (int iy = 0; iy < source->pixels->numRows; iy++) {
     1299            for (int ix = 0; ix < source->pixels->numCols; ix++) {
     1300                // skip masked points
     1301                if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
     1302                    continue;
     1303                }
     1304                // skip zero-variance points
     1305                if (source->variance->data.F32[iy][ix] == 0) {
     1306                    continue;
     1307                }
     1308                // skip nan value points
     1309                if (!isfinite(source->pixels->data.F32[iy][ix])) {
     1310                    continue;
     1311                }
     1312
     1313                float fy = source->pixels->data.F32[iy][ix];
     1314                float fm = source->modelFlux->data.F32[iy][ix];
     1315                float wt = (usePoisson) ? 1.0 / source->variance->data.F32[iy][ix] : 1.0;
     1316
     1317                YY += PS_SQR(fy) * wt;
     1318                YM += fm * fy * wt;
     1319                MM += PS_SQR(fm) * wt;
     1320            }
     1321        }
     1322
     1323        float Io = YM / MM;
     1324        float Chisq = YY - 2 * Io * YM + Io * Io * MM;
     1325        if (isnan(xMin) || (Chisq < xMin)) {
     1326            xMin = Chisq;
     1327            iMin = Io;
     1328            rMin = dref;
     1329        }
     1330        // fprintf (stderr, "%d | %f %f %f | %f %f %f\n", j, dref, Io, Chisq, rMin, iMin, xMin);
     1331    }
     1332
     1333    psEllipseAxes guessAxes;
     1334    guessAxes.major = centerAxes.major + rMin;
     1335    guessAxes.minor = guessAxes.major * centerAxes.minor / centerAxes.major;
     1336    guessAxes.theta = centerAxes.theta;
     1337
     1338    if (!isfinite(guessAxes.major)) return false;
     1339    if (!isfinite(guessAxes.minor)) return false;
     1340    if (!isfinite(guessAxes.theta)) return false;
     1341
     1342    // convert the major,minor,theta to shape parameters for an Reff-like model
     1343    pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
     1344    PAR[PM_PAR_I0] = iMin;
     1345
     1346    return true;
     1347}
     1348
     1349// we have an initial fit, check to see if the current size is besst
     1350bool psphotPCMfitRetry (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, float psfSize) {
     1351
     1352    // PAR is already at my current best guess
     1353    psF32 *PAR = pcm->modelConv->params->data.F32;
     1354
     1355    // store best guess as a shape
     1356    psEllipseAxes centerAxes;
     1357    pmModelParamsToAxes (&centerAxes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
     1358
     1359    // retry with axes smaller by 1 pixel
     1360    psEllipseAxes guessAxes;
     1361    guessAxes.major = centerAxes.major - 0.08;
     1362    guessAxes.minor = guessAxes.major * centerAxes.minor / centerAxes.major;
     1363    guessAxes.theta = centerAxes.theta;
     1364
     1365    if (!isfinite(guessAxes.major)) return false;
     1366    if (!isfinite(guessAxes.minor)) return false;
     1367    if (!isfinite(guessAxes.theta)) return false;
     1368
     1369    // convert the major,minor,theta to shape parameters for an Reff-like model
     1370    pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
     1371
     1372    // generated the modelFlux
     1373            // XXX note that this does not add sky to model
     1374    pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize);
     1375       
     1376    float YY = 0.0;
     1377    float YM = 0.0;
     1378    float MM = 0.0;
     1379    bool usePoisson = false;
     1380
     1381    for (int iy = 0; iy < source->pixels->numRows; iy++) {
     1382        for (int ix = 0; ix < source->pixels->numCols; ix++) {
     1383            // skip masked points
     1384            if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
     1385                continue;
     1386            }
     1387            // skip zero-variance points
     1388            if (source->variance->data.F32[iy][ix] == 0) {
     1389                continue;
     1390            }
     1391            // skip nan value points
     1392            if (!isfinite(source->pixels->data.F32[iy][ix])) {
     1393                continue;
     1394            }
     1395
     1396            float fy = source->pixels->data.F32[iy][ix];
     1397            float fm = source->modelFlux->data.F32[iy][ix];
     1398            float wt = (usePoisson) ? 1.0 / source->variance->data.F32[iy][ix] : 1.0;
     1399
     1400            YY += PS_SQR(fy) * wt;
     1401            YM += fm * fy * wt;
     1402            MM += PS_SQR(fm) * wt;
     1403        }
     1404    }
     1405
     1406    float Io = YM / MM;
     1407    PAR[PM_PAR_I0] = Io;
     1408
     1409    pmSourceFitPCM (pcm, source, fitOptions, maskVal, markVal, psfSize);  // NOTE : 1687 allocs in here
     1410
     1411    return true;
     1412}
     1413
     1414
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotSourceSize.c

    r35180 r37066  
    11# include "psphotInternal.h"
    2 # include <gsl/gsl_sf_gamma.h>
    3 
     2
     3// this structure is only used internally to simplify the function parameters
    44typedef struct {
    55    psImageMaskType maskVal;
     
    1313    bool altDiffExt;
    1414    float altDiffExtThresh;
    15     bool extFitAll;
    16     bool extFitAllReadout;
    17     float extFitAllThresh;
    1815    float soft;
    1916    int grow;
     
    3330bool psphotSourceSelectCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options);
    3431bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal, int maxWindowCR);
    35 bool psphotMaskCosmicRayFootprintCheck (psArray *sources);
    3632int  psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh);
    3733float psphotSourceSizeFindThreshold (psVector *value, psVector *mask, int maskValue, float minValue, float maxValue, float delta, float guess, float fraction);
     
    4137
    4238// we need to call this function after sources have been fitted to the PSF model and
    43 // subtracted.  To determine the CR-nature, this function examines the 9 pixels in the 3x3
    44 // square containing the peak and compares the observed flux to the model.  To determine
    45 // the EXT-nature, this function measures the amount of positive or negative total
    46 // deviation from the psf model at the r = FWHM/2 position
     39// subtracted. 
    4740
    4841// for now, let's store the detections on the readout->analysis for each readout
     
    121114    assert (status);
    122115
    123     // XXX recipe name is not great
     116    // XXX recipe name is not great (NOTE : not used!)
    124117    options.nSigmaMoments = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.MOMENTS");
    125118    assert (status);
    126119
    127     // Optional extended source measurement algorithm to improve diff image trails
     120    // Optional algorithm to define if a source is extended (used by DIFF analysis)
    128121    options.altDiffExt = psMetadataLookupBool(&status, recipe, "PSPHOT.EXT.DIFF.ALTERNATE");
    129122    assert (status);
     123
    130124    // Threshold for this alternate method
    131125    options.altDiffExtThresh = psMetadataLookupF32(&status, recipe, "PSPHOT.EXT.DIFF.ALTERNATE.THRESH");
    132126    assert (status);
    133     // Option to enable fitting of all objects with extended model.
    134     options.extFitAll = psMetadataLookupBool(&status, recipe, "PSPHOT.EXT.FIT.ALL.SOURCES");
    135     assert (status);
    136     // Fitting everything is fine, but if the source density is high, we probably shouldn't.
    137     options.extFitAllThresh = psMetadataLookupF32(&status, recipe, "PSPHOT.EXT.FIT.ALL.THRESH");
    138     assert (status);
    139    
     127
    140128    // location of a single test source
    141129    options.xtest = psMetadataLookupS32 (&status, recipe, "PSPHOT.CRMASK.XTEST");
     
    422410
    423411    psLogMsg("psModules.objects", PS_LOG_INFO, "Source Size classifications: %4s %4s %4s %4s %4s", "Npsf", "Next", "Nsat", "Ncr", "Nskip");
    424     // Determine if this readout is above the threshold to ext fit all sources
    425     options->extFitAllReadout = false;
    426     if (options->extFitAll) {
    427       float maskFrac = psMetadataLookupF32(&status,readout->analysis,"READOUT.MASK.FRAC");
    428       if (status) {
    429         maskFrac = 0.0;
    430       }
    431       if (sources->n * (1.0 - maskFrac) > options->extFitAllThresh) {
    432         options->extFitAllReadout = false;
    433       }
    434       else {
    435         options->extFitAllReadout = true;
    436       }
    437     }
    438    
     412
    439413    if (!psphotSourceClassRegion (NULL, &psfClump, sources, recipe, psf, options)) {
    440414        psLogMsg ("psphot", 4, "Failed to determine source classification for full image\n");
     
    444418    return true;
    445419   
     420    // NOTE : this section is deactivated (EAM : I think we were getting poor boundary effects?)
    446421    int nRegions = psMetadataLookupS32 (&status, readout->analysis, "PSF.CLUMP.NREGIONS");
    447422    for (int i = 0; i < nRegions; i ++) {
     
    582557        // * SAT stars should not be faint, but defects may?
    583558
    584         // If the recipe requests we do extended source fits to everything, set
    585         // the EXT_LIMIT flag
    586         if (options->extFitAllReadout) {
    587           psTrace("psphotSourceClassRegion.EXTALT",10,"In extFitAll: %d %d\n",options->extFitAll,options->extFitAllReadout);
    588           source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
    589         }
    590559        // Defects may not always match CRs from peak curvature analysis
    591560        // Defects may also be marked as SATSTAR -- XXX deactivate this flag?
     
    595564
    596565        // saturated star (too many saturated pixels or peak above saturation limit).  These
    597         // may also be saturated galaxies, or just large saturated regions.
     566        // may also be saturated galaxies, or just large saturated regions.  They are never
     567        // marked as 'extended'
    598568        if (source->mode & PM_SOURCE_MODE_SATSTAR) {
    599569            psTrace("psphotSourceClassRegion.SAT",4,"CLASS: %g %g\t%g %g\t%g %g\t%g %g\t%g SAT\n",
     
    604574        }
    605575
    606         // any sources missing a large fraction should just be treated as PSFs
     576        // any sources missing a large fraction should just be treated as PSFs. They are never
     577        // marked as 'extended'
    607578        if ((source->pixWeightNotBad < 0.9) || (source->pixWeightNotPoor < 0.9)) {
    608579            psTrace("psphotSourceClassRegion.PSF",4,"CLASS: %g %g\t%g %g  %g %g  %g %g\t%g %g\t%g PSF\t%g %g\n",
     
    634605            psTrace("psphotSourceClassRegion.EXT",4,"CLASS: %g %g\t%g %g\t%g %g\t%g %g\t%g EXT\n",
    635606                    source->peak->xf, source->peak->yf, Mminor, kMag, dMag, nSigmaMAG, options->sizeLimitCR, options->magLimitCR, options->nSigmaApResid);
     607            source->type = PM_SOURCE_TYPE_EXTENDED;
    636608            source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
    637609            source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
     
    639611            continue;
    640612        }
     613
    641614        // Alternate extended source limit calculation
    642615        if (options->altDiffExt) {
     
    652625                    source->peak->xf, source->peak->yf, Mminor, kMag, dMag, nSigmaMAG, options->sizeLimitCR, options->magLimitCR, options->nSigmaApResid,
    653626                    momentRatioVeres,options->altDiffExtThresh);
     627            source->type = PM_SOURCE_TYPE_EXTENDED;
    654628            source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
    655629            source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
     
    968942}
    969943
    970 bool psphotMaskCosmicRayFootprintCheck (psArray *sources) {
    971 #ifdef CHECK_FOOTPRINTS
    972     // This gets really expensive for complex images
    973     for (int i = 0; i < sources->n; i++) {
    974         pmSource *source = sources->data[i];
    975         pmPeak *peak = source->peak;
    976         pmFootprint *footprint = peak->footprint;
    977         if (!footprint) continue;
    978         for (int j = 0; j < footprint->spans->n; j++) {
    979             pmSpan *sp = footprint->spans->data[j];
    980             psAssert (sp, "missing span");
    981         }
    982     }
    983 #endif
    984     return true;
    985 }
    986 
    987 /**** ------ old versions of cosmic ray masking ----- ****/
    988 
    989 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask);
    990 
    991 // This attempt to mask the cosmic rays used the isophotal boundary
    992 bool psphotMaskCosmicRay_V1 (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {
    993 
    994     // replace the source flux
    995     pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    996 
    997     // flag this as a CR
    998     source->mode |= PM_SOURCE_MODE_CR_LIMIT;
    999     pmPeak *peak = source->peak;
    1000     psAssert (peak, "NULL peak");
    1001 
    1002     // grab the matching footprint
    1003     pmFootprint *footprint = peak->footprint;
    1004     if (!footprint) {
    1005       psTrace("psphot.czw",2,"Using isophot CR mask code.");
    1006 
    1007         // if we have not footprint, use the old code to mask by isophot
    1008         psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    1009         return true;
    1010     }
    1011 
    1012     if (!footprint->spans) {
    1013       psTrace("psphot.czw",2,"Using isophot CR mask code.");
    1014 
    1015         // if we have no footprint, use the old code to mask by isophot
    1016         psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    1017         return true;
    1018     }
    1019     psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    1020     // mask all of the pixels covered by the spans of the footprint
    1021     for (int j = 1; j < footprint->spans->n; j++) {
    1022         pmSpan *span1 = footprint->spans->data[j];
    1023 
    1024         int iy = span1->y;
    1025         int xs = span1->x0;
    1026         int xe = span1->x1;
    1027 
    1028         for (int ix = xs; ix < xe; ix++) {
    1029             mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;
    1030         }
    1031     }
    1032     return true;
    1033 }
    1034 
    1035944# define VERBOSE 0
    1036945int psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh) {
     
    11761085}
    11771086
    1178 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {
    1179 
    1180     source->mode |= PM_SOURCE_MODE_CR_LIMIT;
    1181     pmPeak *peak = source->peak;
    1182     psAssert (peak, "NULL peak");
    1183 
    1184     psImage *mask   = source->maskView;
    1185     psImage *pixels = source->pixels;
    1186     psImage *variance = source->variance;
    1187 
    1188     // XXX This should be a recipe variable
    1189 # define SN_LIMIT 5.0
    1190 
    1191     int xo = peak->x - pixels->col0;
    1192     int yo = peak->y - pixels->row0;
    1193 
    1194     // mark the pixels in this row to the left, then the right
    1195     for (int ix = xo; ix >= 0; ix--) {
    1196         float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]);
    1197         if (SN > SN_LIMIT) {
    1198             mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask;
    1199         }
    1200     }
    1201     for (int ix = xo + 1; ix < pixels->numCols; ix++) {
    1202         float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]);
    1203         if (SN > SN_LIMIT) {
    1204             mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask;
    1205         }
    1206     }
    1207 
    1208     // for each of the neighboring rows, mark the high pixels if they have a marked neighbor
    1209     // first go up:
    1210     for (int iy = PS_MIN(yo, mask->numRows-2); iy >= 0; iy--) {
    1211         // mark the pixels in this row to the left, then the right
    1212         for (int ix = 0; ix < pixels->numCols; ix++) {
    1213             float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]);
    1214             if (SN < SN_LIMIT) continue;
    1215 
    1216             bool valid = false;
    1217             valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix] & crMask);
    1218             valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix-1] & crMask) : 0;
    1219             valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix+1] & crMask) : 0;
    1220 
    1221             if (!valid) continue;
    1222             mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;
    1223         }
    1224     }
    1225     // next go down:
    1226     for (int iy = PS_MIN(yo+1, mask->numRows-1); iy < pixels->numRows; iy++) {
    1227         // mark the pixels in this row to the left, then the right
    1228         for (int ix = 0; ix < pixels->numCols; ix++) {
    1229             float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]);
    1230             if (SN < SN_LIMIT) continue;
    1231 
    1232             bool valid = false;
    1233             valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix] & crMask);
    1234             valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix-1] & crMask) : 0;
    1235             valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix+1] & crMask) : 0;
    1236 
    1237             if (!valid) continue;
    1238             mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;
    1239         }
    1240     }
    1241     return true;
    1242 }
    1243 
    1244 // given the PSF ellipse parameters, navigate around the 1sigma contour, return the total
    1245 // deviation in sigmas.  This is measured on the residual image - should we ignore negative
    1246 // deviations?  NOTE: This function was an early attempt to classify extended objects, and is
    1247 // no longer used by psphot.
    1248 float psphotModelContour(const psImage *image, const psImage *variance, const psImage *mask,
    1249                          psImageMaskType maskVal, const pmModel *model, float Ro)
    1250 {
    1251     psF32 *PAR = model->params->data.F32; // Model parameters
    1252     float sxx = PAR[PM_PAR_SXX], sxy = PAR[PM_PAR_SXY], syy = PAR[PM_PAR_SYY]; // Ellipse parameters
    1253 
    1254     // We treat the contour as an ellipse:
    1255     // Ro = (x / SXX)^2 + (y / SYY)^2 + x y SXY
    1256     // y^2 (1/SYY^2) + y (x SXY) + (x / SXX)^2 - Ro = 0;
    1257     // This is a quadratic, Ay^2 + By + C with A = 1/SYY^2, B = x*SXY, C = (x / SXX)^2 - Ro
    1258     // The solution is y = [-B +/- sqrt (B^2 - 4 A C)] / [2 A], so:
    1259     // y = [-(x SXY) +/- sqrt ((x SXY)^2 - 4 (1/SYY^2) ((x/SXX)^2 - Ro))] * [SYY^2 / 2]
    1260 
    1261     // min/max value of x is where B^2 - 4AC = 0; solve this for x
    1262     float Q = Ro * PS_SQR(sxx) / (1.0 - PS_SQR(sxx * syy * sxy) / 4.0);
    1263     if (Q < 0.0) {
    1264         // ellipse is imaginary
    1265         return NAN;
    1266     }
    1267 
    1268     int radius = sqrtf(Q) + 0.5;        // Radius of ellipse
    1269     int nPts = 0;                       // Number of points in ellipse
    1270     float nSigma = 0.0;                 //
    1271 
    1272     for (int x = -radius; x <= radius; x++) {
    1273         // Polynomial coefficients
    1274         // XXX Should we be using the centre of the pixel as x or x+0.5?
    1275         float A = PS_SQR (1.0 / syy);
    1276         float B = x * sxy;
    1277         float C = PS_SQR (x / sxx) - Ro;
    1278         float T = PS_SQR(B) - 4*A*C;
    1279         if (T < 0.0) {
    1280             continue;
    1281         }
    1282 
    1283         // y position in source frame
    1284         float yP = (-B + sqrt (T)) / (2.0 * A);
    1285         float yM = (-B - sqrt (T)) / (2.0 * A);
    1286 
    1287         // Get the closest pixel positions (image frame)
    1288         int xPix  = x  + PAR[PM_PAR_XPOS] - image->col0 + 0.5;
    1289         int yPixM = yM + PAR[PM_PAR_YPOS] - image->row0 + 0.5;
    1290         int yPixP = yP + PAR[PM_PAR_YPOS] - image->row0 + 0.5;
    1291 
    1292         if (xPix < 0 || xPix >= image->numCols) {
    1293             continue;
    1294         }
    1295 
    1296         if (yPixM >= 0 && yPixM < image->numRows &&
    1297             !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixM][xPix] & maskVal))) {
    1298             float dSigma = image->data.F32[yPixM][xPix] / sqrtf(variance->data.F32[yPixM][xPix]);
    1299             nSigma += dSigma;
    1300             nPts++;
    1301         }
    1302 
    1303         if (yPixM == yPixP) {
    1304             continue;
    1305         }
    1306 
    1307         if (yPixP >= 0 && yPixP < image->numRows &&
    1308             !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixP][xPix] & maskVal))) {
    1309             float dSigma = image->data.F32[yPixP][xPix] / sqrtf(variance->data.F32[yPixP][xPix]);
    1310             nSigma += dSigma;
    1311             nPts++;
    1312         }
    1313     }
    1314     nSigma /= nPts;
    1315     return nSigma;
    1316 }
    1317 
    1318 // this was an old attempt to identify cosmic rays based on the peak curvature
    1319 bool psphotSourcePeakCurvature (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) {
    1320 
    1321     // classify the sources based on the CR test (place this in a function?)
    1322     // XXX use an internal flag to mark sources which have already been measured
    1323     for (int i = 0; i < sources->n; i++) {
    1324         pmSource *source = sources->data[i];
    1325 
    1326         // skip source if it was already measured
    1327         if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) {
    1328             psTrace("psphot", 7, "Not calculating source size since it has already been measured\n");
    1329             continue;
    1330         }
    1331 
    1332         // source must have been subtracted
    1333         if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) {
    1334             source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED;
    1335             psTrace("psphot", 7, "Not calculating source size since source is not subtracted\n");
    1336             continue;
    1337         }
    1338 
    1339         psF32 **resid  = source->pixels->data.F32;
    1340         psF32 **variance = source->variance->data.F32;
    1341         psImageMaskType **mask = source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA;
    1342 
    1343         // Integer position of peak
    1344         int xPeak = source->peak->xf - source->pixels->col0 + 0.5;
    1345         int yPeak = source->peak->yf - source->pixels->row0 + 0.5;
    1346 
    1347         // Skip sources which are too close to a boundary.  These are mostly caught as DEFECT
    1348         if (xPeak < 1 || xPeak > source->pixels->numCols - 2 ||
    1349             yPeak < 1 || yPeak > source->pixels->numRows - 2) {
    1350             psTrace("psphot", 7, "Not calculating crNsigma due to edge\n");
    1351             continue;
    1352         }
    1353 
    1354         // Skip sources with masked pixels.  These are mostly caught as DEFECT
    1355         bool keep = true;
    1356         for (int iy = -1; (iy <= +1) && keep; iy++) {
    1357             for (int ix = -1; (ix <= +1) && keep; ix++) {
    1358                 if (mask[yPeak+iy][xPeak+ix] & options->maskVal) {
    1359                     keep = false;
    1360                 }
    1361             }
    1362         }
    1363         if (!keep) {
    1364             psTrace("psphot", 7, "Not calculating crNsigma due to masked pixels\n");
    1365             continue;
    1366         }
    1367 
    1368         // Compare the central pixel with those on either side, for the four possible lines through it.
    1369 
    1370         // Soften variances (add systematic error)
    1371         float softening = options->soft * PS_SQR(source->peak->rawFlux); // Softening for variances
    1372 
    1373         // Across the middle: y = 0
    1374         float cX = 2*resid[yPeak][xPeak]   - resid[yPeak+0][xPeak-1]  - resid[yPeak+0][xPeak+1];
    1375         float dcX = 4*variance[yPeak][xPeak] + variance[yPeak+0][xPeak-1] + variance[yPeak+0][xPeak+1];
    1376         float nX = cX / sqrtf(dcX + softening);
    1377 
    1378         // Up the centre: x = 0
    1379         float cY = 2*resid[yPeak][xPeak]   - resid[yPeak-1][xPeak+0]  - resid[yPeak+1][xPeak+0];
    1380         float dcY = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak+0] + variance[yPeak+1][xPeak+0];
    1381         float nY = cY / sqrtf(dcY + softening);
    1382 
    1383         // Diagonal: x = y
    1384         float cL = 2*resid[yPeak][xPeak]   - resid[yPeak-1][xPeak-1]  - resid[yPeak+1][xPeak+1];
    1385         float dcL = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak-1] + variance[yPeak+1][xPeak+1];
    1386         float nL = cL / sqrtf(dcL + softening);
    1387 
    1388         // Diagonal: x = - y
    1389         float cR = 2*resid[yPeak][xPeak]   - resid[yPeak+1][xPeak-1]  - resid[yPeak-1][xPeak+1];
    1390         float dcR = 4*variance[yPeak][xPeak] + variance[yPeak+1][xPeak-1] + variance[yPeak-1][xPeak+1];
    1391         float nR = cR / sqrtf(dcR + softening);
    1392 
    1393         // P(chisq > chisq_obs; Ndof) = gamma_Q (Ndof/2, chisq/2)
    1394         // Ndof = 4 ? (four measurements, no free parameters)
    1395         // XXX this value is going to be biased low because of systematic errors.
    1396         // we need to calibrate it somehow
    1397         // source->psfProb = gsl_sf_gamma_inc_Q (2, 0.5*chisq);
    1398 
    1399         // not strictly accurate: overcounts the chisq contribution from the center pixel (by
    1400         // factor of 4); also biases a bit low if any pixels are masked
    1401         // XXX I am not sure I want to keep this value...
    1402         source->psfChisq = PS_SQR(nX) + PS_SQR(nY) + PS_SQR(nL) + PS_SQR(nR);
    1403 
    1404         float fCR = 0.0;
    1405         int nCR = 0;
    1406         if (nX > 0.0) {
    1407             fCR += nX;
    1408             nCR ++;
    1409         }
    1410         if (nY > 0.0) {
    1411             fCR += nY;
    1412             nCR ++;
    1413         }
    1414         if (nL > 0.0) {
    1415             fCR += nL;
    1416             nCR ++;
    1417         }
    1418         if (nR > 0.0) {
    1419             fCR += nR;
    1420             nCR ++;
    1421         }
    1422         source->crNsigma  = (nCR > 0)  ? fCR / nCR : 0.0;
    1423         source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
    1424 
    1425         if (!isfinite(source->crNsigma)) {
    1426             continue;
    1427         }
    1428 
    1429         // this source is thought to be a cosmic ray.  flag the detection and mask the pixels
    1430         if (source->crNsigma > options->nSigmaCR) {
    1431             source->mode |= PM_SOURCE_MODE_CR_LIMIT;
    1432             // XXX still testing... : psphotMaskCosmicRay (readout->mask, source, maskVal, crMask);
    1433             // XXX acting strange... psphotMaskCosmicRay_Old (source, maskVal, crMask);
    1434         }
    1435     }
    1436 
    1437     // now that we have masked pixels associated with CRs, we can grow the mask
    1438     if (options->grow > 0) {
    1439         bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading for psImageConvolveMask
    1440         psImage *newMask = psImageConvolveMask(NULL, readout->mask, options->crMask, options->crMask, -options->grow, options->grow, -options->grow, options->grow);
    1441         psImageConvolveSetThreads(oldThreads);
    1442         if (!newMask) {
    1443             psError(PS_ERR_UNKNOWN, false, "Unable to grow CR mask");
    1444             return false;
    1445         }
    1446         psFree(readout->mask);
    1447         readout->mask = newMask;
    1448     }
    1449     return true;
    1450 }
    1451 
    14521087float psphotSourceSizeFindThreshold (psVector *value, psVector *mask, int maskValue, float minValue, float maxValue, float delta, float guess, float fraction) {
    14531088
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotSourceStats.c

    r35112 r37066  
    5858    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
    5959    psAssert (detections, "missing detections?");
    60 
    61     // XXX TEST:
    62     if (detections->allSources) {
    63         psphotMaskCosmicRayFootprintCheck(detections->allSources);
    64     }
    65     if (detections->newSources) {
    66         psphotMaskCosmicRayFootprintCheck(detections->newSources);
    67     }
    6860
    6961    // determine the number of allowed threads
     
    246238    psphotVisualShowMoments (sources);
    247239
    248     // clear the mark bits
    249     // psImageMaskPixels (readout->mask, "AND", PS_NOT_IMAGE_MASK(markVal));
    250 
    251     if (detections->allSources) {
    252         psphotMaskCosmicRayFootprintCheck(detections->allSources);
    253     }
    254     if (detections->newSources) {
    255         psphotMaskCosmicRayFootprintCheck(detections->newSources);
    256     }
    257 
    258240    return true;
    259241}
     
    572554
    573555            // measure basic source moments (no S/N clipping on input pixels)
     556            // sources with (mode & MODE_EXTERNAL) or (mode2 & MODE2_MATCHED) use the
     557            // supplied Mx,My value for the centroid (not recalculated)
    574558            status = pmSourceMoments (source, 4*sigma[i], sigma[i], 0.0, 0.0, maskVal);
    575559        }
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotStackImageLoop.c

    • Property svn:mergeinfo deleted
    r35769 r37066  
    2222
    2323    pmFPAview *view = pmFPAviewAlloc (0);
    24     pmFPAfile *inputRaw = psMetadataLookupPtr (&status, config->files, "PSPHOT.STACK.INPUT.RAW");
    25     pmFPAfile *inputCnv = psMetadataLookupPtr (&status, config->files, "PSPHOT.STACK.INPUT.CNV");
    26     pmFPAfile *input = inputRaw ? inputRaw : inputCnv;
     24    pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PSPHOT.STACK.INPUT.RAW");
    2725
    2826    if (!input) {
     
    3230
    3331    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
    34     bool useRaw = psMetadataLookupBool (NULL, recipe, "PSPHOT.STACK.USE.RAW");
    35     if (useRaw && inputRaw == NULL) {
    36         psLogMsg ("psphot", 1, "PSPHOT.STACK.USE.RAW set but no raw input.");
    37         useRaw = false;
    38     }
    39 
    40     bool radial_apertures = psMetadataLookupBool(NULL, recipe, "RADIAL_APERTURES");
    41     bool match_psfs = radial_apertures;
    42     bool needConvolved = radial_apertures || !useRaw;
    43     if (!needConvolved) {
    44         pmFPAfileActivate (config->files, false, "PSPHOT.STACK.INPUT.CNV");
    45         pmFPAfileActivate (config->files, false, "PSPHOT.STACK.MASK.CNV");
    46         pmFPAfileActivate (config->files, false, "PSPHOT.STACK.VARIANCE.CNV");
    47         pmFPAfileActivate (config->files, false, "PSPHOT.STACK.PSF.CNV");
    48     }
    4932
    5033    // just load the full set of images up front except for EXPNUM which we defer
    5134    pmFPAfileActivate (config->files, false, "PSPHOT.STACK.EXPNUM.RAW");
    52     pmFPAfileActivate (config->files, false, "PSPHOT.STACK.EXPNUM.CNV");
    5335    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for fpa in psphot.");
    5436
     
    7153                psMemDump("load");
    7254
    73                 if (match_psfs) {
    74                     // Generate the 1st PSF-matched image set (larger target PSFs are generated by smoothing this image)
    75                     if (!psphotStackMatchPSFs (config, view)) {
    76                         psError(psErrorCodeLast(), false, "failure in psphotStackMatchPSFs for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
    77                         psFree (view);
    78                         return false;
    79                     }
    80                 } else {
    81                     if (!psphotStackAllocateOutput (config, view, recipe)) {
    82                         psError(psErrorCodeLast(), false, "failure in psphotStackAllocateOutput for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
    83                         psFree (view);
    84                         return false;
    85                     }
     55                if (!psphotStackAllocateOutput (config, view, recipe)) {
     56                    psError(psErrorCodeLast(), false, "failure in psphotStackAllocateOutput for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
     57                    psFree (view);
     58                    return false;
    8659                }
    8760                psMemDump("stackmatch");
     
    12699
    127100    // Load the appropriate EXPNUM image
    128     pmFPAfileActivate (config->files, true, useRaw ? "PSPHOT.STACK.EXPNUM.RAW" : "PSPHOT.STACK.EXPNUM.CNV");
     101    pmFPAfileActivate (config->files, true, "PSPHOT.STACK.EXPNUM.RAW");
    129102
    130103    if (!pmFPAfileIOChecks (config, view, PM_FPA_BEFORE)) ESCAPE ("failed input for fpa EXPNUM in psphot.");
     
    146119                if (! readout->data_exists) { continue; }
    147120
    148                 if (!psphotSetNFrames (config, view, useRaw ? inputRaw->name : inputCnv->name)) ESCAPE ("failed to setNFrames.");
     121                if (!psphotSetNFrames (config, view, input->name)) ESCAPE ("failed to setNFrames.");
    149122            }
    150123        }
     
    167140bool UpdateHeadersForReadout (pmConfig *config, pmFPAview *view) {
    168141
    169     psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
    170     bool useRaw = psMetadataLookupBool (NULL, recipe, "PSPHOT.STACK.USE.RAW");
    171 
    172142    int num = psphotFileruleCount(config, "PSPHOT.INPUT");
    173143
     
    179149        psAssert (output, "missing file?");
    180150
    181         pmFPAfile *inputRaw = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.RAW", i); // File of interest
    182         pmFPAfile *inputCnv = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.CNV", i); // File of interest
    183         pmFPAfile *input = useRaw ? inputRaw : inputCnv;
     151        pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.RAW", i); // File of interest
    184152        psAssert (input, "missing input file");
    185153
     
    205173        psAssert (output, "missing file?");
    206174
    207         pmFPAfile *inputRaw = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.RAW", i); // File of interest
    208         pmFPAfile *inputCnv = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.CNV", i); // File of interest
    209         pmFPAfile *input = inputRaw ? inputRaw : inputCnv;
     175        pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.RAW", i); // File of interest
    210176        psAssert (input, "missing input file");
    211177
     
    242208        psAssert (output, "missing file?");
    243209
    244         pmFPAfile *inputRaw = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.RAW", i); // File of interest
    245         pmFPAfile *inputCnv = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.CNV", i); // File of interest
    246         pmFPAfile *input = inputRaw ? inputRaw : inputCnv;
     210        pmFPAfile *input = pmFPAfileSelectSingle(config->files, "PSPHOT.STACK.INPUT.RAW", i); // File of interest
    247211        psAssert (input, "missing input file");
    248212
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotStackMatchPSFsNext.c

    r34317 r37066  
    4343    for (int i = 0; i < num; i++) {
    4444        if (!psphotStackMatchPSFsNextReadout (config, view, filerule, i, lastSize)) {
    45             psError (PSPHOT_ERR_CONFIG, false, "failed to smooth image %s (%d) to target PSF", filerule, i);
     45            psLogMsg ("psphot", PS_LOG_INFO, "failed to smooth image %s (%d) to target PSF", filerule, i);
    4646            psImageConvolveSetThreads(oldThreads);
    4747            return false;
     
    102102
    103103    if (targetFWHM <= currentFWHM) {
    104         psError (PSPHOT_ERR_CONFIG, true, "target FWHM cannot be smaller than current FWHM");
     104        // psError (PSPHOT_ERR_CONFIG, true, "target FWHM cannot be smaller than current FWHM");
     105        psLogMsg ("psphot", PS_LOG_INFO, "target FWHM (%f) is smaller than current FWHM (%f), not smoothing\n", targetFWHM, currentFWHM);
     106        fwhmValues->data.F32[lastSize + 1] = currentFWHM;
     107        pmReadoutMaskInvalid(readout, maskVal, maskSat);
    105108        return false;
    106109    }
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotStackMatchPSFsUtils.c

    r34721 r37066  
    325325    if (deconv > deconvLimit) {
    326326        rejectReadout = true;
    327         psLogMsg("psphot", PS_LOG_WARN, "Maximum deconvolution fraction (%f) exceeds limit (%f) --- rejecting image for matched psf analysis%d\n", deconv, deconvLimit, index);
     327        psLogMsg("psphot", PS_LOG_WARN, "Maximum deconvolution fraction (%f) exceeds limit (%f) --- rejecting input %d for matched psf analysis\n", deconv, deconvLimit, index);
    328328    }
    329329   
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotStackReadout.c

    r34721 r37066  
    11# include "psphotInternal.h"
    22
     3static bool psphotStackMatchPSFsetup (pmConfig *config, const pmFPAview *view, const char *filerule, const char *fPSF);
     4static bool psphotStackMatchPSFsetupReadout (pmConfig *config, const pmFPAview *view, const char *filerule, const char *fPSF, int index);
    35static bool psphotStackLoadWCS(pmConfig *config, const pmFPAview *view, const char *filerule);
    46static void logMemStats(const char *heading);
    57
    6 // we have 3 possible real filesets:
     8// relevant filesets:
    79# define STACK_RAW "PSPHOT.STACK.INPUT.RAW"
    8 # define STACK_CNV "PSPHOT.STACK.INPUT.CNV"
    9 # define STACK_OUT "PSPHOT.STACK.OUTPUT.IMAGE"  /* the psf-matched image */
    10 
    11 // we have 3 files on which we operate:
    12 // DET (detection image)       : nominally RAW (optionally CNV?)
    13 // SRC (source analysis image) : nominally CNV (optionally RAW)
    14 // OUT (psf-matched images)    : always OUT
     10# define STACK_OUT "PSPHOT.STACK.OUTPUT.IMAGE"
     11
     12// XXX STACK_OUT currently is a copy of STACK_RAW, but should be a pointer to is as in psphot (single)
     13
     14// TEST CODE, can be removed
     15bool psphotDumpImages (pmConfig *config, const pmFPAview *view, const char *filerule, char *base) {
     16
     17    // XXX do nothing
     18    return true;
     19
     20    int num = psphotFileruleCount(config, "PSPHOT.INPUT");
     21
     22    for (int i = 0; i < num; i++) {
     23        // find the currently selected readout
     24        pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, i); // File of interest
     25        psAssert (file, "missing file?");
     26
     27        pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     28        psAssert (readout, "missing readout?");
     29
     30        char line[256];
     31        snprintf (line, 256, "%s.%d.im.fits", base, i);
     32        psphotSaveImage (NULL, readout->image, line);
     33
     34        snprintf (line, 256, "%s.%d.wt.fits", base, i);
     35        psphotSaveImage (NULL, readout->variance, line);
     36
     37        snprintf (line, 256, "%s.%d.mk.fits", base, i);
     38        psphotSaveImage (NULL, readout->mask, line);
     39    }
     40    return true;
     41}
    1542
    1643bool psphotStackVisualFilerule(pmConfig *config, const pmFPAview *view, const char *filerule) {
     
    6794    psAssert (breakPt, "configuration error: set BREAK_POINT");
    6895
    69     // we have 3 relevant files: RAW (unconvolved), CNV (convolved stack), OUT (psf-matched stack)
    70     // select which image (RAW or CNV) is used for analysis (RAW always used for detection)
    71     bool useRaw = psMetadataLookupBool (NULL, recipe, "PSPHOT.STACK.USE.RAW");
    72     char *STACK_SRC = useRaw ? STACK_RAW : STACK_CNV;
    73     char *STACK_DET = STACK_RAW;
    74 
    7596    // load WCS
    76     if (!psphotStackLoadWCS(config, view, STACK_SRC)) {
    77         psError (PSPHOT_ERR_CONFIG, false, "trouble loading WCS for %s", STACK_SRC);
     97    if (!psphotStackLoadWCS(config, view, STACK_RAW)) {
     98        psError (PSPHOT_ERR_CONFIG, false, "trouble loading WCS for %s", STACK_RAW);
    7899        return false;
    79100    }
    80101
    81102    // set the photcode for each image
    82     if (!psphotAddPhotcode (config, view, STACK_SRC)) {
     103    if (!psphotAddPhotcode (config, view, STACK_RAW)) {
    83104        psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
    84105        return false;
     
    86107
    87108    // Generate the mask and weight images (if not supplied) and set mask bits.
    88     // This also insures that all invalid pixels are masked (this is done for STACK_CNV in psphotStackMatchPSFs)
    89     if (!psphotSetMaskAndVariance (config, view, STACK_DET)) {
    90         return psphotReadoutCleanup (config, view, STACK_SRC);
    91     }
    92     if (!psphotSetMaskAndVariance (config, view, STACK_OUT)) {
    93         return psphotReadoutCleanup (config, view, STACK_SRC);
     109    if (!psphotSetMaskAndVariance (config, view, STACK_RAW)) {
     110        return psphotReadoutCleanup (config, view, STACK_RAW);
    94111    }
    95112    if (!strcasecmp (breakPt, "NOTHING")) {
    96         return psphotReadoutCleanup (config, view, STACK_SRC);
     113        return psphotReadoutCleanup (config, view, STACK_RAW);
    97114    }
    98115
    99116    // generate a background model (median, smoothed image)
    100     if (!psphotModelBackground (config, view, STACK_DET)) {
    101         return psphotReadoutCleanup (config, view, STACK_SRC);
    102     }
    103     if (!psphotSubtractBackground (config, view, STACK_DET)) {
    104         return psphotReadoutCleanup (config, view, STACK_SRC);
    105     }
    106     if (strcmp(STACK_SRC, STACK_DET)) {
    107 #define MODEL_BACKGROUND_SRC 1
    108 #ifdef MODEL_BACKGROUND_SRC
    109         // work around the fact that the background levels on the convolved
    110         // and unconvolved stacks can be different
    111         if (!psphotModelBackground (config, view, STACK_SRC)) {
    112             return psphotReadoutCleanup (config, view, STACK_SRC);
    113         }
    114 #endif
    115         if (!psphotSubtractBackground (config, view, STACK_SRC)) {
    116             return psphotReadoutCleanup (config, view, STACK_SRC);
    117         }
     117    if (!psphotModelBackground (config, view, STACK_RAW)) {
     118        return psphotReadoutCleanup (config, view, STACK_RAW);
     119    }
     120    if (!psphotSubtractBackground (config, view, STACK_RAW)) {
     121        return psphotReadoutCleanup (config, view, STACK_RAW);
    118122    }
    119123    if (!strcasecmp (breakPt, "BACKMDL")) {
    120         return psphotReadoutCleanup (config, view, STACK_SRC);
     124        return psphotReadoutCleanup (config, view, STACK_RAW);
    121125    }
    122126
    123127#ifdef MAKE_CHISQ_IMAGE
    124128    // also make the chisq detection image
    125     if (!psphotStackChisqImage(config, view, STACK_DET, STACK_SRC)) {
     129    if (!psphotStackChisqImage(config, view, STACK_RAW, STACK_RAW)) {
    126130        psError (PSPHOT_ERR_UNKNOWN, false, "failure to generate chisq image");
    127         return psphotReadoutCleanup (config, view, STACK_SRC);
     131        return psphotReadoutCleanup (config, view, STACK_RAW);
     132    }
     133    if (!strcasecmp (breakPt, "CHISQ")) {
     134        return psphotReadoutCleanup (config, view, STACK_RAW);
    128135    }
    129136#endif
    130     if (!strcasecmp (breakPt, "CHISQ")) {
    131         return psphotReadoutCleanup (config, view, STACK_SRC);
    132     }
    133137
    134138    // find the detections (by peak and/or footprint) in the image.
    135139    // This finds the detections on Chisq image as well as the individuals
    136     if (!psphotFindDetections (config, view, STACK_DET, true)) { // pass 1
    137         // this only happens if we had an error in psphotFindDetections
     140    if (!psphotFindDetections (config, view, STACK_RAW, true)) { // pass 1
    138141        psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
    139         return psphotReadoutCleanup (config, view, STACK_SRC);
    140     }
    141 
    142     // If DET and SRC are different images, copy the detections from DET to SRC.  This 'copy'
    143     // is just a copy of the container pointer; the sources on both DET and SRC are the same
    144     // memory objects
    145     if (strcmp(STACK_SRC, STACK_DET)) {
    146         if (!psphotCopySources (config, view, STACK_SRC, STACK_DET)) {
    147             psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
    148             return psphotReadoutCleanup (config, view, STACK_SRC);
    149         }
     142        return psphotReadoutCleanup (config, view, STACK_RAW);
    150143    }
    151144
    152145    // construct sources and measure basic stats (saved on detections->newSources)
    153     if (!psphotSourceStats (config, view, STACK_SRC, true)) { // pass 1
     146    if (!psphotSourceStats (config, view, STACK_RAW, true)) { // pass 1
    154147        psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
    155         return psphotReadoutCleanup (config, view, STACK_SRC);
     148        return psphotReadoutCleanup (config, view, STACK_RAW);
    156149    }
    157150    if (!strcasecmp (breakPt, "PEAKS")) {
    158         return psphotReadoutCleanup (config, view, STACK_SRC);
    159     }
    160     // psphotDumpTest (config, view, STACK_SRC);
     151        return psphotReadoutCleanup (config, view, STACK_RAW);
     152    }
     153    // psphotDumpTest (config, view, STACK_RAW);
    161154    psMemDump("sourcestats");
    162155    logMemStats("sourcestats");
     
    164157    // classify sources based on moments, brightness
    165158    // only run this on detections from the input images, not chisq image
    166     if (!psphotRoughClass (config, view, STACK_SRC)) {
     159    if (!psphotRoughClass (config, view, STACK_RAW)) {
    167160        psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough classifications");
    168         return psphotReadoutCleanup (config, view, STACK_SRC);
    169     }
    170 
    171     // If DET and SRC are different images, subtract radial profiles for the convolved
    172     // image first.  The profiles found on the convolved image will be replaced by those
    173     // found for the unconvolved image.  Downstream, in psphotFindDetections, we will
    174     // replace the the profiles (and re-subtract them) for the detection image, so we want
    175     // to keep those versions of the profiles on the sources.
    176     if (strcmp(STACK_SRC, STACK_DET)) {
    177       // find and subtract radial profile models for saturated stars (XXX change name eventually)
    178       if (!psphotDeblendSatstars (config, view, STACK_SRC)) {
     161        return psphotReadoutCleanup (config, view, STACK_RAW);
     162    }
     163
     164    // find and subtract radial profile models for saturated stars (XXX change name eventually)
     165    if (!psphotDeblendSatstars (config, view, STACK_RAW)) {
    179166        psError (PSPHOT_ERR_UNKNOWN, false, "failed on satstar deblend analysis");
    180         return psphotReadoutCleanup (config, view, STACK_SRC);
    181       }
    182     }
    183     // find and subtract radial profile models for saturated stars (XXX change name eventually)
    184     if (!psphotDeblendSatstars (config, view, STACK_DET)) {
    185         psError (PSPHOT_ERR_UNKNOWN, false, "failed on satstar deblend analysis");
    186         return psphotReadoutCleanup (config, view, STACK_SRC);
     167        return psphotReadoutCleanup (config, view, STACK_RAW);
    187168    }
    188169
    189170    // if we were not supplied a PSF model, determine the IQ stats here (detections->newSources)
    190171    // only run this on detections from the input images, not chisq image
    191     if (!psphotImageQuality (config, view, STACK_SRC)) { // pass 1
     172    if (!psphotImageQuality (config, view, STACK_RAW)) { // pass 1
    192173        psError (PSPHOT_ERR_UNKNOWN, false, "failed to measure image quality");
    193         return psphotReadoutCleanup (config, view, STACK_SRC);
     174        return psphotReadoutCleanup (config, view, STACK_RAW);
    194175    }
    195176    if (!strcasecmp (breakPt, "MOMENTS")) {
    196         return psphotReadoutCleanup (config, view, STACK_SRC);
     177        return psphotReadoutCleanup (config, view, STACK_RAW);
    197178    }
    198179
    199180    // use bright stellar objects to measure PSF
    200     if (!psphotChoosePSF (config, view, STACK_SRC, true)) { // pass 1
     181    if (!psphotChoosePSF (config, view, STACK_RAW, true)) { // pass 1
    201182        psLogMsg ("psphot", 3, "failure to construct a psf model");
    202         return psphotReadoutCleanup (config, view, STACK_SRC);
     183        return psphotReadoutCleanup (config, view, STACK_RAW);
    203184    }
    204185    if (!strcasecmp (breakPt, "PSFMODEL")) {
    205         return psphotReadoutCleanup (config, view, STACK_SRC);
     186        return psphotReadoutCleanup (config, view, STACK_RAW);
    206187    }
    207188
    208189    // merge the newly selected sources into the existing list
    209190    // NOTE: merge OLD and NEW
    210     psphotMergeSources (config, view, STACK_SRC);
     191    psphotMergeSources (config, view, STACK_RAW);
    211192
    212193    // Construct an initial model for each object, set the radius to fitRadius, set circular
    213194    // fit mask.  NOTE: only applied to sources without guess models
    214     psphotGuessModels (config, view, STACK_SRC);
     195    psphotGuessModels (config, view, STACK_RAW);
    215196
    216197    // linear PSF fit to source peaks, subtract the models from the image (in PSF mask)
    217     psphotFitSourcesLinear (config, view, STACK_SRC, false, false);
    218     psphotStackVisualFilerule(config, view, STACK_SRC);
     198    psphotFitSourcesLinear (config, view, STACK_RAW, false, false);
     199    psphotStackVisualFilerule(config, view, STACK_RAW);
    219200
    220201    // measure the radial profiles to the sky
    221     psphotRadialProfileWings (config, view, STACK_SRC);
     202    psphotRadialProfileWings (config, view, STACK_RAW);
    222203
    223204    // re-measure the kron mags with models subtracted.  this pass starts with a circular
     
    225206    // but iterates to an appropriately larger size
    226207    logMemStats("before.kron.1");
    227     psphotKronIterate(config, view, STACK_SRC, 1);
     208    psphotKronIterate(config, view, STACK_RAW, 1);
    228209    logMemStats("after.kron.1");
    229210       
    230211    // identify CRs and extended sources
    231     psphotSourceSize (config, view, STACK_SRC, true);
     212    psphotSourceSize (config, view, STACK_RAW, true);
    232213
    233214    // non-linear PSF and EXT fit to brighter sources
    234215    // replace model flux, adjust mask as needed, fit, subtract the models (full stamp)
    235     psphotBlendFit (config, view, STACK_SRC); // pass 1 (detections->allSources)
     216    psphotBlendFit (config, view, STACK_RAW); // pass 1 (detections->allSources)
    236217
    237218    // replace all sources (do NOT ignore subtraction state)
    238     psphotReplaceAllSources (config, view, STACK_SRC, false); // pass 1 (detections->allSources)
     219    psphotReplaceAllSources (config, view, STACK_RAW, false); // pass 1 (detections->allSources)
    239220
    240221    logMemStats("pass1");
     
    245226    // linear fit to include all sources (subtract again)
    246227    // NOTE : apply to ALL sources (extended + psf)
    247     // NOTE 2 : this function subtracts the models from the given filerule (SRC), not DET
    248     psphotFitSourcesLinear (config, view, STACK_SRC, true, false); // pass 2 (detections->allSources)
     228    // NOTE 2 : this function subtracts the models from the given filerule
     229    psphotFitSourcesLinear (config, view, STACK_RAW, true, false); // pass 2 (detections->allSources)
    249230
    250231    // NOTE: possibly re-measure background model here with objects subtracted / or masked
     
    252233    // NOTE: this block performs the 2nd pass low-significance PSF detection stage
    253234    {
    254         // if DET and SRC are different images, generate children sources for all sources in
    255         // the SRC image.  This operation replaces the existing DETECTION container on DET
    256         // which is currently a view to the one on SRC).  children sources go to
    257         // det->allSources
    258         if (strcmp(STACK_SRC, STACK_DET)) {
    259             psphotSourceChildren (config, view, STACK_DET, STACK_SRC);
    260 
    261             //  subtract all sources from DET (this will subtract using the psf model for SRC, which
    262             //  will somewhat oversubtract the sources -- this is OK
    263             psphotRemoveAllSources (config, view, STACK_DET, false); // do not ignore subtraction state for sources
    264         }
    265 
    266235        // add noise for subtracted objects
    267         psphotAddNoise (config, view, STACK_DET); // pass 1 (detections->allSources)
     236        psphotAddNoise (config, view, STACK_RAW); // pass 1 (detections->allSources)
    268237
    269238        // find fainter sources
    270239        // NOTE: finds new peaks and new footprints, OLD and FULL set are saved on detections
    271         psphotFindDetections (config, view, STACK_DET, false); // pass 2 (detections->peaks, detections->footprints)
     240        psphotFindDetections (config, view, STACK_RAW, false); // pass 2 (detections->peaks, detections->footprints)
    272241
    273242        // remove noise for subtracted objects (ie, return to normal noise level)
     
    276245        bool footprintsUseUnsubtracted = psMetadataLookupBool(NULL, recipe, "FOOTPRINT_USE_UNSUBTRACTED");
    277246        if (!footprintsUseUnsubtracted) {
    278             psphotSubNoise (config, view, STACK_DET); // pass 1 (detections->allSources)
     247            psphotSubNoise (config, view, STACK_RAW); // pass 1 (detections->allSources)
    279248        }
    280 
    281         // if DET and SRC are different images, copy the detections from DET to SRC
    282         // (this operation just ensures the metadata container has a view on SRC as well
    283         if (strcmp(STACK_SRC, STACK_DET)) {
    284             // replace all sources in DET
    285             psphotReplaceAllSources (config, view, STACK_DET, false); // ignore subtraction state for sources
    286 
    287             // copy the newly detected peaks from DET to SRC so SourceStats below can operate on them
    288             if (!psphotCopyPeaks (config, view, STACK_SRC, STACK_DET)) {
    289                 psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
    290                 return psphotReadoutCleanup (config, view, STACK_SRC);
    291             }
    292         }
    293249
    294250        // define new sources based on only the new peaks & measure moments
    295251        // NOTE: new sources are saved on detections->newSources
    296         psphotSourceStats (config, view, STACK_SRC, false); // pass 2 (detections->newSources)
     252        psphotSourceStats (config, view, STACK_RAW, false); // pass 2 (detections->newSources)
    297253
    298254        // set source type
    299255        // NOTE: apply only to detections->newSources
    300         if (!psphotRoughClass (config, view, STACK_SRC)) { // pass 2 (detections->newSources)
     256        if (!psphotRoughClass (config, view, STACK_RAW)) { // pass 2 (detections->newSources)
    301257            psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
    302             return psphotReadoutCleanup (config, view, STACK_SRC);
     258            return psphotReadoutCleanup (config, view, STACK_RAW);
    303259        }
    304260
    305261        // replace all sources so fit below applies to all at once
    306262        // NOTE: apply only to OLD sources (which have been subtracted)
    307         psphotReplaceAllSources (config, view, STACK_SRC, false); // pass 2
     263        psphotReplaceAllSources (config, view, STACK_RAW, false); // pass 2
    308264
    309265        // merge the newly selected sources into the existing list
    310266        // NOTE: merge OLD and NEW
    311267        // XXX check on free of sources...
    312         psphotMergeSources (config, view, STACK_SRC); // (detections->newSources + detections->allSources -> detections->allSources)
     268        psphotMergeSources (config, view, STACK_RAW); // (detections->newSources + detections->allSources -> detections->allSources)
    313269
    314270        // Construct an initial model for each object, set the radius to fitRadius, set circular
    315271        // fit mask.  NOTE: only applied to sources without guess models
    316         psphotGuessModels (config, view, STACK_SRC);
     272        psphotGuessModels (config, view, STACK_RAW);
    317273    }
    318274
     
    325281    if (splitLinearFit) {
    326282        psLogMsg ("psphot", 3, "splitting fit of detected and matched soures\n");
    327         // Fit the detected sources separately from matched that wea are about to create.
     283        // Fit the detected sources separately from matched ones that we are about to create.
    328284        // NOTE: apply to ALL sources but only include sources with postitive flux in the fit
    329         psphotFitSourcesLinear (config, view, STACK_SRC, true, true); // pass 3 (detections->allSources)
     285        psphotFitSourcesLinear (config, view, STACK_RAW, true, true); // pass 3 (detections->allSources)
    330286    }
    331287
     
    335291    // this just match the detections for the chisq image, and not bother measuring the source
    336292    // stats in that case...?
    337     objects = psphotMatchSources (config, view, STACK_SRC);
     293    objects = psphotMatchSources (config, view, STACK_RAW);
    338294    psMemDump("matchsources");
    339295
     
    344300    // Construct an initial model for each object, set the radius to fitRadius, set circular
    345301    // fit mask.  NOTE: only applied to sources without guess models
    346     psphotGuessModels (config, view, STACK_SRC);
     302    psphotGuessModels (config, view, STACK_RAW);
    347303
    348304    psphotStackObjectsUnifyPosition (objects);
    349305
    350     psphotStackObjectsSelectForAnalysis (config, view, STACK_SRC, objects);
     306    // psphotStackObjectsSelectForAnalysis (config, view, STACK_RAW, objects);
    351307
    352308    // final linear fit. NOTE: if splitLinearFit is true above, this pass will only fit
    353309    // the unsubtracted (matched) sources (the sources that we fit above are subtracted)
    354     psphotFitSourcesLinear (config, view, STACK_SRC, true, false); // pass 4 (detections->allSources)
     310    psphotFitSourcesLinear (config, view, STACK_RAW, true, false); // pass 4 (detections->allSources)
    355311
    356312    // measure the radial profiles to the sky (only measures new objects)
    357     psphotRadialProfileWings (config, view, STACK_SRC);
     313    psphotRadialProfileWings (config, view, STACK_RAW);
    358314
    359315    // re-measure the kron mags with models subtracted
    360316    // psphotKronMasked(config, view, STACK_SRC);
    361317    logMemStats("before.kron.2");
    362     psphotKronIterate(config, view, STACK_SRC, 2);
     318    psphotKronIterate(config, view, STACK_RAW, 2);
    363319    logMemStats("after.kron.2");
    364320
    365321    // measure source size for the remaining sources
    366322    // NOTE: applies only to NEW (unmeasured) sources
    367     psphotSourceSize (config, view, STACK_SRC, false); // pass 2 (detections->allSources)
     323    psphotSourceSize (config, view, STACK_RAW, false); // pass 2 (detections->allSources)
    368324
    369325    psMemDump("psfstats");
     
    371327    // drop matched sources without any useful measurements and set kron radii for the ones
    372328    // we decide to keep
    373     psphotFilterMatchedSources (config, view, STACK_SRC, objects);
     329    psphotFilterMatchedSources (config, view, STACK_RAW, objects);
    374330
    375331    // measure kron fluxes for the matched sources only
    376     psphotKronIterate(config, view, STACK_SRC, 3);
     332    psphotKronIterate(config, view, STACK_RAW, 3);
     333
     334    // decide which source(s) are to be fitted with the extended source analysis code.
     335    psphotChooseAnalysisOptionsByObject (config, view, STACK_RAW, objects);
    377336
    378337    // measure elliptical apertures, petrosians (objects sorted by S/N)
    379338    // psphotExtendedSourceAnalysisByObject (config, objects, view, STACK_SRC); // pass 1 (detections->allSources)
    380     psphotExtendedSourceAnalysis (config, view, STACK_SRC); // pass 1 (detections->allSources)
     339    psphotExtendedSourceAnalysis (config, view, STACK_RAW); // pass 1 (detections->allSources)
    381340
    382341    // measure non-linear extended source models (exponential, deVaucouleur, Sersic) (sources sorted by S/N)
    383     psphotExtendedSourceFits (config, view, STACK_SRC); // pass 1 (detections->allSources)
     342    psphotExtendedSourceFits (config, view, STACK_RAW); // pass 1 (detections->allSources)
    384343
    385344    // create source children for the OUT filerule (for radial aperture photometry and output)
    386     psArray *objectsOut = psphotSourceChildrenByObject (config, view, STACK_OUT, objects);
     345    // NOTE: The new source children have image arrays pointing to the readout associated with
     346    // STACK_OUT.  in psphotStackMatchPSFsetup, we copy the current pixel values from RAW to OUT,
     347    // but keep the pointers the same so we do not break these source image references
     348    // XXX NOTE : if we use the pre-20130914 psphotStackReadout code, we need to use 'false' for the
     349    // sourcesSubtracted argument
     350    psArray *objectsOut = psphotSourceChildrenByObject (config, view, STACK_OUT, objects, true);
    387351    if (!objectsOut) {
    388352        psFree(objects);
    389353        psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
    390         return psphotReadoutCleanup (config, view, STACK_SRC);
     354        return psphotReadoutCleanup (config, view, STACK_RAW);
    391355    }
    392356
     
    396360        // this forces photometry on the undetected sources from other images
    397361
    398         // NOTE: we always do the radial apertures analysis on the convolved image since
    399         // those are the ones that are psf matched and are the source of STACK_OUT's pixels
    400         // XXX: Actually if PSPHOT.STACK.MATCH.PSF.SOURCE were set to RAW this wouldn't be true.
    401         // but in that case we don't get past the psf matching step because there is no
    402         // target psf for the RAW inputs
    403 
    404         // If useRaw copy the sources to the convolved readout
    405         if (strcmp(STACK_SRC, STACK_CNV)) {
    406             if (!psphotCopySources (config, view, STACK_CNV, STACK_SRC)) {
    407                 psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
    408                 return psphotReadoutCleanup (config, view, STACK_SRC);
    409             }
    410         }
    411         // mark any inputs that we want to skip the matched apertures for
    412         psphotStackSetInputsToSkip(config, view, STACK_CNV, true);
    413         psphotStackSetInputsToSkip(config, view, STACK_OUT, true);
    414         psphotRadialApertures (config, view, STACK_CNV, 0); // entry 0 == unmatched
    415         psMemDump("extmeas");
    416 
     362        // set up the FWHM vector
     363        psphotStackMatchPSFsetup (config, view, STACK_OUT, STACK_RAW);
     364        psphotDumpImages (config, view, STACK_RAW, "raw.t0");
     365        psphotDumpImages (config, view, STACK_OUT, "out.t0");
    417366
    418367        int nRadialEntries = psphotStackMatchPSFsEntries(config, view, STACK_OUT);
    419         for (int entry = 1; entry < nRadialEntries; entry++) {
     368
     369        for (int entry = 0; entry < nRadialEntries; entry++) {
    420370            // NOTE: entry 0 is the unmatched image set
    421371
    422             // re-measure the PSF for the smoothed image (using entries in 'allSources')
    423             psphotChoosePSF (config, view, STACK_OUT, false);
    424 
    425             // this is necessary to update the models based on the new PSF
    426             psphotResetModels (config, view, STACK_OUT);
    427 
    428             // this is necessary to get the right normalization for the new models
    429             psphotFitSourcesLinear (config, view, STACK_OUT, false, false);
     372            char line[256];
    430373
    431374            // measure circular, radial apertures (objects sorted by S/N)
    432375            psphotRadialApertures (config, view, STACK_OUT, entry);
     376            snprintf (line, 256, "%s.%d", "out.t1", entry);
     377            psphotDumpImages (config, view, STACK_OUT, line);
    433378
    434379            // replace the flux in the image so it is returned to its original state
    435380            psphotReplaceAllSources (config, view, STACK_OUT, false);
    436 
    437             // smooth to the next FWHM, or set 'smoothAgain' to false if no more
    438             psphotStackMatchPSFsNext(config, view, STACK_OUT, entry);
    439             psMemDump("matched");
     381            snprintf (line, 256, "%s.%d", "out.t2", entry);
     382            psphotDumpImages (config, view, STACK_OUT, line);
     383
     384            if (entry < nRadialEntries - 1) {
     385                // smooth to the next FWHM
     386                // this function does nothing if the targetFWHM is smaller than the currentFWHM
     387                psphotStackMatchPSFsNext(config, view, STACK_OUT, entry);
     388                snprintf (line, 256, "%s.%d", "out.t3", entry);
     389                psphotDumpImages (config, view, STACK_OUT, line);
     390                psMemDump("matched");
     391
     392                // re-measure the PSF for the smoothed image (using entries in 'allSources')
     393                if (!psphotChoosePSF (config, view, STACK_OUT, false)) {
     394                    psLogMsg ("psphot", 3, "failure to construct a psf model in radial aperture loop for entry :%d", entry);
     395                    return psphotReadoutCleanup (config, view, STACK_RAW);
     396                }
     397
     398                // this is necessary to update the models based on the new PSF
     399                psphotResetModels (config, view, STACK_OUT);
     400
     401                // this is necessary to get the right normalization for the new models
     402                // and to subtract the sources
     403                psphotFitSourcesLinear (config, view, STACK_OUT, false, false);
     404                snprintf (line, 256, "%s.%d", "out.t4", entry);
     405                psphotDumpImages (config, view, STACK_OUT, line);
     406            }
    440407        }
    441408    }
    442     psphotStackSetInputsToSkip(config, view, STACK_CNV, false);
    443     psphotStackSetInputsToSkip(config, view, STACK_OUT, false);
    444409
    445410    // measure aperture photometry corrections
    446     if (!psphotApResid (config, view, STACK_SRC)) {
     411    if (!psphotApResid (config, view, STACK_RAW)) {
    447412        psFree (objects);
    448413        psFree (objectsOut);
    449414        psLogMsg ("psphot", 3, "failed on psphotApResid");
    450         return psphotReadoutCleanup (config, view, STACK_SRC);
     415        return psphotReadoutCleanup (config, view, STACK_RAW);
    451416    }
    452417
    453418    // calculate source magnitudes
    454     psphotMagnitudes(config, view, STACK_SRC);
    455 
    456     if (!useRaw) {
    457         // psphotEfficiency wants to have the PSF of the image, but since we are measuring on
    458         // the convolved images we need to generate PSFs for the DET images
    459         if (!psphotChoosePSF (config, view, STACK_DET, false)) {
    460             psLogMsg ("psphot", 3, "failure to construct a psf model for raw input");
    461             return psphotReadoutCleanup (config, view, STACK_DET);
    462         }
    463     }
    464     if (!psphotEfficiency(config, view, STACK_DET)) {
     419    psphotMagnitudes(config, view, STACK_RAW);
     420
     421    // calculate lensing parameters
     422    if (!psphotLensing(config, view, STACK_RAW)) {
     423        psErrorStackPrint(stderr, "Unable to do lensing parameters.");
     424        psErrorClear();
     425    }
     426
     427    if (!psphotEfficiency(config, view, STACK_RAW)) {
    465428        psErrorStackPrint(stderr, "Unable to determine detection efficiencies from fake sources");
    466429        psErrorClear();
    467430    }
    468     psphotCopyEfficiency (config, view, STACK_OUT, STACK_DET);
     431    psphotCopyEfficiency (config, view, STACK_OUT, STACK_RAW);
    469432
    470433    logMemStats("final");
    471434#if (1)
    472     psphotSourceMemory(config, view, STACK_SRC);
     435    psphotSourceMemory(config, view, STACK_RAW);
    473436    psphotSourceMemory(config, view, STACK_OUT);
    474437#endif
    475438
    476     // replace failed sources?
    477     // psphotReplaceUnfitSources (sources);
    478 
    479439    // replace background in residual image
    480     psphotSkyReplace (config, view, STACK_DET);
     440    psphotSkyReplace (config, view, STACK_RAW);
    481441
    482442    // drop the references to the image pixels held by each source
     443    psphotSourceFreePixels (config, view, STACK_RAW);
    483444    psphotSourceFreePixels (config, view, STACK_OUT);
    484     psphotSourceFreePixels (config, view, STACK_SRC);
    485445
    486446#ifdef MAKE_CHISQ_IMAGE
    487447    // remove chisq image from config->file:PSPHOT.INPUT
    488     psphotStackRemoveChisqFromInputs(config, STACK_DET);
    489     if (strcmp(STACK_SRC, STACK_DET)) {
    490         psphotStackRemoveChisqFromInputs(config, STACK_SRC);
    491     }
     448    psphotStackRemoveChisqFromInputs(config, STACK_RAW);
    492449#endif
    493450
     
    496453
    497454    // create the exported-metadata and free local data
    498     return psphotReadoutCleanup (config, view, STACK_SRC);
     455    return psphotReadoutCleanup (config, view, STACK_RAW);
    499456}
    500457
     
    552509}
    553510
    554 
    555 
    556511/* here is the process:
    557512
    558  * we have three(*) images:
    559  * RAW : unconvolved image stack
    560  * CNV : input convolved image
     513 * we have two image sets:
     514 * RAW : unconvolved image stacks
    561515
    562516 * OUT : psf-matched output image (there may be more than one of
     
    649603
    650604   */
     605
     606
     607// generate a vector fwhmValues where the first has the fwhm of the raw image and the
     608// successive entries have the target values
     609
     610bool psphotStackMatchPSFsetup (pmConfig *config, const pmFPAview *view, const char *filerule, const char *filerulePSF) {
     611
     612    bool status;
     613
     614    int num = psphotFileruleCount(config, filerule);
     615
     616    // skip the chisq image (optionally?)
     617    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     618    if (!status) chisqNum = -1;
     619
     620    // loop over the available readouts
     621    for (int i = 0; i < num; i++) {
     622        if (i == chisqNum) continue; // skip chisq image
     623
     624        if (!psphotStackMatchPSFsetupReadout (config, view, filerule, filerulePSF, i)) {
     625            psError (PSPHOT_ERR_CONFIG, false, "failed to define target PSF sizes");
     626            return false;
     627        }
     628    }
     629
     630    return true;
     631}
     632
     633float psphotPSFseeing (pmPSF *psf, pmReadout *readout, int index);
     634
     635// copy the pixels from RAW to OUT (
     636
     637bool psphotStackMatchPSFsetupReadout (pmConfig *config, const pmFPAview *view, const char *fileruleOut, const char *fileruleRaw, int index) {
     638
     639    bool status;
     640
     641    // select the appropriate recipe information
     642    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     643
     644    // find the currently selected readout
     645    pmFPAfile *fileOut = pmFPAfileSelectSingle(config->files, fileruleOut, index); // File of interest
     646    psAssert (fileOut, "missing file?");
     647
     648    pmReadout *readoutOut = pmFPAviewThisReadout(view, fileOut->fpa);
     649    psAssert (readoutOut, "missing readout?");
     650
     651    // find the currently selected readout
     652    pmFPAfile *fileRaw = pmFPAfileSelectSingle(config->files, fileruleRaw, index); // File of interest
     653    psAssert (fileRaw, "missing file?");
     654
     655    pmReadout *readoutRaw = pmFPAviewThisReadout(view, fileRaw->fpa);
     656    psAssert (readoutRaw, "missing readout?");
     657
     658    readoutOut->image = psImageCopy(readoutOut->image, readoutRaw->image, PS_TYPE_F32);
     659    if (readoutRaw->variance) {
     660        readoutOut->variance = psImageCopy(readoutOut->variance, readoutRaw->variance, PS_TYPE_F32);
     661    }
     662    if (readoutRaw->mask) {
     663        readoutOut->mask = psImageCopy(readoutOut->mask, readoutRaw->mask, PS_TYPE_IMAGE_MASK);
     664    }
     665
     666    // pmChip *chipRaw = pmFPAviewThisChip(view, fileRaw->fpa); // The chip holds the PSF
     667    // psAssert (chipRaw, "missing chip");
     668
     669    pmPSF *psf = psMetadataLookupPtr(&status, readoutRaw->analysis, "PSPHOT.PSF"); // PSF
     670    if (!psf) {
     671        // we should have a PSF by this point in psphot
     672        psError(PSPHOT_ERR_PROG, true, "Unable to find PSF.");
     673        return false;
     674    }
     675
     676    float fwhmRaw = psphotPSFseeing (psf, readoutRaw, index);
     677
     678    psVector *fwhmValues = psVectorAllocEmpty(10, PS_TYPE_F32);
     679    psVectorAppend(fwhmValues, fwhmRaw);
     680
     681    // is a single target FWHM specified, or a set of values?  set up the vector options->targetSeeing and the local 1st value
     682    float targetSeeing = psMetadataLookupF32 (&status, recipe, "PSPHOT.STACK.TARGET.PSF.FWHM");
     683    if (!status) {
     684        psVector *targetSeeing = psMetadataLookupVector(&status, recipe, "PSPHOT.STACK.TARGET.PSF.FWHM"); // Magnitude offsets
     685        psAssert (status, "missing psphot recipe value PSPHOT.STACK.TARGET.PSF.FWHM");
     686        for (int i = 0; i < targetSeeing->n; i++) {
     687            psVectorAppend(fwhmValues, targetSeeing->data.F32[i]);
     688        }           
     689    } else {
     690        psVectorAppend(fwhmValues, targetSeeing);
     691    }
     692
     693    psMetadataAddVector(readoutOut->analysis, PS_LIST_TAIL, "STACK.PSF.FWHM.VALUES", PS_META_REPLACE, "PSF sizes", fwhmValues);
     694    psFree (fwhmValues);
     695
     696    return true;
     697}
     698
     699float psphotPSFseeing (pmPSF *psf, pmReadout *readout, int index) {
     700
     701    psImage *image = readout->image;
     702
     703    int Nx = image->numCols;
     704    int Ny = image->numRows;
     705
     706    float sumFWHM = 0.0;                  // FWHM for image
     707    int numFWHM = 0;                      // Number of FWHM measurements
     708    for (float x = 0; x < Nx; x += 0.25*Nx) {
     709        for (float y = 0; y < Ny; y += 0.25*Ny) {
     710            float fwhm = pmPSFtoFWHM(psf, x, y);
     711            if (isfinite(fwhm)) {
     712                sumFWHM += fwhm;
     713                numFWHM++;
     714            }
     715        }
     716    }
     717    if (numFWHM == 0) {
     718        psLogMsg("ppStack", PS_LOG_INFO, "Unable to measure PSF FWHM for image %d --- rejected.", index);
     719        return NAN;
     720    }
     721
     722    float fwhm = sumFWHM / (float) numFWHM;
     723    psLogMsg ("psphotStack", PS_LOG_INFO, "Input Seeing for %d: %f\n", index, fwhm);
     724
     725    return fwhm;
     726}
  • branches/eam_branches/ipp-ops-20130712/psphot/src/psphotVisual.c

    r35769 r37066  
    14441444            coord->data.F32[1] = r;
    14451445            coord->data.F32[0] = 0.0;
    1446             fmaj->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord));
     1446            fmaj->data.F32[i] = log10(source->modelPSF->class->modelFunc (NULL, params, coord));
    14471447
    14481448            coord->data.F32[0] = r;
    14491449            coord->data.F32[1] = 0.0;
    1450             fmin->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord));
     1450            fmin->data.F32[i] = log10(source->modelPSF->class->modelFunc (NULL, params, coord));
    14511451        }
    14521452        psFree (coord);
    14531453        psFree (params);
    14541454
    1455         float FWHM_MAJOR = 2.0*source->modelPSF->modelRadius (source->modelPSF->params, 0.5*source->modelPSF->params->data.F32[PM_PAR_I0]);
     1455        float FWHM_MAJOR = 2.0*source->modelPSF->class->modelRadius (source->modelPSF->params, 0.5*source->modelPSF->params->data.F32[PM_PAR_I0]);
    14561456        float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
    14571457        if (FWHM_MAJOR < FWHM_MINOR) PS_SWAP (FWHM_MAJOR, FWHM_MINOR);
Note: See TracChangeset for help on using the changeset viewer.