IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

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

updates from trunk

Location:
branches/tap_branches
Files:
69 edited
19 copied

Legend:

Unmodified
Added
Removed
  • branches/tap_branches

  • branches/tap_branches/psphot

  • branches/tap_branches/psphot/doc/efficiency.txt

    • Property svn:mergeinfo deleted
  • branches/tap_branches/psphot/doc/footprints.txt

    r17710 r27838  
     1
     22010.01.18
     3
     4  * we are having some problems with footprints being freed to early in the second pass
     5
     6  * footprint memory history:
     7
     8    * entering psphotFindFootprints, on the first pass, we have an
     9      array of detected peak in detections->peaks
     10
     11    * in pmFootprintsFind, footprints array owns allocated footprints
     12      footprints each own their spans
     13
     14    * from pmFootprintAssignPeaks:
     15      * the footprints have an array of peaks with valid memory references
     16      * the peaks have just the pointer to the corresponding footprint (not owned)
     17      * all peaks get assigned to a footprint
     18      * at end of pmFootprintAssignPeaks, only a single copy of each peak is/should be available from the collection of footprints
    119
    220pmFootprintCullPeaks is very expensive (15 - 30 msec per object) and
  • branches/tap_branches/psphot/doc/stack.txt

    r24583 r27838  
     1
     220100126:
     3
     4  * watch out for psphotSetMomentsWindow & MOMENTS_SX_MAX,etc
     5  * watch out for psphotSignificanceImage.c:,psphotEfficiency using the FWHM_MAJ from psphotChoosePSF
     6    * ppSimDetections.c : SIGMA_SMOOTH
     7ppSmooth/src/ppSmoothReadout.c:    psMetadataAddF32(recipe, PS_LIST_TAIL, "EFFECTIVE_AREA", PS_META_REPLACE, "Effective Area", effArea);
     8ppSmooth/src/ppSmoothReadout.c:    psMetadataAddF32(recipe, PS_LIST_TAIL, "SIGNIFICANCE_SCALE_FACTOR", PS_META_REPLACE, "Signicance scale factor", factor);
     9
     10
     1120100120 : more stack processing mods:
     12
     13  there are a number of data collections generated during psphotReadout:
     14
     15  * detections (currently a structure containing multiple arrays)
     16  * sources (a psArray)
     17  * psf (the psf model structure)
     18 
     19  * new sources vs old sources:
     20    there is a sequence on the second pass in which we need to distinguish the sources
     21    from the first pass from those on the second pass:
     22
     23    - add noise (old sources only)
     24    - find detections
     25    - subtract noise (old sources only)
     26    - generate sources (new detections only)
     27    - source classifications (new sources only)
     28    - guess models (new sources only)
     29    - replace sources (old sources only)
     30    - merge sources (new + old -> sources)
     31
     32    currently we are distiguishing the old vs new based on different arrays.
     33    can we use the processing flags to distinguish the these cases and carry around
     34    only a single source list?
     35
     36    * detections->peaks holds the most recently detected set of peaks
     37      detections->oldPeaks holds the previous collection
     38
     39      detections->footprints holds the full set of merged footprints,
     40      including assigned peaks from the old and new set.
     41
     4220100107 : updates for stack processing
     43
     44  I am building a new version of psphot that operates on a set of
     45  images (eg, multi-filter or multi-epoch).  The assumptions are:
     46
     47  * each input image represents the same sky pixels : they are warped to a common frame.
     48  * each image has been previously processed, with the background
     49    subtracted (and the psf model determined?)
     50  * all planes are / can be loaded into memory at once (otherwise I
     51    need to add a lot of I/O layers)
     52
     53  psphot currently expects the pmFPAfile of interest to be available in
     54  config->files with the name PSPHOT.INPUT.  To update the code for
     55  stacks, I am extending this concept with the pmFPAfileSelectSingle
     56  API: config->files may contain multiple PSPHOT.INPUT entries, and
     57  functions which access this file / these files need to specify
     58  *which* image they want.  The number of PSPHOT.INPUT entries is
     59  saved in config->arguments as PSPHOT.INPUT.NUM (this can be
     60  generated from the filerule PSPHOT.INPUT for extension).
     61
     62  As a result, we need a number of wrapper functions which loop over
     63  all PSPHOT.INPUT.NUM entries and perform a particular operation on
     64  one of the entries.  Here are the functions which I have modified
     65  in this way (function -> child)
     66
     67  * psphotAddPhotcode -> psphotAddPhotcodeReadout
     68    * note that the photcode is now saved on readout->analysis
     69  * psphotSetMaskAndVariance -> psphotSetMaskAndVarianceReadout
     70  * psphotModelBackground -> psphotModelBackgroundReadoutFileIndex
     71  * psphotSubtractBackground -> psphotSubtractBackgroundReadout
     72
     73  side notes on
     74 
     75  * psphotModelBackground vs psphotBackgroundModel : I've renamed
     76    psphotBackgroundModel (used only by ppStack for now) to
     77    psphotModelBackgroundReadoutNoFile.  I've also named the
     78    single-readout version used by psphotModelBackground to
     79    psphotModelBackgroundReadoutFileIndex.  These two functions do the
     80    same thing, but psphotModelBackgroundReadoutNoFile does not save
     81    a pmFPAfile on config->files
     82
    183
    28420090606 : design notes on the multi-image photometry analysis
  • branches/tap_branches/psphot/src

    • Property svn:ignore
      •  

        old new  
        1919psphotMomentsStudy
        2020psphotPetrosianStudy
         21psphotForced
         22psphotMakePSF
         23psphotStack
  • branches/tap_branches/psphot/src/Makefile.am

    r25755 r27838  
    2525libpsphot_la_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
    2626
    27 bin_PROGRAMS = psphot psphotTest psphotMomentsStudy
    28 # bin_PROGRAMS = psphotPetrosianStudy
    29 # bin_PROGRAMS = psphot
     27bin_PROGRAMS = psphot psphotForced psphotMakePSF psphotStack
     28# bin_PROGRAMS = psphotPetrosianStudy psphotTest psphotMomentsStudy
    3029
    3130psphot_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     
    3332psphot_LDADD = libpsphot.la
    3433
    35 psphotTest_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
    36 psphotTest_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
    37 psphotTest_LDADD = libpsphot.la
    38 
    39 psphotMomentsStudy_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
    40 psphotMomentsStudy_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
    41 psphotMomentsStudy_LDADD = libpsphot.la
     34psphotForced_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     35psphotForced_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     36psphotForced_LDADD = libpsphot.la
     37
     38psphotMakePSF_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     39psphotMakePSF_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     40psphotMakePSF_LDADD = libpsphot.la
     41
     42psphotStack_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     43psphotStack_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     44psphotStack_LDADD = libpsphot.la
     45
     46# psphotMomentsStudy_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     47# psphotMomentsStudy_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     48# psphotMomentsStudy_LDADD = libpsphot.la
    4249
    4350# psphotPetrosianStudy_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     
    4552# psphotPetrosianStudy_LDADD = libpsphot.la
    4653
     54# psphotTest_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     55# psphotTest_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     56# psphotTest_LDADD = libpsphot.la
     57
     58# standard psphot for generic photometry
    4759psphot_SOURCES = \
    4860        psphot.c                \
    4961        psphotArguments.c       \
    50         psphotCleanup.c         \
     62        psphotParseCamera.c     \
    5163        psphotImageLoop.c       \
    5264        psphotMosaicChip.c      \
    53         psphotParseCamera.c
    54 
    55 psphotDetect_SOURCES =            \
    56         psphotDetect.c            \
    57         psphotDetectArguments.c   \
    58         psphotDetectParseCamera.c \
    59         psphotDetectImageLoop.c   \
    60         psphotDetectReadout.c     \
    61         psphotMosaicChip.c        \
    62         psphotCleanup.c
    63 
    64 psphotTest_SOURCES = \
    65         psphotTest.c
    66 
    67 psphotMomentsStudy_SOURCES = \
    68         psphotMomentsStudy.c
    69 
     65        psphotCleanup.c
     66
     67# forced photometry of specified positions given a specified psf
     68psphotForced_SOURCES = \
     69        psphotForced.c             \
     70        psphotForcedArguments.c    \
     71        psphotForcedImageLoop.c    \
     72        psphotForcedReadout.c      \
     73        psphotParseCamera.c        \
     74        psphotMosaicChip.c         \
     75        psphotCleanup.c
     76
     77# a psphot-variant that simply generates the PSF model
     78psphotMakePSF_SOURCES = \
     79        psphotMakePSF.c            \
     80        psphotMakePSFArguments.c   \
     81        psphotMakePSFImageLoop.c   \
     82        psphotMakePSFReadout.c     \
     83        psphotParseCamera.c        \
     84        psphotMosaicChip.c         \
     85        psphotCleanup.c
     86
     87# a psphot-variant for stack photometry
     88psphotStack_SOURCES = \
     89        psphotStack.c                 \
     90        psphotStackArguments.c        \
     91        psphotStackParseCamera.c      \
     92        psphotStackImageLoop.c        \
     93        psphotStackReadout.c          \
     94        psphotStackChisqImage.c       \
     95        psphotFitSourcesLinearStack.c \
     96        psphotSourceMatch.c           \
     97        psphotCleanup.c
     98
     99
     100
     101# # psphot analysis of the detectability of specified positions
     102# psphotDetect_SOURCES =            \
     103#         psphotDetect.c            \
     104#       psphotDetectArguments.c   \
     105#       psphotDetectParseCamera.c \
     106#       psphotDetectImageLoop.c   \
     107#       psphotDetectReadout.c     \
     108#       psphotMosaicChip.c        \
     109#       psphotCleanup.c
     110
     111# psphotTest_SOURCES = \
     112#         psphotTest.c
     113#
     114# psphotMomentsStudy_SOURCES = \
     115#         psphotMomentsStudy.c
     116#
    70117# psphotPetrosianStudy_SOURCES = \
    71118#         psphotPetrosianStudy.c
     
    115162        psphotKernelFromPSF.c          \
    116163        psphotPSFConvModel.c           \
    117         psphotModelTest.c              \
    118164        psphotFitSet.c                 \
    119165        psphotSourceFreePixels.c       \
     
    121167        psphotMergeSources.c           \
    122168        psphotLoadPSF.c                \
     169        psphotLoadSRCTEXT.c            \
    123170        psphotReadoutCleanup.c         \
    124171        psphotSourcePlots.c            \
     
    138185        psphotEllipticalContour.c      \
    139186        psphotEllipticalProfile.c      \
     187        psphotRadialBins.c             \
    140188        psphotPetrosian.c              \
    141189        psphotPetrosianRadialBins.c    \
    142190        psphotPetrosianStats.c         \
     191        psphotPetrosianVisual.c        \
    143192        psphotEfficiency.c
     193
     194# XXX need to fix this for the new apis
     195#       psphotModelTest.c             
    144196
    145197# re-instate these
     
    147199#       psphotAnnuli.c                 \
    148200#       psphotKron.c                   \
    149 #       psphotPetrosianVisual.c        \
    150201#
    151202
  • branches/tap_branches/psphot/src/psphot.h

    r25852 r27838  
    1212
    1313#define PSPHOT_RECIPE_PSF_FAKE_ALLOW "PSF.FAKE.ALLOW" // Name for recipe component permitting fake PSFs
     14
     15// pmPCMData : PSF Convolved Model data storage structure
     16typedef struct {
     17    psImage *model;
     18    psArray *dmodels;
     19    psImage *modelConv;
     20    psArray *dmodelsConv;
     21} pmPCMData;
    1422
    1523// top-level psphot functions
     
    2937bool            psphotReadoutMinimal(pmConfig *config, const pmFPAview *view);
    3038
    31 bool            psphotReadoutCleanup (pmConfig *config, pmReadout *readout, psMetadata *recipe, pmDetections *detections, pmPSF *psf, psArray *sources);
     39bool            psphotReadoutCleanup (pmConfig *config, const pmFPAview *view);
     40bool            psphotReadoutCleanupReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     41
    3242bool            psphotDefineFiles (pmConfig *config, pmFPAfile *input);
    3343void            psphotFilesActivate(pmConfig *config, bool state);
     
    3848// XXX test functions
    3949psArray        *psphotFakeSources (void);
     50bool            psphotMaskCosmicRayFootprintCheck (psArray *sources);
    4051
    4152// psphotReadout functions
    42 bool            psphotModelBackground (pmConfig *config, const pmFPAview *view, const char *filename);
    43 bool            psphotSubtractBackground (pmConfig *config, const pmFPAview *view, const char *filename) ;
    44 pmDetections   *psphotFindDetections (pmDetections *detections, pmReadout *readout, psMetadata *recipe);
    45 
    46 bool            psphotRoughClass (pmReadout *readout, psArray *sources, psMetadata *recipe, const bool findPsfClump);
    47 bool            psphotBasicDeblend (psArray *sources, psMetadata *recipe);
    48 pmPSF          *psphotChoosePSF (pmReadout *readout, psArray *sources, psMetadata *recipe);
    49 bool            psphotPSFstats (pmReadout *readout, psMetadata *recipe, pmPSF *psf);
    50 bool            psphotMomentsStats (pmReadout *readout, psMetadata *recipe, psArray *sources);
    51 bool            psphotFitSourcesLinear (pmReadout *readout, psArray *sources, const psMetadata *recipe, const pmPSF *psf, bool final);
    52 bool            psphotReplaceUnfitSources (psArray *sources, psImageMaskType maskVal);
    53 
    54 bool            psphotReplaceAllSources (psArray *sources, psMetadata *recipe);
    55 bool            psphotRemoveAllSources (const psArray *sources, const psMetadata *recipe);
    56 
    57 bool            psphotBlendFit (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
     53bool            psphotAddPhotcode (pmConfig *config, const pmFPAview *view);
     54bool            psphotAddPhotcodeReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index);
     55
     56bool            psphotSetMaskAndVariance (pmConfig *config, const pmFPAview *view);
     57bool            psphotSetMaskAndVarianceReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     58
     59bool            psphotModelBackground (pmConfig *config, const pmFPAview *view);
     60bool            psphotModelBackgroundReadoutFileIndex (pmConfig *config, const pmFPAview *view, const char *filename, int index);
     61
     62bool            psphotSubtractBackground (pmConfig *config, const pmFPAview *view);
     63bool            psphotSubtractBackgroundReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     64
     65bool            psphotFindDetections (pmConfig *config, const pmFPAview *view, bool firstPass);
     66bool            psphotFindDetectionsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool firstPass);
     67
     68bool            psphotSourceStats (pmConfig *config, const pmFPAview *view, bool setWindow);
     69bool            psphotSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool setWindow);
     70
     71bool            psphotDeblendSatstars (pmConfig *config, const pmFPAview *view);
     72bool            psphotDeblendSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index);
     73
     74bool            psphotBasicDeblend (pmConfig *config, const pmFPAview *view);
     75bool            psphotBasicDeblendReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index);
     76
     77bool            psphotRoughClass (pmConfig *config, const pmFPAview *view);
     78bool            psphotRoughClassReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     79bool            psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *analysis, psMetadata *recipe, const bool havePSF);
     80
     81bool            psphotImageQuality (pmConfig *config, const pmFPAview *view);
     82bool            psphotImageQualityReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     83
     84bool            psphotChoosePSF (pmConfig *config, const pmFPAview *view);
     85bool            psphotChoosePSFReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     86
     87bool            psphotGuessModels (pmConfig *config, const pmFPAview *view);
     88bool            psphotGuessModelsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index);
     89
     90bool            psphotMergeSources (pmConfig *config, const pmFPAview *view);
     91bool            psphotMergeSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index);
     92
     93bool            psphotFitSourcesLinear (pmConfig *config, const pmFPAview *view, bool final);
     94bool            psphotFitSourcesLinearReadout (psMetadata *recipe, pmReadout *readout, psArray *sources, pmPSF *psf, bool final);
     95
     96bool            psphotSourceSize (pmConfig *config, const pmFPAview *view, bool getPSFsize);
     97bool            psphotSourceSizeReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool getPSFsize);
     98
     99bool            psphotBlendFit (pmConfig *config, const pmFPAview *view);
     100bool            psphotBlendFitReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
    58101bool            psphotBlendFit_Threaded (psThreadJob *job);
    59102
    60 psArray        *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections, bool setWindow);
    61 bool            psphotSourceStats_Threaded (psThreadJob *job);
    62 
    63 bool            psphotGuessModels (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
    64 bool            psphotGuessModel_Threaded (psThreadJob *job);
    65 
    66 bool            psphotMagnitudes (pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources, const pmPSF *psf);
     103bool            psphotReplaceAllSources (pmConfig *config, const pmFPAview *view);
     104bool            psphotReplaceAllSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     105
     106bool            psphotAddNoise (pmConfig *config, const pmFPAview *view);
     107bool            psphotSubNoise (pmConfig *config, const pmFPAview *view);
     108bool            psphotAddOrSubNoise (pmConfig *config, const pmFPAview *view, bool add);
     109bool            psphotAddOrSubNoiseReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool add);
     110
     111bool            psphotExtendedSourceAnalysis (pmConfig *config, const pmFPAview *view);
     112bool            psphotExtendedSourceAnalysisReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     113
     114bool            psphotExtendedSourceFits (pmConfig *config, const pmFPAview *view);
     115bool            psphotExtendedSourceFitsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     116
     117bool            psphotApResid (pmConfig *config, const pmFPAview *view);
     118bool            psphotApResidReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
     119
     120bool            psphotMagnitudes (pmConfig *config, const pmFPAview *view);
     121bool            psphotMagnitudesReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, pmReadout *readout, psArray *sources, pmPSF *psf);
    67122bool            psphotMagnitudes_Threaded (psThreadJob *job);
     123
     124bool            psphotEfficiency (pmConfig *config, const pmFPAview *view);
     125bool            psphotEfficiencyReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe);
    68126
    69127bool            psphotPSFWeights(pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources);
    70128bool            psphotPSFWeights_Threaded (psThreadJob *job);
    71129
    72 bool            psphotApResid (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);
    73 
    74130bool            psphotSkyReplace (pmConfig *config, const pmFPAview *view);
    75 bool            psphotExtendedSourceAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe);
    76 bool            psphotExtendedSourceFits (pmReadout *readout, psArray *sources, psMetadata *recipe);
    77 bool            psphotEfficiency(pmConfig *config, pmReadout *readout, const pmFPAview *view, const pmPSF *psf, psMetadata *recipe, const psArray *realSources);
     131bool            psphotSkyReplaceReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index);
     132
     133bool            psphotSourceFreePixels (pmConfig *config, const pmFPAview *view);
     134bool            psphotSourceFreePixelsReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index);
     135
     136// in psphotSourceStats.c:
     137bool            psphotSourceStats_Threaded (psThreadJob *job);
     138bool            psphotSourceStatsUpdate (psArray *sources, pmConfig *config, pmReadout *readout);
     139bool            psphotSetMomentsWindow (psMetadata *recipe, psMetadata *analysis, psArray *sources);
     140
     141// in psphotChoosePSF.c:
     142bool            psphotPSFstats (pmReadout *readout, pmPSF *psf);
     143bool            psphotMomentsStats (pmReadout *readout, psArray *sources);
     144
     145// in psphotGuessModel.c
     146bool            psphotGuessModel_Threaded (psThreadJob *job);
     147
     148// in psphotMergeSources.c:
     149bool            psphotLoadExtSources (pmConfig *config, const pmFPAview *view);
     150psArray        *psphotLoadPSFSources (pmConfig *config, const pmFPAview *view);
     151bool            psphotRepairLoadedSources (pmConfig *config, const pmFPAview *view);
     152bool            psphotCheckExtSources (pmConfig *config, const pmFPAview *view);
     153
     154// generate the detection structure for the supplied array of sources
     155bool            psphotDetectionsFromSources (pmConfig *config, const pmFPAview *view, psArray *sources);
     156
     157// generate the detection structure for the supplied array of sources
     158bool            psphotSetSourceParams (pmConfig *config, psArray *sources, pmPSF *psf);
     159
     160// in psphotModelBackground.c:
     161// Create a background model for a readout, without saving the result as a pmFPAfile on config->files.  Otherwise identical to psphotModelBackgroundFileIndex.
     162psImage        *psphotModelBackgroundReadoutNoFile(pmReadout *readout, const pmConfig *config);
     163psImageBinning *psphotBackgroundBinning(const psImage *image, const pmConfig *config);
     164
     165// in psphotReplaceUnfit.c:
     166bool            psphotRemoveAllSources (const psArray *sources, const psMetadata *recipe);
     167bool            psphotReplaceUnfitSources (psArray *sources, psImageMaskType maskVal);
    78168
    79169// thread-related:
     
    87177psArray        *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax);
    88178bool            psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int pass, psImageMaskType maskVal);
    89 psErrorCode     psphotCullPeaks(const psImage *img, const psImage *weight, const psMetadata *recipe, psArray *footprints);
    90 
    91 // generate the detection structure for the supplied array of sources
    92 pmDetections   *psphotDetectionsFromSources (pmConfig *config, psArray *sources);
    93 
    94 // used by ApResid
     179psErrorCode     psphotCullPeaks(const pmReadout *readout, const psMetadata *recipe, psArray *footprints);
     180
     181// in psphotApResid.c:
    95182pmTrend2D      *psphotApResidTrend (float *apResidSysErr, pmReadout *readout, int Nx, int Ny, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag);
    96183bool            psphotApResidMags_Threaded (psThreadJob *job);
     
    99186void            psphotModelClassInit (void);
    100187bool            psphotGrowthCurve (pmReadout *readout, pmPSF *psf, bool ignore, psImageMaskType maskVal);
    101 bool            psphotSetMaskAndVariance (pmConfig *config, pmReadout *readout, psMetadata *recipe);
    102 void            psphotSourceFreePixels (psArray *sources);
    103188
    104189// functions to set the correct source pixels
    105 bool            psphotInitRadiusPSF (const psMetadata *recipe, const pmModelType type);
     190bool            psphotInitRadiusPSF(const psMetadata *recipe, const psMetadata *analysis, const pmModelType type);
     191
    106192bool            psphotCheckRadiusPSF (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal);
    107193bool            psphotCheckRadiusPSFBlend (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal, float dR);
     
    110196float           psphotSetRadiusEXT (pmReadout *readout, pmSource *source, psImageMaskType markVal);
    111197
    112 // output functions
    113 bool            psphotAddPhotcode (psMetadata *recipe, pmConfig *config, const pmFPAview *view, const char *filerule);
    114198bool            psphotDumpMoments (psMetadata *recipe, psArray *sources);
    115199psMetadata     *psphotDefineHeader (psMetadata *recipe);
     
    142226bool            psphotFitSummary (void);
    143227
    144 bool            psphotMergeSources (psArray *oldSources, psArray *newSources);
    145 bool            psphotLoadExtSources (pmConfig *config, const pmFPAview *view, psArray *sources);
    146 psArray        *psphotLoadPSFSources (pmConfig *config, const pmFPAview *view);
    147 
    148 pmPSF          *psphotLoadPSF (pmConfig *config, const pmFPAview *view, psMetadata *recipe);
     228bool            psphotLoadPSF (pmConfig *config, const pmFPAview *view);
     229bool            psphotLoadPSFReadout (pmConfig *config, const pmFPAview *view, const char *outFilename, const char *inFilename, int index);
     230
    149231bool            psphotSetHeaderNstars (psMetadata *recipe, psArray *sources);
    150 bool            psphotAddNoise (pmReadout *readout, const psArray *sources, const psMetadata *recipe);
    151 bool            psphotSubNoise (pmReadout *readout, const psArray *sources, const psMetadata *recipe);
    152 bool            psphotAddOrSubNoise (pmReadout *readout, const psArray *sources, const psMetadata *recipe, bool add);
    153232bool            psphotRadialPlot (int *kapa, const char *filename, pmSource *source);
    154233bool            psphotSourcePlots (pmReadout *readout, psArray *sources, psMetadata *recipe);
    155234bool            psphotMosaicSubimage (psImage *outImage, pmSource *source, int Xo, int Yo, int DX, int DY, bool normalize);
    156235
    157 bool            psphotAddWithTest (pmSource *source, bool useState, psImageMaskType maskVal);
    158 bool            psphotSubWithTest (pmSource *source, bool useState, psImageMaskType maskVal);
    159 bool            psphotSetState (pmSource *source, bool curState, psImageMaskType maskVal);
    160 bool            psphotDeblendSatstars (pmReadout *readout, psArray *sources, psMetadata *recipe);
    161 bool            psphotSourceSize (pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, long first);
    162 
    163236bool            psphotMakeResiduals (psArray *sources, psMetadata *recipe, pmPSF *psf, psImageMaskType maskVal);
    164237
     
    168241
    169242// functions related to extended source analysis
    170 bool  psphotRadialProfile (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal);
    171 bool  psphotRadialProfilesByAngles (pmSource *source, int Nsec, float Rmax);
    172 float psphotRadiusFromProfile (pmSource *source, psVector *radius, psVector *flux, float fluxMin, float fluxMax);
    173 bool  psphotRadiiFromProfiles (pmSource *source, float fluxMin, float fluxMax);
    174 bool  psphotEllipticalProfile (pmSource *source);
    175 bool  psphotEllipticalContour (pmSource *source);
     243bool            psphotRadialProfile (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal);
     244bool            psphotRadialProfilesByAngles (pmSource *source, int Nsec, float Rmax);
     245float           psphotRadiusFromProfile (pmSource *source, psVector *radius, psVector *flux, float fluxMin, float fluxMax);
     246bool            psphotRadiiFromProfiles (pmSource *source, float fluxMin, float fluxMax);
     247bool            psphotEllipticalProfile (pmSource *source, bool RAW_RADIUS);
     248bool            psphotEllipticalContour (pmSource *source);
    176249
    177250// psphotVisual functions
    178 bool psphotVisualShowImage (pmReadout *readout);
    179 bool psphotVisualShowBackground (pmConfig *config, const pmFPAview *view, pmReadout *readout);
    180 bool psphotVisualShowSignificance (psImage *image);
    181 bool psphotVisualShowPeaks (pmDetections *detections);
    182 bool psphotVisualShowFootprints (pmDetections *detections);
    183 bool psphotVisualShowMoments (psArray *sources);
    184 bool psphotVisualPlotMoments (psMetadata *recipe, psMetadata *analysis, psArray *sources);
    185 bool psphotVisualShowRoughClass (psArray *sources);
    186 bool psphotVisualShowPSFStars (psMetadata *recipe, pmPSF *psf, psArray *sources);
    187 bool psphotVisualShowSatStars (psMetadata *recipe, pmPSF *psf, psArray *sources);
    188 bool psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf);
    189 bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal);
    190 bool psphotVisualPlotRadialProfiles (psMetadata *recipe, psArray *sources);
    191 bool psphotVisualShowFlags (psArray *sources);
    192 bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources);
    193 bool psphotVisualShowResidualImage (pmReadout *readout);
    194 bool psphotVisualPlotApResid (psArray *sources, float mean, float error);
    195 bool psphotVisualPlotSourceSize (psMetadata *recipe, psMetadata *analysis, psArray *sources);
    196 bool psphotVisualShowPetrosians (psArray *sources);
    197 
    198 // bool psphotPetrosianAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe);
    199 // bool psphotPetrosianProfile (pmReadout *readout, pmSource *source, float skynoise);
     251bool            psphotVisualShowImage (pmReadout *readout);
     252bool            psphotVisualShowBackground (pmConfig *config, const pmFPAview *view, pmReadout *readout);
     253bool            psphotVisualShowSignificance (psImage *image, float min, float max);
     254bool            psphotVisualShowPeaks (pmDetections *detections);
     255bool            psphotVisualShowFootprints (pmDetections *detections);
     256bool            psphotVisualShowMoments (psArray *sources);
     257bool            psphotVisualPlotMoments (psMetadata *recipe, psMetadata *analysis, psArray *sources);
     258bool            psphotVisualShowRoughClass (psArray *sources);
     259bool            psphotVisualShowPSFStars (psMetadata *recipe, pmPSF *psf, psArray *sources);
     260bool            psphotVisualShowSatStars (psMetadata *recipe, pmPSF *psf, psArray *sources);
     261bool            psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf);
     262bool            psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal);
     263bool            psphotVisualPlotRadialProfiles (psMetadata *recipe, psArray *sources);
     264bool            psphotVisualShowFlags (psArray *sources);
     265bool            psphotVisualShowSourceSize (pmReadout *readout, psArray *sources);
     266bool            psphotVisualShowResidualImage (pmReadout *readout);
     267bool            psphotVisualPlotApResid (psArray *sources, float mean, float error);
     268bool            psphotVisualPlotChisq (psArray *sources);
     269bool            psphotVisualPlotSourceSize (psMetadata *recipe, psMetadata *analysis, psArray *sources);
     270bool            psphotVisualShowPetrosians (psArray *sources);
     271bool            psphotVisualEraseOverlays (int channel, char *overlay);
    200272
    201273bool psphotPetrosian (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal);
     
    203275bool psphotPetrosianStats (pmSource *source);
    204276
    205 // XXX old versions, currently disabled
     277// currently disabled:
    206278// bool            psphotIsophotal (pmSource *source, psMetadata *recipe, psImageMaskType maskVal);
    207279// bool            psphotAnnuli (pmSource *source, psMetadata *recipe, psImageMaskType maskVal);
     
    209281
    210282// XXX visualization functions related to radial profiles (disabled)
    211 // bool psphotPetrosianVisualProfileByAngle (psVector *radius, psVector *flux);
    212 // bool psphotPetrosianVisualProfileRadii (psVector *radius, psVector *flux, psVector *radiusBin, psVector *fluxBin, float peakFlux, float RadiusRef);
    213 // bool psphotPetrosianVisualEllipticalContour (pmPetrosian *petrosian);
    214 // bool psphotPetrosianVisualStats (psVector *radBin, psVector *fluxBin,
    215 //                               psVector *refRadius, psVector *meanSB,
    216 //                               psVector *petRatio, psVector *petRatioErr, psVector *fluxSum,
    217 //                               float petRadius, float ratioForRadius,
    218 //                               float petFlux, float radiusForFlux);
    219 
    220 bool psphotImageQuality (psMetadata *recipe, psArray *sources);
     283bool psphotPetrosianVisualProfileByAngle (psVector *radius, psVector *flux);
     284bool psphotPetrosianVisualProfileRadii (psVector *radius, psVector *flux, psVector *radiusBin, psVector *fluxBin, float peakFlux, float RadiusRef);
     285bool psphotPetrosianVisualEllipticalContour (pmSourceRadialFlux *radFlux, pmSourceExtendedPars *extpars);
     286bool psphotPetrosianVisualStats (psVector *radBin, psVector *fluxBin,
     287                               psVector *refRadius, psVector *meanSB,
     288                               psVector *petRatio, psVector *petRatioErr, psVector *fluxSum,
     289                               float petRadius, float ratioForRadius,
     290                               float petFlux, float radiusForFlux);
     291
     292bool psphotRadialBins (psMetadata *recipe, pmSource *source, float radiusMax, float skynoise);
    221293
    222294// structures & functions to support psf-convolved model fitting
    223 
    224 // pmPCMData : PSF Convolved Model data storage structure
    225 typedef struct {
    226     psImage *model;
    227     psArray *dmodels;
    228     psImage *modelConv;
    229     psArray *dmodelsConv;
    230 } pmPCMData;
    231 
    232295
    233296// psf-convolved model fitting
     
    267330bool psphotDumpPSFStars (pmReadout *readout, pmPSFtry *try, float radius, psImageMaskType maskVal, psImageMaskType markVal);
    268331
     332bool psphotLoadSRCTEXT (pmFPA *fpa, pmConfig *config);
     333
    269334bool psphotCheckStarDistribution (psArray *sources, psArray *stars, pmPSFOptions *options);
    270335int psphotSupplementStars (psArray *stars, psArray *sources, psImageBinning *binning, int ix, int iy);
    271336
    272 
    273 // Create a background model for a readout
    274 // Essentially identical to psphotModelBackground, but with a more convenient API for outsiders.
    275 psImage *psphotBackgroundModel(pmReadout *ro, // Readout for which to generate background model
    276                                const pmConfig *config // Configuration
    277     );
    278 
     337pmConfig *psphotForcedArguments(int argc, char **argv);
     338bool psphotForcedImageLoop (pmConfig *config);
     339bool psphotForcedReadout(pmConfig *config, const pmFPAview *view);
     340
     341pmConfig *psphotMakePSFArguments(int argc, char **argv);
     342bool psphotMakePSFImageLoop (pmConfig *config);
     343bool psphotMakePSFReadout(pmConfig *config, const pmFPAview *view);
     344
     345/**** psphotStack prototypes ****/
     346
     347pmConfig *psphotStackArguments(int argc, char **argv);
     348bool psphotStackParseCamera (pmConfig *config);
     349bool psphotStackImageLoop (pmConfig *config);
     350bool psphotStackReadout (pmConfig *config, const pmFPAview *view);
     351bool psphotStackChisqImage (pmConfig *config, const pmFPAview *view);
     352bool psphotStackChisqImageAddReadout(const pmConfig *config, // Configuration
     353                                     const pmFPAview *view,
     354                                     pmReadout **chiReadout,
     355                                     char *filename,
     356                                     int index);
     357
     358bool psphotStackRemoveChisqFromInputs (pmConfig *config);
     359bool pmFPAfileRemoveSingle(psMetadata *files, const char *name, int num);
     360
     361psArray *psphotMatchSources (pmConfig *config, const pmFPAview *view);
     362bool psphotMatchSourcesReadout (psArray *objects, pmConfig *config, const pmFPAview *view, char *filename, int index);
     363bool psphotMatchSourcesToObjects (psArray *objects, psArray *sources, float RADIUS);
     364
     365bool psphotFitSourcesLinearStack (pmConfig *config, psArray *objects, bool final);
     366int pmPhotObjSortBySN (const void **a, const void **b);
     367int pmPhotObjSortByX (const void **a, const void **b);
    279368
    280369#endif
  • branches/tap_branches/psphot/src/psphotAddNoise.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
    3 bool psphotAddNoise (pmReadout *readout, const psArray *sources, const psMetadata *recipe) {
    4   return psphotAddOrSubNoise (readout, sources, recipe, true);
     3bool psphotAddNoise (pmConfig *config, const pmFPAview *view) {
     4    return psphotAddOrSubNoise (config, view, true);
    55}
    66
    7 bool psphotSubNoise (pmReadout *readout, const psArray *sources, const psMetadata *recipe) {
    8   return psphotAddOrSubNoise (readout, sources, recipe, false);
     7bool psphotSubNoise (pmConfig *config, const pmFPAview *view) {
     8    return psphotAddOrSubNoise (config, view, false);
    99}
    1010
    11 bool psphotAddOrSubNoise (pmReadout *readout, const psArray *sources, const psMetadata *recipe, bool add) {
     11// for now, let's store the detections on the readout->analysis for each readout
     12bool psphotAddOrSubNoise (pmConfig *config, const pmFPAview *view, bool add)
     13{
     14    bool status = true;
     15
     16    // select the appropriate recipe information
     17    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     18    psAssert (recipe, "missing recipe?");
     19
     20    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     21    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     22
     23    // loop over the available readouts
     24    for (int i = 0; i < num; i++) {
     25        if (!psphotAddOrSubNoiseReadout (config, view, "PSPHOT.INPUT", i, recipe, add)) {
     26            psError (PSPHOT_ERR_CONFIG, false, "failed on to modify noise for PSPHOT.INPUT entry %d", i);
     27            return false;
     28        }
     29    }
     30    return true;
     31}
     32
     33bool psphotAddOrSubNoiseReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool add) {
    1234
    1335    bool status = false;
     
    1638    psEllipseAxes axes;
    1739
    18     PS_ASSERT (readout, false);
    19     PS_ASSERT (readout->parent, false);
    20     PS_ASSERT (readout->parent->concepts, false);
     40    // find the currently selected readout
     41    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     42    psAssert (file, "missing file?");
     43
     44    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     45    psAssert (readout, "missing readout?");
     46    psAssert (readout->parent, "missing cell?");
     47    psAssert (readout->parent->concepts, "missing concepts?");
     48
     49    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     50    psAssert (detections, "missing detections?");
     51
     52    psArray *sources = detections->allSources;
     53    psAssert (sources, "missing sources?");
    2154
    2255    psTimerStart ("psphot.noise");
     
    2457    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    2558    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    26     assert (maskVal);
     59    psAssert (maskVal, "missing mask value?");
    2760
    2861    // increase variance by factor*(object noise):
  • branches/tap_branches/psphot/src/psphotApResid.c

    r25755 r27838  
    44// measure the aperture residual statistics and 2D variations
    55
    6 bool psphotApResid (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf)
     6// for now, let's store the detections on the readout->analysis for each readout
     7bool psphotApResid (pmConfig *config, const pmFPAview *view)
     8{
     9    bool status = true;
     10
     11    // select the appropriate recipe information
     12    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     13    psAssert (recipe, "missing recipe?");
     14
     15    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     16    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     17
     18    // skip the chisq image (optionally?)
     19    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     20    if (!status) chisqNum = -1;
     21
     22    // loop over the available readouts
     23    for (int i = 0; i < num; i++) {
     24        if (i == chisqNum) continue; // skip chisq image
     25        if (!psphotApResidReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     26            psError (PSPHOT_ERR_CONFIG, false, "failed to measure aperture residual for PSPHOT.INPUT entry %d", i);
     27            return false;
     28        }
     29    }
     30    return true;
     31}
     32
     33bool psphotApResidReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe)
    734{
    835    int Nfail = 0;
     
    1340    pmSource *source;
    1441
    15     PS_ASSERT_PTR_NON_NULL(config, false);
    16     PS_ASSERT_PTR_NON_NULL(readout, false);
    17     PS_ASSERT_PTR_NON_NULL(sources, false);
    18     PS_ASSERT_PTR_NON_NULL(psf, false);
    19 
    2042    psTimerStart ("psphot.apresid");
    2143
    22     // select the appropriate recipe information
    23     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    24     assert (recipe);
     44    // find the currently selected readout
     45    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     46    psAssert (file, "missing file?");
     47
     48    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     49    psAssert (readout, "missing readout?");
     50
     51    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     52    psAssert (detections, "missing detections?");
     53
     54    psArray *sources = detections->allSources;
     55    psAssert (sources, "missing sources?");
     56
     57    if (!sources->n) {
     58        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping ap resid");
     59        return true;
     60    }
     61
     62    pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
     63    psAssert (psf, "missing psf?");
    2564
    2665    // determine the number of allowed threads
     
    3372    if (!measureAptrend) {
    3473        // save nan values since these were not calculated
    35         psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   NAN);
    36         psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN);
    37         psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0);
    38         psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN);
     74        psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   NAN);
     75        psMetadataAdd (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN);
     76        psMetadataAdd (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0);
     77        psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN);
    3978        return true;
    4079    }
     
    217256    }
    218257
    219     // XXX set the min number of needed source more carefully
    220     if ((Npsf < 15) && (APTREND_ORDER_MAX >= 4)) APTREND_ORDER_MAX = 3;
    221     if ((Npsf < 11) && (APTREND_ORDER_MAX >= 3)) APTREND_ORDER_MAX = 2;
    222     if ((Npsf <  8) && (APTREND_ORDER_MAX >= 2)) APTREND_ORDER_MAX = 1;
     258    // this is a bit tricky, because we have two cases (MAP vs POLY), and they have a different
     259    // definition for 'order' (order_MAP = order_POLY + 1).  in addition, we have a
     260    // user-specified MAX order, which we should respect, regardless of the mode
     261
     262    // set the max order (0 = constant) which the number of psf stars can support:
     263    // rule of thumb: require 3 stars per 'cell' (order+1)^2
     264    int MaxOrderForStars = 0;
     265    if (Npsf >= 12) MaxOrderForStars = 1; // 4 cells
     266    if (Npsf >= 27) MaxOrderForStars = 2; // 9 cells
     267    if (Npsf >= 48) MaxOrderForStars = 3; // 16 cells
     268    if (Npsf >  75) MaxOrderForStars = 4; // 25 cells
     269
     270    pmTrend2DMode mode = PM_TREND_MAP;
     271    if (mode == PM_TREND_MAP) {
     272        MaxOrderForStars ++;
     273    }
     274    APTREND_ORDER_MAX = PS_MIN (APTREND_ORDER_MAX, MaxOrderForStars);
    223275
    224276    psFree (psf->ApTrend);
     
    275327
    276328    // save results for later output
    277     psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   psf->ApResid);
    278     psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid);
    279     psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid);
    280     psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth->apLoss);
     329    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   psf->ApResid);
     330    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid);
     331    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid);
     332    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth->apLoss);
    281333
    282334    psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid);
     
    295347escape:
    296348    // save nan values since these were not calculated
    297     psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   NAN);
    298     psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN);
    299     psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0);
    300     psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN);
     349    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APMIFIT",  PS_DATA_F32 | PS_META_REPLACE, "aperture residual",   NAN);
     350    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN);
     351    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0);
     352    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "APLOSS",   PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN);
    301353
    302354    psFree (xPos);
     
    305357    psFree (mag);
    306358    psFree (dMag);
    307     return false;
     359    return true;
     360    // this is a quality error, not a programming error
    308361}
    309362
  • branches/tap_branches/psphot/src/psphotArguments.c

    r24587 r27838  
    218218    // override any configuration-specified source for these files
    219219    //
    220     pmConfigFileSetsMD (config->arguments, &argc, argv, "MASK",   "-mask",   "-masklist");
    221     pmConfigFileSetsMD (config->arguments, &argc, argv, "VARIANCE", "-variance", "-variancelist");
    222     pmConfigFileSetsMD (config->arguments, &argc, argv, "PSPHOT.PSF", "-psf", "-psflist");
    223     pmConfigFileSetsMD (config->arguments, &argc, argv, "SRC",    "-src",    "-srclist");
     220    pmConfigFileSetsMD (config->arguments, &argc, argv, "MASK",       "-mask",     "-masklist");
     221    pmConfigFileSetsMD (config->arguments, &argc, argv, "VARIANCE",   "-variance", "-variancelist");
     222    pmConfigFileSetsMD (config->arguments, &argc, argv, "PSPHOT.PSF", "-psf",      "-psflist");
     223    pmConfigFileSetsMD (config->arguments, &argc, argv, "SRC",        "-src",      "-srclist");
    224224
    225225    if (argc == 1) {
     
    228228    }
    229229
    230     if (psArgumentGet(argc, argv, "-help")
    231         || psArgumentGet(argc, argv, "-h"))
     230    if (psArgumentGet(argc, argv, "-help") ||
     231        psArgumentGet(argc, argv, "-h"))
    232232      writeHelpInfo(argv[0], config, stdout);
    233233     
  • branches/tap_branches/psphot/src/psphotBasicDeblend.c

    r20453 r27838  
    11# include "psphotInternal.h"
    22
    3 bool psphotBasicDeblend (psArray *sources, psMetadata *recipe) {
     3// for now, let's store the detections on the readout->analysis for each readout
     4bool psphotBasicDeblend (pmConfig *config, const pmFPAview *view)
     5{
     6    bool status = true;
     7
     8    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     9    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     10
     11    // loop over the available readouts
     12    for (int i = 0; i < num; i++) {
     13        if (!psphotBasicDeblendReadout (config, view, "PSPHOT.INPUT", i)) {
     14            psError (PSPHOT_ERR_CONFIG, false, "failed on basic deblend analysis for PSPHOT.INPUT entry %d", i);
     15            return false;
     16        }
     17    }
     18    return true;
     19}
     20
     21bool psphotBasicDeblendReadout (pmConfig *config, const pmFPAview *view, const char *filename, int fileIndex) {
    422
    523    int N;
     
    826    pmSource *source, *testSource;
    927
     28    psTimerStart ("psphot.deblend.basic");
     29
    1030    int Nblend = 0;
    1131
    12     psTimerStart ("psphot.deblend.basic");
     32    // find the currently selected readout
     33    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, fileIndex); // File of interest
     34    psAssert (file, "missing file?");
     35
     36    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     37    psAssert (readout, "missing readout?");
     38
     39    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     40    psAssert (detections, "missing detections?");
     41
     42    psArray *sources = detections->newSources;
     43    psAssert (sources, "missing sources?");
     44
     45    if (!sources->n) {
     46        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping basic deblend");
     47        return true;
     48    }
     49
     50    // select the appropriate recipe information
     51    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     52    psAssert (recipe, "missing recipe?");
    1353
    1454    float FRACTION = psMetadataLookupF32 (&status, recipe, "DEBLEND_PEAK_FRACTION");
  • branches/tap_branches/psphot/src/psphotBlendFit.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
     3// for now, let's store the detections on the readout->analysis for each readout
     4bool psphotBlendFit (pmConfig *config, const pmFPAview *view)
     5{
     6    bool status = true;
     7
     8    // select the appropriate recipe information
     9    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     10    psAssert (recipe, "missing recipe?");
     11
     12    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     13    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     14
     15    // loop over the available readouts
     16    for (int i = 0; i < num; i++) {
     17        if (!psphotBlendFitReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     18            psError (PSPHOT_ERR_CONFIG, false, "failed to fit sources (non-linear) for PSPHOT.INPUT entry %d", i);
     19            return false;
     20        }
     21    }
     22    return true;
     23}
     24
    325// XXX I don't like this name
    4 bool psphotBlendFit (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf) {
     26bool psphotBlendFitReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {
    527
    628    int Nfit = 0;
     
    1234    psTimerStart ("psphot.fit.nonlinear");
    1335
    14     // select the appropriate recipe information
    15     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    16     assert (recipe);
     36    // find the currently selected readout
     37    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     38    psAssert (file, "missing file?");
     39
     40    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     41    psAssert (readout, "missing readout?");
     42
     43    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     44    psAssert (detections, "missing detections?");
     45
     46    psArray *sources = detections->allSources;
     47    psAssert (sources, "missing sources?");
     48
     49    if (!sources->n) {
     50        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping blend fit");
     51        return true;
     52    }
     53
     54    pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
     55    psAssert (psf, "missing psf?");
    1756
    1857    // determine the number of allowed threads
     
    4079    psphotInitLimitsPSF (recipe, readout);
    4180    psphotInitLimitsEXT (recipe);
    42     psphotInitRadiusPSF (recipe, psf->type);
     81    psphotInitRadiusPSF (recipe, readout->analysis, psf->type);
    4382
    4483    // starts the timer, sets up the array of fitSets
     
    4786    // source analysis is done in S/N order (brightest first)
    4887    sources = psArraySort (sources, pmSourceSortBySN);
     88    if (!sources->n) {
     89        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping blend");
     90        return true;
     91    }
    4992
    5093    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     
    272315}
    273316
    274 # if (0)
    275 bool psphotBlendFit_Unthreaded (int *nfit, int *npsf, int *next, int *nfail, pmReadout *readout, psMetadata *recipe, psArray *sources, pmPSF *psf, psArray *newSources) {
    276 
    277     bool status = false;
    278     int Nfit = 0;
    279     int Npsf = 0;
    280     int Next = 0;
    281     int Nfail = 0;
    282 
    283     // bit-masks to test for good/bad pixels
    284     psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT");
    285     assert (maskVal);
    286 
    287     // bit-mask to mark pixels not used in analysis
    288     psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT");
    289     assert (markVal);
    290 
    291     // maskVal is used to test for rejected pixels, and must include markVal
    292     maskVal |= markVal;
    293 
    294     // S/N limit to perform full non-linear fits
    295     float FIT_SN_LIM = psMetadataLookupF32 (&status, recipe, "FULL_FIT_SN_LIM");
    296 
    297     // option to limit analysis to a specific region
    298     char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");
    299     psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region));
    300     if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");
    301 
    302     for (int i = 0; i < sources->n; i++) {
    303         pmSource *source = sources->data[i];
    304 
    305         // skip non-astronomical objects (very likely defects)
    306         if (source->mode &  PM_SOURCE_MODE_BLEND) continue;
    307         if (source->mode &  PM_SOURCE_MODE_CR_LIMIT) continue;
    308         if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
    309         if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
    310 
    311         // skip DBL second sources (ie, added by psphotFitBlob)
    312         if (source->mode &  PM_SOURCE_MODE_PAIR) continue;
    313 
    314         // limit selection to some SN limit
    315         if (source->peak->SN < FIT_SN_LIM) continue;
    316 
    317         // exclude sources outside optional analysis region
    318         if (source->peak->xf < AnalysisRegion.x0) continue;
    319         if (source->peak->yf < AnalysisRegion.y0) continue;
    320         if (source->peak->xf > AnalysisRegion.x1) continue;
    321         if (source->peak->yf > AnalysisRegion.y1) continue;
    322 
    323         // if model is NULL, we don't have a starting guess
    324         if (source->modelPSF == NULL) continue;
    325 
    326         // skip sources which are insignificant flux?
    327         // XXX this is somewhat ad-hoc
    328         if (source->modelPSF->params->data.F32[1] < 0.1) {
    329             psTrace ("psphot", 5, "skipping near-zero source: %f, %f : %f\n",
    330                      source->modelPSF->params->data.F32[1],
    331                      source->modelPSF->params->data.F32[2],
    332                      source->modelPSF->params->data.F32[3]);
    333             continue;
    334         }
    335 
    336         // replace object in image
    337         if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) {
    338             pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    339         }
    340         Nfit ++;
    341 
    342         // try fitting PSFs or extended sources depending on source->mode
    343         // these functions subtract the resulting fitted source
    344         if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    345             if (psphotFitBlob (readout, source, newSources, psf, maskVal, markVal)) {
    346                 source->type = PM_SOURCE_TYPE_EXTENDED;
    347                 psTrace ("psphot", 5, "source at %7.1f, %7.1f is ext", source->peak->xf, source->peak->yf);
    348                 Next ++;
    349                 continue;
    350             }
    351         } else {
    352             if (psphotFitBlend (readout, source, psf, maskVal, markVal)) {
    353                 source->type = PM_SOURCE_TYPE_STAR;
    354                 psTrace ("psphot", 5, "source at %7.1f, %7.1f is psf", source->peak->xf, source->peak->yf);
    355                 Npsf ++;
    356                 continue;
    357             }
    358         }
    359 
    360         psTrace ("psphot", 5, "source at %7.1f, %7.1f failed", source->peak->xf, source->peak->yf);
    361         Nfail ++;
    362 
    363         // re-subtract the object, leave local sky
    364         pmSourceCacheModel (source, maskVal);
    365         pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    366     }
    367 
    368     // change the value of a scalar on the array (wrap this and put it in psArray.h)
    369     *nfit  = Nfit;
    370     *npsf  = Npsf;
    371     *next  = Next;
    372     *nfail = Nfail;
    373 
    374     // moments are modified by the fit; re-display
    375     psphotVisualPlotMoments (recipe, sources);
    376     psphotVisualShowResidualImage (readout);
    377 
    378     return true;
    379 }
    380 # endif
  • branches/tap_branches/psphot/src/psphotChoosePSF.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
     3// generate a PSF model for inputs without PSF models already loaded
     4bool psphotChoosePSF (pmConfig *config, const pmFPAview *view)
     5{
     6    bool status = true;
     7
     8    // select the appropriate recipe information
     9    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     10    psAssert (recipe, "missing recipe?");
     11
     12    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     13    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     14
     15    // skip the chisq image (optionally?)
     16    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     17    if (!status) chisqNum = -1;
     18
     19    // loop over the available readouts
     20    for (int i = 0; i < num; i++) {
     21        if (i == chisqNum) continue; // skip chisq image
     22        if (!psphotChoosePSFReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     23            psError (PSPHOT_ERR_CONFIG, false, "failed to choose a psf model for PSPHOT.INPUT entry %d", i);
     24            return false;
     25        }
     26    }
     27    return true;
     28}
     29
    330// try PSF models and select best option
    4 pmPSF *psphotChoosePSF (pmReadout *readout, psArray *sources, psMetadata *recipe) {
     31bool psphotChoosePSFReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {
    532
    633    bool status;
    734
    835    psTimerStart ("psphot.choose.psf");
     36
     37    // find the currently selected readout
     38    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     39    psAssert (file, "missing file?");
     40
     41    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     42    psAssert (readout, "missing readout?");
     43
     44    // do not generate a PSF if we already were supplied one
     45    if (psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF")) {
     46        psLogMsg ("psphot", PS_LOG_DETAIL, "psf model supplied for input file %d", index);
     47        return true;
     48    }
     49
     50    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     51    psAssert (detections, "missing detections?");
     52
     53    psArray *sources = detections->newSources;
     54    psAssert (sources, "missing sources?");
     55
     56    if (!sources->n) {
     57        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping PSF model");
     58        return false;
     59    }
    960
    1061    // bit-masks to test for good/bad pixels
    1162    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT");
    12     assert (maskVal);
     63    psAssert (maskVal, "missing mask value?");
    1364
    1465    // bit-mask to mark pixels not used in analysis
    1566    psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT");
    16     assert (markVal);
     67    psAssert (markVal, "missing mark value?");
    1768
    1869    // maskVal is used to test for rejected pixels, and must include markVal
     
    61112    // assert (status);
    62113
    63     // We have calculated a Gaussian window function, use that for both the PSF fit radius and
    64     // the aperture radius (scaling SIGMA)
    65     float gaussSigma = psMetadataLookupF32(&status, recipe, "MOMENTS_GAUSS_SIGMA");
     114    // values on readout->analysis if we have calculated a Gaussian window function, use that
     115    // for both the PSF fit radius and the aperture radius (scaling SIGMA), otherwise base the value on the recipe value for MOMENTS_GAUSS_SIGMA
     116    float gaussSigma = psMetadataLookupF32 (&status, readout->analysis, "MOMENTS_GAUSS_SIGMA");
     117    if (!status) {
     118        gaussSigma = psMetadataLookupF32 (&status, recipe, "MOMENTS_GAUSS_SIGMA");
     119    }
    66120    float fitScale = psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS_SCALE");
    67121    float apScale = psMetadataLookupF32(&status, recipe, "PSF_APERTURE_SCALE");
     
    70124
    71125    // XXX use the same radii for standard analysis as for the PSF creation
    72     psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_FIT_RADIUS", PS_META_REPLACE, "fit radius", options->fitRadius);
    73     psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_APERTURE", PS_META_REPLACE, "psf aperture", options->apRadius);
    74 
    75     // XXX ROBUST seems to be too agressive given the small numbers.
    76     // options->stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    77     options->stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
     126    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "PSF_FIT_RADIUS", PS_META_REPLACE, "fit radius", options->fitRadius);
     127    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "PSF_APERTURE", PS_META_REPLACE, "psf aperture", options->apRadius);
    78128
    79129    // dimensions of the field for which the PSF is defined
     
    116166    psLogMsg ("psphot.pspsf", PS_LOG_DETAIL, "selected candidate %ld PSF objects\n", stars->n);
    117167
     168    if (stars->n < 50) {
     169        // ROBUST is too agressive if we only have a small number of PSF stars
     170        options->stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
     171    } else {
     172        options->stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
     173    }
     174
    118175    // get the list pointers for the PSF_MODEL entries
    119176    psArray *modelNames = NULL;
     
    155212        bool status = true;
    156213        status &= psphotMakeFluxScale (readout->image, recipe, psf);
    157         status &= psphotPSFstats (readout, recipe, psf);
     214        status &= psphotPSFstats (readout, psf);
    158215        if (!status) {
    159216            psError(PSPHOT_ERR_PSF, false, "Failed to fit any models when choosing PSF");
     
    230287        bool status = true;
    231288        status &= psphotMakeFluxScale (readout->image, recipe, psf);
    232         status &= psphotPSFstats (readout, recipe, psf);
     289        status &= psphotPSFstats (readout, psf);
    233290        if (!status) {
    234291            psError(PSPHOT_ERR_PSF, false, "Failed to fit any models when choosing PSF");
     
    287344    psFree (models);
    288345
    289     if (!psphotPSFstats (readout, recipe, psf)) {
     346    if (!psphotPSFstats (readout, psf)) {
    290347        psError(PSPHOT_ERR_PSF, false, "cannot measure PSF shape terms");
    291348        psFree(options);
     
    299356
    300357    psFree (options);
    301     return (psf);
     358
     359    // save PSF on readout->analysis
     360    if (!psMetadataAddPtr (readout->analysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot psf model", psf)) {
     361        psError (PSPHOT_ERR_UNKNOWN, false, "problem saving sources on readout");
     362        return false;
     363    }
     364    psFree (psf); // XXX double-check
     365
     366    // move into psphotChoosePSF
     367    psphotVisualShowPSFModel (readout, psf);
     368
     369    return true;
    302370}
    303371
    304372// measure average parameters of the PSF model
    305 bool psphotPSFstats (pmReadout *readout, psMetadata *recipe, pmPSF *psf) {
     373bool psphotPSFstats (pmReadout *readout, pmPSF *psf) {
    306374
    307375    psEllipseShape shape;
     
    309377
    310378    PS_ASSERT_PTR_NON_NULL(readout, false);
    311     PS_ASSERT_PTR_NON_NULL(recipe, false);
    312379    PS_ASSERT_PTR_NON_NULL(psf, false);
    313380
     
    329396            pmModel *modelPSF = pmModelFromPSFforXY (psf, xc, yc, 1.0);
    330397            if (!modelPSF) {
    331                 fprintf (stderr, "?");
    332                 continue;
    333             }
     398                fprintf (stderr, "?");
     399                continue;
     400            }
    334401
    335402            // get the model full-width at half-max
     
    345412            float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
    346413            if (!isfinite(FWHM_MAJOR) || !isfinite(FWHM_MINOR)) {
    347                 fprintf (stderr, "!");
    348                 continue;
    349             }
     414                fprintf (stderr, "!");
     415                continue;
     416            }
    350417            psVectorAppend (fwhmMajor, FWHM_MAJOR);
    351418            psVectorAppend (fwhmMinor, FWHM_MINOR);
     
    359426    }
    360427
    361     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_MAJ",   PS_META_REPLACE, "PSF FWHM Major axis (mean)", stats->sampleMean);
    362     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_SG",   PS_META_REPLACE, "PSF FWHM Major axis (sigma)", stats->sampleStdev);
    363     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_LQ",   PS_META_REPLACE, "PSF FWHM Major axis (lower quartile)", stats->sampleLQ);
    364     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_UQ",   PS_META_REPLACE, "PSF FWHM Major axis (upper quartile)", stats->sampleUQ);
     428    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FWHM_MAJ",   PS_META_REPLACE, "PSF FWHM Major axis (mean)", stats->sampleMean);
     429    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MJ_SG",   PS_META_REPLACE, "PSF FWHM Major axis (sigma)", stats->sampleStdev);
     430    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MJ_LQ",   PS_META_REPLACE, "PSF FWHM Major axis (lower quartile)", stats->sampleLQ);
     431    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MJ_UQ",   PS_META_REPLACE, "PSF FWHM Major axis (upper quartile)", stats->sampleUQ);
     432
     433    float fwhmMaj = stats->sampleMean;  // FWHM on major axis
    365434
    366435    if (!psVectorStats (stats, fwhmMinor, NULL, NULL, 0)) {
     
    368437        return false;
    369438    }
    370     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_MIN",   PS_META_REPLACE, "PSF FWHM Minor axis (mean)", stats->sampleMean);
    371     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_SG",   PS_META_REPLACE, "PSF FWHM Minor axis (sigma)", stats->sampleStdev);
    372     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_LQ",   PS_META_REPLACE, "PSF FWHM Minor axis (lower quartile)", stats->sampleLQ);
    373     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_UQ",   PS_META_REPLACE, "PSF FWHM Minor axis (upper quartile)", stats->sampleUQ);
    374 
    375     psMetadataAddF32 (recipe, PS_LIST_TAIL, "ANGLE",    PS_META_REPLACE, "PSF angle",           axes.theta);
    376     psMetadataAddS32 (recipe, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", psf->nPSFstars);
    377     psMetadataAddBool(recipe, PS_LIST_TAIL, "PSFMODEL", PS_META_REPLACE, "Valid PSF Model?", true);
     439    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FWHM_MIN",   PS_META_REPLACE, "PSF FWHM Minor axis (mean)", stats->sampleMean);
     440    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MN_SG",   PS_META_REPLACE, "PSF FWHM Minor axis (sigma)", stats->sampleStdev);
     441    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MN_LQ",   PS_META_REPLACE, "PSF FWHM Minor axis (lower quartile)", stats->sampleLQ);
     442    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MN_UQ",   PS_META_REPLACE, "PSF FWHM Minor axis (upper quartile)", stats->sampleUQ);
     443
     444    float fwhmMin = stats->sampleMean;  // FWHM on minor axis
     445    if (readout->parent) {
     446        pmChip *chip = readout->parent->parent; // Parent chip
     447        psAssert(chip, "Cell should be attached to a chip.");
     448        psMetadataItem *item = psMetadataLookup(chip->concepts, "CHIP.SEEING"); // Item with chip
     449        item->data.F32 = 0.5 * (fwhmMaj + fwhmMin);
     450    }
     451
     452    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "ANGLE",    PS_META_REPLACE, "PSF angle",           axes.theta);
     453    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", psf->nPSFstars);
     454    psMetadataAddBool(readout->analysis, PS_LIST_TAIL, "PSFMODEL", PS_META_REPLACE, "Valid PSF Model?", true);
    378455
    379456    psFree (fwhmMajor);
     
    384461
    385462// determine approximate PSF shape parameters based on the moments
    386 bool psphotMomentsStats (pmReadout *readout, psMetadata *recipe, psArray *sources) {
     463bool psphotMomentsStats (pmReadout *readout, psArray *sources) {
    387464
    388465    // without the PSF model, we can only rely on the source->moments
     
    398475
    399476    PS_ASSERT_PTR_NON_NULL(readout, false);
    400     PS_ASSERT_PTR_NON_NULL(recipe, false);
    401477    PS_ASSERT_PTR_NON_NULL(sources, false);
    402478
     
    426502    FWHM_T /= FWHM_N;
    427503
    428     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_MAJ",   PS_META_REPLACE, "PSF FWHM Major axis (mean)", FWHM_X);
    429     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_SG",   PS_META_REPLACE, "PSF FWHM Major axis (sigma)", 0);
    430     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_LQ",   PS_META_REPLACE, "PSF FWHM Major axis (lower quartile)", 0);
    431     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_UQ",   PS_META_REPLACE, "PSF FWHM Major axis (upper quartile)", 0);
    432 
    433     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_MIN",   PS_META_REPLACE, "PSF FWHM Minor axis (mean)", FWHM_Y);
    434     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_SG",   PS_META_REPLACE, "PSF FWHM Minor axis (sigma)", 0);
    435     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_LQ",   PS_META_REPLACE, "PSF FWHM Minor axis (lower quartile)", 0);
    436     psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_UQ",   PS_META_REPLACE, "PSF FWHM Minor axis (upper quartile)", 0);
    437 
    438     psMetadataAddF32 (recipe, PS_LIST_TAIL, "ANGLE",    PS_META_REPLACE, "PSF angle",           FWHM_T);
    439     psMetadataAddS32 (recipe, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", 0);
    440     psMetadataAddBool(recipe, PS_LIST_TAIL, "PSFMODEL", PS_META_REPLACE, "Valid PSF Model?", false);
     504    if (readout->parent) {
     505        pmChip *chip = readout->parent->parent; // Parent chip
     506        psAssert(chip, "Cell should be attached to a chip.");
     507        psMetadataItem *item = psMetadataLookup(chip->concepts, "CHIP.SEEING"); // Item with chip
     508        item->data.F32 = 0.5 * (FWHM_X + FWHM_Y);
     509    }
     510
     511    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FWHM_MAJ",   PS_META_REPLACE, "PSF FWHM Major axis (mean)", FWHM_X);
     512    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MJ_SG",   PS_META_REPLACE, "PSF FWHM Major axis (sigma)", 0);
     513    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MJ_LQ",   PS_META_REPLACE, "PSF FWHM Major axis (lower quartile)", 0);
     514    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MJ_UQ",   PS_META_REPLACE, "PSF FWHM Major axis (upper quartile)", 0);
     515    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FWHM_MIN",   PS_META_REPLACE, "PSF FWHM Minor axis (mean)", FWHM_Y);
     516    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MN_SG",   PS_META_REPLACE, "PSF FWHM Minor axis (sigma)", 0);
     517    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MN_LQ",   PS_META_REPLACE, "PSF FWHM Minor axis (lower quartile)", 0);
     518    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "FW_MN_UQ",   PS_META_REPLACE, "PSF FWHM Minor axis (upper quartile)", 0);
     519    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "ANGLE",    PS_META_REPLACE, "PSF angle",           FWHM_T);
     520    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", 0);
     521    psMetadataAddBool(readout->analysis, PS_LIST_TAIL, "PSFMODEL", PS_META_REPLACE, "Valid PSF Model?", false);
    441522
    442523    return true;
  • branches/tap_branches/psphot/src/psphotCleanup.c

    r24144 r27838  
    1414    psFree (config);
    1515
    16     psThreadPoolFinalize ();
    17     psTimerStop ();
    1816    psMemCheckCorruption (stderr, true);
    1917    pmModelClassCleanup ();
    20     psTimeFinalize ();
    2118    pmSourceFitSetDone ();
    2219    pmConceptsDone ();
  • branches/tap_branches/psphot/src/psphotCullPeaks.c

    r24877 r27838  
    55 */
    66psErrorCode
    7 psphotCullPeaks(const psImage *image,   // the image wherein lives the footprint
    8                 const psImage *weight,  // corresponding variance image
     7psphotCullPeaks(const pmReadout *readout,   // the image wherein lives the footprint
    98                const psMetadata *recipe,
    109                psArray *footprints) {  // array of pmFootprints
     10
    1111    bool status = false;
     12
    1213    float nsigma_delta = psMetadataLookupF32(&status, recipe, "FOOTPRINT_CULL_NSIGMA_DELTA");
    1314    if (!status) {
     
    2223        fPadding = 0;
    2324    }
    24     const float skyStdev = psMetadataLookupF32(NULL, recipe, "SKY_STDEV");
     25    const float skyStdev = psMetadataLookupF32(&status, readout->analysis, "SKY_STDEV");
     26    psAssert (status, "cannot find SKY_STDEV in readout->analysis");
     27
    2528    const float min_threshold = nsigma_min*skyStdev;
    2629   
    2730    for (int i = 0; i < footprints->n; i++) {
     31        // if (i % 50 == 0) fprintf (stderr, "cull %d\n", i);
    2832        pmFootprint *fp = footprints->data[i];
    29         if (pmFootprintCullPeaks(image, weight, fp, nsigma_delta, fPadding, min_threshold) != PS_ERR_NONE) {
     33        if (fp->npix > 30000) {
     34            fprintf (stderr, "big footprint: %f %f to %f %f (%d pix)\n", fp->bbox.x0, fp->bbox.y0, fp->bbox.x1, fp->bbox.y1, fp->npix);
     35        }
     36        psTimerStart ("psphot.cull.footprints");
     37        if (pmFootprintCullPeaks(readout->image, readout->variance, fp, nsigma_delta, fPadding, min_threshold) != PS_ERR_NONE) {
    3038            return psError(PS_ERR_UNKNOWN, false, "Culling pmFootprint %d", fp->id);
    3139        }
     40        float dtime = psTimerMark ("psphot.cull.footprints");
     41        if (dtime > 1.0) {
     42            fprintf (stderr, "slow cull for %d (%f sec)\n", i, dtime);
     43        }
    3244    }
    33    
    3445    return PS_ERR_NONE;
    3546}
     47
     48// psLogMsg ("psphot", PS_LOG_INFO, "%ld peaks, %ld total footprints: %f sec\n", detections->peaks->n, detections->footprints->n,
  • branches/tap_branches/psphot/src/psphotDeblendSatstars.c

    r25885 r27838  
    11# include "psphotInternal.h"
    22
    3 bool psphotDeblendSatstars (pmReadout *readout, psArray *sources, psMetadata *recipe) {
     3// for now, let's store the detections on the readout->analysis for each readout
     4bool psphotDeblendSatstars (pmConfig *config, const pmFPAview *view)
     5{
     6    bool status = true;
     7
     8    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     9    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     10
     11    // loop over the available readouts
     12    for (int i = 0; i < num; i++) {
     13        if (!psphotDeblendSatstarsReadout (config, view, "PSPHOT.INPUT", i)) {
     14            psError (PSPHOT_ERR_CONFIG, false, "failed on saturated star deblend analysis for PSPHOT.INPUT entry %d", i);
     15            return false;
     16        }
     17    }
     18    return true;
     19}
     20
     21bool psphotDeblendSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int fileIndex) {
    422
    523    int N;
    624    pmSource *source;
     25    bool status;
    726
    827    psTimerStart ("psphot.deblend.sat");
     
    1130    float SAT_MIN_RADIUS = 5.0;
    1231
    13     bool status;
     32    // find the currently selected readout
     33    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, fileIndex); // File of interest
     34    psAssert (file, "missing file?");
     35
     36    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     37    psAssert (readout, "missing readout?");
     38
     39    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     40    psAssert (detections, "missing detections?");
     41
     42    psArray *sources = detections->newSources;
     43    psAssert (sources, "missing sources?");
     44
     45    if (!sources->n) {
     46        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping satstar blend");
     47        return true;
     48    }
     49
     50    // select the appropriate recipe information
     51    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     52    psAssert (recipe, "missing recipe?");
     53
    1454    pmCell *cell = readout->parent;
    1555    float SATURATION = 0.75*psMetadataLookupF32 (&status, cell->concepts, "CELL.SATURATION");
  • branches/tap_branches/psphot/src/psphotDefineFiles.c

    r23688 r27838  
    126126    }
    127127
     128    if (psMetadataLookupPtr(NULL, config->arguments, "SRCTEXT")) {
     129        // XXX cannot use pmFPAfileDefineFromArgs: this is explicitly a FITS-based I/O function
     130        // supply the attach the
     131        if (!psphotLoadSRCTEXT(input->fpa, config)) {
     132            psError(PSPHOT_ERR_CONFIG, false, "Failed to load PSPHOT.INPUT.TEXT");
     133            return status;
     134        }
     135    }
     136
    128137    if (psMetadataLookupPtr(NULL, config->arguments, "PSPHOT.PSF")) {
    129138        pmFPAfileBindFromArgs(&status, input, config, "PSPHOT.PSF.LOAD", "PSPHOT.PSF");
  • branches/tap_branches/psphot/src/psphotEfficiency.c

    • Property svn:mergeinfo deleted
    r25890 r27838  
    44                    PM_MODEL_STATUS_BADARGS | PM_MODEL_STATUS_LIMITS) // Mask to apply to models
    55
    6 //#define TESTING
    7 
     6# define TESTING 0
    87
    98// Calculate the limiting magnitude for an image
     
    1716                     float *covarFactor,// Covariance factor
    1817                     const pmReadout *ro,     // Readout of interest
    19                      const pmPSF *psf,        // Point-spread function
     18                     pmPSF *psf,              // Point-spread function
    2019                     float thresh,            // Threshold for source identification
    2120                     float smoothSigma,       // Gaussian smoothing sigma
     
    3332
    3433    psKernel *kernel = psImageSmoothKernel(smoothSigma, smoothNsigma); // Kernel used for smoothing
    35     psKernel *newCovar = psImageCovarianceCalculate(kernel, ro->covariance); // Covariance matrix
     34    *covarFactor = psImageCovarianceCalculateFactor(kernel, ro->covariance);
    3635    psFree(kernel);
    37     *covarFactor = psImageCovarianceFactor(newCovar); // Variance factor
    38     psFree(newCovar);
    3936
    4037    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for variance
     
    128125    psFree(rng);
    129126
     127    bool oldThreads = pmReadoutFakeThreads(true); // Old threading status
     128
    130129    pmReadout *fakeRO = pmReadoutAlloc(NULL); // Fake readout
    131130    if (!pmReadoutFakeFromVectors(fakeRO, numCols, numRows, xAll, yAll, magAll,
     
    142141    psFree(yAll);
    143142
     143    pmReadoutFakeThreads(oldThreads);
     144
    144145    psBinaryOp(ro->image, ro->image, "+", fakeRO->image);
    145146    psFree(fakeRO);
     
    148149}
    149150
     151bool psphotEfficiency (pmConfig *config, const pmFPAview *view)
     152{
     153    bool status = true;
     154
     155    // select the appropriate recipe information
     156    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     157    psAssert (recipe, "missing recipe?");
     158
     159    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     160    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     161
     162    // skip the chisq image (optionally?)
     163    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     164    if (!status) chisqNum = -1;
     165
     166    // loop over the available readouts
     167    for (int i = 0; i < num; i++) {
     168        if (i == chisqNum) continue; // skip chisq image
     169        if (!psphotEfficiencyReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     170            psError (PSPHOT_ERR_CONFIG, false, "failed to measure detection efficiency for PSPHOT.INPUT entry %d", i);
     171            return false;
     172        }
     173    }
     174    return true;
     175}
    150176
    151177// Determine detection efficiency
    152 bool psphotEfficiency(pmConfig *config, pmReadout *readout, const pmFPAview *view, const pmPSF *psf,
    153                 psMetadata *recipe, const psArray *realSources)
     178bool psphotEfficiencyReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe)
    154179{
     180    bool status = true;
     181
     182    psTimerStart("psphot.fake");
     183
     184    // find the currently selected readout
     185    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     186    psAssert (file, "missing file?");
     187
     188    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     189    psAssert (readout, "missing readout?");
     190
     191    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     192    psAssert (detections, "missing detections?");
     193
     194    psArray *realSources = detections->allSources;
     195    psAssert (realSources, "missing sources?");
     196
     197    // XXX do we need to skip this step if we do not have a psf?
     198    pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
     199    psAssert (psf, "missing psf?");
     200
    155201    PM_ASSERT_READOUT_NON_NULL(readout, false);
    156202    PM_ASSERT_READOUT_IMAGE(readout, false);
    157203    PS_ASSERT_PTR_NON_NULL(psf, false);
    158204    PS_ASSERT_METADATA_NON_NULL(recipe, false);
    159     PS_ASSERT_ARRAY_NON_NULL(realSources, false);
    160 
    161     psTimerStart("psphot.fake");
    162205
    163206    // Collect recipe information
    164     float fwhmMajor = psMetadataLookupF32(NULL, recipe, "FWHM_MAJ"); // PSF size in x
    165     float fwhmMinor = psMetadataLookupF32(NULL, recipe, "FWHM_MIN"); // PSF size in y
     207    float smoothNsigma = psMetadataLookupF32(&status, recipe, "PEAKS_SMOOTH_NSIGMA"); // Smoothing limit
     208    psAssert (status && isfinite(smoothNsigma), "Unable to find PEAKS_SMOOTH_NSIGMA in recipe (or invalid value)");
     209
     210    float thresh = psMetadataLookupF32(&status, recipe, "PEAKS_NSIGMA_LIMIT_2");
     211    psAssert (status && isfinite(thresh), "Unable to find PEAKS_NSIGMA_LIMIT_2 in recipe (or invalid value)");
     212
     213    psVector *magOffsets = psMetadataLookupVector(&status, recipe, "EFF.MAG"); // Magnitude offsets
     214    psAssert (status, "Unable to find EFF.MAG F32 vector in recipe");
     215    psAssert (magOffsets->type.type == PS_TYPE_F32, "Unable to find EFF.MAG F32 vector in recipe");
     216
     217    int numSources = psMetadataLookupS32(&status, recipe, "EFF.NUM"); // Number of sources for each bin
     218    psAssert (status && (numSources > 0), "Unable to find EFF.NUM in recipe (or invalid value)");
     219
     220    float minGauss = psMetadataLookupF32(&status, recipe, "PEAKS_MIN_GAUSS"); // Minimum valid fraction of kernel
     221    psAssert (status && isfinite(minGauss), "PEAKS_MIN_GAUSS is not set in recipe (or invalid)");
     222
     223    // find the PSF size information (why is this not part of the psf structure?)
     224    float fwhmMajor = psMetadataLookupF32(NULL, readout->analysis, "FWHM_MAJ"); // PSF size in x
     225    float fwhmMinor = psMetadataLookupF32(NULL, readout->analysis, "FWHM_MIN"); // PSF size in y
    166226    if (!isfinite(fwhmMajor) || !isfinite(fwhmMinor) || fwhmMajor == 0.0 || fwhmMinor == 0.0) {
    167         psError(PSPHOT_ERR_CONFIG, false, "Unable to find FWHM_MAJ and FWHM_MIN in recipe");
    168         return false;
    169     }
    170     float smoothNsigma = psMetadataLookupF32(NULL, recipe, "PEAKS_SMOOTH_NSIGMA"); // Smoothing limit
    171     if (!isfinite(smoothNsigma)) {
    172         psError(PSPHOT_ERR_CONFIG, false, "Unable to find PEAKS_SMOOTH_NSIGMA in recipe");
    173         return false;
    174     }
    175     float thresh = psMetadataLookupF32(NULL, recipe, "PEAKS_NSIGMA_LIMIT_2");
    176     if (!isfinite(thresh)) {
    177         psError(PSPHOT_ERR_CONFIG, false, "Unable to find PEAKS_NSIGMA_LIMIT_2 in recipe");
    178         return false;
    179     }
    180     psVector *magOffsets = psMetadataLookupVector(NULL, recipe, "EFF.MAG"); // Magnitude offsets
    181     if (!magOffsets || magOffsets->type.type != PS_TYPE_F32) {
    182         psError(PSPHOT_ERR_CONFIG, false, "Unable to find EFF.MAG F32 vector in recipe");
    183         return NULL;
    184     }
    185     int numSources = psMetadataLookupS32(NULL, recipe, "EFF.NUM"); // Number of sources for each bin
    186     if (numSources == 0) {
    187         psError(PSPHOT_ERR_CONFIG, false, "Unable to find EFF.NUM in recipe");
    188         return NULL;
    189     }
    190     float minGauss = psMetadataLookupF32(NULL, recipe, "PEAKS_MIN_GAUSS"); // Minimum valid fraction of kernel
    191     if (!isfinite(minGauss)) {
    192         psWarning("PEAKS_MIN_GAUSS is not set in recipe; using default value");
    193         minGauss = 0.5;
     227        psError(PSPHOT_ERR_CONFIG, false, "Unable to find FWHM_MAJ and FWHM_MIN in readout->analysis");
     228        return false;
    194229    }
    195230
     
    202237    // remove all sources, adding noise for subtracted sources
    203238    psphotRemoveAllSources(realSources, recipe);
    204     //    psphotAddNoise(readout, realSources, recipe);
    205 
    206 
    207 #if defined(TESTING) && 0
     239
     240#if TESTING
    208241    {
    209242        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
     
    234267    }
    235268
    236 #ifdef TESTING
     269#if TESTING
    237270    psphotSaveImage(NULL, readout->image, "orig_image.fits");
    238271    psphotSaveImage(NULL, readout->variance, "orig_variance.fits");
     
    249282    }
    250283
    251 #ifdef TESTING
     284#if TESTING
    252285    psphotSaveImage(NULL, readout->image, "fake_image.fits");
    253286    psphotSaveImage(NULL, readout->variance, "fake_variance.fits");
     
    364397    psFree(significance);
    365398
    366     if (!psphotFitSourcesLinear(readout, fakeSourcesAll, recipe, psf, true)) {
     399    if (!psphotFitSourcesLinearReadout(recipe, readout, fakeSourcesAll, psf, true)) {
    367400        psError(PS_ERR_UNKNOWN, false, "Unable to perform linear fit on fake sources.");
    368401        psFree(fakeSources);
     
    371404    }
    372405
    373     // Disable aperture corrections; casting away const!
     406    // Disable aperture corrections (save current value)
    374407    pmTrend2D *apTrend = psf->ApTrend;  // Aperture trend
    375     ((pmPSF*)psf)->ApTrend = NULL;
    376 
    377     if (!psphotMagnitudes(config, readout, view, fakeSourcesAll, psf)) {
     408    psf->ApTrend = NULL;
     409
     410    if (!psphotMagnitudesReadout(config, recipe, view, readout, fakeSourcesAll, psf)) {
    378411        psError(PS_ERR_UNKNOWN, false, "Unable to measure magnitudes of fake sources.");
    379412        psFree(fakeSources);
    380413        psFree(count);
    381         ((pmPSF*)psf)->ApTrend = apTrend; // Casting away const!
     414        psf->ApTrend = apTrend; // Casting away const!
    382415        return false;
    383416    }
    384417    psFree(fakeSourcesAll);
    385418
    386     // Re-enable aperture corrections; casting away const!
    387     ((pmPSF*)psf)->ApTrend = apTrend;
     419    // Replace aperture corrections
     420    psf->ApTrend = apTrend;
    388421
    389422    psVector *magDiffMean = psVectorAlloc(numBins, PS_TYPE_F32); // Mean difference in magnitude for each bin
     
    399432        psVectorInit(magMask, 0);
    400433
    401 #ifdef TESTING
     434#if TESTING
    402435        psString name = NULL;
    403436        psStringAppend(&name, "fake_%d.dat", i);
     
    415448            }
    416449
    417 #ifdef TESTING
     450#if TESTING
    418451            fprintf(file, "%f %f %f %f %f %f %f\n", source->peak->xf, source->peak->yf,
    419452                    source->modelPSF->params->data.F32[PM_PAR_XPOS],
     
    451484        }
    452485
    453 #ifdef TESTING
     486#if TESTING
    454487        fclose(file);
    455488#endif
     
    476509    psLogMsg("psphot", PS_LOG_INFO, "Detection efficiency: %lf sec\n", psTimerClear("psphot.fake"));
    477510
    478 
    479511    return true;
    480512}
  • branches/tap_branches/psphot/src/psphotEllipticalContour.c

    r25755 r27838  
    77bool psphotEllipticalContour (pmSource *source) {
    88
    9     pmSourceRadialProfile *profile = source->extpars->profile;
     9    psAssert (source, "missing source");
     10    psAssert (source->extpars, "missing extpars");
     11    psAssert (source->extpars->radFlux, "missing radFlux");
     12
     13    pmSourceRadialFlux *profile = source->extpars->radFlux;
     14    pmSourceExtendedPars *extpars = source->extpars;
    1015
    1116    // use LMM to fit theta vs radius to an ellipse
     
    8590    /// XXX rationalize? if epsilon > 1, flip major and minor axes (rotate by 90 degrees)
    8691    if (params->data.F32[PAR_EPSILON] < 1.0) {
    87         profile->axes.major = params->data.F32[PAR_RMIN] / params->data.F32[PAR_EPSILON];
    88         profile->axes.minor = params->data.F32[PAR_RMIN];
    89         profile->axes.theta = params->data.F32[PAR_PHI];
     92        extpars->axes.major = params->data.F32[PAR_RMIN] / params->data.F32[PAR_EPSILON];
     93        extpars->axes.minor = params->data.F32[PAR_RMIN];
     94        extpars->axes.theta = params->data.F32[PAR_PHI];
    9095    } else {
    91         profile->axes.major = params->data.F32[PAR_RMIN];
    92         profile->axes.minor = params->data.F32[PAR_RMIN] / params->data.F32[PAR_EPSILON];
    93         profile->axes.theta = params->data.F32[PAR_PHI] + 0.5*M_PI;
     96        extpars->axes.major = params->data.F32[PAR_RMIN];
     97        extpars->axes.minor = params->data.F32[PAR_RMIN] / params->data.F32[PAR_EPSILON];
     98        extpars->axes.theta = params->data.F32[PAR_PHI] + 0.5*M_PI;
    9499    }
    95100
    96101    psTrace ("psphot", 4, "# fitted values:\n");
    97     psTrace ("psphot", 4, "Phi:   %f\n", profile->axes.theta*PS_DEG_RAD);
    98     psTrace ("psphot", 4, "Rmaj:  %f\n", profile->axes.major);
    99     psTrace ("psphot", 4, "Rmin:  %f\n", profile->axes.minor);
     102    psTrace ("psphot", 4, "Phi:   %f\n", extpars->axes.theta*PS_DEG_RAD);
     103    psTrace ("psphot", 4, "Rmaj:  %f\n", extpars->axes.major);
     104    psTrace ("psphot", 4, "Rmin:  %f\n", extpars->axes.minor);
    100105   
    101106    // show the results
    102     // psphotPetrosianVisualEllipticalContour (petrosian);
     107    // psphotPetrosianVisualEllipticalContour (profile, extpars);
    103108
    104109    psFree (x);
  • branches/tap_branches/psphot/src/psphotEllipticalProfile.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
    3 bool psphotEllipticalProfile (pmSource *source) {
     3bool psphotEllipticalProfile (pmSource *source, bool RAW_RADIUS) {
    44
    5     pmSourceRadialProfile *profile = source->extpars->profile;
     5    psAssert (source, "missing source");
     6    psAssert (source->extpars, "missing extpars");
     7    psAssert (source->pixels, "missing pixels");
     8
     9    pmSourceExtendedPars *extpars = source->extpars;
     10
     11    if (!source->extpars->ellipticalFlux) {
     12        source->extpars->ellipticalFlux = pmSourceEllipticalFluxAlloc();
     13    }
     14    pmSourceEllipticalFlux *profile = source->extpars->ellipticalFlux;
    615
    716    profile->radiusElliptical = psVectorAllocEmpty(100, PS_TYPE_F32);
     
    2130
    2231    psEllipseAxes axes;
    23     axes.major = M_SQRT1_2;
    24     axes.minor = M_SQRT1_2 * (profile->axes.minor / profile->axes.major);
     32    if (RAW_RADIUS) {
     33        // force circular profile
     34        axes.major = M_SQRT1_2;
     35        axes.minor = M_SQRT1_2;
     36    } else {
     37        axes.major = M_SQRT1_2;
     38        axes.minor = M_SQRT1_2 * (extpars->axes.minor / extpars->axes.major);
     39    }
    2540
    2641    // axes.major = 1.0;
    27     // axes.minor = profile->axes.minor / profile->axes.major;
     42    // axes.minor = extpars->axes.minor / extpars->axes.major;
    2843
    29     axes.theta = profile->axes.theta;
     44    axes.theta = extpars->axes.theta;
    3045    psEllipseShape shape = psEllipseAxesToShape (axes);
    3146
     
    4661
    4762            float r2 = 0.5*PS_SQR(x/Sxx) + 0.5*PS_SQR(y/Syy) + x*y*Sxy;
     63            float Rraw = hypot(x, y);
    4864
    4965            psVectorAppend(radius, sqrt(r2));
    5066            psVectorAppend(flux, source->pixels->data.F32[iy][ix]);
    5167
    52             float Rraw = hypot(x, y);
    5368            psVectorAppend(radiusRaw, Rraw);
    5469            psVectorAppend(fluxRaw, source->pixels->data.F32[iy][ix]);
     
    6782    // }
    6883
    69     // psphotPetrosianVisualProfileRadii (radius, flux, radiusRaw, fluxRaw, 0.0);
     84    psphotPetrosianVisualProfileRadii (radius, flux, radiusRaw, fluxRaw, source->peak->flux, 0.0);
    7085    // psphotPetrosianVisualProfileByAngle (radius, flux);
    7186
  • branches/tap_branches/psphot/src/psphotErrorCodes.dat

    r11308 r27838  
    22# This file is used to generate psphotErrorClasses.h
    33#
     4BASE = 3000             First value we use
    45UNKNOWN                 Unknown PM error code
    56NOT_IMPLEMENTED         Desired feature is not yet implemented
  • branches/tap_branches/psphot/src/psphotExtendedSourceAnalysis.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
     3// for now, let's store the detections on the readout->analysis for each readout
     4bool psphotExtendedSourceAnalysis (pmConfig *config, const pmFPAview *view)
     5{
     6    bool status = true;
     7
     8    // select the appropriate recipe information
     9    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     10    psAssert (recipe, "missing recipe?");
     11
     12    // perform full non-linear fits / extended source analysis?
     13    if (!psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANALYSIS")) {
     14        psLogMsg ("psphot", PS_LOG_INFO, "skipping extended source measurements\n");
     15        return true;
     16    }
     17
     18    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     19    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     20
     21    // loop over the available readouts
     22    for (int i = 0; i < num; i++) {
     23        if (!psphotExtendedSourceAnalysisReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     24            psError (PSPHOT_ERR_CONFIG, false, "failed on measure extended source aperture-like parameters for PSPHOT.INPUT entry %d", i);
     25            return false;
     26        }
     27    }
     28    return true;
     29}
     30
    331// aperture-like measurements for extended sources
    4 bool psphotExtendedSourceAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe) {
     32bool psphotExtendedSourceAnalysisReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {
    533
    634    bool status;
     
    1139    int Nkron = 0;
    1240
     41    psTimerStart ("psphot.extended");
     42
     43    // find the currently selected readout
     44    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     45    psAssert (file, "missing file?");
     46
     47    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     48    psAssert (readout, "missing readout?");
     49
     50    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     51    psAssert (detections, "missing detections?");
     52
     53    psArray *sources = detections->allSources;
     54    psAssert (sources, "missing sources?");
     55
     56    if (!sources->n) {
     57        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source size");
     58        return true;
     59    }
     60
    1361    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    1462    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    1563    assert (maskVal);
    16 
    17     // perform full non-linear fits / extended source analysis?
    18     if (!psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANALYSIS")) {
    19         psLogMsg ("psphot", PS_LOG_INFO, "skipping extended source measurements\n");
    20         return true;
    21     }
    2264
    2365    // XXX require petrosian analysis for non-linear fits?
     
    2567    // XXX temporary user-supplied systematic sky noise measurement (derive from background model)
    2668    float skynoise = psMetadataLookupF32 (&status, recipe, "SKY.NOISE");
    27 
    28 # if (0)
    29     // if backModel or backStdev are missing, the values of sky and/or skyErr will be set to NAN
    30     // XXX use this to set skynoise
    31     pmReadout *backModel = psphotSelectBackground (config, view);
    32     pmReadout *backStdev = psphotSelectBackgroundStdev (config, view);
    33 # endif
    3469
    3570    // S/N limit to perform full non-linear fits
     
    4176    bool doAnnuli       = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
    4277    bool doKron         = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_KRON");
     78
     79# if (0)
     80    // if backModel or backStdev are missing, the values of sky and/or skyErr will be set to NAN
     81    // XXX use this to set skynoise
     82    pmReadout *backModel = psphotSelectBackground (config, view);
     83    pmReadout *backStdev = psphotSelectBackgroundStdev (config, view);
     84# endif
    4385
    4486    // source analysis is done in S/N order (brightest first)
     
    79121        Next ++;
    80122
     123        // force source image to be a bit larger...
     124        float radius = source->peak->xf - source->pixels->col0;
     125        radius = PS_MAX (radius, source->peak->yf - source->pixels->row0);
     126        radius = PS_MAX (radius, source->pixels->numRows - source->peak->yf + source->pixels->row0);
     127        radius = PS_MAX (radius, source->pixels->numCols - source->peak->xf + source->pixels->col0);
     128        pmSourceRedefinePixels (source, readout, source->peak->xf, source->peak->yf, 1.5*radius);
     129
    81130        // if we request any of these measurements, we require the radial profile
    82131        if (doPetrosian || doIsophotal || doAnnuli || doKron) {
     
    94143        if (doPetrosian) {
    95144            if (!psphotPetrosian (source, recipe, skynoise, maskVal)) {
    96                 psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
     145                psTrace ("psphot", 5, "FAILED petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    97146            } else {
    98147                psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
     
    129178
    130179        if (source->extpars) {
    131             pmSourceRadialProfileFreeVectors(source->extpars->profile);
     180            psFree(source->extpars->radFlux);
     181            psFree(source->extpars->ellipticalFlux);
    132182        }
    133183    }
    134184
    135     psLogMsg ("psphot", PS_LOG_INFO, "extended source analysis: %f sec for %d objects\n", psTimerMark ("psphot"), Next);
     185    psLogMsg ("psphot", PS_LOG_INFO, "extended source analysis: %f sec for %d objects\n", psTimerMark ("psphot.extended"), Next);
    136186    psLogMsg ("psphot", PS_LOG_INFO, "  %d petrosian\n", Npetro);
    137187    psLogMsg ("psphot", PS_LOG_INFO, "  %d isophotal\n", Nisophot);
  • branches/tap_branches/psphot/src/psphotExtendedSourceFits.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
     3// for now, let's store the detections on the readout->analysis for each readout
     4bool psphotExtendedSourceFits (pmConfig *config, const pmFPAview *view)
     5{
     6    bool status = true;
     7
     8    // select the appropriate recipe information
     9    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     10    psAssert (recipe, "missing recipe?");
     11
     12    // perform full extended source non-linear fits?
     13    if (!psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_FITS")) {
     14        psLogMsg ("psphot", PS_LOG_INFO, "skipping extended source measurements\n");
     15        return true;
     16    }
     17
     18    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     19    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     20
     21    // loop over the available readouts
     22    for (int i = 0; i < num; i++) {
     23        if (!psphotExtendedSourceFitsReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     24            psError (PSPHOT_ERR_CONFIG, false, "failed on to fit extended sources for PSPHOT.INPUT entry %d", i);
     25            return false;
     26        }
     27    }
     28    return true;
     29}
     30
    331// non-linear model fitting for extended sources
    4 bool psphotExtendedSourceFits (pmReadout *readout, psArray *sources, psMetadata *recipe) {
     32bool psphotExtendedSourceFitsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {
    533
    634    bool status;
     
    1240    bool savePics = false;
    1341
     42    // find the currently selected readout
     43    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     44    psAssert (file, "missing file?");
     45
     46    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     47    psAssert (readout, "missing readout?");
     48
     49    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     50    psAssert (detections, "missing detections?");
     51
     52    psArray *sources = detections->allSources;
     53    psAssert (sources, "missing sources?");
     54
     55    if (!sources->n) {
     56        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source size");
     57        return true;
     58    }
     59
    1460    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    1561    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
     
    2167    // maskVal is used to test for rejected pixels, and must include markVal
    2268    maskVal |= markVal;
    23 
    24     // perform full extended source non-linear fits?
    25     if (!psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_FITS")) {
    26         psLogMsg ("psphot", PS_LOG_INFO, "skipping extended source measurements\n");
    27         return true;
    28     }
    2969
    3070    // select the collection of desired models
  • branches/tap_branches/psphot/src/psphotFake.c

    • Property svn:mergeinfo deleted
    r25890 r27838  
    2828    float smoothSigma  = 0.5*(FWHM_X + FWHM_Y) / (2.0*sqrtf(2.0*log(2.0)));
    2929    psKernel *kernel = psImageSmoothKernel(smoothSigma, smoothNsigma); // Kernel used for smoothing
    30     psKernel *newCovar = psImageCovarianceCalculate(kernel, readout->covariance); // Covariance matrix
     30    float factor = psImageCovarianceCalculateFactor(kernel, readout->covariance); // Covariance matrix
    3131    psFree(kernel);
    32     float factor = psImageCovarianceFactor(newCovar); // Variance factor
    33     psFree(newCovar);
    3432
    3533    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for variance
     
    213211
    214212    // Putting results on recipe because that appears to be the psphot standard, but it's not a good idea
    215     psMetadataAddVector(recipe, PS_LIST_TAIL, "FAKE.EFF", PS_META_REPLACE,
    216                         "Efficiency fractions", frac);
    217     psMetadataAddVector(recipe, PS_LIST_TAIL, "FAKE.MAG", PS_META_REPLACE,
    218                         "Efficiency magnitudes", magOffsets);
    219     psMetadataAddF32(recipe, PS_LIST_TAIL, "FAKE.REF", PS_META_REPLACE,
    220                      "Efficiency reference magnitude", magLim);
     213    psMetadataAddVector(readout->analysis, PS_LIST_TAIL, "FAKE.EFF", PS_META_REPLACE, "Efficiency fractions", frac);
     214    psMetadataAddVector(readout->analysis, PS_LIST_TAIL, "FAKE.MAG", PS_META_REPLACE, "Efficiency magnitudes", magOffsets);
     215    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "FAKE.REF", PS_META_REPLACE, "Efficiency reference magnitude", magLim);
    221216
    222217    psFree(frac);
  • branches/tap_branches/psphot/src/psphotFindDetections.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
     3// we store the detections on the readout->analysis for each readout this function finds new
     4// peaks and new footprints.  any old peaks are saved on oldPeaks.  the resulting footprint set
     5// contains all footprints (old and new)
     6bool psphotFindDetections (pmConfig *config, const pmFPAview *view, bool firstPass)
     7{
     8    bool status = true;
     9
     10    // select the appropriate recipe information
     11    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     12    psAssert (recipe, "missing recipe?");
     13
     14    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     15    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     16
     17    // loop over the available readouts
     18    for (int i = 0; i < num; i++) {
     19        if (!psphotFindDetectionsReadout (config, view, "PSPHOT.INPUT", i, recipe, firstPass)) {
     20            psError (PSPHOT_ERR_CONFIG, false, "failed to find initial detections for PSPHOT.INPUT entry %d", i);
     21            return false;
     22        }
     23    }
     24    return true;
     25}
     26
    327// smooth the image, search for peaks, optionally define footprints based on the peaks
    4 pmDetections *psphotFindDetections (pmDetections *detections, pmReadout *readout, psMetadata *recipe) {
     28bool psphotFindDetectionsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool firstPass) {
    529
    630    bool status;
     
    933    int NMAX = 0;
    1034
     35    // find the currently selected readout
     36    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     37    psAssert (file, "missing file?");
     38
     39    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     40    psAssert (readout, "missing readout?");
     41
    1142    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    1243    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    13     assert (maskVal);
     44    psAssert (maskVal, "missing mask value?");
    1445
    1546    // Use the new pmFootprints approach?
    1647    const bool useFootprints = psMetadataLookupBool(NULL, recipe, "USE_FOOTPRINTS");
    1748
    18     // on first pass, detections have not yet been allocated
     49    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     50    // on the initial pass, detections have not yet been allocated or saved on readout->analysis
    1951    if (!detections) {
     52        // create the container
    2053        detections = pmDetectionsAlloc();
     54       
     55        // save detections on the readout->analysis
     56        if (!psMetadataAddPtr (readout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot detections", detections)) {
     57            psError (PSPHOT_ERR_CONFIG, false, "problem saving detections on readout");
     58            return false;
     59        }
     60    } else {
     61        psMemIncrRefCounter(detections); // so we can free the detections below
     62    }
     63
     64    if (firstPass) {
    2165        pass = 1;
    2266        NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT"); PS_ASSERT (status, NULL);
     
    3074    float threshold = PS_SQR(NSIGMA_PEAK);
    3175
    32     // move the old peaks array (if it exists) to oldPeaks
    33     // XXX generically, we should be able to call this function an arbitrary number of times
     76    // move the old peaks array (if it exists) to oldPeaks XXX generically, we should be able
     77    // to call this function an arbitrary number of times the old peaks are saved so they can
     78    // be freed later -- the have to be freed after psphotFindFootprints is called below, since
     79    // they are also owned by the oldFootprints, which are in turn merged into the new
     80    // footprints.  (what about the source->peak entry?)
     81   
    3482    assert (detections->oldPeaks == NULL);
    3583    detections->oldPeaks = detections->peaks;
     
    3987    psImage *significance = psphotSignificanceImage (readout, recipe, pass, maskVal);
    4088
    41     // display the backsub and backgnd images
    42     psphotVisualShowSignificance (significance);
     89    // display the significance image
     90    psphotVisualShowSignificance (significance, -1.0, PS_SQR(3.0*NSIGMA_PEAK));
     91
     92    // XXX getting some strange results from significance image
     93    if (0) {
     94        psImage *lsig = (psImage *) psUnaryOp (NULL, significance, "log");
     95        psphotVisualShowSignificance (lsig, 0.0, 4.0);
     96        psFree (lsig);
     97    }   
    4398
    4499    // detect the peaks in the significance image
    45100    detections->peaks = psphotFindPeaks (significance, readout, recipe, threshold, NMAX);
    46     psMetadataAddF32  (recipe, PS_LIST_TAIL, "PEAK_THRESHOLD", PS_META_REPLACE, "Peak Detection Threshold", threshold);
     101    psMetadataAddF32  (readout->analysis, PS_LIST_TAIL, "PEAK_THRESHOLD", PS_META_REPLACE, "Peak Detection Threshold", threshold);
    47102    if (!detections->peaks) {
    48         // No peaks found
    49         return NULL;
     103        // we only get a NULL peaks array due to a programming or config error.
     104        // this will result in a failure.
     105        psFree (detections);
     106        psError (PSPHOT_ERR_CONFIG, false, "failed on peak search");
     107        return false;
    50108    }
    51109
    52110    // optionally merge peaks into footprints
    53111    if (useFootprints) {
    54         psphotFindFootprints (detections, significance, readout, recipe, threshold, pass, maskVal);
     112        psphotFindFootprints (detections, significance, readout, recipe, threshold, pass, maskVal);
    55113    }
    56114
     
    61119    psphotVisualShowFootprints (detections);
    62120
    63     return detections;
     121    psFree (detections);
     122
     123    return true;
    64124}
    65125
  • branches/tap_branches/psphot/src/psphotFindFootprints.c

    r25755 r27838  
    4141    if (pass == 2) {
    4242        // merge in old peaks;
    43         const int includePeaks = 0x0 | 0x2; // i.e. just from newFootprints
    44 
    45         // XXX EAM : still not sure I understand this: are we double-couning or undercounting peaks
     43        const int includePeaks = 0x1 | 0x2; // i.e. both new and old footprints
    4644
    4745        psArray *mergedFootprints = pmFootprintArraysMerge(detections->footprints, footprints, includePeaks);
     
    5048        psFree(footprints);
    5149        psFree(detections->footprints);
     50
     51        // replace the merged footprints on the detection structure
    5252        detections->footprints = mergedFootprints;
    5353    } else {
     
    5555    }
    5656
    57     psphotCullPeaks(readout->image, readout->variance, recipe, detections->footprints);
     57    psphotCullPeaks(readout, recipe, detections->footprints);
    5858    detections->peaks = pmFootprintArrayToPeaks(detections->footprints);
    5959    psLogMsg ("psphot", PS_LOG_INFO, "%ld peaks, %ld total footprints: %f sec\n", detections->peaks->n, detections->footprints->n, psTimerMark ("psphot.footprints"));
     
    6161    return detections;
    6262}
     63
     64bool psphotCheckFootprints (pmDetections *detections) {
     65
     66    // check for messed up footprints in the old peaks
     67    for (int i = 0; i < detections->oldPeaks->n; i++) {
     68        pmPeak *peak = detections->oldPeaks->data[i];
     69        pmFootprint *footprint = peak->footprint;
     70        if (!footprint) continue;
     71        for (int j = 0; j < footprint->spans->n; j++) {
     72            pmSpan *sp = footprint->spans->data[j];
     73            psAssert (sp, "missing span");
     74        }
     75    }
     76    return true;
     77}
  • branches/tap_branches/psphot/src/psphotFindPeaks.c

    r25755 r27838  
    1313    psArray *peaks = pmPeaksInImage (significance, threshold);
    1414    if (peaks == NULL) {
    15         // XXX should we be sending back an empty array instead of NULL?
    16         // XXX this may also be due to a programming or config error
     15        // we only get a NULL peaks array due to a programming or config error.
     16        // this will result in a failure.
     17        psError(PSPHOT_ERR_DATA, false, "no peaks found in this image");
     18        return NULL;
     19    }
     20
     21    if (peaks->n == 0) {
    1722        // XXX do we need to set something in the readout->analysis to indicate that
    1823        // we tried and failed to find peaks (something in the header data)
    19         psError(PSPHOT_ERR_DATA, false, "no peaks found in this image");
    20         return false;
     24        psLogMsg ("psphot", PS_LOG_INFO, "no peaks found in this image");
     25        return peaks;
    2126    }
    2227
  • branches/tap_branches/psphot/src/psphotFitSourcesLinear.c

    r25755 r27838  
    1212static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, int SKY_FIT_ORDER, psImageMaskType markVal);
    1313
    14 bool psphotFitSourcesLinear (pmReadout *readout, psArray *sources, const psMetadata *recipe, const pmPSF *psf, bool final) {
     14// for now, let's store the detections on the readout->analysis for each readout
     15bool psphotFitSourcesLinear (pmConfig *config, const pmFPAview *view, bool final)
     16{
     17    bool status = true;
     18
     19    // select the appropriate recipe information
     20    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     21    assert (recipe);
     22
     23    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     24    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     25
     26    // loop over the available readouts
     27    for (int i = 0; i < num; i++) {
     28
     29        // find the currently selected readout
     30        pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", i); // File of interest
     31        psAssert (file, "missing file?");
     32
     33        pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     34        psAssert (readout, "missing readout?");
     35
     36        pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     37        psAssert (detections, "missing detections?");
     38
     39        psArray *sources = detections->allSources;
     40        psAssert (sources, "missing sources?");
     41
     42        pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
     43        psAssert (psf, "missing psf?");
     44
     45        if (!psphotFitSourcesLinearReadout (recipe, readout, sources, psf, final)) {
     46            psError (PSPHOT_ERR_CONFIG, false, "failed to fit sources (linear) for PSPHOT.INPUT entry %d", i);
     47            return false;
     48        }
     49    }
     50    return true;
     51}
     52
     53bool psphotFitSourcesLinearReadout (psMetadata *recipe, pmReadout *readout, psArray *sources, pmPSF *psf, bool final) {
    1554
    1655    bool status;
     
    1857    float y;
    1958    float f;
    20     // float r;
     59
     60    if (!sources->n) {
     61        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping linear fit");
     62        return true;
     63    }
    2164
    2265    psTimerStart ("psphot.linear");
     
    59102    }
    60103
     104    // XXX test: choose a larger-than expected radius:
     105    float covarFactor = psImageCovarianceFactorForAperture(readout->covariance, 10.0); // Covariance matrix
     106    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "covariance factor: %f\n", covarFactor);
     107
     108    // XXX do not apply covarFactor for the moment...
     109    // covarFactor = 1.0;
     110
    61111    // select the sources which will be used for the fitting analysis
    62112    for (int i = 0; i < sources->n; i++) {
     
    120170
    121171        // diagonal elements of the sparse matrix (auto-cross-product)
    122         f = pmSourceModelDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS);
     172        f = pmSourceModelDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor);
    123173        psSparseMatrixElement (sparse, i, i, f);
    124174
    125175        // the formal error depends on the weighting scheme
    126176        if (CONSTANT_PHOTOMETRIC_WEIGHTS) {
    127             float var = pmSourceModelDotModel (SRCi, SRCi, false);
     177            float var = pmSourceModelDotModel (SRCi, SRCi, false, covarFactor);
    128178            errors->data.F32[i] = 1.0 / sqrt(var);
    129179        } else {
     
    133183
    134184        // find the image x model value
    135         f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS);
     185        f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor);
    136186        psSparseVectorElement (sparse, i, f);
    137187
     
    139189        switch (SKY_FIT_ORDER) {
    140190          case 1:
    141             f = pmSourceModelWeight (SRCi, 1, CONSTANT_PHOTOMETRIC_WEIGHTS);
     191            f = pmSourceModelWeight (SRCi, 1, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor);
    142192            psSparseBorderElementB (border, i, 1, f);
    143             f = pmSourceModelWeight (SRCi, 2, CONSTANT_PHOTOMETRIC_WEIGHTS);
     193            f = pmSourceModelWeight (SRCi, 2, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor);
    144194            psSparseBorderElementB (border, i, 2, f);
    145195
    146196          case 0:
    147             f = pmSourceModelWeight (SRCi, 0, CONSTANT_PHOTOMETRIC_WEIGHTS);
     197            f = pmSourceModelWeight (SRCi, 0, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor);
    148198            psSparseBorderElementB (border, i, 0, f);
    149199            break;
     
    165215
    166216            // got an overlap; calculate cross-product and add to output array
    167             f = pmSourceModelDotModel (SRCi, SRCj, CONSTANT_PHOTOMETRIC_WEIGHTS);
     217            f = pmSourceModelDotModel (SRCi, SRCj, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor);
    168218            psSparseMatrixElement (sparse, j, i, f);
    169219        }
     
    219269
    220270    // measure chisq for each source
    221     for (int i = 0; final && (i < fitSources->n); i++) {
     271    // for (int i = 0; final && (i < fitSources->n); i++) {
     272    for (int i = 0; i < fitSources->n; i++) {
    222273        pmSource *source = fitSources->data[i];
    223274        if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) continue;
    224275        pmModel *model = pmSourceGetModel (NULL, source);
    225         pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal);
     276        pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal, covarFactor);
    226277    }
    227278    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "get chisqs: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem);
     
    238289
    239290    psphotVisualShowResidualImage (readout);
     291    psphotVisualPlotChisq (sources);
    240292    // psphotVisualShowFlags (sources);
     293
     294    // We have to place this visualization here because the models are not realized until
     295    // psphotGuessModels or fitted until psphotFitSourcesLinear.
     296    psphotVisualShowPSFStars (recipe, psf, sources);
    241297
    242298    return true;
     
    244300
    245301// XXX do we need this?
     302// XXX disallow the simultaneous sky fit and remove this code...
    246303
    247304// Calculate the weight terms for the sky fit component of the matrix.  This function operates
  • branches/tap_branches/psphot/src/psphotFitSourcesLinearStack.c

    r25755 r27838  
    11# include "psphotInternal.h"
     2// XXX need array of covar factors for each image
     3// XXX define the 'good' / 'bad' flags?
    24
    3 // fit flux (and optionally sky model) to all reasonable sources
    4 // with the linear fitting process.  sources must have an associated
    5 // model with selected pixels, and the fit radius must be defined
     5# define COVAR_FACTOR 1.0
    66
    7 // given the set of sources, each of which points to the pixels in the
    8 // science image, we construct a set of simulated sources with their own pixels.
    9 // these are used to determine the simultaneous linear fit of fluxes.
    10 // the analysis is performed wrt the simulated pixel values
    11 
    12 static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, psImageMaskType markVal);
    13 
    14 bool psphotFitSourcesLinear (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, bool final) {
     7bool psphotFitSourcesLinearStack (pmConfig *config, psArray *objects, bool final) {
    158
    169    bool status;
    17     float x;
    18     float y;
    1910    float f;
    20     // float r;
     11
     12    // select the appropriate recipe information
     13    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     14    assert (recipe);
    2115
    2216    psTimerStart ("psphot.linear");
     
    3327    maskVal |= markVal;
    3428
    35     // source analysis is done in spatial order
    36     sources = psArraySort (sources, pmSourceSortByY);
     29    // analysis is done in spatial order (to speed up overlap search)
     30    // sort by first element in each source list
     31    objects = psArraySort (objects, pmPhotObjSortByX);
    3732
    3833    // storage array for fitSources
    39     psArray *fitSources = psArrayAllocEmpty (sources->n);
     34    psArray *fitSources = psArrayAllocEmpty (objects->n);
    4035
    41     bool CONSTANT_PHOTOMETRIC_WEIGHTS =
    42         psMetadataLookupBool(&status, recipe, "CONSTANT_PHOTOMETRIC_WEIGHTS");
    43     if (!status) {
    44         psAbort("You must provide a value for the BOOL recipe CONSTANT_PHOTOMETRIC_WEIGHTS");
    45     }
     36    bool CONSTANT_PHOTOMETRIC_WEIGHTS = psMetadataLookupBool(&status, recipe, "CONSTANT_PHOTOMETRIC_WEIGHTS");
     37    psAssert (status, "You must provide a value for the BOOL recipe CONSTANT_PHOTOMETRIC_WEIGHTS");
     38
     39    // XXX store a local static array of covar factors for each of the images (by image ID)
     40    // float covarFactor = psImageCovarianceFactorForAperture(readout->covariance, 10.0); // Covariance matrix
     41    // psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "covariance factor: %f\n", covarFactor);
    4642
    4743    // select the sources which will be used for the fitting analysis
    48     for (int i = 0; i < sources->n; i++) {
    49         pmSource *source = sources->data[i];
     44    for (int i = 0; i < objects->n; i++) {
     45        pmPhotObj *object = objects->data[i];
     46        if (!object) continue;
     47        if (!object->sources) continue;
    5048
    51         // turn this bit off and turn it on again if we pass this test
    52         source->mode &= ~PM_SOURCE_MODE_LINEAR_FIT;
     49        // XXX check an element of the group to see if we should use it
     50        // if (!object->flags & PM_PHOT_OBJ_BAD) continue;
    5351
    54         // skip non-astronomical objects (very likely defects)
    55         if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
    56         if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
     52        for (int j = 0; j < object->sources->n; j++) {
     53          pmSource *source = object->sources->data[j];
     54          if (!source) continue;
    5755
    58         // do not include CRs in the full ensemble fit
    59         if (source->mode & PM_SOURCE_MODE_CR_LIMIT) continue;
     56          // turn this bit off and turn it on again if we keep this source
     57          source->mode &= ~PM_SOURCE_MODE_LINEAR_FIT;
    6058
    61         if (final) {
    62             if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) continue;
    63         } else {
    64             if (source->mode & PM_SOURCE_MODE_BLEND) continue;
    65         }
     59          // generate model for sources without, or skip if we can't
     60          if (!source->modelFlux) {
     61            if (!pmSourceCacheModel (source, maskVal)) continue;
     62          }
    6663
    67         // generate model for sources without, or skip if we can't
    68         if (!source->modelFlux) {
    69             if (!pmSourceCacheModel (source, maskVal)) continue;
    70         }
    71 
    72         source->mode |= PM_SOURCE_MODE_LINEAR_FIT;
    73         psArrayAdd (fitSources, 100, source);
     64          source->mode |= PM_SOURCE_MODE_LINEAR_FIT;
     65          psArrayAdd (fitSources, 100, source);
     66        }
    7467    }
    75     psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "built fitSources: %f sec (%ld objects)\n", psTimerMark ("psphot.linear"), sources->n);
     68    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "built fitSources: %f sec (%ld objects)\n", psTimerMark ("psphot.linear"), objects->n);
    7669
    7770    if (fitSources->n == 0) {
     
    8376    psVector *errors = psVectorAlloc (fitSources->n, PS_TYPE_F32);
    8477
    85     // create the border matrix (includes the sparse matrix)
    86     // for just sky: 1 row; for x,y terms: 3 rows
     78    // create the sparse matrix
    8779    psSparse *sparse = psSparseAlloc (fitSources->n, 100);
    88     psSparseBorder *border = psSparseBorderAlloc (sparse, 1);
    8980
    9081    // fill out the sparse matrix elements and border elements (B)
     
    9586
    9687        // diagonal elements of the sparse matrix (auto-cross-product)
    97         f = pmSourceModelDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS);
     88        f = pmSourceModelDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, COVAR_FACTOR);
    9889        psSparseMatrixElement (sparse, i, i, f);
    9990
    10091        // the formal error depends on the weighting scheme
    10192        if (CONSTANT_PHOTOMETRIC_WEIGHTS) {
    102             float var = pmSourceModelDotModel (SRCi, SRCi, false);
     93            float var = pmSourceModelDotModel (SRCi, SRCi, false, COVAR_FACTOR);
    10394            errors->data.F32[i] = 1.0 / sqrt(var);
    10495        } else {
     
    10697        }
    10798
    108 
    10999        // find the image x model value
    110         f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS);
     100        f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, COVAR_FACTOR);
    111101        psSparseVectorElement (sparse, i, f);
    112 
    113         f = pmSourceModelWeight (SRCi, 0, CONSTANT_PHOTOMETRIC_WEIGHTS);
    114         psSparseBorderElementB (border, i, 0, f);
    115102
    116103        // loop over all other stars following this one
     
    118105            pmSource *SRCj = fitSources->data[j];
    119106
     107            // we only need to generate dot terms for source on the same image
     108            if (SRCj->imageID != SRCi->imageID) { continue; }
     109
    120110            // skip over disjoint source images, break after last possible overlap
    121             if (SRCi->pixels->row0 + SRCi->pixels->numRows < SRCj->pixels->row0) break;
    122             if (SRCj->pixels->row0 + SRCj->pixels->numRows < SRCi->pixels->row0) continue;
    123             if (SRCi->pixels->col0 + SRCi->pixels->numCols < SRCj->pixels->col0) continue;
    124             if (SRCj->pixels->col0 + SRCj->pixels->numCols < SRCi->pixels->col0) continue;
     111            if (SRCj->pixels->row0 + SRCj->pixels->numRows < SRCi->pixels->row0) continue;  // source(i) is above source(j)
     112            if (SRCi->pixels->row0 + SRCi->pixels->numRows < SRCj->pixels->row0) continue;  // source(i) is below source(j)
     113            if (SRCj->pixels->col0 + SRCj->pixels->numCols < SRCi->pixels->col0) continue;  // source(i) is right of source(j)
     114            if (SRCi->pixels->col0 + SRCi->pixels->numCols < SRCj->pixels->col0) break;     // source(i) is left of source(j) [no other source(j) can overlap source(i)]
    125115
    126116            // got an overlap; calculate cross-product and add to output array
    127             f = pmSourceModelDotModel (SRCi, SRCj, CONSTANT_PHOTOMETRIC_WEIGHTS);
     117            f = pmSourceModelDotModel (SRCi, SRCj, CONSTANT_PHOTOMETRIC_WEIGHTS, COVAR_FACTOR);
    128118            psSparseMatrixElement (sparse, j, i, f);
    129119        }
     
    133123    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "built matrix: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem);
    134124
    135     // set the sky, sky_x, sky_y components of border matrix
    136     SetBorderMatrixElements (border, readout, fitSources, CONSTANT_PHOTOMETRIC_WEIGHTS, SKY_FIT_ORDER, markVal);
    137 
    138125    psSparseConstraint constraint;
    139126    constraint.paramMin   = 0.0;
     
    142129
    143130    // solve for normalization terms (need include local sky?)
    144     psVector *norm = psSparseSolve (NULL, constraint, sparse, 5);
    145 
     131    psVector *norm = NULL;
     132    norm = psSparseSolve (NULL, constraint, sparse, 5);
    146133    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "solve matrix: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem);
    147 
    148     // XXXX **** philosophical question:
    149     // we measure bright objects in three passes: 1) linear fit; 2) non-linear fit; 3) linear fit:
    150     // should retain the chisq and errors from the intermediate non-linear fit?
    151     // the non-linear fit provides better values for the position errors, and for
    152     // extended sources, the shape errors
    153134
    154135    // adjust I0 for fitSources and subtract
     
    164145        model->params->data.F32[PM_PAR_I0] = norm->data.F32[i];
    165146        model->dparams->data.F32[PM_PAR_I0] = errors->data.F32[i];
    166         // XXX is the value of 'errors' modified by the sky fit?
    167147
    168148        // subtract object
     
    172152
    173153    // measure chisq for each source
    174     for (int i = 0; final && (i < fitSources->n); i++) {
     154    // for (int i = 0; final && (i < fitSources->n); i++) {
     155    for (int i = 0; i < fitSources->n; i++) {
    175156        pmSource *source = fitSources->data[i];
    176157        if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) continue;
    177158        pmModel *model = pmSourceGetModel (NULL, source);
    178         pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal);
     159        pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal, COVAR_FACTOR);
    179160    }
    180161    psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "get chisqs: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem);
     
    185166    psFree (norm);
    186167    psFree (errors);
    187     psFree (border);
    188168
    189169    psLogMsg ("psphot.ensemble", PS_LOG_INFO, "measure ensemble of PSFs: %f sec\n", psTimerMark ("psphot.linear"));
    190 
    191     psphotVisualShowResidualImage (readout);
    192     psphotVisualShowFlags (sources);
    193170
    194171    return true;
    195172}
    196173
    197 // Calculate the weight terms for the sky fit component of the matrix.  This function operates
    198 // on the pixels which correspond to all of the sources of interest.  These elements fill in
    199 // the border matrix components in the sparse matrix equation.
    200 static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, psImageMaskType markVal) {
     174// sort by X (ascending)
     175int pmPhotObjSortByX (const void **a, const void **b)
     176{
     177    pmPhotObj *objA = *(pmPhotObj **)a;
     178    pmPhotObj *objB = *(pmPhotObj **)b;
    201179
    202     // generate the image-wide weight terms
    203     // turn on MARK for all image pixels
    204     psRegion fullArray = psRegionSet (0, 0, 0, 0);
    205     fullArray = psRegionForImage (readout->mask, fullArray);
    206     psImageMaskRegion (readout->mask, fullArray, "OR", markVal);
     180    psF32 fA = objA->x;
     181    psF32 fB = objB->x;
    207182
    208     // turn off MARK for all object pixels
    209     for (int i = 0; i < sources->n; i++) {
    210         pmSource *source = sources->data[i];
    211         pmModel *model = pmSourceGetModel (NULL, source);
    212         if (model == NULL) continue;
    213         float x = model->params->data.F32[PM_PAR_XPOS];
    214         float y = model->params->data.F32[PM_PAR_YPOS];
    215         psImageMaskCircle (source->maskView, x, y, model->radiusFit, "AND", PS_NOT_IMAGE_MASK(markVal));
    216     }
    217 
    218     // accumulate the image statistics from the masked regions
    219     psF32 **image  = readout->image->data.F32;
    220     psF32 **variance = readout->variance->data.F32;
    221     psImageMaskType  **mask   = readout->mask->data.PS_TYPE_IMAGE_MASK_DATA;
    222 
    223     double w, x, y, x2, xy, y2, xc, yc, wt, f, fo, fx, fy;
    224     w = x = y = x2 = xy = y2 = fo = fx = fy = 0;
    225 
    226     int col0 = readout->image->col0;
    227     int row0 = readout->image->row0;
    228 
    229     for (int j = 0; j < readout->image->numRows; j++) {
    230         for (int i = 0; i < readout->image->numCols; i++) {
    231             if (mask[j][i]) continue;
    232             if (constant_weights) {
    233                 wt = 1.0;
    234             } else {
    235                 wt = variance[j][i];
    236             }
    237             f = image[j][i];
    238             w   += 1/wt;
    239             fo  += f/wt;
    240         }
    241     }
    242 
    243     // turn off MARK for all image pixels
    244     psImageMaskRegion (readout->mask, fullArray, "AND", PS_NOT_IMAGE_MASK(markVal));
    245 
    246     // set the Border T elements
    247     psSparseBorderElementG (border, 0, fo);
    248     psSparseBorderElementT (border, 0, 0, w);
    249 
    250     return true;
     183    psF32 diff = fA - fB;
     184    if (diff > FLT_EPSILON) return (+1);
     185    if (diff < FLT_EPSILON) return (-1);
     186    return (0);
    251187}
  • branches/tap_branches/psphot/src/psphotGuessModels.c

    r25755 r27838  
    33// XXX : the threading here is not great.  this may be due to blocks between elements, but
    44// the selection of the objects in a cell is not optimal.  To fix:
    5 // 1) define the boundaries of the cells up front 
     5// 1) define the boundaries of the cells up front
    66// 2) loop over the sources once and associate them with their cell
    77// 3) define the threaded function to work with sources for a given cell
    88
    9 // construct an initial PSF model for each object
    10 bool psphotGuessModels (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf) {
     9// for now, let's store the detections on the readout->analysis for each readout
     10bool psphotGuessModels (pmConfig *config, const pmFPAview *view)
     11{
     12    bool status = true;
     13
     14    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     15    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     16
     17    // skip the chisq image (optionally?)
     18    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     19    if (!status) chisqNum = -1;
     20
     21    // loop over the available readouts
     22    for (int i = 0; i < num; i++) {
     23        if (i == chisqNum) continue; // skip chisq image
     24        if (!psphotGuessModelsReadout (config, view, "PSPHOT.INPUT", i)) {
     25            psError (PSPHOT_ERR_CONFIG, false, "failed on to guess models for PSPHOT.INPUT entry %d", i);
     26            return false;
     27        }
     28    }
     29    return true;
     30}
     31
     32// construct an initial PSF model for each object (new sources only)
     33bool psphotGuessModelsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index) {
    1134
    1235    bool status;
    1336
    1437    psTimerStart ("psphot.models");
     38
     39    // find the currently selected readout
     40    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     41    psAssert (file, "missing file?");
     42
     43    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     44    psAssert (readout, "missing readout?");
     45
     46    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     47    psAssert (detections, "missing detections?");
     48
     49    psArray *sources = detections->newSources;
     50    psAssert (sources, "missing sources?");
     51
     52    if (!sources->n) {
     53        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping model guess");
     54        return true;
     55    }
     56
     57    pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
     58    psAssert (psf, "missing psf?");
    1559
    1660    // select the appropriate recipe information
     
    2165    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
    2266    if (!status) {
    23         nThreads = 0;
     67        nThreads = 0;
    2468    }
    2569
     
    3680
    3781    // setup the PSF fit radius details
    38     psphotInitRadiusPSF (recipe, psf->type);
     82    psphotInitRadiusPSF (recipe, readout->analysis, psf->type);
    3983
    4084    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     
    4690    for (int i = 0; i < cellGroups->n; i++) {
    4791
    48         psArray *cells = cellGroups->data[i];
    49 
    50         for (int j = 0; j < cells->n; j++) {
    51 
    52             // allocate a job -- if threads are not defined, this just runs the job
    53             psThreadJob *job = psThreadJobAlloc ("PSPHOT_GUESS_MODEL");
    54             psArrayAdd(job->args, 1, readout);
    55             psArrayAdd(job->args, 1, cells->data[j]); // sources
    56             psArrayAdd(job->args, 1, psf);
    57 
    58             // XXX change these to use abstract mask type info
    59             PS_ARRAY_ADD_SCALAR(job->args, maskVal,  PS_TYPE_IMAGE_MASK);
    60             PS_ARRAY_ADD_SCALAR(job->args, markVal,  PS_TYPE_IMAGE_MASK);
    61 
    62             if (!psThreadJobAddPending(job)) {
    63                 psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    64                 psFree (job);
    65                 return false;
    66             }
    67             psFree(job);
    68         }
    69 
    70         // wait for the threads to finish and manage results
    71         // wait here for the threaded jobs to finish
    72         // fprintf (stderr, "wait for threads (%d, %d)\n", jx, jy);
    73         if (!psThreadPoolWait (false)) {
    74             psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    75             return false;
    76         }
    77 
    78         // we have only supplied one type of job, so we can assume the types here
    79         psThreadJob *job = NULL;
    80         while ((job = psThreadJobGetDone()) != NULL) {
    81             // we have no returned data from this operation
    82             if (job->args->n < 1) {
    83                 fprintf (stderr, "error with job\n");
    84             }
    85             psFree(job);
    86         }
     92        psArray *cells = cellGroups->data[i];
     93
     94        for (int j = 0; j < cells->n; j++) {
     95
     96            // allocate a job -- if threads are not defined, this just runs the job
     97            psThreadJob *job = psThreadJobAlloc ("PSPHOT_GUESS_MODEL");
     98            psArrayAdd(job->args, 1, readout);
     99            psArrayAdd(job->args, 1, cells->data[j]); // sources
     100            psArrayAdd(job->args, 1, psf);
     101
     102            // XXX change these to use abstract mask type info
     103            PS_ARRAY_ADD_SCALAR(job->args, maskVal,  PS_TYPE_IMAGE_MASK);
     104            PS_ARRAY_ADD_SCALAR(job->args, markVal,  PS_TYPE_IMAGE_MASK);
     105
     106            if (!psThreadJobAddPending(job)) {
     107                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     108                psFree (job);
     109                return false;
     110            }
     111            psFree(job);
     112        }
     113
     114        // wait for the threads to finish and manage results
     115        // wait here for the threaded jobs to finish
     116        // fprintf (stderr, "wait for threads (%d, %d)\n", jx, jy);
     117        if (!psThreadPoolWait (false)) {
     118            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     119            return false;
     120        }
     121
     122        // we have only supplied one type of job, so we can assume the types here
     123        psThreadJob *job = NULL;
     124        while ((job = psThreadJobGetDone()) != NULL) {
     125            // we have no returned data from this operation
     126            if (job->args->n < 1) {
     127                fprintf (stderr, "error with job\n");
     128            }
     129            psFree(job);
     130        }
    87131    }
    88132
     
    90134    int nMiss = 0;
    91135    for (int i = 0; i < sources->n; i++) {
    92         pmSource *source = sources->data[i];
    93         if (source->tmpFlags & PM_SOURCE_TMPF_MODEL_GUESS) {
    94             continue;
    95         }
    96         nMiss ++;
     136        pmSource *source = sources->data[i];
     137        if (source->tmpFlags & PM_SOURCE_TMPF_MODEL_GUESS) {
     138            continue;
     139        }
     140        nMiss ++;
    97141    }
    98142    psAssert (nMiss == 0, "failed to attempt to build models for %d objects\n", nMiss);
     
    110154    psArray *sources   = job->args->data[1];
    111155    pmPSF *psf         = job->args->data[2];
    112    
     156
    113157    psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3],PS_TYPE_IMAGE_MASK_DATA);
    114158    psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA);
     
    117161
    118162    for (int i = 0; i < sources->n; i++) {
    119         pmSource *source = sources->data[i];
    120 
    121         // this is used to mark sources for which the model is measured. We check later that
    122         // all are used.
    123         source->tmpFlags |= PM_SOURCE_TMPF_MODEL_GUESS;
    124 
    125         // skip non-astronomical objects (very likely defects)
    126         if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
    127         if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
    128         if (!source->peak) continue;
    129 
    130         nSrc ++;
    131        
    132         // the guess central intensity comes from the peak:
    133         float Io = source->peak->flux;
    134 
    135         // We have two options to get a guess for the object position: the position from the
    136         // peak and the position from the moments.  Use the peak position if (a) there are no
    137         // moments and (b) the sources is not saturated
    138 
    139         bool useMoments = false;
    140         useMoments = (source->mode & PM_SOURCE_MODE_SATSTAR);  // we only want to try if SATSTAR is set, but..
    141         useMoments = (useMoments && source->moments);          // can't if there are no moments
    142         useMoments = (useMoments && source->moments->nPixels); // can't if the moments were not measured
    143         useMoments = (useMoments && !(source->mode && PM_SOURCE_MODE_MOMENTS_FAILURE)); // can't if the moments failed...
    144 
    145         float Xo, Yo;
    146         if (useMoments) {
    147             Xo = source->moments->Mx;
    148             Yo = source->moments->My;
    149         } else {
    150             Xo = source->peak->xf;
    151             Yo = source->peak->yf;
    152         }
    153 
    154         // set PSF parameters for this model (apply 2D shape model to coordinates Xo, Yo)
    155         pmModel *modelPSF = pmModelFromPSFforXY(psf, Xo, Yo, Io);
    156 
    157         if (modelPSF == NULL) {
    158             psWarning ("Failed to determine PSF model at (%f,%f); trying image center", Xo, Yo);
    159 
    160             float Xc = 0.5*readout->image->numCols;
    161             float Yc = 0.5*readout->image->numRows;
    162             pmModel *modelPSF = pmModelFromPSFforXY(psf, Xc, Yc, Io);
    163             if (modelPSF == NULL) {
    164                 psError(PSPHOT_ERR_PSF, false, "Failed to determine PSF model at center of image");
    165                 return false;
    166             }
    167 
    168             // Now set the object position at the expected location:
    169             modelPSF->params->data.F32[PM_PAR_XPOS] = Xo;
    170             modelPSF->params->data.F32[PM_PAR_YPOS] = Yo;
    171             source->mode |= PM_SOURCE_MODE_BADPSF;
    172         }
    173 
    174         // set the fit radius based on the object flux limit and the model
    175         // this function affects the mask pixels
    176         psphotCheckRadiusPSF (readout, source, modelPSF, markVal);
    177 
    178         // set the source PSF model
    179         psAssert (source->modelPSF == NULL, "failed to free one of the models?");
    180         source->modelPSF = modelPSF;
    181         source->modelPSF->residuals = psf->residuals;
    182 
    183         pmSourceCacheModel (source, maskVal);  // ALLOC x14 (!)
     163        pmSource *source = sources->data[i];
     164
     165        // this is used to mark sources for which the model is measured. We check later that
     166        // all are used.
     167        source->tmpFlags |= PM_SOURCE_TMPF_MODEL_GUESS;
     168
     169        // skip non-astronomical objects (very likely defects)
     170        if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
     171        if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
     172        if (!source->peak) continue;
     173
     174        nSrc ++;
     175
     176        // the guess central intensity comes from the peak:
     177        float Io = source->peak->flux;
     178
     179        // We have two options to get a guess for the object position: the position from the
     180        // peak and the position from the moments.  Use the peak position if (a) there are no
     181        // moments and (b) the sources is not saturated
     182
     183        bool useMoments = false;
     184        useMoments = (source->mode & PM_SOURCE_MODE_SATSTAR);  // we only want to try if SATSTAR is set, but..
     185        useMoments = (useMoments && source->moments);          // can't if there are no moments
     186        useMoments = (useMoments && source->moments->nPixels); // can't if the moments were not measured
     187        useMoments = (useMoments && !(source->mode && PM_SOURCE_MODE_MOMENTS_FAILURE)); // can't if the moments failed...
     188
     189        float Xo, Yo;
     190        if (useMoments) {
     191            Xo = source->moments->Mx;
     192            Yo = source->moments->My;
     193        } else {
     194            Xo = source->peak->xf;
     195            Yo = source->peak->yf;
     196        }
     197
     198        // set PSF parameters for this model (apply 2D shape model to coordinates Xo, Yo)
     199        pmModel *modelPSF = pmModelFromPSFforXY(psf, Xo, Yo, Io);
     200
     201        if (modelPSF == NULL) {
     202            psWarning ("Failed to determine PSF model at (%f,%f); trying image center", Xo, Yo);
     203
     204            float Xc = 0.5*readout->image->numCols;
     205            float Yc = 0.5*readout->image->numRows;
     206            pmModel *modelPSF = pmModelFromPSFforXY(psf, Xc, Yc, Io);
     207            if (modelPSF == NULL) {
     208                psError(PSPHOT_ERR_PSF, false, "Failed to determine PSF model at center of image");
     209                return false;
     210            }
     211
     212            // Now set the object position at the expected location:
     213            modelPSF->params->data.F32[PM_PAR_XPOS] = Xo;
     214            modelPSF->params->data.F32[PM_PAR_YPOS] = Yo;
     215            source->mode |= PM_SOURCE_MODE_BADPSF;
     216        }
     217
     218        // set the fit radius based on the object flux limit and the model
     219        // this function affects the mask pixels
     220        psphotCheckRadiusPSF (readout, source, modelPSF, markVal);
     221
     222        // set the source PSF model
     223        psAssert (source->modelPSF == NULL, "failed to free one of the models?");
     224        source->modelPSF = modelPSF;
     225        source->modelPSF->residuals = psf->residuals;
     226
     227        pmSourceCacheModel (source, maskVal);  // ALLOC x14 (!)
    184228    }
    185229
  • branches/tap_branches/psphot/src/psphotImageLoop.c

    r25755 r27838  
    9191            }
    9292
    93             status = true;
    94             status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL");
    95             status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV");
    96             status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKGND");
    97             if (!status) {
    98                 psError(PSPHOT_ERR_PROG, false, "trouble dropping internal files");
    99                 psFree (view);
    100                 return false;
    101             }
     93            // drop all versions of the internal files
     94            status = true;
     95            status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL");
     96            status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV");
     97            status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKGND");
     98            if (!status) {
     99                psError(PSPHOT_ERR_PROG, false, "trouble dropping internal files");
     100                psFree (view);
     101                return false;
     102            }
    102103        }
    103 
    104104        // save output which is saved at the chip level
    105105        if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed output for Chip in psphot.");
  • branches/tap_branches/psphot/src/psphotImageQuality.c

    r25755 r27838  
    44// XXX Lots of code duplication here
    55
     6// for now, let's store the detections on the readout->analysis for each readout
     7bool psphotImageQuality (pmConfig *config, const pmFPAview *view)
     8{
     9    bool status = true;
     10
     11    // select the appropriate recipe information
     12    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     13    psAssert (recipe, "missing recipe?");
     14
     15    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     16    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     17
     18    // skip the chisq image (optionally?)
     19    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     20    if (!status) chisqNum = -1;
     21
     22    // loop over the available readouts
     23    for (int i = 0; i < num; i++) {
     24        if (i == chisqNum) continue; // skip chisq image
     25        if (!psphotImageQualityReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     26            psError (PSPHOT_ERR_CONFIG, false, "failed on to measure image quality for PSPHOT.INPUT entry %d", i);
     27            return false;
     28        }
     29    }
     30    return true;
     31}
     32
    633// selecting the 'good' stars (likely to be psf stars), measure the M_cn, M_sn terms for n = 2,3,4
    7 bool psphotImageQuality(psMetadata *recipe, psArray *sources)
     34bool psphotImageQualityReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe)
    835{
     36    bool status = true;
     37
     38    // find the currently selected readout
     39    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     40    psAssert (file, "missing file?");
     41
     42    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     43    psAssert (readout, "missing readout?");
     44
     45    // if we have a PSF, skip this analysis
     46    if (psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF")) {
     47        return true;
     48    }
     49
     50    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     51    psAssert (detections, "missing detections?");
     52
     53    psArray *sources = detections->newSources;
     54    psAssert (sources, "missing sources?");
     55
     56    if (!sources->n) {
     57        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping image quality");
     58        return true;
     59    }
     60
    961    psVector *FWHM_MAJOR = psVectorAllocEmpty(100, PS_TYPE_F32);
    1062    psVector *FWHM_MINOR = psVectorAllocEmpty(100, PS_TYPE_F32);
     
    81133
    82134    if (num == 0) {
    83       psWarning("Unable to find sources from which to measure image quality");
    84       return false;
    85     }
    86 
    87     psMetadataAddS32(recipe, PS_LIST_TAIL, "IQ_NSTAR", PS_META_REPLACE,
    88                      "Number of stars used for IQ measurements", M2->n);
     135        psLogMsg ("psphot", PS_LOG_INFO, "no valid sources for image quality, skipping");
     136        return true;
     137    }
     138
     139    psMetadataAddS32(readout->analysis, PS_LIST_TAIL, "IQ_NSTAR", PS_META_REPLACE, "Number of stars used for IQ measurements", M2->n);
    89140
    90141// XXX make this a recipe option
     
    98149
    99150    float fwhm_major = stats->sampleMean;
    100     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_FW1",   PS_META_REPLACE,
    101                      "FWHM of Major Axis from moments", stats->sampleMean);
    102     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_FW1_E", PS_META_REPLACE,
    103                      "FWHM scatter (Major) from moments", stats->sampleStdev);
     151    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_FW1",   PS_META_REPLACE, "FWHM of Major Axis from moments", stats->sampleMean);
     152    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_FW1_E", PS_META_REPLACE, "FWHM scatter (Major) from moments", stats->sampleStdev);
    104153
    105154    if (!psVectorStats(stats, FWHM_MINOR, NULL, NULL, 0)) {
     
    108157    }
    109158    float fwhm_minor = stats->sampleMean;
    110     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_FW2",   PS_META_REPLACE,
    111                      "FWHM of Minor Axis from moments", stats->sampleMean);
    112     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_FW2_E", PS_META_REPLACE,
    113                      "FWHM scatter (Minor) from moments", stats->sampleStdev);
     159    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_FW2",   PS_META_REPLACE, "FWHM of Minor Axis from moments", stats->sampleMean);
     160    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_FW2_E", PS_META_REPLACE, "FWHM scatter (Minor) from moments", stats->sampleStdev);
    114161
    115162    if (!psVectorStats(stats, M2, NULL, NULL, 0)) {
     
    119166    float vM2 = stats->sampleMean;
    120167    float dM2 = stats->sampleStdev;
    121     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2",    PS_META_REPLACE,
    122                      "M_2 = sqrt (M_c2^2 + M_s2^2)", vM2);
    123     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2_ER", PS_META_REPLACE,
    124                      "Stdev of M_2", dM2);
    125     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2_LQ", PS_META_REPLACE,
    126                      "Lower Quartile of M_2", stats->sampleLQ);
    127     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2_UQ", PS_META_REPLACE,
    128                      "Upper Quartile of M_2", stats->sampleUQ);
     168    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2",    PS_META_REPLACE, "M_2 = sqrt (M_c2^2 + M_s2^2)", vM2);
     169    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2_ER", PS_META_REPLACE, "Stdev of M_2", dM2);
     170    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2_LQ", PS_META_REPLACE, "Lower Quartile of M_2", stats->sampleLQ);
     171    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2_UQ", PS_META_REPLACE, "Upper Quartile of M_2", stats->sampleUQ);
    129172
    130173    if (!psVectorStats(stats, M2c, NULL, NULL, 0)) {
     
    132175        goto FAIL;
    133176    }
    134     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2C",   PS_META_REPLACE,
    135                      "M_2c = sum f r^2 cos(2phi) / sum f", stats->sampleMean);
    136     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2C_E", PS_META_REPLACE,
    137                      "Stdev of M_2c", stats->sampleStdev);
    138     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2C_L", PS_META_REPLACE,
    139                      "Lower Quartile of M_2c", stats->sampleLQ);
    140     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2C_U", PS_META_REPLACE,
    141                      "Upper Quartile of M_2c", stats->sampleUQ);
     177    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2C",   PS_META_REPLACE, "M_2c = sum f r^2 cos(2phi) / sum f", stats->sampleMean);
     178    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2C_E", PS_META_REPLACE, "Stdev of M_2c", stats->sampleStdev);
     179    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2C_L", PS_META_REPLACE, "Lower Quartile of M_2c", stats->sampleLQ);
     180    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2C_U", PS_META_REPLACE, "Upper Quartile of M_2c", stats->sampleUQ);
    142181
    143182    if (!psVectorStats(stats, M2s, NULL, NULL, 0)) {
     
    145184        goto FAIL;
    146185    }
    147     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2S",   PS_META_REPLACE,
    148                      "M_2s = sum f r^2 cos(2phi) / sum f", stats->sampleMean);
    149     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2S_E", PS_META_REPLACE,
    150                      "Stdev of M_2s", stats->sampleStdev);
    151     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2S_L", PS_META_REPLACE,
    152                      "Lower Quartile of M_2s", stats->sampleLQ);
    153     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2S_U", PS_META_REPLACE,
    154                      "Upper Quartile of M_2s", stats->sampleUQ);
     186    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2S",   PS_META_REPLACE, "M_2s = sum f r^2 cos(2phi) / sum f", stats->sampleMean);
     187    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2S_E", PS_META_REPLACE, "Stdev of M_2s", stats->sampleStdev);
     188    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2S_L", PS_META_REPLACE, "Lower Quartile of M_2s", stats->sampleLQ);
     189    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2S_U", PS_META_REPLACE, "Upper Quartile of M_2s", stats->sampleUQ);
    155190
    156191    if (!psVectorStats(stats, M3, NULL, NULL, 0)) {
     
    160195    float vM3 = stats->sampleMean;
    161196    float dM3 = stats->sampleStdev;
    162     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M3",   PS_META_REPLACE,
    163                      "M_3 = sqrt (M_c3^2 + M_s3^2)", vM3);
    164     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M3_ER", PS_META_REPLACE,
    165                      "Stdev of M_3", dM3);
    166     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M3_LQ", PS_META_REPLACE,
    167                      "Lower Quartile of M_3", stats->sampleLQ);
    168     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M3_UQ", PS_META_REPLACE,
    169                      "Upper Quartile of M_3", stats->sampleUQ);
     197    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M3",   PS_META_REPLACE, "M_3 = sqrt (M_c3^2 + M_s3^2)", vM3);
     198    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M3_ER", PS_META_REPLACE, "Stdev of M_3", dM3);
     199    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M3_LQ", PS_META_REPLACE, "Lower Quartile of M_3", stats->sampleLQ);
     200    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M3_UQ", PS_META_REPLACE, "Upper Quartile of M_3", stats->sampleUQ);
    170201
    171202    if (!psVectorStats(stats, M4, NULL, NULL, 0)) {
     
    175206    float vM4 = stats->sampleMean;
    176207    float dM4 = stats->sampleStdev;
    177     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M4",   PS_META_REPLACE,
    178                      "M_4 = sqrt (M_c4^2 + M_s4^2)", vM4);
    179     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M4_ER", PS_META_REPLACE,
    180                      "Stdev of M_4", dM4);
    181     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M4_LQ", PS_META_REPLACE,
    182                      "Lower Quartile of M_4", stats->sampleLQ);
    183     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M4_UQ", PS_META_REPLACE,
    184                      "Upper Quartile of M_4", stats->sampleUQ);
     208    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M4",   PS_META_REPLACE, "M_4 = sqrt (M_c4^2 + M_s4^2)", vM4);
     209    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M4_ER", PS_META_REPLACE, "Stdev of M_4", dM4);
     210    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M4_LQ", PS_META_REPLACE, "Lower Quartile of M_4", stats->sampleLQ);
     211    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M4_UQ", PS_META_REPLACE, "Upper Quartile of M_4", stats->sampleUQ);
    185212
    186213#else
     
    192219    }
    193220    float fwhm_major = stats->robustMedian;
    194     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_FW1",   PS_META_REPLACE,
    195                      "FWHM of Major Axis from moments", stats->robustMedian);
    196     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_FW1_E", PS_META_REPLACE,
    197                      "FWHM scatter (Major) from moments", stats->robustStdev);
     221    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_FW1",   PS_META_REPLACE, "FWHM of Major Axis from moments", stats->robustMedian);
     222    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_FW1_E", PS_META_REPLACE, "FWHM scatter (Major) from moments", stats->robustStdev);
    198223
    199224    if (!psVectorStats(stats, FWHM_MINOR, NULL, NULL, 0)) {
     
    202227    }
    203228    float fwhm_minor = stats->robustMedian;
    204     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_FW2",   PS_META_REPLACE,
    205                      "FWHM of Minor Axis from moments", stats->robustMedian);
    206     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_FW2_E", PS_META_REPLACE,
    207                      "FWHM scatter (Minor) from moments", stats->robustStdev);
     229    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_FW2",   PS_META_REPLACE, "FWHM of Minor Axis from moments", stats->robustMedian);
     230    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_FW2_E", PS_META_REPLACE, "FWHM scatter (Minor) from moments", stats->robustStdev);
    208231
    209232    if (!psVectorStats(stats, M2, NULL, NULL, 0)) {
     
    213236    float vM2 = stats->robustMedian;
    214237    float dM2 = stats->robustStdev;
    215     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2",    PS_META_REPLACE,
    216                      "M_2 = sqrt (M_c2^2 + M_s2^2)", vM2);
    217     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2_ER", PS_META_REPLACE,
    218                      "Stdev of M_2", dM2);
    219     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2_LQ", PS_META_REPLACE,
    220                      "Lower Quartile of M_2", stats->robustLQ);
    221     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2_UQ", PS_META_REPLACE,
    222                      "Upper Quartile of M_2", stats->robustUQ);
     238    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2",    PS_META_REPLACE, "M_2 = sqrt (M_c2^2 + M_s2^2)", vM2);
     239    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2_ER", PS_META_REPLACE, "Stdev of M_2", dM2);
     240    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2_LQ", PS_META_REPLACE, "Lower Quartile of M_2", stats->robustLQ);
     241    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2_UQ", PS_META_REPLACE, "Upper Quartile of M_2", stats->robustUQ);
    223242
    224243    if (!psVectorStats(stats, M2c, NULL, NULL, 0)) {
     
    226245        goto FAIL;
    227246    }
    228     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2C",   PS_META_REPLACE,
    229                      "M_2c = sum f r^2 cos(2phi) / sum f", stats->robustMedian);
    230     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2C_E", PS_META_REPLACE,
    231                      "Stdev of M_2c", stats->robustStdev);
    232     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2C_L", PS_META_REPLACE,
    233                      "Lower Quartile of M_2c", stats->robustLQ);
    234     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2C_U", PS_META_REPLACE,
    235                      "Upper Quartile of M_2c", stats->robustUQ);
     247    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2C",   PS_META_REPLACE, "M_2c = sum f r^2 cos(2phi) / sum f", stats->robustMedian);
     248    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2C_E", PS_META_REPLACE, "Stdev of M_2c", stats->robustStdev);
     249    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2C_L", PS_META_REPLACE, "Lower Quartile of M_2c", stats->robustLQ);
     250    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2C_U", PS_META_REPLACE, "Upper Quartile of M_2c", stats->robustUQ);
    236251
    237252    if (!psVectorStats(stats, M2s, NULL, NULL, 0)) {
     
    239254        goto FAIL;
    240255    }
    241     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2S",   PS_META_REPLACE,
    242                      "M_2s = sum f r^2 cos(2phi) / sum f", stats->robustMedian);
    243     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2S_E", PS_META_REPLACE,
    244                      "Stdev of M_2s", stats->robustStdev);
    245     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2S_L", PS_META_REPLACE,
    246                      "Lower Quartile of M_2s", stats->robustLQ);
    247     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M2S_U", PS_META_REPLACE,
    248                      "Upper Quartile of M_2s", stats->robustUQ);
     256    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2S",   PS_META_REPLACE, "M_2s = sum f r^2 cos(2phi) / sum f", stats->robustMedian);
     257    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2S_E", PS_META_REPLACE, "Stdev of M_2s", stats->robustStdev);
     258    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2S_L", PS_META_REPLACE, "Lower Quartile of M_2s", stats->robustLQ);
     259    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M2S_U", PS_META_REPLACE, "Upper Quartile of M_2s", stats->robustUQ);
    249260
    250261    if (!psVectorStats(stats, M3, NULL, NULL, 0)) {
     
    254265    float vM3 = stats->robustMedian;
    255266    float dM3 = stats->robustStdev;
    256     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M3",   PS_META_REPLACE,
    257                      "M_3 = sqrt (M_c3^2 + M_s3^2)", vM3);
    258     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M3_ER", PS_META_REPLACE,
    259                      "Stdev of M_3", dM3);
    260     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M3_LQ", PS_META_REPLACE,
    261                      "Lower Quartile of M_3", stats->robustLQ);
    262     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M3_UQ", PS_META_REPLACE,
    263                      "Upper Quartile of M_3", stats->robustUQ);
     267    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M3",   PS_META_REPLACE, "M_3 = sqrt (M_c3^2 + M_s3^2)", vM3);
     268    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M3_ER", PS_META_REPLACE, "Stdev of M_3", dM3);
     269    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M3_LQ", PS_META_REPLACE, "Lower Quartile of M_3", stats->robustLQ);
     270    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M3_UQ", PS_META_REPLACE, "Upper Quartile of M_3", stats->robustUQ);
    264271
    265272    if (!psVectorStats(stats, M4, NULL, NULL, 0)) {
     
    269276    float vM4 = stats->robustMedian;
    270277    float dM4 = stats->robustStdev;
    271     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M4",   PS_META_REPLACE,
    272                      "M_4 = sqrt (M_c4^2 + M_s4^2)", vM4);
    273     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M4_ER", PS_META_REPLACE,
    274                      "Stdev of M_4", dM4);
    275     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M4_LQ", PS_META_REPLACE,
    276                      "Lower Quartile of M_4", stats->robustLQ);
    277     psMetadataAddF32(recipe, PS_LIST_TAIL, "IQ_M4_UQ", PS_META_REPLACE,
    278                      "Upper Quartile of M_4", stats->robustUQ);
     278    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M4",   PS_META_REPLACE, "M_4 = sqrt (M_c4^2 + M_s4^2)", vM4);
     279    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M4_ER", PS_META_REPLACE, "Stdev of M_4", dM4);
     280    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M4_LQ", PS_META_REPLACE, "Lower Quartile of M_4", stats->robustLQ);
     281    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "IQ_M4_UQ", PS_META_REPLACE, "Upper Quartile of M_4", stats->robustUQ);
    279282#endif
    280283
  • branches/tap_branches/psphot/src/psphotKernelFromPSF.c

    r17396 r27838  
    44
    55    assert (source);
    6     assert (source->psfFlux); // XXX build if needed?
     6    assert (source->psfImage); // XXX build if needed?
    77
    8     int x0 = source->peak->xf - source->psfFlux->col0;
    9     int y0 = source->peak->yf - source->psfFlux->row0;
     8    int x0 = source->peak->xf - source->psfImage->col0;
     9    int y0 = source->peak->yf - source->psfImage->row0;
    1010
    1111    // need to decide on the size: dynamically? statically?
     
    1717    // if the realized PSF for this object does not cover the full kernel, give up for now
    1818    if (x0 + psf->xMin < 0) goto escape;
    19     if (x0 + psf->xMax >= source->psfFlux->numCols) goto escape;
     19    if (x0 + psf->xMax >= source->psfImage->numCols) goto escape;
    2020    if (y0 + psf->yMin < 0) goto escape;
    21     if (y0 + psf->yMax >= source->psfFlux->numRows) goto escape;
     21    if (y0 + psf->yMax >= source->psfImage->numRows) goto escape;
    2222
    2323    double sum = 0.0;
    2424    for (int j = psf->yMin; j <= psf->yMax; j++) {
    2525        for (int i = psf->xMin; i <= psf->xMax; i++) {
    26             double value = source->psfFlux->data.F32[y0 + j][x0 + i];
     26            double value = source->psfImage->data.F32[y0 + j][x0 + i];
    2727            psf->kernel[j][i] = value;
    2828            sum += value;
  • branches/tap_branches/psphot/src/psphotLoadPSF.c

    r18002 r27838  
    11# include "psphotInternal.h"
    22
     3// NOTE : pmPSF_IO.c functions must load the psf model onto the chip->analysis metadata because
     4// the I/O operation likely occurs before the readout exists.  This implementation assumes that
     5// a single psf model is valid for the entire set of readouts (not valid for a time series of readouts)
     6
     7// XXX for now (2010.01.27), the supporting programs do not define multiple PSPHOT.PSF.LOAD
     8// files to go with multiple PSPHOT.INPUT files.  as a result, the implementation below is
     9// currently going to work for the case of a single input file, but will fail if we try with a
     10// stack of images.
     11
    312// load an externally supplied psf model
    4 pmPSF *psphotLoadPSF (pmConfig *config, const pmFPAview *view, psMetadata *recipe) {
     13bool psphotLoadPSFReadout (pmConfig *config, const pmFPAview *view, const char *outFilename, const char *inFilename, int index) {
     14
     15    bool status;
     16
     17    // find the currently selected readout
     18    pmFPAfile *inFile = pmFPAfileSelectSingle(config->files, inFilename, index); // File of interest
     19    if (inFile == NULL) {
     20        psLogMsg ("psphot", 3, "no psf supplied for this chip");
     21        return true;
     22    }
     23
     24    // find the currently selected readout
     25    pmFPAfile *outFile = pmFPAfileSelectSingle(config->files, outFilename, index); // File of interest
     26    if (outFile == NULL) {
     27        psLogMsg ("psphot", 3, "no psf supplied for this chip");
     28        return true;
     29    }
    530
    631    // find the currently selected chip
    7     pmChip *chip = pmFPAfileThisChip (config->files, view, "PSPHOT.PSF.LOAD");
    8     if (!chip) return NULL;
     32    pmChip *chip = pmFPAviewThisChip (view, inFile->fpa);
     33    if (!chip) return false;
    934
    1035    // find the currently selected readout
    11     pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.PSF.LOAD");
    12     if (!readout) return NULL;
     36    pmReadout *readout = pmFPAviewThisReadout (view, outFile->fpa);
     37    if (!readout) return false;
    1338
    1439    // check if a PSF model is supplied by the user
    15     pmPSF *psf = psMetadataLookupPtr (NULL, chip->analysis, "PSPHOT.PSF");
     40    pmPSF *psf = psMetadataLookupPtr (&status, chip->analysis, "PSPHOT.PSF");
    1641    if (psf == NULL) {
    1742        psLogMsg ("psphot", 3, "no psf supplied for this chip");
    18         return NULL;
     43        return true;
    1944    }
    2045
    21     if (!psphotPSFstats (readout, recipe, psf)) psAbort("cannot measure PSF shape terms");
     46    if (!psphotPSFstats (readout, psf)) {
     47        psAbort("cannot measure PSF shape terms");
     48    }
    2249
    2350    psLogMsg ("psphot", 3, "using externally supplied PSF model for this readout");
    2451
    25     // we return a psf which can be free (and which may be removed from the metadata)
    26     psMemIncrRefCounter (psf);
    27     return psf;
     52    // save PSF on readout->analysis
     53    if (!psMetadataAddPtr (readout->analysis, PS_LIST_TAIL, "PSPHOT.PSF", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot psf model", psf)) {
     54        psError (PSPHOT_ERR_UNKNOWN, false, "problem saving sources on readout");
     55        return false;
     56    }
     57
     58    return true;
    2859}
     60
     61bool psphotLoadPSF (pmConfig *config, const pmFPAview *view) {
     62
     63    bool status = false;
     64
     65    // XXX PSPHOT.PSF.LOAD vs PSPHOT.INPUT -- see note at top
     66    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     67    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     68
     69    // loop over the available readouts
     70    for (int i = 0; i < num; i++) {
     71
     72        // Generate the mask and weight images, including the user-defined analysis region of interest
     73        if (!psphotLoadPSFReadout (config, view, "PSPHOT.INPUT", "PSPHOT.PSF.LOAD", i)) {
     74            psError (PSPHOT_ERR_CONFIG, false, "failed to load PSF model for PSPHOT.PSF.LOAD entry %d", i);
     75            return false;
     76        }
     77    }
     78    return true;
     79}
  • branches/tap_branches/psphot/src/psphotMagnitudes.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
    3 bool psphotMagnitudes(pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources, const pmPSF *psf) {
     3bool psphotMagnitudes (pmConfig *config, const pmFPAview *view)
     4{
     5    bool status = true;
     6
     7    // select the appropriate recipe information
     8    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     9    psAssert (recipe, "missing recipe?");
     10
     11    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     12    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     13
     14    // skip the chisq image (optionally?)
     15    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     16    if (!status) chisqNum = -1;
     17
     18    // loop over the available readouts
     19    for (int i = 0; i < num; i++) {
     20        if (i == chisqNum) continue; // skip chisq image
     21
     22        // find the currently selected readout
     23        pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", i); // File of interest
     24        psAssert (file, "missing file?");
     25
     26        pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     27        psAssert (readout, "missing readout?");
     28
     29        pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     30        psAssert (detections, "missing detections?");
     31
     32        psArray *sources = detections->allSources;
     33        psAssert (sources, "missing sources?");
     34
     35        pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
     36        psAssert (psf, "missing psf?");
     37
     38        if (!psphotMagnitudesReadout (config, recipe, view, readout, sources, psf)) {
     39            psError (PSPHOT_ERR_CONFIG, false, "failed to measure magnitudes for PSPHOT.INPUT entry %d", i);
     40            return false;
     41        }
     42    }
     43    return true;
     44}
     45
     46bool psphotMagnitudesReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, pmReadout *readout, psArray *sources, pmPSF *psf) {
    447
    548    bool status = false;
    649    int Nap = 0;
    750
     51    if (!sources->n) {
     52        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source magnitudes");
     53        return true;
     54    }
     55       
    856    psTimerStart ("psphot.mags");
    9 
    10     // select the appropriate recipe information
    11     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    12     assert (recipe);
    1357
    1458    // determine the number of allowed threads
     
    4185    }
    4286
    43     bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH");
     87    bool IGNORE_GROWTH  = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH");
    4488    bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP");
     89    bool DIFF_STATS     = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP");
    4590
    4691    pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_APCORR | PM_SOURCE_PHOT_WEIGHT;
    4792    if (!IGNORE_GROWTH) photMode |= PM_SOURCE_PHOT_GROWTH;
    4893    if (INTERPOLATE_AP) photMode |= PM_SOURCE_PHOT_INTERP;
     94    if (DIFF_STATS)     photMode |= PM_SOURCE_PHOT_DIFFSTATS;
    4995
    5096    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     
    64110
    65111            psArrayAdd(job->args, 1, cells->data[j]); // sources
    66             psArrayAdd(job->args, 1, (pmPSF*)psf);    // Casting away const
     112            psArrayAdd(job->args, 1, psf);
    67113            psArrayAdd(job->args, 1, binning);
    68114            psArrayAdd(job->args, 1, backModel);
     
    179225}
    180226
    181 # if (0)
    182 bool psphotMagnitudes_Unthreaded (int *nap, psArray *sources, pmPSF *psf, psImageBinning *binning, pmReadout *backModel, pmReadout *backStdev, pmSourcePhotometryMode photMode, psImageMaskType maskVal) {
    183 
    184     bool status;
    185     int Nap = 0;
    186 
    187     for (int i = 0; i < sources->n; i++) {
    188         pmSource *source = (pmSource *) sources->data[i];
    189         status = pmSourceMagnitudes (source, psf, photMode, maskVal);
    190         if (status && isfinite(source->apMag)) Nap ++;
    191 
    192         if (backModel) {
    193             psAssert (binning, "if backModel is defined, so should binning be");
    194             source->sky = psImageUnbinPixel(source->peak->x, source->peak->y, backModel->image, binning);
    195             if (isnan(source->sky) && false) {
    196                 psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "error setting pmSource.sky");
    197             }
    198         } else {
    199             source->sky = NAN;
    200         }
    201 
    202         if (backStdev) {
    203             psAssert (binning, "if backStdev is defined, so should binning be");
    204             source->skyErr = psImageUnbinPixel(source->peak->x, source->peak->y, backStdev->image, binning);
    205             if (isnan(source->skyErr) && false) {
    206                 psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "error setting pmSource.skyErr");
    207             }
    208         } else {
    209             source->skyErr = NAN;
    210         }
    211     }
    212 
    213     // change the value of a scalar on the array (wrap this and put it in psArray.h)
    214     *nap = Nap;
    215 
    216     return true;
    217 }
    218 # endif
    219 
    220227bool psphotPSFWeights(pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources) {
    221228
  • branches/tap_branches/psphot/src/psphotMakeResiduals.c

    r25755 r27838  
    305305                if (fabs(resid->Ro->data.F32[oy][ox]) < pixelSN*dRo/sqrt(nKeep)) {
    306306                  resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1;
     307                  resid->Ro->data.F32[oy][ox] = 0.0;
     308                  resid->Rx->data.F32[oy][ox] = 0.0;
     309                  resid->Ry->data.F32[oy][ox] = 0.0;
    307310                }
    308311            }
  • branches/tap_branches/psphot/src/psphotMaskReadout.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
     3bool psphotSetMaskAndVariance (pmConfig *config, const pmFPAview *view) {
     4
     5    bool status = false;
     6
     7    // select the appropriate recipe information
     8    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     9    psAssert (recipe, "missing recipe?");
     10
     11    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     12    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     13
     14    // loop over the available readouts
     15    for (int i = 0; i < num; i++) {
     16
     17        // Generate the mask and weight images, including the user-defined analysis region of interest
     18        if (!psphotSetMaskAndVarianceReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     19            psError (PSPHOT_ERR_CONFIG, false, "failed to generate mask for PSPHOT.INPUT entry %d", i);
     20            return false;
     21        }
     22    }
     23    return true;
     24}
     25
    326// generate mask and variance if not defined, additional mask for restricted subregion
    4 bool psphotSetMaskAndVariance (pmConfig *config, pmReadout *readout, psMetadata *recipe) {
     27bool psphotSetMaskAndVarianceReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {
    528
    629    bool status;
    730
    8     // ** Interpret the mask values:
    9     // XXX drop the write to recipe and move config into psphotRoughClass?
    10     // XXX alternatively, define a function to set the psphot recipe masks
     31    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", index); // File of interest
     32    psAssert (file, "missing file?");
     33
     34    // find the currently selected readout
     35    pmReadout  *readout = pmFPAviewThisReadout (view, file->fpa);
     36    psAssert (readout, "missing readout?");
     37
     38    // save maskSat and maskBad on the psphot recipe (mostly for psphotRoughClass)
    1139    psImageMaskType maskSat  = pmConfigMaskGet("SAT", config); // Mask value for saturated pixels
    1240    psMetadataAddImageMask (recipe, PS_LIST_TAIL, "MASK.SAT", PS_META_REPLACE, "user-defined mask", maskSat);
     
    1442    psImageMaskType maskBad  = pmConfigMaskGet("LOW", config); // Mask value for low pixels
    1543    if (!maskBad) {
    16         // XXX: for backward compatability look up old name
     44        // for backward compatability look up old name
    1745        maskBad  = pmConfigMaskGet("BAD", config);
    1846    }
     
    73101    }
    74102
     103    // display the image, weight, mask (ch 1,2,3)
     104    psphotVisualShowImage (readout);
     105
    75106    return true;
    76107}
  • branches/tap_branches/psphot/src/psphotMergeSources.c

    r21519 r27838  
    55                         PM_SOURCE_MODE_CR_LIMIT | PM_SOURCE_MODE_EXT_LIMIT) // Mask to apply for PSF sources
    66
     7// for now, let's store the detections on the readout->analysis for each readout
     8bool psphotMergeSources (pmConfig *config, const pmFPAview *view)
     9{
     10    bool status = true;
     11
     12    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     13    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     14
     15    // loop over the available readouts
     16    for (int i = 0; i < num; i++) {
     17        if (!psphotMergeSourcesReadout (config, view, "PSPHOT.INPUT", i)) {
     18            psError (PSPHOT_ERR_CONFIG, false, "failed to merge sources for PSPHOT.INPUT entry %d", i);
     19            return false;
     20        }
     21    }
     22    return true;
     23}
     24
    725// add newly selected sources to the existing list of sources
    8 bool psphotMergeSources (psArray *oldSources, psArray *newSources) {
     26bool psphotMergeSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index) {
     27
     28    bool status;
     29
     30    // find the currently selected readout
     31    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     32    psAssert (file, "missing file?");
     33
     34    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     35    psAssert (readout, "missing readout?");
     36
     37    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     38    psAssert (detections, "missing detections?");
     39
     40    psArray *newSources = detections->newSources;
     41    psAssert (newSources, "missing sources?");
     42
     43    // XXX TEST:
     44    if (detections->allSources) {
     45        psphotMaskCosmicRayFootprintCheck(detections->allSources);
     46    }
     47    if (detections->newSources) {
     48        psphotMaskCosmicRayFootprintCheck(detections->newSources);
     49    }
     50
     51    if (!detections->allSources) {
     52        detections->allSources = psArrayAllocEmpty(newSources->n);
     53    }
     54    psArray *allSources = detections->allSources;
    955
    1056    for (int i = 0; i < newSources->n; i++) {
    1157        pmSource *source = newSources->data[i];
    12         psArrayAdd (oldSources, 100, source);
    13     }
    14     return true;
    15 }
    16 
    17 // merge the externally supplied sources with the existing sources.  mark them as having
    18 // mode PM_SOURCE_MODE_EXTERNAL
    19 bool psphotLoadExtSources (pmConfig *config, const pmFPAview *view, psArray *sources) {
    20 
    21     // find the currently selected readout
    22     pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT.CMF");
    23     if (!readout) {
    24         psLogMsg ("psphot", 3, "no external sources supplied");
    25         return true;
    26     }
    27 
    28     psArray *extSources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES");
    29     if (!extSources) {
     58        psArrayAdd (allSources, 100, source);
     59    }
     60
     61    psFree (detections->newSources);
     62    detections->newSources = NULL;
     63
     64    return true;
     65}
     66
     67// Merge the externally supplied sources with the existing sources.  Mark them as having mode
     68// PM_SOURCE_MODE_EXTERNAL.
     69
     70// XXX This function needs to be updated to loop over set of input files.  At the moment, we
     71// only expect a single entry for PSPHOT.INPUT.CMF and PSPHOT.SOURCES.TEXT, so we can only
     72// associate input sources with a single entry for PSPHOT.INPUT
     73bool psphotLoadExtSources (pmConfig *config, const pmFPAview *view) {
     74
     75    bool status;
     76    pmDetections *extCMF = NULL;
     77    psArray *extSourcesTXT = NULL;
     78    int index = 0;
     79
     80    // find the currently selected readout
     81    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", index); // File of interest
     82    psAssert (file, "missing file?");
     83
     84    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     85    psAssert (readout, "missing readout?");
     86
     87    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     88    if (!detections) {
     89        detections = pmDetectionsAlloc();
     90        detections->newSources = psArrayAllocEmpty (100);
     91        // save detections on the readout->analysis
     92        if (!psMetadataAddPtr (readout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot detections", detections)) {
     93            psError (PSPHOT_ERR_CONFIG, false, "problem saving detections on readout");
     94            return false;
     95        }
     96    } else {
     97        psMemIncrRefCounter(detections); // so we can free the detections below
     98    }
     99
     100    psArray *sources = detections->newSources;
     101    psAssert (sources, "missing sources?");
     102
     103    // load data from input CMF file:
     104    {
     105        pmReadout *readoutCMF = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT.CMF");
     106        if (!readoutCMF) goto loadTXT;
     107
     108        extCMF = psMetadataLookupPtr (NULL, readoutCMF->analysis, "PSPHOT.DETECTIONS");
     109        if (extCMF) {
     110            for (int i = 0; i < extCMF->allSources->n; i++) {
     111                pmSource *source = extCMF->allSources->data[i];
     112                source->mode |= PM_SOURCE_MODE_EXTERNAL;
     113
     114                // the supplied peak flux needs to be re-normalized
     115                source->peak->flux = 1.0;
     116                source->peak->value = 1.0;
     117
     118                // drop the loaded source modelPSF
     119                psFree (source->modelPSF);
     120                source->modelPSF = NULL;
     121                source->imageID = index;
     122
     123                psArrayAdd (detections->newSources, 100, source);
     124            }
     125        }
     126    }
     127
     128loadTXT:
     129
     130    // load data from input TXT file:
     131    {
     132        pmChip *chipTXT = pmFPAfileThisChip (config->files, view, "PSPHOT.INPUT");
     133        if (!chipTXT) goto finish;
     134
     135        extSourcesTXT = psMetadataLookupPtr (NULL, chipTXT->analysis, "PSPHOT.SOURCES.TEXT");
     136        if (extSourcesTXT) {
     137            for (int i = 0; i < extSourcesTXT->n; i++) {
     138                pmSource *source = extSourcesTXT->data[i];
     139                source->mode |= PM_SOURCE_MODE_EXTERNAL;
     140
     141                // drop the loaded source modelPSF
     142                psFree (source->modelPSF);
     143                source->modelPSF = NULL;
     144                source->imageID = index;
     145
     146                psArrayAdd (detections->newSources, 100, source);
     147            }
     148        }
     149    }
     150
     151finish:
     152
     153    psFree (detections);
     154
     155    if (!extCMF && !extSourcesTXT) {
    30156        psLogMsg ("psphot", 3, "no external sources for this readout");
    31157        return true;
    32158    }
    33159
    34     for (int i = 0; i < extSources->n; i++) {
    35         pmSource *source = extSources->data[i];
    36         source->mode |= PM_SOURCE_MODE_EXTERNAL;
    37         pmModel *model = source->modelPSF;
    38 
    39         float xpos = model->params->data.F32[PM_PAR_XPOS];
    40         float ypos = model->params->data.F32[PM_PAR_YPOS];
    41 
    42         source->peak = pmPeakAlloc(xpos, ypos, 1.0, PM_PEAK_LONE);
    43         source->peak->xf = xpos;
    44         source->peak->yf = ypos;
    45         source->peak->flux = 1.0;
    46 
    47         // drop the loaded source modelPSF
    48         psFree (source->modelPSF);
    49         source->modelPSF = NULL;
    50     }
    51 
    52     psphotMergeSources (sources, extSources);
    53     psLogMsg ("psphot", 3, "%ld external sources merged to yield %ld total sources", extSources->n, sources->n);
    54 
     160    int nCMF = extCMF        ? extCMF->allSources->n        : 0;
     161    int nTXT = extSourcesTXT ? extSourcesTXT->n : 0;
     162
     163    psLogMsg ("psphot", 3, "%d external sources (%d cmf, %d text) merged to yield %ld total sources",
     164              nCMF + nTXT, nCMF, nTXT, sources->n);
    55165    return true;
    56166}
    57167
    58168// extract the input sources corresponding to this readout
     169// XXX this function needs to be updated to work with the new context of pshot inputs
    59170psArray *psphotLoadPSFSources (pmConfig *config, const pmFPAview *view) {
     171
     172    bool status;
    60173
    61174    // find the currently selected readout
     
    66179    }
    67180
    68     psArray *sources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES");
     181    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     182    if (!detections) {
     183        psLogMsg ("psphot", 3, "no psf sources for this readout");
     184        return NULL;
     185    }
     186
     187    psArray *sources = detections->allSources;
    69188    if (!sources) {
    70189        psLogMsg ("psphot", 3, "no psf sources for this readout");
     190        return NULL;
    71191    }
    72192
     
    74194}
    75195
     196// this function is used to fix sources which were loaded externally, but have passed from
     197// psphotDetectionsFromSources to psphotSourceStats and are now stored on
     198// detections->newSources.
     199bool psphotRepairLoadedSources (pmConfig *config, const pmFPAview *view) {
     200
     201    // find the currently selected readout
     202    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", 0); // File of interest
     203    psAssert (file, "missing file?");
     204
     205    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     206    psAssert (readout, "missing readout?");
     207
     208    pmDetections *detections = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.DETECTIONS");
     209    if (!detections) {
     210        psError(PSPHOT_ERR_CONFIG, false, "missing detections");
     211        return false;
     212    }
     213
     214    psArray *sources = detections->newSources;
     215    psAssert (sources, "missing sources?");
     216
     217    // peak flux is wrong : set based on previous image
     218    // use the peak measured in the moments analysis:
     219    for (int i = 0; i < sources->n; i++) {
     220      pmSource *source = sources->data[i];
     221      source->peak->flux = source->moments->Peak;
     222    }
     223
     224    return true;
     225}
     226
    76227// generate the detection structure for the supplied array of sources
    77 pmDetections *psphotDetectionsFromSources (pmConfig *config, psArray *sources) {
     228// XXX this currently assumes there is a single input file
     229bool psphotDetectionsFromSources (pmConfig *config, const pmFPAview *view, psArray *sources) {
     230
     231    // find the currently selected readout
     232    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", 0); // File of interest
     233    psAssert (file, "missing file?");
     234
     235    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     236    psAssert (readout, "missing readout?");
    78237
    79238    pmDetections *detections = pmDetectionsAlloc();
     
    88247    float snMin = psMetadataLookupF32(NULL, recipe, "MOMENTS_SN_MIN");
    89248    if (!isfinite(snMin)) {
    90         return NULL;
     249        return false;
    91250    }
    92251
     
    96255
    97256        if (source->mode & PSF_SOURCE_MASK || !isfinite(source->psfMag)) {
     257            continue;
     258        }
     259
     260        // use the existing peak information, otherwise generate a new peak
     261        if (source->peak) {
     262            source->peak->assigned = false; // So the moments will be measured
     263            psArrayAdd (detections->peaks, 100, source->peak);
    98264            continue;
    99265        }
     
    108274        peak->flux = flux; // this are being set wrong, but does it matter?
    109275
    110         if (isfinite (source->errMag) && (source->errMag > 0.0)) {
    111           peak->SN = 1.0 / source->errMag;
    112         } else {
    113           peak->SN = 0.0;
    114         }
     276        if (isfinite (source->errMag) && (source->errMag > 0.0)) {
     277          peak->SN = 1.0 / source->errMag;
     278        } else {
     279          peak->SN = 0.0;
     280        }
    115281
    116282        psArrayAdd (detections->peaks, 100, peak);
     
    120286    psLogMsg ("psphot", 3, "%ld PSF sources loaded", detections->peaks->n);
    121287
    122     return detections;
     288    // save detections on the readout->analysis
     289    if (!psMetadataAddPtr (readout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_META_REPLACE | PS_DATA_UNKNOWN, "psphot detectinos", detections)) {
     290        psError (PSPHOT_ERR_CONFIG, false, "problem saving detections on readout");
     291        return false;
     292    }
     293    psFree (detections);
     294    return true;
    123295}
    124296
     
    149321        peak->flux = flux; // this are being set wrong, but does it matter?
    150322
    151         if (isfinite (source->errMag) && (source->errMag > 0.0)) {
    152           peak->SN = 1.0 / source->errMag;
    153         } else {
    154           peak->SN = 0.0;
    155         }
     323        if (isfinite (source->errMag) && (source->errMag > 0.0)) {
     324          peak->SN = 1.0 / source->errMag;
     325        } else {
     326          peak->SN = 0.0;
     327        }
    156328
    157329        source->peak = peak;
     
    162334    return true;
    163335}
     336
     337bool psphotCheckExtSources (pmConfig *config, const pmFPAview *view) {
     338
     339    bool status;
     340
     341    psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
     342    psAssert (recipe, "missing recipe");
     343
     344    // find the currently selected readout
     345    pmFPAfile *file = pmFPAfileSelectSingle(config->files, "PSPHOT.INPUT", 0); // File of interest
     346    psAssert (file, "missing file?");
     347
     348    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     349    psAssert (readout, "missing readout?");
     350
     351    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     352    psAssert (detections, "missing detections?");
     353
     354    // XXX allSources of newSources?
     355    psArray *sources = detections->allSources;
     356    psAssert (sources, "missing sources?");
     357
     358    if (sources->n) {
     359        // the user wants to make the psf from these stars; define them as psf stars:
     360        for (int i = 0; i < sources->n; i++) {
     361            pmSource *source = sources->data[i];
     362            source->mode |= PM_SOURCE_MODE_PSFSTAR;
     363        }
     364        // force psphotChoosePSF to use all loaded sources
     365        psMetadataAddS32 (recipe, PS_LIST_TAIL, "PSF_MAX_NSTARS", PS_META_REPLACE, "max number of sources for PSF model", sources->n);
     366
     367        // measure stats of externally specified sources
     368        if (!psphotSourceStatsUpdate (sources, config, readout)) {
     369            psError(PSPHOT_ERR_CONFIG, false, "failure to measure stats of existing sources");
     370            return false;
     371        }
     372    } else {
     373
     374        // find the detections (by peak and/or footprint) in the image.
     375        if (!psphotFindDetections (config, view, true)) {
     376            psError(PSPHOT_ERR_CONFIG, false, "unable to find detections in this image");
     377            return psphotReadoutCleanup (config, view);
     378        }
     379
     380        // construct sources and measure basic stats
     381        psphotSourceStats (config, view, true);
     382
     383        // find blended neighbors of very saturated stars
     384        psphotDeblendSatstars (config, view);
     385
     386        // mark blended peaks PS_SOURCE_BLEND
     387        if (!psphotBasicDeblend (config, view)) {
     388            psLogMsg ("psphot", 3, "failed on deblend analysis");
     389            return psphotReadoutCleanup (config, view);
     390        }
     391
     392        // classify sources based on moments, brightness
     393        if (!psphotRoughClass (config, view)) {
     394            psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
     395            return psphotReadoutCleanup (config, view);
     396        }
     397    }
     398
     399    return true;
     400}
  • branches/tap_branches/psphot/src/psphotModelBackground.c

    r24188 r27838  
    55// Determine the binning characteristics for the background model
    66// Sets the ruff image size and skip based on recipe values for the binning
    7 static psImageBinning *backgroundBinning(const psImage *image, // Image for which to generate a bg model
     7psImageBinning *psphotBackgroundBinning(const psImage *image, // Image for which to generate a bg model
    88                                         const pmConfig *config // Configuration
    99                                         )
     
    2828}
    2929
     30
    3031// Generate the background model
    31 static bool backgroundModel(psImage *model,  // Model image
    32                             psImage *modelStdev, // Model stdev image
    33                             psMetadata *analysis, // Analysis metadata for outputs
    34                             pmReadout *readout, // Readout for which to generate a background model
    35                             psImageBinning *binning, // Binning parameters
    36                             const pmConfig *config // Configuration
    37                             )
     32// generate the median in NxN boxes, clipping heavily
     33// linear interpolation to generate full-scale model
     34//
     35// NOTE that the 'analysis' metedata pass in here is used to store the binning information.
     36// This may be the analysis for this readout, but it may be the analysis for the pmFPAfile
     37// corresponding to the model.  Other information about the background model is saved on the
     38// readout->analysis
     39static bool psphotModelBackgroundReadout(psImage *model,  // Model image
     40                                  psImage *modelStdev, // Model stdev image
     41                                  psMetadata *analysis, // Analysis metadata for outputs
     42                                  pmReadout *readout, // Readout for which to generate a background model
     43                                  psImageBinning *binning, // Binning parameters
     44                                  const pmConfig *config // Configuration
     45    )
    3846{
    3947    psTimerStart ("psphot.background");
     
    137145
    138146    // we save the binning structure for use in psphotMagnitudes
    139     psMetadataAddPtr(analysis, PS_LIST_TAIL, "PSPHOT.BACKGROUND.BINNING",
    140                      PS_DATA_UNKNOWN | PS_META_REPLACE, "Background binning", binning);
     147    psMetadataAddPtr(analysis, PS_LIST_TAIL, "PSPHOT.BACKGROUND.BINNING", PS_DATA_UNKNOWN | PS_META_REPLACE, "Background binning", binning);
    141148
    142149    psF32 **modelData = model->data.F32;
     
    144151
    145152    // XXXX we can thread this here by running blocks in parallel
     153
     154    int nFailures = 0;
     155    psImageBackgroundInit();
    146156
    147157    // measure clipped median for subimages
     
    211221                stats->options = PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV;
    212222                if (!psImageBackground(stats, &sample, subset, submask, maskVal, rng)) {
    213                     psLogMsg ("psphot", PS_LOG_WARN, "Failed to estimate background using ROBUST_MEDIAN for "
    214                                "(%dx%d, (row0,col0) = (%d,%d)",
    215                                subset->numRows, subset->numCols, subset->row0, subset->col0);
     223                    if ((nFailures < 3) || (nFailures % 100 == 0)) {
     224                        psLogMsg ("psphot", PS_LOG_WARN, "Failed to estimate background using ROBUST_MEDIAN for "
     225                                  "(%dx%d, (row0,col0) = (%d,%d)",
     226                                  subset->numRows, subset->numCols, subset->row0, subset->col0);
     227                    }
     228                    nFailures ++;
    216229                    modelData[iy][ix] = modelStdevData[iy][ix] = NAN;
    217230                } else {
     
    232245            psFree (submask);
    233246        }
     247    }
     248
     249    if (nFailures) {
     250        psLogMsg ("psphot", PS_LOG_WARN, "Failed to estimate background for %d of %d subimages", nFailures, (model->numRows*model->numCols));
    234251    }
    235252
     
    293310    psLogMsg ("psphot", PS_LOG_INFO, "built background image: %f sec\n", psTimerMark ("psphot.background"));
    294311
    295     psMetadataAddF32(recipe, PS_LIST_TAIL, "SKY_MEAN", PS_META_REPLACE, "sky mean", Value);
    296     psMetadataAddF32(recipe, PS_LIST_TAIL, "SKY_STDEV", PS_META_REPLACE, "sky stdev", ValueStdev);
     312    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "SKY_MEAN", PS_META_REPLACE, "sky mean", Value);
     313    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "SKY_STDEV", PS_META_REPLACE, "sky stdev", ValueStdev);
    297314    psLogMsg ("psphot", PS_LOG_INFO, "image sky : mean %f stdev %f", Value, ValueStdev);
    298315
     
    303320                                      PS_STAT_MAX);
    304321    psImageStats (statsBck, model, NULL, 0);
    305     psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_MN",
    306                       PS_META_REPLACE, "sky model mean",          statsBck->sampleMean);
    307     psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_SIG",
    308                       PS_META_REPLACE, "sky model stdev",         statsBck->sampleStdev);
    309     psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_MAX",
    310                       PS_META_REPLACE, "sky model maximum value", statsBck->max);
    311     psMetadataAddF32 (recipe, PS_LIST_TAIL, "MSKY_MIN",
    312                       PS_META_REPLACE, "sky model minimum value", statsBck->min);
    313     psMetadataAddS32 (recipe, PS_LIST_TAIL, "MSKY_NX",
    314                       PS_META_REPLACE, "sky model size (x)",      model->numCols);
    315     psMetadataAddS32 (recipe, PS_LIST_TAIL, "MSKY_NY",
    316                       PS_META_REPLACE, "sky model size (y)",      model->numRows);
     322    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "MSKY_MN", PS_META_REPLACE, "sky model mean",          statsBck->sampleMean);
     323    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "MSKY_SIG", PS_META_REPLACE, "sky model stdev",         statsBck->sampleStdev);
     324    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "MSKY_MAX", PS_META_REPLACE, "sky model maximum value", statsBck->max);
     325    psMetadataAddF32 (readout->analysis, PS_LIST_TAIL, "MSKY_MIN", PS_META_REPLACE, "sky model minimum value", statsBck->min);
     326    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "MSKY_NX", PS_META_REPLACE, "sky model size (x)",      model->numCols);
     327    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "MSKY_NY", PS_META_REPLACE, "sky model size (y)",      model->numRows);
    317328    psLogMsg ("psphot", PS_LOG_INFO, "background sky : min %f mean %f max %f stdev %f",
    318329              statsBck->min, statsBck->sampleMean, statsBck->max, statsBck->sampleStdev);
     
    327338}
    328339
    329 
    330 
    331 psImage *psphotBackgroundModel(pmReadout *ro, const pmConfig *config)
     340// generate a background model for a single readout. do not save an associated pmFPAfile for possible output
     341psImage *psphotModelBackgroundReadoutNoFile(pmReadout *readout, const pmConfig *config)
    332342{
    333     PM_ASSERT_READOUT_NON_NULL(ro, NULL);
    334     PM_ASSERT_READOUT_IMAGE(ro, NULL);
     343    PM_ASSERT_READOUT_NON_NULL(readout, NULL);
     344    PM_ASSERT_READOUT_IMAGE(readout, NULL);
    335345    PS_ASSERT_PTR_NON_NULL(config, NULL);
    336346
    337     psImageBinning *binning = backgroundBinning(ro->image, config); // Image binning parameters
     347    psImageBinning *binning = psphotBackgroundBinning(readout->image, config); // Image binning parameters
    338348    psImage *model = psImageAlloc(binning->nXruff, binning->nYruff, PS_TYPE_F32); // Background model
    339349    psImage *modelStdev = psImageAlloc(binning->nXruff, binning->nYruff, PS_TYPE_F32); // Standard deviation
    340350
    341     if (!backgroundModel(model, modelStdev, ro->analysis, ro, binning, config)) {
     351    if (!psphotModelBackgroundReadout(model, modelStdev, readout->analysis, readout, binning, config)) {
    342352        psFree(model);
    343353        psFree(modelStdev);
     
    345355        return NULL;
    346356    }
    347 
    348357    psFree(modelStdev);
    349 
    350358    return model;
    351359}
    352360
    353 
    354 // generate the median in NxN boxes, clipping heavily
    355 // linear interpolation to generate full-scale model
    356 bool psphotModelBackground (pmConfig *config, const pmFPAview *view, const char *filename)
     361// generate a background model for readout number index; save an associated pmFPAfile for possible output
     362bool psphotModelBackgroundReadoutFileIndex (pmConfig *config, const pmFPAview *view, const char *filename, int index)
    357363{
    358     bool status = true;
    359 
    360364    // find the currently selected readout
    361     pmFPAfile *file = psMetadataLookupPtr (&status, config->files, filename);
     365    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     366    psAssert (file, "missing file?");
     367
    362368    pmFPA *inFPA = file->fpa;
    363369    pmReadout *readout = pmFPAviewThisReadout(view, inFPA);
    364 
    365     psImageBinning *binning = backgroundBinning(readout->image, config); // Image binning parameters
    366     pmReadout *model = pmFPAGenerateReadout(config, view, "PSPHOT.BACKMDL", inFPA, binning);
    367     pmReadout *modelStdev = pmFPAGenerateReadout(config, view, "PSPHOT.BACKMDL.STDEV", inFPA, binning);
    368 
    369     if (!backgroundModel(model->image, modelStdev->image, model->analysis, readout, binning, config)) {
     370    psAssert (readout, "missing readout?");
     371
     372    psImageBinning *binning = psphotBackgroundBinning(readout->image, config); // Image binning parameters
     373    pmReadout *model = pmFPAGenerateReadout(config, view, "PSPHOT.BACKMDL", inFPA, binning, index);
     374    pmReadout *modelStdev = pmFPAGenerateReadout(config, view, "PSPHOT.BACKMDL.STDEV", inFPA, binning, index);
     375
     376    if (!psphotModelBackgroundReadout(model->image, modelStdev->image, model->analysis, readout, binning, config)) {
    370377        psError(PS_ERR_UNKNOWN, false, "Unable to generate background model");
    371378        return false;
     
    375382    return true;
    376383}
     384
     385// XXX supply filename or keep PSPHOT.INPUT fixed?
     386bool psphotModelBackground (pmConfig *config, const pmFPAview *view)
     387{
     388    bool status = false;
     389
     390    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     391    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     392
     393    // loop over the available readouts
     394    for (int i = 0; i < num; i++) {
     395        if (!psphotModelBackgroundReadoutFileIndex(config, view, "PSPHOT.INPUT", i)) {
     396            psError (PSPHOT_ERR_CONFIG, false, "failed to model background for PSPHOT.INPUT entry %d", i);
     397            return false;
     398        }
     399    }
     400    return true;
     401}
  • branches/tap_branches/psphot/src/psphotModelTest.c

    r24588 r27838  
    139139
    140140    // get the source moments
    141     status = pmSourceMoments (source, mRADIUS, 0.0, 1.0);
     141    status = pmSourceMoments (source, mRADIUS, 0.0, 1.0, maskVal);
    142142    if (!status) psAbort("psSourceMoments error");
    143143    source->peak->value = source->moments->Peak;
  • branches/tap_branches/psphot/src/psphotMomentsStudy.c

    r24585 r27838  
    148148      pmSourceAdd(source, PM_MODEL_OP_FUNC, 0);
    149149
    150       pmSourceMoments (source, 32.0, sigWindow, 0.0);
     150      pmSourceMoments (source, 32.0, sigWindow, 0.0, 0xffff);
    151151      // fprintf (stderr, "sigOut : %f\n", sqrt(source->moments->Mxx));
    152152
  • branches/tap_branches/psphot/src/psphotOutput.c

    r25755 r27838  
    126126}
    127127
    128 bool psphotAddPhotcode (psMetadata *recipe, pmConfig *config, const pmFPAview *view, const char *filerule) {
    129 
    130     bool status;
    131 
    132     pmFPAfile *input = psMetadataLookupPtr (&status, config->files, filerule);
    133     PS_ASSERT (status, false);
    134 
    135     // determine PHOTCODE from fpa & view, overwrite in recipe
    136     char *photcode = pmConceptsPhotcodeForView (input, view);
     128bool psphotAddPhotcode (pmConfig *config, const pmFPAview *view) {
     129
     130    bool status = false;
     131
     132    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     133    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     134
     135    // loop over the available readouts
     136    for (int i = 0; i < num; i++) {
     137        if (!psphotAddPhotcodeReadout (config, view, "PSPHOT.INPUT", i)) {
     138            psError (PSPHOT_ERR_CONFIG, false, "failed to add photcode to PSPHOT.INPUT entry %d", i);
     139            return false;
     140        }
     141    }
     142    return true;
     143}
     144
     145bool psphotAddPhotcodeReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index) {
     146
     147    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filerule, index); // File of interest
     148    PS_ASSERT (file, false);
     149
     150    pmReadout  *readout = pmFPAviewThisReadout (view, file->fpa);
     151
     152    // determine PHOTCODE from fpa & view, overwrite in readout->analysis
     153    char *photcode = pmConceptsPhotcodeForView (file, view);
    137154    PS_ASSERT (photcode, false);
    138155
    139     psMetadataAddStr (recipe, PS_LIST_TAIL, "PHOTCODE", PS_META_REPLACE, "photcode from FPA concepts", photcode);
     156    psMetadataAddStr (readout->analysis, PS_LIST_TAIL, "PHOTCODE", PS_META_REPLACE, "photcode from FPA concepts", photcode);
    140157    psLogMsg ("psphot", 3, "PHOTCODE is %s", photcode);
    141158
     
    144161}
    145162
    146 bool psphotSetHeaderNstars (psMetadata *recipe, psArray *sources) {
     163bool psphotSetHeaderNstars (psMetadata *header, psArray *sources) {
    147164
    148165    int nSrc = 0;
     
    173190    }
    174191
    175     psMetadataAddS32 (recipe, PS_LIST_TAIL, "NSTARS",   PS_META_REPLACE, "Number of sources", nSrc);
    176     psMetadataAddS32 (recipe, PS_LIST_TAIL, "NDET_EXT", PS_META_REPLACE, "Number of extended sources", nEXT);
    177     psMetadataAddS32 (recipe, PS_LIST_TAIL, "NDET_CR",  PS_META_REPLACE, "Number of cosmic rays", nCR);
    178     return true;
    179 }
    180 
    181 // these values are saved in an output header stub - they are added to either the
    182 // PHU header (CMP) or the MEF table header (CMF)
    183 psMetadata *psphotDefineHeader (psMetadata *recipe) {
     192    psMetadataAddS32 (header, PS_LIST_TAIL, "NSTARS",   PS_META_REPLACE, "Number of sources", nSrc);
     193    psMetadataAddS32 (header, PS_LIST_TAIL, "NDET_EXT", PS_META_REPLACE, "Number of extended sources", nEXT);
     194    psMetadataAddS32 (header, PS_LIST_TAIL, "NDET_CR",  PS_META_REPLACE, "Number of cosmic rays", nCR);
     195    return true;
     196}
     197
     198// these values are saved in an output header stub - they are added to either the PHU header
     199// (CMP) or the MEF table header (CMF).  before the header is created, each readout has these
     200// values stored on readout->analysis
     201psMetadata *psphotDefineHeader (psMetadata *analysis) {
     202
     203    bool status = true;
    184204
    185205    psMetadata *header = psMetadataAlloc ();
    186206
    187207    // write necessary information to output header
    188     psMetadataItemSupplement (header, recipe, "ZERO_PT");
    189     psMetadataItemSupplement (header, recipe, "PHOTCODE");
    190 
    191     psMetadataItemSupplement (header, recipe, "APMIFIT");
    192     psMetadataItemSupplement (header, recipe, "DAPMIFIT");
    193     psMetadataItemSupplement (header, recipe, "NAPMIFIT");
     208    psMetadataItemSupplement (&status, header, analysis, "ZERO_PT");
     209    psMetadataItemSupplement (&status, header, analysis, "PHOTCODE");
     210
     211    psMetadataItemSupplement (&status, header, analysis, "APMIFIT");
     212    psMetadataItemSupplement (&status, header, analysis, "DAPMIFIT");
     213    psMetadataItemSupplement (&status, header, analysis, "NAPMIFIT");
    194214
    195215    // PSF model parameters (shape values for image center)
    196     psMetadataItemSupplement (header, recipe, "NPSFSTAR");
    197     psMetadataItemSupplement (header, recipe, "APLOSS");
    198 
    199     psMetadataItemSupplement (header, recipe, "FWHM_MAJ");
    200     psMetadataItemSupplement (header, recipe, "FW_MJ_SG");
    201     psMetadataItemSupplement (header, recipe, "FW_MJ_LQ");
    202     psMetadataItemSupplement (header, recipe, "FW_MJ_UQ");
    203 
    204     psMetadataItemSupplement (header, recipe, "FWHM_MIN");
    205     psMetadataItemSupplement (header, recipe, "FW_MN_SG");
    206     psMetadataItemSupplement (header, recipe, "FW_MN_LQ");
    207     psMetadataItemSupplement (header, recipe, "FW_MN_UQ");
    208 
    209     psMetadataItemSupplement (header, recipe, "ANGLE");
     216    psMetadataItemSupplement (&status, header, analysis, "NPSFSTAR");
     217    psMetadataItemSupplement (&status, header, analysis, "APLOSS");
     218
     219    psMetadataItemSupplement (&status, header, analysis, "FWHM_MAJ");
     220    psMetadataItemSupplement (&status, header, analysis, "FW_MJ_SG");
     221    psMetadataItemSupplement (&status, header, analysis, "FW_MJ_LQ");
     222    psMetadataItemSupplement (&status, header, analysis, "FW_MJ_UQ");
     223
     224    psMetadataItemSupplement (&status, header, analysis, "FWHM_MIN");
     225    psMetadataItemSupplement (&status, header, analysis, "FW_MN_SG");
     226    psMetadataItemSupplement (&status, header, analysis, "FW_MN_LQ");
     227    psMetadataItemSupplement (&status, header, analysis, "FW_MN_UQ");
     228
     229    psMetadataItemSupplement (&status, header, analysis, "ANGLE");
    210230
    211231    // Image Quality measurements
    212     psMetadataItemSupplement (header, recipe, "IQ_NSTAR");
    213 
    214     psMetadataItemSupplement (header, recipe, "IQ_FW1");
    215     psMetadataItemSupplement (header, recipe, "IQ_FW1_E");
    216     psMetadataItemSupplement (header, recipe, "IQ_FW2");
    217     psMetadataItemSupplement (header, recipe, "IQ_FW2_E");
    218 
    219     psMetadataItemSupplement (header, recipe, "IQ_M2");
    220     psMetadataItemSupplement (header, recipe, "IQ_M2_ER");
    221     psMetadataItemSupplement (header, recipe, "IQ_M2_LQ");
    222     psMetadataItemSupplement (header, recipe, "IQ_M2_UQ");
    223 
    224     psMetadataItemSupplement (header, recipe, "IQ_M2C");
    225     psMetadataItemSupplement (header, recipe, "IQ_M2C_E");
    226     psMetadataItemSupplement (header, recipe, "IQ_M2C_L");
    227     psMetadataItemSupplement (header, recipe, "IQ_M2C_U");
    228 
    229     psMetadataItemSupplement (header, recipe, "IQ_M2S");
    230     psMetadataItemSupplement (header, recipe, "IQ_M2S_E");
    231     psMetadataItemSupplement (header, recipe, "IQ_M2S_L");
    232     psMetadataItemSupplement (header, recipe, "IQ_M2S_U");
    233 
    234     psMetadataItemSupplement (header, recipe, "IQ_M3");
    235     psMetadataItemSupplement (header, recipe, "IQ_M3_ER");
    236     psMetadataItemSupplement (header, recipe, "IQ_M3_LQ");
    237     psMetadataItemSupplement (header, recipe, "IQ_M3_UQ");
    238 
    239     psMetadataItemSupplement (header, recipe, "IQ_M4");
    240     psMetadataItemSupplement (header, recipe, "IQ_M4_ER");
    241     psMetadataItemSupplement (header, recipe, "IQ_M4_LQ");
    242     psMetadataItemSupplement (header, recipe, "IQ_M4_UQ");
     232    psMetadataItemSupplement (&status, header, analysis, "IQ_NSTAR");
     233
     234    psMetadataItemSupplement (&status, header, analysis, "IQ_FW1");
     235    psMetadataItemSupplement (&status, header, analysis, "IQ_FW1_E");
     236    psMetadataItemSupplement (&status, header, analysis, "IQ_FW2");
     237    psMetadataItemSupplement (&status, header, analysis, "IQ_FW2_E");
     238
     239    psMetadataItemSupplement (&status, header, analysis, "IQ_M2");
     240    psMetadataItemSupplement (&status, header, analysis, "IQ_M2_ER");
     241    psMetadataItemSupplement (&status, header, analysis, "IQ_M2_LQ");
     242    psMetadataItemSupplement (&status, header, analysis, "IQ_M2_UQ");
     243
     244    psMetadataItemSupplement (&status, header, analysis, "IQ_M2C");
     245    psMetadataItemSupplement (&status, header, analysis, "IQ_M2C_E");
     246    psMetadataItemSupplement (&status, header, analysis, "IQ_M2C_L");
     247    psMetadataItemSupplement (&status, header, analysis, "IQ_M2C_U");
     248
     249    psMetadataItemSupplement (&status, header, analysis, "IQ_M2S");
     250    psMetadataItemSupplement (&status, header, analysis, "IQ_M2S_E");
     251    psMetadataItemSupplement (&status, header, analysis, "IQ_M2S_L");
     252    psMetadataItemSupplement (&status, header, analysis, "IQ_M2S_U");
     253
     254    psMetadataItemSupplement (&status, header, analysis, "IQ_M3");
     255    psMetadataItemSupplement (&status, header, analysis, "IQ_M3_ER");
     256    psMetadataItemSupplement (&status, header, analysis, "IQ_M3_LQ");
     257    psMetadataItemSupplement (&status, header, analysis, "IQ_M3_UQ");
     258
     259    psMetadataItemSupplement (&status, header, analysis, "IQ_M4");
     260    psMetadataItemSupplement (&status, header, analysis, "IQ_M4_ER");
     261    psMetadataItemSupplement (&status, header, analysis, "IQ_M4_LQ");
     262    psMetadataItemSupplement (&status, header, analysis, "IQ_M4_UQ");
    243263
    244264    // XXX these need to be defined from elsewhere
    245265    psMetadataAdd (header, PS_LIST_TAIL, "FSATUR",   PS_DATA_F32 | PS_META_REPLACE, "SATURATION MAG",      0.0);
    246266    psMetadataAdd (header, PS_LIST_TAIL, "FLIMIT",   PS_DATA_F32 | PS_META_REPLACE, "COMPLETENESS MAG",    0.0);
    247     psMetadataItemSupplement (header, recipe, "NSTARS");
    248 
    249     psMetadataItemSupplement (header, recipe, "NDET_EXT");
    250     psMetadataItemSupplement (header, recipe, "NDET_CR");
     267    psMetadataItemSupplement (&status, header, analysis, "NSTARS");
     268
     269    psMetadataItemSupplement (&status, header, analysis, "NDET_EXT");
     270    psMetadataItemSupplement (&status, header, analysis, "NDET_CR");
    251271
    252272    // sky background model statistics
    253     psMetadataItemSupplement (header, recipe, "MSKY_MN");
    254     psMetadataItemSupplement (header, recipe, "MSKY_SIG");
    255     psMetadataItemSupplement (header, recipe, "MSKY_MIN");
    256     psMetadataItemSupplement (header, recipe, "MSKY_MAX");
    257     psMetadataItemSupplement (header, recipe, "MSKY_NX");
    258     psMetadataItemSupplement (header, recipe, "MSKY_NY");
     273    psMetadataItemSupplement (&status, header, analysis, "MSKY_MN");
     274    psMetadataItemSupplement (&status, header, analysis, "MSKY_SIG");
     275    psMetadataItemSupplement (&status, header, analysis, "MSKY_MIN");
     276    psMetadataItemSupplement (&status, header, analysis, "MSKY_MAX");
     277    psMetadataItemSupplement (&status, header, analysis, "MSKY_NX");
     278    psMetadataItemSupplement (&status, header, analysis, "MSKY_NY");
    259279
    260280    psMetadataAddF32 (header, PS_LIST_TAIL, "DT_PHOT", PS_META_REPLACE, "elapsed psphot time", psTimerMark ("psphotReadout"));
    261 
    262     // XXX : don't require any of these about values to exist
    263     psErrorClear ();
    264281
    265282    return header;
  • branches/tap_branches/psphot/src/psphotPSFConvModel.c

    r25755 r27838  
    3939    // adjust the pixels based on the footprint
    4040    float radius = psphotSetRadiusEXT (readout, source, markVal);
    41     if (!pmSourceMoments (source, radius, 0.0, 0.0)) return false;
     41    if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) return false;
    4242
    4343    // XXX test : modify the Io, SXX, SYY terms based on the psf SXX, SYY terms:
  • branches/tap_branches/psphot/src/psphotParseCamera.c

    r21458 r27838  
    3939        return NULL;
    4040    }
     41    // specify the number of psphot input images
     42    psMetadataAddS32 (config->arguments, PS_LIST_TAIL, "PSPHOT.INPUT.NUM", PS_META_REPLACE, "number of inputs", 1);
    4143
    4244    // define the additional input/output files associated with psphot
  • branches/tap_branches/psphot/src/psphotPetrosian.c

    r25755 r27838  
    77
    88    psAssert (source->extpars, "need to run psphotRadialProfile first");
    9     psAssert (source->extpars->profile, "need to run psphotRadialProfile first");
     9    psAssert (source->extpars->ellipticalFlux, "need to run psphotRadialProfile first");
    1010
    1111    // integrate the radial profile for radial bins defined for the petrosian measurement:
     
    2424    psTrace ("psphot", 3, "source at %f,%f: petrosian radius: %f, flux: %f, axis ratio: %f, angle: %f",
    2525             source->peak->xf, source->peak->yf,
    26              source->extpars->petrosian_80->radius,
    27              source->extpars->petrosian_80->flux,
    28              source->extpars->profile->axes.minor/source->extpars->profile->axes.major,
    29              source->extpars->profile->axes.theta*PS_DEG_RAD);
     26             source->extpars->petrosianRadius,
     27             source->extpars->petrosianFlux,
     28             source->extpars->axes.minor/source->extpars->axes.major,
     29             source->extpars->axes.theta*PS_DEG_RAD);
    3030
    3131    return true;
  • branches/tap_branches/psphot/src/psphotPetrosianRadialBins.c

    r25755 r27838  
    11# include "psphotInternal.h"
     2float InterpolateValues (float X0, float Y0, float X1, float Y1, float X);
    23
    34// convert the flux vs elliptical radius to annular bins
     
    56// we are guaranteed to be limited by either the seeing (1 - few pixels) or by the pixels
    67// themselves.  this function does not attempt to measure the radial profiles accurately
    7 // for radii that are smaller than a minimum (currently 1.0 pixels). 
     8// for radii that are smaller than ~2 pixels
    89
    910// for small radii, we are measuring the mean surface brightness in non-overlapping radial
     
    1314// track the non-overlapping radius values.
    1415
     16// Photo interpolates the image of interest to place the peak on the center of the central
     17// pixel, and then uses the exact fractions of the pixels in each of the first few annuli.
     18// Seems like a reasonable thing, but is there any significance to the difference?
     19
    1520// XXX move the resulting elements from profile to extpars->petrosian?
    1621bool psphotPetrosianRadialBins (pmSource *source, float radiusMax, float skynoise) {
    1722
    18     pmSourceRadialProfile *profile = source->extpars->profile;
    19 
    20     float skyModelErrorSQ = PS_SQR(skynoise);
    21 
    22     psVector *radius = profile->radiusElliptical;
    23     psVector *flux = profile->fluxElliptical;
     23    psAssert (source, "missing source");
     24    psAssert (source->extpars, "missing extpars");
     25    psAssert (source->extpars->ellipticalFlux, "missing ellipticalFlux");
     26
     27    psVector *radius = source->extpars->ellipticalFlux->radiusElliptical;
     28    psVector *flux = source->extpars->ellipticalFlux->fluxElliptical;
    2429
    2530    // sort incoming vectors by radius
    2631    pmSourceRadialProfileSortPair (radius, flux);
     32
     33    if (!source->extpars->petProfile) {
     34        source->extpars->petProfile = pmSourceRadialProfileAlloc();
     35    }
     36    pmSourceRadialProfile *profile = source->extpars->petProfile;
     37
     38    float skyModelErrorSQ = PS_SQR(skynoise);
    2739
    2840    int nMax = radiusMax;
     
    107119    psVector *values = psVectorAllocEmpty (flux->n, PS_TYPE_F32);
    108120    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    109     // psStats *stats = psStatsAlloc(PS_STAT_FITTED_MEAN_V4 | PS_STAT_FITTED_STDEV_V4);
    110 
    111     // integrate flux, radius for each of these bins.  since flux is sorted by radius,
    112     // we can do this fairly quickly
    113121
    114122    bool done = false;
     
    133141                dvalue = NAN;
    134142            }
    135             // binSB->data.F32[nOut] = stats->sampleMedian;
     143
    136144            binSB->data.F32[nOut] = value;
    137145            binSBstdev->data.F32[nOut] = sqrt(PS_SQR(dvalue) / values->n + skyModelErrorSQ);
    138             // binSB->data.F32[nOut] = stats->fittedMean;
    139             // binSBstdev->data.F32[nOut] = sqrt(PS_SQR(stats->fittedStdev) / values->n + skyModelErrorSQ);
    140146
    141147            // error in the SB is the stdev per bin / sqrt (number of pixels)
     
    143149            // residual flux, but the sky from the sky model)
    144150
    145             psTrace ("psphot", 5, "%3d  %5.1f %5.1f : %5.1f  %5.2f\n",
    146                      nOut, radAlp->data.F32[nOut], radBet->data.F32[nOut], binSB->data.F32[nOut], binSBstdev->data.F32[nOut]);
     151            psTrace ("psphot", 5, "%3d  %5.1f %5.1f : %5.1f  %5.2f\n", nOut, radAlp->data.F32[nOut], radBet->data.F32[nOut], binSB->data.F32[nOut], binSBstdev->data.F32[nOut]);
    147152
    148153            nOut ++;
     
    163168    // XXX I think this misses the last radial bin -- do we care?
    164169
     170    // interpolate any bins that were empty (extrapolate to center if needed)
     171    if (!isfinite(binSB->data.F32[0]) && !isfinite(binSB->data.F32[1])) {
     172        psWarning ("center 2 bins of source at %f, %f are NAN, skipping this source", source->peak->xf, source->peak->yf);
     173        // XXX raise a flag
     174        psFree(binSB);
     175        psFree(binSBstdev);
     176        psFree(binRad);
     177        psFree(binArea);
     178        psFree(radMin);
     179        psFree(radMax);
     180        psFree(radAlp);
     181        psFree(radBet);
     182        psFree(values);
     183        psFree(stats);
     184        return false;
     185    }
     186
     187    // if center bin is empty assume same SB as next radius (probably true due to PSF)
     188    if (!isfinite(binSB->data.F32[0])) {
     189        binSB->data.F32[0] = binSB->data.F32[1];
     190        binSBstdev->data.F32[0] = binSBstdev->data.F32[1];
     191    }
     192
     193    // interpolate any bins that were empty (if center if needed)
     194    for (int i = 1; i < binSB->n - 1; i++) {
     195        if (isfinite(binSB->data.F32[i])) continue;
     196        binSB->data.F32[i] = InterpolateValues (binRad->data.F32[i-1], binSB->data.F32[i-1], binRad->data.F32[i+1], binSB->data.F32[i+1], binRad->data.F32[i]);
     197        binSBstdev->data.F32[i] = InterpolateValues (binRad->data.F32[i-1], binSBstdev->data.F32[i-1], binRad->data.F32[i+1], binSBstdev->data.F32[i+1], binRad->data.F32[i]);
     198    }
     199
     200    psFree(profile->binSB);
     201    psFree(profile->binSBstdev);
     202    psFree(profile->radialBins);
     203    psFree(profile->area);
     204
    165205    // save the vectors
    166206    profile->radialBins = binRad;
  • branches/tap_branches/psphot/src/psphotPetrosianStats.c

    r25755 r27838  
    1010bool psphotPetrosianStats (pmSource *source) {
    1111
    12     pmSourceRadialProfile *profile = source->extpars->profile;
    13 
    14     float petRadius = NAN;
    15     float petFlux = NAN;
     12    psAssert (source, "missing source");
     13    psAssert (source->extpars, "missing extpars");
     14    psAssert (source->extpars->petProfile, "missing petProfile");
     15
     16    pmSourceRadialProfile *profile = source->extpars->petProfile;
    1617
    1718    psVector *binSB      = profile->binSB;
     
    2829    psVector *areaSum     = psVectorAllocEmpty(binSB->n, PS_TYPE_F32);
    2930
     31    float petRadius = NAN;
     32    float petFlux = NAN;
     33
    3034    bool anyPetro = false;
    3135    bool manyPetro = false;
     
    3842    int lowestSignificantRadius = 0;
    3943    float lowestSignificantRatio = 1.0;
     44
     45    // find the Petrosian Radius and Petrosian Flux
    4046
    4147    int nOut = 0;
     
    142148    }
    143149
    144     if (!source->extpars->petrosian_80) {
    145         source->extpars->petrosian_80 = pmSourceExtendedFluxAlloc ();
    146     }
    147     pmSourceExtendedFlux *petrosian = source->extpars->petrosian_80;
     150    // now measure the radii R90 and R50 where flux = 0.9 (or 0.5) * petFlux;
     151    float flux90 = 0.9 * petFlux;
     152    float flux50 = 0.5 * petFlux;
     153    float R50 = NAN;
     154    float R90 = NAN;
     155    bool found50 = false;
     156    bool found90 = false;
     157    // XXX use bisection to do this faster:
     158    for (int i = 0; !(found50 && found90) && i < refRadius->n; i++) {
     159        if (!found50 && (fluxSum->data.F32[i] > flux50)) {
     160            if (i == 0) {
     161                psWarning ("does this case make any sense? (fluxSum[0] > flux50)");
     162                continue;
     163            } else {
     164                R50 = InterpolateValues (fluxSum->data.F32[i-1], refRadius->data.F32[i-1], fluxSum->data.F32[i], refRadius->data.F32[i], flux50);
     165                found50 = true;
     166            }
     167        }
     168        if (!found90 && (fluxSum->data.F32[i] > flux90)) {
     169            if (i == 0) {
     170                psWarning ("does this case make any sense? (fluxSum[0] > flux90)");
     171                continue;
     172            } else {
     173                R90 = InterpolateValues (fluxSum->data.F32[i-1], refRadius->data.F32[i-1], fluxSum->data.F32[i], refRadius->data.F32[i], flux90);
     174                found90 = true;
     175            }
     176        }
     177    }
     178
    148179
    149180    // XXX save flags (anyPetro, manyPetro)
    150     petrosian->radius = petRadius;
    151     petrosian->flux   = petFlux;
    152 
    153     // psphotPetrosianVisualStats (binRad, binSB, refRadius, meanSB, petRatio, petRatioErr, fluxSum, petRadius, PETROSIAN_RATIO, petFlux, apRadius);
     181    source->extpars->petrosianRadius = petRadius;
     182    source->extpars->petrosianFlux   = petFlux;
     183    source->extpars->petrosianR50    = R50;
     184    source->extpars->petrosianR90    = R90;
     185   
     186    // XXX add the errors
     187    source->extpars->petrosianRadiusErr = NAN;
     188    source->extpars->petrosianFluxErr   = NAN;
     189    source->extpars->petrosianR50Err    = NAN;
     190    source->extpars->petrosianR90Err    = NAN;
     191
     192    fprintf (stderr, "source @ %f,%f\n", source->peak->xf, source->peak->yf);
     193    psphotPetrosianVisualStats (binRad, binSB, refRadius, meanSB, petRatio, petRatioErr, fluxSum, petRadius, PETROSIAN_RATIO, petFlux, apRadius);
    154194
    155195    psFree(fluxSum);
  • branches/tap_branches/psphot/src/psphotPetrosianVisual.c

    r25755 r27838  
    11# include "psphotInternal.h"
     2# define FORCE_VISUAL 0
    23
    34// this function displays representative images as the psphot analysis progresses:
     
    5455
    5556    // return true;
    56     if (!pmVisualIsVisual()) return true;
     57    if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
    5758
    5859    if (kapa2 == -1) {
     
    101102
    102103    // return true;
    103     if (!pmVisualIsVisual()) return true;
     104    if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
    104105
    105106    if (kapa == -1) {
     
    172173    KapaSection section;
    173174
    174     if (!pmVisualIsVisual()) return true;
     175    if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
     176
     177    if (kapa2 == -1) {
     178        kapa2 = KapaOpenNamedSocket ("kapa", "psphot:stats");
     179        if (kapa2 == -1) {
     180            fprintf (stderr, "failure to open kapa; visual mode disabled\n");
     181            pmVisualSetVisual(false);
     182            return false;
     183        }
     184    }
     185
     186    KapaClearPlots (kapa2);
     187    KapaInitGraph (&graphdata);
     188    KapaSetFont (kapa2, "courier", 14);
     189
     190    // radius vs flux
     191    // radius vs mean SB
     192    // radius vs petRatio
     193
     194    // *** section 1: radius vs mean SB
     195    section.dx = 1.00;
     196    section.dy = 0.33;
     197    section.x  = 0.00;
     198    section.y  = 0.00;
     199    section.name = psStringCopy ("meanSB");
     200    KapaSetSection (kapa2, &section);
     201    psFree (section.name);
     202
     203    graphdata.color = KapaColorByName ("black");
     204    pmVisualLimitsFromVectors (&graphdata, radBin, fluxBin);
     205    KapaSetLimits (kapa2, &graphdata);
     206
     207    KapaBox (kapa2, &graphdata);
     208    KapaSendLabel (kapa2, "radius", KAPA_LABEL_XM);
     209    KapaSendLabel (kapa2, "mean SB", KAPA_LABEL_YM);
     210
     211    graphdata.color = KapaColorByName ("black");
     212    graphdata.style = 2;
     213    graphdata.ptype = 0;
     214    graphdata.size = 1.0;
     215    KapaPrepPlot (kapa2, radBin->n, &graphdata);
     216    KapaPlotVector (kapa2, radBin->n, radBin->data.F32, "x");
     217    KapaPlotVector (kapa2, radBin->n, fluxBin->data.F32, "y");
     218
     219    graphdata.color = KapaColorByName ("red");
     220    graphdata.style = 2;
     221    graphdata.ptype = 1;
     222    graphdata.size = 2.0;
     223    KapaPrepPlot (kapa2, refRadius->n, &graphdata);
     224    KapaPlotVector (kapa2, refRadius->n, refRadius->data.F32, "x");
     225    KapaPlotVector (kapa2, refRadius->n, meanSB->data.F32, "y");
     226
     227    // *** section 2: radius vs petrosian ratio
     228    section.dx = 1.00;
     229    section.dy = 0.33;
     230    section.x  = 0.00;
     231    section.y  = 0.33;
     232    section.name = psStringCopy ("ratio");
     233    KapaSetSection (kapa2, &section);
     234    psFree (section.name);
     235
     236    graphdata.color = KapaColorByName ("black");
     237    graphdata.ymax = +1.05;
     238    graphdata.ymin = -0.05;
     239    pmVisualLimitsFromVectors (&graphdata, radBin, NULL);
     240    KapaSetLimits (kapa2, &graphdata);
     241
     242    KapaBox (kapa2, &graphdata);
     243    KapaSendLabel (kapa2, "radius", KAPA_LABEL_XM);
     244    KapaSendLabel (kapa2, "ratio", KAPA_LABEL_YM);
     245
     246    graphdata.color = KapaColorByName ("black");
     247    graphdata.style = 2;
     248    graphdata.ptype = 0;
     249    graphdata.size = 1.0;
     250    graphdata.etype = 0x01;
     251    KapaPrepPlot (kapa2, refRadius->n, &graphdata);
     252    KapaPlotVector (kapa2, refRadius->n, refRadius->data.F32, "x");
     253    KapaPlotVector (kapa2, refRadius->n, petRatio->data.F32, "y");
     254    KapaPlotVector (kapa2, refRadius->n, petRatioErr->data.F32, "dym");
     255    KapaPlotVector (kapa2, refRadius->n, petRatioErr->data.F32, "dyp");
     256    graphdata.etype = 0;
     257
     258    graphdata.color = KapaColorByName ("red");
     259    graphdata.style = 2;
     260    graphdata.ptype = 2;
     261    graphdata.size = 2.0;
     262    KapaPrepPlot   (kapa2, 1, &graphdata);
     263    KapaPlotVector (kapa2, 1, &petRadius, "x");
     264    KapaPlotVector (kapa2, 1, &ratioForRadius, "y");
     265
     266    // *** section 3: radius vs integrated flux
     267    section.dx = 1.00;
     268    section.dy = 0.33;
     269    section.x  = 0.00;
     270    section.y  = 0.66;
     271    section.name = psStringCopy ("flux");
     272    KapaSetSection (kapa2, &section);
     273    psFree (section.name);
     274
     275    graphdata.color = KapaColorByName ("black");
     276    pmVisualLimitsFromVectors (&graphdata, radBin, fluxSum);
     277    KapaSetLimits (kapa2, &graphdata);
     278
     279    KapaBox (kapa2, &graphdata);
     280    KapaSendLabel (kapa2, "radius", KAPA_LABEL_XM);
     281    KapaSendLabel (kapa2, "integrated flux", KAPA_LABEL_YM);
     282
     283    graphdata.color = KapaColorByName ("black");
     284    graphdata.style = 2;
     285    graphdata.ptype = 0;
     286    graphdata.size = 1.0;
     287    KapaPrepPlot   (kapa2, refRadius->n, &graphdata);
     288    KapaPlotVector (kapa2, refRadius->n, refRadius->data.F32, "x");
     289    KapaPlotVector (kapa2, refRadius->n, fluxSum->data.F32, "y");
     290
     291    graphdata.color = KapaColorByName ("red");
     292    graphdata.ptype = 2;
     293    graphdata.style = 2;
     294    graphdata.size = 2.0;
     295    KapaPrepPlot   (kapa2, 1, &graphdata);
     296    KapaPlotVector (kapa2, 1, &radiusForFlux, "x");
     297    KapaPlotVector (kapa2, 1, &petFlux, "y");
     298
     299    // pause and wait for user input:
     300    // continue, save (provide name), ??
     301    char key[10];
     302    fprintf (stdout, "[c]ontinue? ");
     303    if (!fgets(key, 8, stdin)) {
     304        psWarning("Unable to read option");
     305    }
     306    return true;
     307}
     308
     309bool psphotPetrosianVisualEllipticalContour (pmSourceRadialFlux *radFlux, pmSourceExtendedPars *extpars) {
     310
     311    Graphdata graphdata;
     312
     313    if (!FORCE_VISUAL && !pmVisualIsVisual()) return true;
    175314
    176315    if (kapa == -1) {
     
    187326    KapaSetFont (kapa, "courier", 14);
    188327
    189     // radius vs flux
    190     // radius vs mean SB
    191     // radius vs petRatio
    192 
    193     // *** section 1: radius vs mean SB
    194     section.dx = 1.00;
    195     section.dy = 0.33;
    196     section.x  = 0.00;
    197     section.y  = 0.00;
    198     section.name = psStringCopy ("meanSB");
    199     KapaSetSection (kapa, &section);
    200     psFree (section.name);
    201 
    202     graphdata.color = KapaColorByName ("black");
    203     pmVisualLimitsFromVectors (&graphdata, radBin, fluxBin);
     328    psVector *theta = radFlux->theta;
     329    psVector *radius = radFlux->isophotalRadii;
     330
     331    // find Rmin and Rmax for the initial guess
     332    float Rmin = radius->data.F32[0];
     333    float Rmax = radius->data.F32[0];
     334
     335    psVector *Rx = psVectorAlloc(radius->n, PS_TYPE_F32);
     336    psVector *Ry = psVectorAlloc(radius->n, PS_TYPE_F32);
     337
     338    for (int i = 0; i < theta->n; i++) {
     339        Rx->data.F32[i] = radius->data.F32[i]*cos(theta->data.F32[i]);
     340        Ry->data.F32[i] = radius->data.F32[i]*sin(theta->data.F32[i]);
     341
     342        // check the radius range
     343        Rmin = MIN (Rmin, radius->data.F32[i]);
     344        Rmax = MAX (Rmax, radius->data.F32[i]);
     345    }   
     346
     347    psVector *rx = psVectorAlloc(361, PS_TYPE_F32);
     348    psVector *ry = psVectorAlloc(361, PS_TYPE_F32);
     349
     350    float epsilon = extpars->axes.minor / extpars->axes.major;
     351
     352    for (int i = 0; i < 361; i++) {
     353
     354        float alpha = PS_RAD_DEG * i;
     355
     356        float cs_alpha = cos(alpha);
     357        float sn_alpha = sin(alpha);
     358
     359        float cs_phi = cos(alpha - extpars->axes.theta);
     360        float sn_phi = sin(alpha - extpars->axes.theta);
     361
     362        float r = 1.0 / sqrt(SQ(sn_phi) + SQ(epsilon*cs_phi));
     363
     364        // generate the model fit here
     365        rx->data.F32[i] = extpars->axes.minor * cs_alpha * r;
     366        ry->data.F32[i] = extpars->axes.minor * sn_alpha * r;
     367    }   
     368
     369    graphdata.color = KapaColorByName ("black");
     370    graphdata.xmin = -1.1*Rmax;
     371    graphdata.ymin = -1.1*Rmax;
     372    graphdata.xmax = +1.1*Rmax;
     373    graphdata.ymax = +1.1*Rmax;
    204374    KapaSetLimits (kapa, &graphdata);
    205375
    206376    KapaBox (kapa, &graphdata);
    207     KapaSendLabel (kapa, "radius", KAPA_LABEL_XM);
    208     KapaSendLabel (kapa, "mean SB", KAPA_LABEL_YM);
    209 
    210     graphdata.color = KapaColorByName ("black");
    211     graphdata.style = 2;
    212     graphdata.ptype = 0;
    213     graphdata.size = 1.0;
    214     KapaPrepPlot (kapa, radBin->n, &graphdata);
    215     KapaPlotVector (kapa, radBin->n, radBin->data.F32, "x");
    216     KapaPlotVector (kapa, radBin->n, fluxBin->data.F32, "y");
     377    KapaSendLabel (kapa, "R_x", KAPA_LABEL_XM);
     378    KapaSendLabel (kapa, "R_y", KAPA_LABEL_YM);
    217379
    218380    graphdata.color = KapaColorByName ("red");
    219381    graphdata.style = 2;
    220     graphdata.ptype = 1;
    221     graphdata.size = 2.0;
    222     KapaPrepPlot (kapa, refRadius->n, &graphdata);
    223     KapaPlotVector (kapa, refRadius->n, refRadius->data.F32, "x");
    224     KapaPlotVector (kapa, refRadius->n, meanSB->data.F32, "y");
    225 
    226     // *** section 2: radius vs petrosian ratio
    227     section.dx = 1.00;
    228     section.dy = 0.33;
    229     section.x  = 0.00;
    230     section.y  = 0.33;
    231     section.name = psStringCopy ("ratio");
    232     KapaSetSection (kapa, &section);
    233     psFree (section.name);
    234 
    235     graphdata.color = KapaColorByName ("black");
    236     graphdata.ymax = +1.05;
    237     graphdata.ymin = -0.05;
    238     pmVisualLimitsFromVectors (&graphdata, radBin, NULL);
    239     KapaSetLimits (kapa, &graphdata);
    240 
    241     KapaBox (kapa, &graphdata);
    242     KapaSendLabel (kapa, "radius", KAPA_LABEL_XM);
    243     KapaSendLabel (kapa, "ratio", KAPA_LABEL_YM);
    244 
    245     graphdata.color = KapaColorByName ("black");
    246     graphdata.style = 2;
    247     graphdata.ptype = 0;
    248     graphdata.size = 1.0;
    249     graphdata.etype = 0x01;
    250     KapaPrepPlot (kapa, refRadius->n, &graphdata);
    251     KapaPlotVector (kapa, refRadius->n, refRadius->data.F32, "x");
    252     KapaPlotVector (kapa, refRadius->n, petRatio->data.F32, "y");
    253     KapaPlotVector (kapa, refRadius->n, petRatioErr->data.F32, "dym");
    254     KapaPlotVector (kapa, refRadius->n, petRatioErr->data.F32, "dyp");
    255     graphdata.etype = 0;
    256 
    257     graphdata.color = KapaColorByName ("red");
    258     graphdata.style = 2;
    259382    graphdata.ptype = 2;
    260     graphdata.size = 2.0;
    261     KapaPrepPlot   (kapa, 1, &graphdata);
    262     KapaPlotVector (kapa, 1, &petRadius, "x");
    263     KapaPlotVector (kapa, 1, &ratioForRadius, "y");
    264 
    265     // *** section 3: radius vs integrated flux
    266     section.dx = 1.00;
    267     section.dy = 0.33;
    268     section.x  = 0.00;
    269     section.y  = 0.66;
    270     section.name = psStringCopy ("flux");
    271     KapaSetSection (kapa, &section);
    272     psFree (section.name);
    273 
    274     graphdata.color = KapaColorByName ("black");
    275     pmVisualLimitsFromVectors (&graphdata, radBin, fluxSum);
    276     KapaSetLimits (kapa, &graphdata);
    277 
    278     KapaBox (kapa, &graphdata);
    279     KapaSendLabel (kapa, "radius", KAPA_LABEL_XM);
    280     KapaSendLabel (kapa, "integrated flux", KAPA_LABEL_YM);
    281 
    282     graphdata.color = KapaColorByName ("black");
    283     graphdata.style = 2;
    284     graphdata.ptype = 0;
    285     graphdata.size = 1.0;
    286     KapaPrepPlot   (kapa, refRadius->n, &graphdata);
    287     KapaPlotVector (kapa, refRadius->n, refRadius->data.F32, "x");
    288     KapaPlotVector (kapa, refRadius->n, fluxSum->data.F32, "y");
    289 
    290     graphdata.color = KapaColorByName ("red");
    291     graphdata.ptype = 2;
    292     graphdata.style = 2;
    293     graphdata.size = 2.0;
    294     KapaPrepPlot   (kapa, 1, &graphdata);
    295     KapaPlotVector (kapa, 1, &radiusForFlux, "x");
    296     KapaPlotVector (kapa, 1, &petFlux, "y");
     383    graphdata.size = 1.0;
     384    KapaPrepPlot (kapa, Rx->n, &graphdata);
     385    KapaPlotVector (kapa, Rx->n, Rx->data.F32, "x");
     386    KapaPlotVector (kapa, Rx->n, Ry->data.F32, "y");
     387
     388    graphdata.color = KapaColorByName ("black");
     389    graphdata.style = 0;
     390    graphdata.ptype = 0;
     391    graphdata.size = 1.0;
     392    KapaPrepPlot (kapa, rx->n, &graphdata);
     393    KapaPlotVector (kapa, rx->n, rx->data.F32, "x");
     394    KapaPlotVector (kapa, rx->n, ry->data.F32, "y");
    297395
    298396    // pause and wait for user input:
     
    306404}
    307405
    308 bool psphotPetrosianVisualEllipticalContour (pmPetrosian *petrosian) {
    309 
    310     Graphdata graphdata;
    311 
    312     if (!pmVisualIsVisual()) return true;
    313 
    314     if (kapa == -1) {
    315         kapa = KapaOpenNamedSocket ("kapa", "psphot:plots");
    316         if (kapa == -1) {
    317             fprintf (stderr, "failure to open kapa; visual mode disabled\n");
    318             pmVisualSetVisual(false);
    319             return false;
    320         }
    321     }
    322 
    323     KapaClearPlots (kapa);
    324     KapaInitGraph (&graphdata);
    325     KapaSetFont (kapa, "courier", 14);
    326 
    327     psVector *theta = petrosian->theta;
    328     psVector *radius = petrosian->isophotalRadii;
    329 
    330     // find Rmin and Rmax for the initial guess
    331     float Rmin = radius->data.F32[0];
    332     float Rmax = radius->data.F32[0];
    333 
    334     psVector *Rx = psVectorAlloc(radius->n, PS_TYPE_F32);
    335     psVector *Ry = psVectorAlloc(radius->n, PS_TYPE_F32);
    336 
    337     for (int i = 0; i < theta->n; i++) {
    338         Rx->data.F32[i] = radius->data.F32[i]*cos(theta->data.F32[i]);
    339         Ry->data.F32[i] = radius->data.F32[i]*sin(theta->data.F32[i]);
    340 
    341         // check the radius range
    342         Rmin = MIN (Rmin, radius->data.F32[i]);
    343         Rmax = MAX (Rmax, radius->data.F32[i]);
    344     }   
    345 
    346     psVector *rx = psVectorAlloc(361, PS_TYPE_F32);
    347     psVector *ry = psVectorAlloc(361, PS_TYPE_F32);
    348 
    349     float epsilon = petrosian->axes.minor / petrosian->axes.major;
    350 
    351     for (int i = 0; i < 361; i++) {
    352 
    353         float alpha = PS_RAD_DEG * i;
    354 
    355         float cs_alpha = cos(alpha);
    356         float sn_alpha = sin(alpha);
    357 
    358         float cs_phi = cos(alpha - petrosian->axes.theta);
    359         float sn_phi = sin(alpha - petrosian->axes.theta);
    360 
    361         float r = 1.0 / sqrt(SQ(sn_phi) + SQ(epsilon*cs_phi));
    362 
    363         // generate the model fit here
    364         rx->data.F32[i] = petrosian->axes.minor * cs_alpha * r;
    365         ry->data.F32[i] = petrosian->axes.minor * sn_alpha * r;
    366     }   
    367 
    368     graphdata.color = KapaColorByName ("black");
    369     graphdata.xmin = -1.1*Rmax;
    370     graphdata.ymin = -1.1*Rmax;
    371     graphdata.xmax = +1.1*Rmax;
    372     graphdata.ymax = +1.1*Rmax;
    373     KapaSetLimits (kapa, &graphdata);
    374 
    375     KapaBox (kapa, &graphdata);
    376     KapaSendLabel (kapa, "R_x", KAPA_LABEL_XM);
    377     KapaSendLabel (kapa, "R_y", KAPA_LABEL_YM);
    378 
    379     graphdata.color = KapaColorByName ("red");
    380     graphdata.style = 2;
    381     graphdata.ptype = 2;
    382     graphdata.size = 1.0;
    383     KapaPrepPlot (kapa, Rx->n, &graphdata);
    384     KapaPlotVector (kapa, Rx->n, Rx->data.F32, "x");
    385     KapaPlotVector (kapa, Rx->n, Ry->data.F32, "y");
    386 
    387     graphdata.color = KapaColorByName ("black");
    388     graphdata.style = 0;
    389     graphdata.ptype = 0;
    390     graphdata.size = 1.0;
    391     KapaPrepPlot (kapa, rx->n, &graphdata);
    392     KapaPlotVector (kapa, rx->n, rx->data.F32, "x");
    393     KapaPlotVector (kapa, rx->n, ry->data.F32, "y");
    394 
    395     // pause and wait for user input:
    396     // continue, save (provide name), ??
    397     char key[10];
    398     fprintf (stdout, "[c]ontinue? ");
    399     if (!fgets(key, 8, stdin)) {
    400         psWarning("Unable to read option");
    401     }
    402     return true;
    403 }
    404 
    405406# endif
  • branches/tap_branches/psphot/src/psphotRadialProfile.c

    r25755 r27838  
    33bool psphotRadialProfile (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal) {
    44
     5    bool status;
     6
    57    // allocate pmSourceExtendedParameters, if not already defined
    68    if (!source->extpars) {
    79        source->extpars = pmSourceExtendedParsAlloc ();
    8     }
    9 
    10     if (!source->extpars->profile) {
    11         source->extpars->profile = pmSourceRadialProfileAlloc ();
    1210    }
    1311
     
    1715    float fluxMin = 0.0;
    1816    float fluxMax = source->peak->flux;
     17
     18    bool RAW_RADIUS = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_RAW_RADIUS");
    1919
    2020    // generate a series of radial profiles at Nsec evenly spaced angles.  the profile flux
     
    2828    // use the radial profiles to determine the radius of a given isophote.  this isophote
    2929    // is used to determine the elliptical shape of the object, so it has a relatively high
    30     // value (nominally 50% of the peak)
     30    // value (nominally 25% of the peak)
    3131    if (!psphotRadiiFromProfiles (source, fluxMin, fluxMax)) {
    3232        psError (PS_ERR_UNKNOWN, false, "failed to measure isophotal radii from profiles");
     
    4242    // generate a single, normalized radial profile following the elliptical contours.
    4343    // the radius is normalized by the axis ratio so that on the major axis, 1 pixel = 1 pixel
    44     if (!psphotEllipticalProfile (source)) {
     44    if (!psphotEllipticalProfile (source, RAW_RADIUS)) {
    4545        psError (PS_ERR_UNKNOWN, false, "failed to generate elliptical profile");
     46        return false;
     47    }
     48 
     49    // generated profile in averaged bins
     50    if (!psphotRadialBins (recipe, source, Rmax, skynoise)) {
     51        psError (PS_ERR_UNKNOWN, false, "failed to generate radial bins");
    4652        return false;
    4753    }
  • branches/tap_branches/psphot/src/psphotRadialProfileByAngles.c

    r25755 r27838  
    1212bool psphotRadialProfilesByAngles (pmSource *source, int Nsec, float Rmax) {
    1313
     14    psAssert (source->extpars, "define extpars");
     15
    1416    // we want to have an even number of sectors so we can do 180 deg symmetrizing
    1517    Nsec = (Nsec % 2) ? Nsec + 1 : Nsec;
    1618    float dtheta = 2.0*M_PI / Nsec;
    1719
    18     pmSourceRadialProfile *profile = source->extpars->profile;
     20    if (!source->extpars->radFlux) {
     21        source->extpars->radFlux = pmSourceRadialFluxAlloc();
     22    }
     23    pmSourceRadialFlux *profile = source->extpars->radFlux;
    1924    psFree(profile->radii);
    2025    psFree(profile->fluxes);
     
    2429    profile->fluxes = psArrayAllocEmpty(Nsec);
    2530    profile->theta = psVectorAllocEmpty(Nsec, PS_TYPE_F32);
    26 
    2731
    2832    for (int i = 0; i < Nsec; i++) {
  • branches/tap_branches/psphot/src/psphotRadiiFromProfiles.c

    r25755 r27838  
    55bool psphotRadiiFromProfiles (pmSource *source, float fluxMin, float fluxMax) {
    66
    7     pmSourceRadialProfile *profile = source->extpars->profile;
     7    psAssert (source, "missing source");
     8    psAssert (source->extpars, "missing extpars");
     9    psAssert (source->extpars->radFlux, "missing radFlux");
     10
     11    pmSourceRadialFlux *profile = source->extpars->radFlux;
    812
    913    psFree(profile->isophotalRadii);
     
    146150
    147151    // show the results
    148     // psphotPetrosianVisualProfileRadii (radius, flux, radiusBinned, fluxBinned, Ro);
     152    // psphotPetrosianVisualProfileRadii (radius, flux, radiusBinned, fluxBinned, fluxMax, Ro);
    149153
    150154    psFree(fluxBinned);
     
    152156    return Ro;
    153157}
     158
     159
     160
  • branches/tap_branches/psphot/src/psphotRadiusChecks.c

    r25755 r27838  
    44static float PSF_FIT_NSIGMA;
    55static float PSF_FIT_PADDING;
     6static float PSF_APERTURE = 0;  // radius to use in PSF aperture mags
    67static float PSF_FIT_RADIUS = 0;        // radius to use in fitting (ignored if <= 0,
    78                                        // and a per-object radius is calculated)
    89
    9 static float PSF_APERTURE = 0;  // radius to use in PSF aperture mags
    10 
    11 
    12 bool psphotInitRadiusPSF(const psMetadata *recipe, const pmModelType type) {
     10bool psphotInitRadiusPSF(const psMetadata *recipe, const psMetadata *analysis, const pmModelType type) {
    1311
    1412    bool status = true;
    1513
    16     PSF_FIT_NSIGMA  = psMetadataLookupF32(&status, recipe, "PSF_FIT_NSIGMA");
     14    PSF_FIT_NSIGMA = psMetadataLookupF32(&status, recipe, "PSF_FIT_NSIGMA");
    1715    PSF_FIT_PADDING = psMetadataLookupF32(&status, recipe, "PSF_FIT_PADDING");
    18     PSF_FIT_RADIUS  =  psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS");
    19     PSF_APERTURE    =  psMetadataLookupF32(&status, recipe, "PSF_APERTURE");
     16
     17    PSF_FIT_RADIUS =  psMetadataLookupF32(&status, analysis, "PSF_FIT_RADIUS");
     18    if (!status) {
     19        PSF_FIT_RADIUS = psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS");
     20    }
     21
     22    PSF_APERTURE =  psMetadataLookupF32(&status, analysis, "PSF_APERTURE");
     23    if (!status) {
     24        PSF_APERTURE =  psMetadataLookupF32(&status, recipe, "PSF_APERTURE");
     25    }
    2026
    2127    return true;
  • branches/tap_branches/psphot/src/psphotReadout.c

    r25755 r27838  
    33// this should be called by every program that links against libpsphot
    44bool psphotInit (void) {
    5 
    65    psphotErrorRegister();              // register our error codes/messages
    76    psphotModelClassInit ();            // load implementation-specific models
     
    1211bool psphotReadout(pmConfig *config, const pmFPAview *view) {
    1312
    14     // measure the total elapsed time in psphotReadout.  XXX the current threading plan
    15     // for psphot envisions threading within psphotReadout, not multiple threads calling
    16     // the same psphotReadout.  In the current plan, this dtime is the elapsed time used
    17     // jointly by the multiple threads, not the total time used by all threads.
     13    // measure the total elapsed time in psphotReadout.  dtime is the elapsed time used jointly
     14    // by the multiple threads, not the total time used by all threads.
    1815    psTimerStart ("psphotReadout");
    1916
     
    2623        return false;
    2724    }
     25    // optional break-point for processing
     26    char *breakPt = psMetadataLookupStr (NULL, recipe, "BREAK_POINT");
     27    psAssert (breakPt, "configuration error: set BREAK_POINT");
    2828
    2929    // set the photcode for this image
    30     if (!psphotAddPhotcode (recipe, config, view, "PSPHOT.INPUT")) {
     30    if (!psphotAddPhotcode (config, view)) {
    3131        psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
    3232        return false;
    3333    }
    3434
    35     // find the currently selected readout
    36     pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
    37     PS_ASSERT_PTR_NON_NULL (readout, false);
    38 
    39     // optional break-point for processing
    40     char *breakPt = psMetadataLookupStr (NULL, recipe, "BREAK_POINT");
    41     PS_ASSERT_PTR_NON_NULL (breakPt, false);
    42 
    4335    // Generate the mask and weight images, including the user-defined analysis region of interest
    44     psphotSetMaskAndVariance (config, readout, recipe);
     36    if (!psphotSetMaskAndVariance (config, view)) {
     37        return psphotReadoutCleanup(config, view);
     38    }
    4539    if (!strcasecmp (breakPt, "NOTHING")) {
    46         return psphotReadoutCleanup(config, readout, recipe, NULL, NULL, NULL);
    47     }
    48 
    49     // display the image, weight, mask (ch 1,2,3)
    50     psphotVisualShowImage (readout);
     40        return psphotReadoutCleanup(config, view);
     41    }
    5142
    5243    // generate a background model (median, smoothed image)
    53     if (!psphotModelBackground (config, view, "PSPHOT.INPUT")) {
    54         return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
    55     }
    56     if (!psphotSubtractBackground (config, view, "PSPHOT.INPUT")) {
    57         return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
     44    if (!psphotModelBackground (config, view)) {
     45        return psphotReadoutCleanup (config, view);
     46    }
     47    if (!psphotSubtractBackground (config, view)) {
     48        return psphotReadoutCleanup (config, view);
    5849    }
    5950    if (!strcasecmp (breakPt, "BACKMDL")) {
    60         return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
    61     }
    62 
    63     // display the backsub and backgnd images
    64     psphotVisualShowBackground (config, view, readout);
    65 
    66     // run a single-model test if desired (exits from here if test is run)
    67     psphotModelTest (config, view, recipe);
    68 
    69     // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are saved in the recipe
    70     pmPSF *psf = psphotLoadPSF (config, view, recipe);
    71 
    72     // several functions below behave differently if we have a PSF model already
    73     bool havePSF = (psf != NULL);
     51        return psphotReadoutCleanup (config, view);
     52    }
     53
     54    // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are determined and saved on
     55    // readout->analysis XXX this function currently only works with a single PSPHOT.INPUT
     56    if (!psphotLoadPSF (config, view)) {
     57        psError (PSPHOT_ERR_UNKNOWN, false, "error loading psf model");
     58        return psphotReadoutCleanup (config, view);
     59    }
    7460
    7561    // find the detections (by peak and/or footprint) in the image.
    76     pmDetections *detections = psphotFindDetections (NULL, readout, recipe);
    77     if (!detections) {
    78         psLogMsg ("psphot", 3, "unable to find detections in this image");
    79         return psphotReadoutCleanup (config, readout, recipe, detections, psf, NULL);
    80     }
    81 
    82     // construct sources and measure basic stats
    83     psArray *sources = psphotSourceStats (config, readout, detections, true);
    84     if (!sources) return false;
     62    if (!psphotFindDetections (config, view, true)) { // pass 1
     63        // this only happens if we had an error in psphotFindDetections
     64        psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
     65        return psphotReadoutCleanup (config, view);
     66    }
     67
     68    // construct sources and measure basic stats (saved on detections->newSources)
     69    if (!psphotSourceStats (config, view, true)) { // pass 1
     70        psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
     71        return psphotReadoutCleanup (config, view);
     72    }
    8573    if (!strcasecmp (breakPt, "PEAKS")) {
    86         return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
    87     }
    88 
    89     // find blended neighbors of very saturated stars
    90     // XXX merge this with Basic Deblend?
    91     psphotDeblendSatstars (readout, sources, recipe);
    92 
    93     // mark blended peaks PS_SOURCE_BLEND
    94     if (!psphotBasicDeblend (sources, recipe)) {
    95         psLogMsg ("psphot", 3, "failed on deblend analysis");
    96         return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
    97     }
    98 
    99     // classify sources based on moments, brightness
    100     if (!psphotRoughClass (readout, sources, recipe, havePSF)) {
    101         psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
    102         return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     74        return psphotReadoutCleanup(config, view);
     75    }
     76
     77    // find blended neighbors of very saturated stars (detections->newSources)
     78    if (!psphotDeblendSatstars (config, view)) {
     79        psError (PSPHOT_ERR_UNKNOWN, false, "failed on satstar deblend analysis");
     80        return psphotReadoutCleanup (config, view);
     81    }
     82
     83    // mark blended peaks PS_SOURCE_BLEND (detections->newSources)
     84    if (!psphotBasicDeblend (config, view)) {
     85        psError (PSPHOT_ERR_UNKNOWN, false, "failed on deblend analysis");
     86        return psphotReadoutCleanup (config, view);
     87    }
     88
     89    // classify sources based on moments, brightness.  if a PSF model has been loaded, the PSF
     90    // clump defined for it is used not measured (detections->newSources)
     91    if (!psphotRoughClass (config, view)) { // pass 1
     92        psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough classifications");
     93        return psphotReadoutCleanup (config, view);
     94    }
     95    // if we were not supplied a PSF model, determine the IQ stats here (detections->newSources)
     96    if (!psphotImageQuality (config, view)) { // pass 1
     97        psError (PSPHOT_ERR_UNKNOWN, false, "failed to measure image quality");
     98        return psphotReadoutCleanup(config, view);
    10399    }
    104100    if (!strcasecmp (breakPt, "MOMENTS")) {
    105         return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
    106     }
    107 
    108     if (!havePSF && !psphotImageQuality (recipe, sources)) {
    109         psLogMsg("psphot", 3, "failed to measure image quality");
    110         return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
    111     }
    112 
    113     // if we were not supplied a PSF, choose one here
    114     if (psf == NULL) {
    115         // use bright stellar objects to measure PSF
    116         // XXX if we do not have enough stars to generate the PSF, build one
    117         // from the SEEING guess and model class
    118         psf = psphotChoosePSF (readout, sources, recipe);
    119         if (psf == NULL) {
    120             psLogMsg ("psphot", 3, "failure to construct a psf model");
    121             return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
    122         }
    123         havePSF = true;
     101        return psphotReadoutCleanup(config, view);
     102    }
     103
     104    // use bright stellar objects to measure PSF if we were supplied a PSF for any input file,
     105    // this step is skipped
     106    if (!psphotChoosePSF (config, view)) { // pass 1
     107        psLogMsg ("psphot", 3, "failure to construct a psf model");
     108        return psphotReadoutCleanup (config, view);
    124109    }
    125110    if (!strcasecmp (breakPt, "PSFMODEL")) {
    126         return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
    127     }
    128     psphotVisualShowPSFModel (readout, psf);
     111        return psphotReadoutCleanup (config, view);
     112    }
    129113
    130114    // include externally-supplied sources
    131     psphotLoadExtSources (config, view, sources);
    132 
    133     // construct an initial model for each object, set the radius to fitRadius, set circular fit mask
    134     psphotGuessModels (config, readout, sources, psf);
     115    // XXX fix this in the new multi-input context
     116    // psphotLoadExtSources (config, view); // pass 1
     117
     118    // construct an initial model for each object, set the radius to fitRadius, set circular
     119    // fit mask (detections->newSources)
     120    psphotGuessModels (config, view); // pass 1
     121
     122    // merge the newly selected sources into the existing list
     123    // NOTE: merge OLD and NEW
     124    psphotMergeSources (config, view);
    135125
    136126    // linear PSF fit to source peaks, subtract the models from the image (in PSF mask)
    137     psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE);
    138 
    139     // We have to place these visualizations here because the models are not realized until
    140     // psphotGuessModels or fitted until psphotFitSourcesLinear.
    141     psphotVisualShowPSFStars (recipe, psf, sources);
    142 
    143     // identify CRs and extended sources
    144     psphotSourceSize (config, readout, sources, recipe, psf, 0);
     127    psphotFitSourcesLinear (config, view, false); // pass 1 (detections->allSources)
     128
     129    // identify CRs and extended sources (only unmeasured sources are measured)
     130    psphotSourceSize (config, view, true); // pass 1 (detections->allSources)
    145131    if (!strcasecmp (breakPt, "ENSEMBLE")) {
    146132        goto finish;
    147133    }
    148     psphotVisualShowSatStars (recipe, psf, sources);
    149134
    150135    // non-linear PSF and EXT fit to brighter sources
    151136    // replace model flux, adjust mask as needed, fit, subtract the models (full stamp)
    152     psphotBlendFit (config, readout, sources, psf);
     137    psphotBlendFit (config, view); // pass 1 (detections->allSources)
    153138
    154139    // replace all sources
    155     psphotReplaceAllSources (sources, recipe);
     140    psphotReplaceAllSources (config, view); // pass 1 (detections->allSources)
    156141
    157142    // linear fit to include all sources (subtract again)
    158     psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE);
     143    // NOTE : apply to ALL sources (extended + psf)
     144    psphotFitSourcesLinear (config, view, true); // pass 2 (detections->allSources)
    159145
    160146    // if we only do one pass, skip to extended source analysis
    161     if (!strcasecmp (breakPt, "PASS1")) {
    162         goto pass1finish;
    163     }
    164     // NOTE: possibly re-measure background model here with objects subtracted
     147    if (!strcasecmp (breakPt, "PASS1")) goto pass1finish;
     148
     149    // NOTE: possibly re-measure background model here with objects subtracted / or masked
    165150
    166151    // add noise for subtracted objects
    167     psphotAddNoise (readout, sources, recipe);
    168 
    169     // find fainter sources (pass 2)
    170     detections = psphotFindDetections (detections, readout, recipe);
     152    psphotAddNoise (config, view); // pass 1 (detections->allSources)
     153
     154    // find fainter sources
     155    // NOTE: finds new peaks and new footprints, OLD and FULL set are saved on detections
     156    psphotFindDetections (config, view, false); // pass 2 (detections->peaks, detections->footprints)
    171157
    172158    // remove noise for subtracted objects (ie, return to normal noise level)
    173     psphotSubNoise (readout, sources, recipe);
     159    // NOTE: this needs to operate only on the OLD sources
     160    psphotSubNoise (config, view); // pass 1 (detections->allSources)
    174161
    175162    // define new sources based on only the new peaks
    176     psArray *newSources = psphotSourceStats (config, readout, detections, false);
     163    // NOTE: new sources are saved on detections->newSources
     164    psphotSourceStats (config, view, false); // pass 2 (detections->newSources)
    177165
    178166    // set source type
    179     if (!psphotRoughClass (readout, newSources, recipe, havePSF)) {
     167    // NOTE: apply only to detections->newSources
     168    if (!psphotRoughClass (config, view)) { // pass 2 (detections->newSources)
    180169        psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
    181         return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     170        return psphotReadoutCleanup (config, view);
    182171    }
    183172
    184173    // create full input models, set the radius to fitRadius, set circular fit mask
    185     psphotGuessModels (config, readout, newSources, psf);
     174    // NOTE: apply only to detections->newSources
     175    psphotGuessModels (config, view); // pass 2 (detections->newSources)
    186176
    187177    // replace all sources so fit below applies to all at once
    188     psphotReplaceAllSources (sources, recipe);
     178    // NOTE: apply only to OLD sources (which have been subtracted)
     179    psphotReplaceAllSources (config, view); // pass 2
    189180
    190181    // merge the newly selected sources into the existing list
    191     psphotMergeSources (sources, newSources);
    192     psFree (newSources);
    193 
    194     // linear fit to all sources
    195     psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE);
     182    // NOTE: merge OLD and NEW
     183    // XXX check on free of sources...
     184    psphotMergeSources (config, view); // (detections->newSources + detections->allSources -> detections->allSources)
     185
     186    // NOTE: apply to ALL sources
     187    psphotFitSourcesLinear (config, view, true); // pass 3 (detections->allSources)
    196188
    197189pass1finish:
    198190
    199191    // measure source size for the remaining sources
    200     psphotSourceSize (config, readout, sources, recipe, psf, 0);
    201 
    202     psphotExtendedSourceAnalysis (readout, sources, recipe);
    203 
    204     psphotExtendedSourceFits (readout, sources, recipe);
     192    // NOTE: applies only to NEW (unmeasured) sources
     193    psphotSourceSize (config, view, false); // pass 2 (detections->allSources)
     194
     195    psphotExtendedSourceAnalysis (config, view); // pass 1 (detections->allSources)
     196    psphotExtendedSourceFits (config, view); // pass 1 (detections->allSources)
    205197
    206198finish:
     
    210202
    211203    // measure aperture photometry corrections
    212     if (!psphotApResid (config, readout, sources, psf)) {
     204    if (!psphotApResid (config, view)) { // pass 1 (detections->allSources)
    213205        psLogMsg ("psphot", 3, "failed on psphotApResid");
    214         return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     206        return psphotReadoutCleanup (config, view);
    215207    }
    216208
    217209    // calculate source magnitudes
    218     psphotMagnitudes(config, readout, view, sources, psf);
    219 
    220     if (!psphotEfficiency(config, readout, view, psf, recipe, sources)) {
     210    psphotMagnitudes(config, view); // pass 1 (detections->allSources)
     211
     212    if (!psphotEfficiency(config, view)) { // pass 1
    221213        psErrorStackPrint(stderr, "Unable to determine detection efficiencies from fake sources");
    222214        psErrorClear();
     
    227219
    228220    // replace background in residual image
    229     psphotSkyReplace (config, view);
     221    psphotSkyReplace (config, view); // pass 1
    230222
    231223    // drop the references to the image pixels held by each source
    232     psphotSourceFreePixels (sources);
     224    psphotSourceFreePixels (config, view); // pass 1
    233225
    234226    // create the exported-metadata and free local data
    235     return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
     227    return psphotReadoutCleanup(config, view);
    236228}
    237 
  • branches/tap_branches/psphot/src/psphotReadoutCleanup.c

    r24203 r27838  
    11# include "psphotInternal.h"
    22
    3 // psphotReadoutCleanup is called on exit from psphotReadout.  If the last raised error is
    4 // not a DATA error, then there was a serious problem.  Only in this case, or if the fail
    5 // on the stats measurement, do we return false
    6 bool psphotReadoutCleanup (pmConfig *config, pmReadout *readout, psMetadata *recipe, pmDetections *detections, pmPSF *psf, psArray *sources) {
     3// for now, let's store the detections on the readout->analysis for each readout
     4bool psphotReadoutCleanup (pmConfig *config, const pmFPAview *view)
     5{
     6    bool status = true;
    77
    88    // remove internal pmFPAfiles, if created
     
    1212    }
    1313    if (psErrorCodeLast() != PS_ERR_NONE) {
    14         psFree (psf);
    15         psFree (sources);
    16         psFree (detections);
    1714        return false;
    1815    }
    1916
     17    // select the appropriate recipe information
     18    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     19    psAssert (recipe, "missing recipe?");
     20
     21    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     22    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     23
     24    // loop over the available readouts
     25    for (int i = 0; i < num; i++) {
     26        if (!psphotReadoutCleanupReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     27            psError (PSPHOT_ERR_CONFIG, false, "failed on psphotReadoutCleanup for PSPHOT.INPUT entry %d", i);
     28            return false;
     29        }
     30    }
     31
     32    // XXX move this to top of loop?
     33    pmKapaClose ();
     34
     35    return true;
     36}
     37
     38// psphotReadoutCleanup is called on exit from psphotReadout.  If the last raised error is
     39// not a DATA error, then there was a serious problem.  Only in this case, or if the fail
     40// on the stats measurement, do we return false
     41bool psphotReadoutCleanupReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {
     42
     43    bool status = true;
     44
     45    // find the currently selected readout
     46    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     47    psAssert (file, "missing file?");
     48
     49    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     50    psAssert (readout, "missing readout?");
     51
     52    // when psphotReadoutCleanup is called, these are not necessarily defined
     53    pmPSF        *psf        = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
     54    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     55    psArray      *sources    = detections ? detections->allSources : NULL;
     56    // XXX where do we free these, in here (psMetadataRemove?)
     57
    2058    // use the psf-model to measure FWHM stats
    2159    if (psf) {
    22         if (!psphotPSFstats (readout, recipe, psf)) {
     60        if (!psphotPSFstats (readout, psf)) {
    2361            psError(PSPHOT_ERR_PROG, false, "Failed to measure PSF shape parameters");
    24             psFree (psf);
    25             psFree (sources);
    26             psFree (detections);
    2762            return false;
    2863        }
     
    3065    // otherwise, use the source moments to measure FWHM stats
    3166    if (!psf && sources) {
    32         if (!psphotMomentsStats (readout, recipe, sources)) {
     67        if (!psphotMomentsStats (readout, sources)) {
    3368            psError(PSPHOT_ERR_PROG, false, "Failed to measure Moment shape parameters");
    34             psFree (psf);
    35             psFree (sources);
    36             psFree (detections);
    3769            return false;
    3870        }
     
    4072
    4173    // Check to see if the image quality was measured
    42     if (!psf) {
     74    // XXX not sure we want / need this test
     75    if (0 && !psf) {
    4376        bool mdok;                      // Status of MD lookup
    4477        int nIQ = psMetadataLookupS32(&mdok, recipe, "IQ_NSTAR"); // Number of stars for IQ measurement
    4578        if (!mdok || nIQ <= 0) {
    4679            psError(PSPHOT_ERR_DATA, false, "Unable to measure image quality");
    47             psFree (psf);
    48             psFree (sources);
    49             psFree (detections);
    5080            return false;
    5181        }
    5282    }
    5383
     84    // create an output header with stats results currently saved on readout->analysis
     85    psMetadata *header = psphotDefineHeader (readout->analysis);
    5486
    5587    // write NSTARS to the image header
    56     psphotSetHeaderNstars (recipe, sources);
    57 
    58     // create an output header with stats results
    59     psMetadata *header = psphotDefineHeader (recipe);
     88    psphotSetHeaderNstars (header, sources);
    6089
    6190    // save the results of the analysis
     91    // this should happen way up stream (when needed?)
    6292    psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.HEADER",  PS_DATA_METADATA, "header stats", header);
    63     if (sources) {
    64         psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY, "psphot sources", sources);
    65     }
     93
    6694    if (psf) {
     95        // XXX this seems a little silly : we saved the psf on readout->analysis above, but now
     96        // we are moving it to chip->analysis.
    6797        // save the psf for possible output.  if there was already an entry, it was loaded from external sources
    6898        // the new one may have been updated or modified, so replace the existing entry.  We
     
    79109    }
    80110
    81     // XXX move this to top of loop?
    82     pmKapaClose ();
    83 
    84     psFree (detections);
    85     psFree (psf);
    86111    psFree (header);
    87     psFree (sources);
    88 
    89112    return true;
    90113}
  • branches/tap_branches/psphot/src/psphotReadoutFindPSF.c

    r25755 r27838  
    77    psTimerStart ("psphotReadout");
    88
    9     // select the current recipe
    10     psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
    11     if (!recipe) {
    12         psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
    13         return false;
    14     }
    15 
    16     // set the photcode for this image
    17     if (!psphotAddPhotcode(recipe, config, view, "PSPHOT.INPUT")) {
     9    // set the photcode for the PSPHOT.INPUT
     10    if (!psphotAddPhotcode(config, view)) {
    1811        psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
    1912        return false;
    2013    }
    2114
    22     // find the currently selected readout
    23     pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
    24     PS_ASSERT_PTR_NON_NULL (readout, false);
    25 
    2615    // Generate the mask and variance images, including the user-defined analysis region of interest
    27     psphotSetMaskAndVariance (config, readout, recipe);
    28 
    29     // display the image, weight, mask (ch 1,2,3)
    30     psphotVisualShowImage (readout);
     16    psphotSetMaskAndVariance (config, view);
    3117
    3218    // Note that in this implementation, we do NOT model the background and we do not
     
    3420
    3521    // include externally-supplied sources (supplied as PSPHOT.INPUT.CMF)
    36     pmDetections *detections = psphotDetectionsFromSources (config, inSources);
    37     if (!detections || !detections->peaks) {
     22    // XXX we assume a single set of input sources is supplied
     23    if (!psphotDetectionsFromSources (config, view, inSources)) {
    3824        psError(PSPHOT_ERR_ARGUMENTS, true, "Can't find PSF stars");
    39         return psphotReadoutCleanup(config, readout, recipe, detections, NULL, NULL);
     25        return psphotReadoutCleanup(config, view);
    4026    }
    4127
    42     // construct sources and measure basic stats (moments, local sky)
    43     psArray *sources = psphotSourceStats(config, readout, detections, true);
    44     if (!sources) return false;
     28    // construct detections->newSources and measure basic stats (moments, local sky)
     29    if (!psphotSourceStats(config, view, true)) {
     30        psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
     31        return false;
     32    }
    4533
    46     // peak flux is wrong : set based on previous image
    47     // use the peak measured in the moments analysis:
    48     for (int i = 0; i < sources->n; i++) {
    49       pmSource *source = sources->data[i];
    50       source->peak->flux = source->moments->Peak;
     34    // peak flux is wrong : use the peak measured in the moments analysis:
     35    if (!psphotRepairLoadedSources(config, view)) {
     36        psError(PSPHOT_ERR_UNKNOWN, false, "failure to repair sources");
     37        return false;
    5138    }
    5239
    5340    // classify sources based on moments, brightness (psf is not known)
    54     if (!psphotRoughClass (readout, sources, recipe, false)) {
    55         psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
    56         return psphotReadoutCleanup (config, readout, recipe, detections, NULL, sources);
     41    if (!psphotRoughClass (config, view)) {
     42        psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough source class");
     43        return psphotReadoutCleanup (config, view);
    5744    }
    5845
    59     pmPSF *psf = psphotChoosePSF(readout, sources, recipe);
    60     if (!psf) {
     46    if (!psphotImageQuality (config, view)) {
     47        psError (PSPHOT_ERR_UNKNOWN, false, "failed to measure image quality");
     48        return psphotReadoutCleanup(config, view);
     49    }
     50
     51    if (!psphotChoosePSF(config, view)) {
    6152        psError(PSPHOT_ERR_PSF, false, "Failed to construct a psf model");
    62         psFree(sources);
    63         return psphotReadoutCleanup(config, readout, recipe, detections, NULL, NULL);
     53        return psphotReadoutCleanup(config, view);
    6454    }
    65     psphotVisualShowPSFModel(readout, psf);
     55
     56# if 0
     57    // XXX if we want to determine the aperture residual correction here, we either
     58    // need to carry it out of the PSF determination analysis above, or save the model
     59    // fits from that analysis, or run the linear PSF fit for all objects currently in hand
     60    // construct an initial model for each object, set the radius to fitRadius, set circular fit mask
     61    psphotGuessModels (config, view);
     62# endif
     63
     64    // merge the newly selected sources into the existing list
     65    // NOTE: merge OLD and NEW
     66    psphotMergeSources (config, view);
     67
     68# if 0
     69    // measure aperture photometry corrections
     70    if (!psphotApResid (config, view)) {
     71        psLogMsg ("psphot", 3, "failed on psphotApResid");
     72        return psphotReadoutCleanup (config, view);
     73    }
     74# endif
    6675
    6776    // drop the references to the image pixels held by each source
    68     psphotSourceFreePixels(sources);
    69     psFree(sources);
     77    psphotSourceFreePixels(config, view);
    7078
    7179    // create the exported-metadata and free local data
    72     return psphotReadoutCleanup(config, readout, recipe, detections, psf, NULL);
     80    return psphotReadoutCleanup(config, view);
    7381}
  • branches/tap_branches/psphot/src/psphotReadoutKnownSources.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
    3 // in this psphotReadout-variant, we are only measuring the photometry for known sources,
    4 // using a PSF generated from this observation those sources
     3// in this psphotReadout-variant, we are only measuring the photometry for known sources, using
     4// a PSF generated for this observation from those sources
    55bool psphotReadoutKnownSources(pmConfig *config, const pmFPAview *view, psArray *inSources) {
    66
    77    psTimerStart ("psphotReadout");
    88
    9     // select the current recipe
    10     psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
    11     if (!recipe) {
    12         psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
    13         return false;
    14     }
    15 
    169    // set the photcode for this image
    17     if (!psphotAddPhotcode(recipe, config, view, "PSPHOT.INPUT")) {
     10    if (!psphotAddPhotcode(config, view)) {
    1811        psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
    1912        return false;
    2013    }
    2114
    22     // find the currently selected readout
    23     pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
    24     PS_ASSERT_PTR_NON_NULL (readout, false);
    25 
    2615    // Generate the mask and weight images, including the user-defined analysis region of interest
    27     psphotSetMaskAndVariance (config, readout, recipe);
    28 
    29     // display the image, weight, mask (ch 1,2,3)
    30     psphotVisualShowImage (readout);
     16    psphotSetMaskAndVariance (config, view);
    3117
    3218    // Note that in this implementation, we do NOT model the background and we do not
     
    3420
    3521    // include externally-supplied sources (supplied as PSPHOT.INPUT.CMF)
    36     pmDetections *detections = psphotDetectionsFromSources (config, inSources);
    37     if (!detections || !detections->peaks) {
     22    if (!psphotDetectionsFromSources (config, view, inSources)) {
    3823        psError(PSPHOT_ERR_ARGUMENTS, true, "Can't find PSF stars");
    39         return psphotReadoutCleanup(config, readout, recipe, detections, NULL, NULL);
     24        return psphotReadoutCleanup(config, view);
    4025    }
    4126
    4227    // construct sources and measure basic stats
    43     psArray *sources = psphotSourceStats (config, readout, detections, true);
    44     if (!sources) return false;
     28    if (!psphotSourceStats (config, view, true)) {
     29        psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
     30        return false;
     31    }
    4532
    46     // peak flux is wrong : set based on previous image
    47     // use the peak measured in the moments analysis:
    48     for (int i = 0; i < sources->n; i++) {
    49         pmSource *source = sources->data[i];
    50         source->peak->flux = source->moments->Peak;
     33    // peak flux is wrong : use the peak measured in the moments analysis:
     34    if (!psphotRepairLoadedSources(config, view)) {
     35        psError(PSPHOT_ERR_UNKNOWN, false, "failure to repair sources");
     36        return false;
    5137    }
    5238
    5339    // classify sources based on moments, brightness (psf is not known)
    54     if (!psphotRoughClass (readout, sources, recipe, false)) {
    55         psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
    56         return psphotReadoutCleanup (config, readout, recipe, detections, NULL, sources);
     40    if (!psphotRoughClass (config, view)) {
     41        psError (PSPHOT_ERR_UNKNOWN, false, "failed to determine rough source class");
     42        return psphotReadoutCleanup(config, view);
    5743    }
    5844
    59     pmPSF *psf = psphotChoosePSF (readout, sources, recipe);
    60     if (!psf) {
    61         psLogMsg ("psphot", 3, "failure to construct a psf model");
    62         return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     45    if (!psphotChoosePSF (config, view)) {
     46        psError(PSPHOT_ERR_PSF, false, "Failed to construct a psf model");
     47        return psphotReadoutCleanup(config, view);
    6348    }
    64     psphotVisualShowPSFModel (readout, psf);
    6549
    6650    // construct an initial model for each object
    67     psphotGuessModels (config, readout, sources, psf);
     51    psphotGuessModels (config, view);
     52
     53    // merge the newly selected sources into the existing list
     54    // NOTE: merge OLD and NEW
     55    psphotMergeSources (config, view);
    6856
    6957    // linear PSF fit to source peaks
    70     psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE);
    71 
    72     // We have to place these visualizations here because the models are not realized until
    73     // psphotGuessModels or fitted until psphotFitSourcesLinear.
    74     psphotVisualShowPSFStars (recipe, psf, sources);
    75     psphotVisualShowSatStars (recipe, psf, sources);
     58    psphotFitSourcesLinear (config, view, false);
    7659
    7760    // measure aperture photometry corrections
    78     if (!psphotApResid (config, readout, sources, psf)) {
     61    if (!psphotApResid (config, view)) {
    7962        psLogMsg ("psphot", 3, "failed on psphotApResid");
    80         return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     63        return psphotReadoutCleanup(config, view);
    8164    }
    8265
    8366    // calculate source magnitudes
    84     psphotMagnitudes(config, readout, view, sources, psf);
     67    psphotMagnitudes(config, view);
    8568
    8669    // drop the references to the image pixels held by each source
    87     psphotSourceFreePixels (sources);
     70    psphotSourceFreePixels (config, view);
    8871
    8972    // create the exported-metadata and free local data
    90     return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
     73    return psphotReadoutCleanup(config, view);
    9174}
  • branches/tap_branches/psphot/src/psphotReadoutMinimal.c

    r25755 r27838  
    11# include "psphotInternal.h"
    22
    3 // this badly-named function performs photometry assuming (a) a supplied PSF, (b)
    4 // background subtraction, (c) linear psf-model fits only.  it is currently only being
    5 // used by ppSub.
     3// this badly-named function performs photometry assuming (a) a supplied PSF, (b) background
     4// subtraction, (c) linear psf-model fits only, (d) a prior analysis has supplied the moments
     5// window parameters.  It is currently only being used by ppSub.
    66
    77// NOTE: ppSub needs to perform extended source analysis for comets and trails.
     
    1717    pmModelClassSetLimits(PM_MODEL_LIMITS_LAX);
    1818
    19     // select the current recipe
    20     psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE);
    21     if (!recipe) {
    22         psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE);
    23         return false;
    24     }
    25 
    2619    // set the photcode for this image
    27     if (!psphotAddPhotcode(recipe, config, view, "PSPHOT.INPUT")) {
     20    if (!psphotAddPhotcode(config, view)) {
    2821        psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode");
    2922        return false;
    3023    }
    3124
    32     // find the currently selected readout
    33     pmReadout  *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
    34     PS_ASSERT_PTR_NON_NULL (readout, false);
     25    // Generate the mask and weight images, including the user-defined analysis region of interest
     26    psphotSetMaskAndVariance (config, view);
    3527
    36     // Generate the mask and weight images, including the user-defined analysis region of interest
    37     psphotSetMaskAndVariance (config, readout, recipe);
    38 
    39     // display the image, weight, mask (ch 1,2,3)
    40     psphotVisualShowImage (readout);
    41 
    42     // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are saved in the recipe
    43     pmPSF *psf = psphotLoadPSF (config, view, recipe);
    44     if (!psf) {
     28    // load the psf model, if suppled.  FWHM_X,FWHM_Y,etc are saved on readout->analysis
     29    if (!psphotLoadPSF (config, view)) {
    4530      psError (PSPHOT_ERR_CONFIG, false, "missing psf model");
    46       return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);
     31      return psphotReadoutCleanup (config, view);
    4732    }
    4833
    49     // find the detections (by peak and/or footprint) in the image.
    50     pmDetections *detections = pmDetectionsAlloc(); // New detections; allocated to ensure pass=2
    51     detections = psphotFindDetections(detections, readout, recipe);
    52     if (!detections) {
    53         psLogMsg ("psphot", 3, "unable to find detections in this image");
    54         return psphotReadoutCleanup (config, readout, recipe, detections, psf, NULL);
     34    // find the detections (by peak and/or footprint) in the image. (final pass)
     35    if (!psphotFindDetections(config, view, false)) {
     36        psError (PSPHOT_ERR_UNKNOWN, false, "failure in peak analysis");
     37        return psphotReadoutCleanup (config, view);
    5538    }
    5639
    57     // construct sources and measure basic stats
    58     psArray *sources = psphotSourceStats (config, readout, detections, true);
    59     if (!sources) return false;
     40    // construct sources and measure basic stats (saved on detections->newSources)
     41    if (!psphotSourceStats (config, view, false)) { // pass 1
     42        psError(PSPHOT_ERR_UNKNOWN, false, "failure to generate sources");
     43        return psphotReadoutCleanup (config, view);
     44    }
    6045
    6146    // find blended neighbors of very saturated stars
    62     // XXX merge this with Basic Deblend?
    63     psphotDeblendSatstars (readout, sources, recipe);
     47    psphotDeblendSatstars (config, view);
    6448
    6549    // mark blended peaks PS_SOURCE_BLEND
    66     if (!psphotBasicDeblend (sources, recipe)) {
     50    if (!psphotBasicDeblend (config, view)) {
    6751        psLogMsg ("psphot", 3, "failed on deblend analysis");
    68         return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     52        return psphotReadoutCleanup (config, view);
    6953    }
    7054
    7155    // classify sources based on moments, brightness (use supplied psf shape parameters)
    72     if (!psphotRoughClass (readout, sources, recipe, true)) {
     56    if (!psphotRoughClass (config, view)) {
    7357        psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image");
    74         return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);
     58        return psphotReadoutCleanup (config, view);
    7559    }
    7660
    7761    // construct an initial model for each object
    78     psphotGuessModels (config, readout, sources, psf);
     62    psphotGuessModels (config, view);
     63
     64    // merge the newly selected sources into the existing list
     65    psphotMergeSources (config, view);
    7966
    8067    // linear PSF fit to source peaks
    81     psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE);
    82 
    83     // We have to place these visualizations here because the models are not realized until
    84     // psphotGuessModels or fitted until psphotFitSourcesLinear.
    85     psphotVisualShowPSFStars (recipe, psf, sources);
    86     psphotVisualShowSatStars (recipe, psf, sources);
     68    psphotFitSourcesLinear (config, view, false);
    8769
    8870// XXX eventually, add the extended source fits here
    8971# if (0)
    9072    // measure source size for the remaining sources
    91     psphotSourceSize (config, readout, sources, recipe, 0);
     73    psphotSourceSize (config, view);
    9274
    93     psphotExtendedSourceAnalysis (readout, sources, recipe);
     75    psphotExtendedSourceAnalysis (config, view);
    9476
    95     psphotExtendedSourceFits (readout, sources, recipe);
     77    psphotExtendedSourceFits (config, view);
    9678# endif
    9779
    9880    // calculate source magnitudes
    99     psphotMagnitudes(config, readout, view, sources, psf);
     81    psphotMagnitudes(config, view);
    10082
    101     if (!psphotEfficiency(config, readout, view, psf, recipe, sources)) {
     83    // XXX ensure this is measured if the analysis succeeds (even if quality is low)
     84    if (!psphotEfficiency(config, view)) {
    10285        psErrorStackPrint(stderr, "Unable to determine detection efficiencies from fake sources");
    10386        psErrorClear();
     
    10588
    10689    // drop the references to the image pixels held by each source
    107     psphotSourceFreePixels (sources);
     90    psphotSourceFreePixels (config, view);
    10891
    10992    // create the exported-metadata and free local data
    110     return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);
     93    return psphotReadoutCleanup(config, view);
    11194}
  • branches/tap_branches/psphot/src/psphotReplaceUnfit.c

    r25755 r27838  
    2222}
    2323
    24 bool psphotReplaceAllSources (psArray *sources, psMetadata *recipe) {
     24// for now, let's store the detections on the readout->analysis for each readout
     25bool psphotReplaceAllSources (pmConfig *config, const pmFPAview *view)
     26{
     27    bool status = true;
     28
     29    // select the appropriate recipe information
     30    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     31    psAssert (recipe, "missing recipe?");
     32
     33    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     34    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     35
     36    // loop over the available readouts
     37    for (int i = 0; i < num; i++) {
     38        if (!psphotReplaceAllSourcesReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     39            psError (PSPHOT_ERR_CONFIG, false, "failed to replace all sources for PSPHOT.INPUT entry %d", i);
     40            return false;
     41        }
     42    }
     43    return true;
     44}
     45
     46bool psphotReplaceAllSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {
    2547
    2648    bool status;
     
    2951    psTimerStart ("psphot.replace");
    3052
     53    // find the currently selected readout
     54    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     55    psAssert (file, "missing file?");
     56
     57    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     58    psAssert (readout, "missing readout?");
     59
     60    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     61    psAssert (detections, "missing detections?");
     62
     63    psArray *sources = detections->allSources;
     64    psAssert (sources, "missing sources?");
     65
    3166    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    3267    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    33     assert (maskVal);
     68    psAssert (maskVal, "missing mask value?");
    3469
    3570    for (int i = 0; i < sources->n; i++) {
     
    67102    return true;
    68103}
    69 
    70 # if (0)
    71 // add source, if the source has been subtracted; do not modify state
    72 bool psphotAddWithTest (pmSource *source, bool useState, psImageMaskType maskVal) {
    73 
    74     // what is current state? (true : add; false : sub)
    75     bool state = !(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    76     if (state && useState) return true;
    77 
    78     pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    79     return true;
    80 }
    81 
    82 // sub source, if the source has been added; do not modify state
    83 bool psphotSubWithTest (pmSource *source, bool useState, psImageMaskType maskVal) {
    84 
    85     // what is current state? (true : sub; false : add)
    86     bool state = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    87     if (state && useState) return true;
    88 
    89     pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    90     return true;
    91 }
    92 
    93 // add or sub source to match recorded state: supply current state as true (add) or false (sub)
    94 bool psphotSetState (pmSource *source, bool curState, psImageMaskType maskVal) {
    95 
    96     // what is desired state? (true : add; false : sub)
    97     bool newState = !(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);
    98     if (curState == newState) return true;
    99 
    100     if (curState && !newState) {
    101         pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    102     }
    103     if (newState && !curState) {
    104         pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    105     }
    106     return true;
    107 }
    108 # endif
  • branches/tap_branches/psphot/src/psphotRoughClass.c

    r25852 r27838  
    77        } }
    88
    9 bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *target, psMetadata *recipe, const bool havePSF);
     9// for now, let's store the detections on the readout->analysis for each readout
     10bool psphotRoughClass (pmConfig *config, const pmFPAview *view)
     11{
     12    bool status = true;
    1013
    11 // 2006.02.02 : no leaks
    12 bool psphotRoughClass (pmReadout *readout, psArray *sources, psMetadata *recipe, const bool havePSF) {
     14    // select the appropriate recipe information
     15    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     16    psAssert (recipe, "missing recipe?");
     17
     18    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     19    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     20
     21    // skip the chisq image (optionally?)
     22    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     23    if (!status) chisqNum = -1;
     24
     25    // loop over the available readouts
     26    for (int i = 0; i < num; i++) {
     27        if (i == chisqNum) continue; // skip chisq image
     28        if (!psphotRoughClassReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     29            psError (PSPHOT_ERR_CONFIG, false, "failed on rough classification for PSPHOT.INPUT entry %d", i);
     30            return false;
     31        }
     32    }
     33    return true;
     34}
     35
     36bool psphotRoughClassReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) {
    1337
    1438    bool status;
    1539
    1640    psTimerStart ("psphot.rough");
     41
     42    // find the currently selected readout
     43    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     44    psAssert (file, "missing file?");
     45
     46    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     47    psAssert (readout, "missing readout?");
     48
     49    // if we have a PSF, use the existing PSF clump region below
     50    bool havePSF = false;
     51    if (psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF")) {
     52        havePSF = true;
     53    }
     54
     55    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     56    psAssert (detections, "missing detections?");
     57
     58    psArray *sources = detections->newSources;
     59    psAssert (sources, "missing sources?");
     60
     61    if (!sources->n) {
     62        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping rough classification");
     63        return true;
     64    }
    1765
    1866    // we make this measurement on a NxM grid of regions across the readout
     
    3785        }
    3886    }
    39     psMetadataAddS32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", nRegion);
     87    psMetadataAddS32 (readout->analysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS",  PS_META_REPLACE, "psf clump regions", nRegion);
    4088
    4189    // optional printout of source moments only
     
    5199}
    52100
    53 bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *target, psMetadata *recipe, const bool havePSF) {
     101bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *analysis, psMetadata *recipe, const bool havePSF) {
    54102
    55103    bool status;
     
    61109    assert (maskSat);
    62110
     111    // the regions are saved on the readout->analysis metadata folder (passed to us as analysis)
    63112    snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", nRegion);
    64     psMetadata *regionMD = psMetadataLookupPtr (&status, target, regionName);
     113    psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName);
    65114    if (!regionMD) {
    66115        // allocate the region metadata folder and add this region to it.
    67116        regionMD = psMetadataAlloc();
    68         psMetadataAddMetadata (target, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
     117        psMetadataAddMetadata (analysis, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD);
    69118        psFree (regionMD);
    70119    }
     
    74123        // determine the PSF parameters from the source moment values
    75124        // XXX why not save the psfClump as a PTR?
    76         psfClump = pmSourcePSFClump (region, sources, target);
     125
     126        float PSF_SN_LIM = psMetadataLookupF32(&status, recipe, "PSF_SN_LIM"); psAssert (status, "missing PSF_SN_LIM");
     127        float MOMENTS_AR_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_AR_MAX"); psAssert (status, "missing MOMENTS_AR_MAX");
     128
     129        float PSF_CLUMP_GRID_SCALE = psMetadataLookupF32(&status, analysis, "PSF_CLUMP_GRID_SCALE");
     130        if (!status) {
     131            PSF_CLUMP_GRID_SCALE = psMetadataLookupF32(&status, recipe, "PSF_CLUMP_GRID_SCALE");
     132            psAssert (status, "missing PSF_CLUMP_GRID_SCALE");
     133        }
     134        float MOMENTS_SX_MAX = psMetadataLookupF32(&status, analysis, "MOMENTS_SX_MAX");
     135        if (!status) {
     136            MOMENTS_SX_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_SX_MAX");
     137            psAssert (status, "missing MOMENTS_SX_MAX");
     138        }
     139        float MOMENTS_SY_MAX = psMetadataLookupF32(&status, analysis, "MOMENTS_SY_MAX");
     140        if (!status) {
     141            MOMENTS_SY_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_SY_MAX");
     142            psAssert (status, "missing MOMENTS_SY_MAX");
     143        }
     144
     145        psfClump = pmSourcePSFClump (NULL, region, sources, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_AR_MAX);
     146
    77147        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X",  PS_META_REPLACE, "psf clump center", psfClump.X);
    78148        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y",  PS_META_REPLACE, "psf clump center", psfClump.Y);
     
    102172    psLogMsg ("psphot", 3, "psf clump DX, DY: %f, %f\n", psfClump.dX, psfClump.dY);
    103173
     174    // get basic parameters, or set defaults
     175    float PSF_SN_LIM = psMetadataLookupF32 (&status, recipe, "PSF_SN_LIM"); psAssert (status, "missing PSF_SN_LIM");
     176    float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA"); psAssert (status, "missing PSF_CLUMP_NSIGMA");
     177
    104178    // group into STAR, COSMIC, EXTENDED, SATURATED, etc.
    105     if (!pmSourceRoughClass (region, sources, recipe, psfClump, maskSat)) {
     179    if (!pmSourceRoughClass (region, sources, PSF_SN_LIM, PSF_CLUMP_NSIGMA, psfClump, maskSat)) {
    106180        psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourceRoughClass");
    107181        return false;
  • branches/tap_branches/psphot/src/psphotSetThreads.c

    r25755 r27838  
    2525    psFree(task);
    2626
    27     task = psThreadTaskAlloc("PSPHOT_SOURCE_STATS", 5);
     27    task = psThreadTaskAlloc("PSPHOT_SOURCE_STATS", 10);
    2828    task->function = &psphotSourceStats_Threaded;
    2929    psThreadTaskAdd(task);
  • branches/tap_branches/psphot/src/psphotSignificanceImage.c

    r25383 r27838  
    2222    }
    2323
     24    // if we have already determined the PSF model, then we have a better idea how to smooth this image
    2425    bool statusMajor, statusMinor;
    25     float fwhmMajor = psMetadataLookupF32(&statusMajor, recipe, "FWHM_MAJ");
    26     float fwhmMinor = psMetadataLookupF32(&statusMinor, recipe, "FWHM_MIN");
     26    float fwhmMajor = psMetadataLookupF32(&statusMajor, readout->analysis, "FWHM_MAJ");
     27    float fwhmMinor = psMetadataLookupF32(&statusMinor, readout->analysis, "FWHM_MIN");
    2728    if (statusMajor && statusMinor) {
    2829        // if we know the FHWM, use that to set the smoothing kernel (XXX allow an optional override?)
     
    4344    }
    4445    // record the actual smoothing sigma
    45     psMetadataAddF32(recipe, PS_LIST_TAIL, "SIGMA_SMOOTH", PS_META_REPLACE, "Smoothing sigma for detections",
    46                      SIGMA_SMTH);
     46    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "SIGMA_SMOOTH", PS_META_REPLACE, "Smoothing sigma for detections", SIGMA_SMTH);
    4747
    4848    // smooth the image, applying the mask as we go
     
    5959    // effective per-pixel variance is maintained.
    6060    psImage *smooth_wt = psImageCopy(NULL, readout->variance, PS_TYPE_F32);
    61     psImageSmoothMask_Threaded(smooth_wt, smooth_wt, readout->mask, maskVal, SIGMA_SMTH * M_SQRT1_2,
    62                       NSIGMA_SMTH, minGauss);
     61    psImageSmoothMask_Threaded(smooth_wt, smooth_wt, readout->mask, maskVal, SIGMA_SMTH * M_SQRT1_2, NSIGMA_SMTH, minGauss);
    6362    psLogMsg("psphot", PS_LOG_MINUTIA, "smooth variance: %f sec\n", psTimerMark("psphot.smooth"));
    6463
     
    7776    // Calculate correction factor for the covariance produced by the (potentially multiple) smoothing
    7877    psKernel *kernel = psImageSmoothKernel(SIGMA_SMTH, NSIGMA_SMTH); // Kernel used for smoothing
    79     psKernel *covar = psImageCovarianceCalculate(kernel, readout->covariance); // Covariance matrix
     78    float factor = 1.0 / psImageCovarianceCalculateFactor(kernel, readout->covariance);
    8079    psFree(kernel);
    81     float factor = 1.0 / psImageCovarianceFactor(covar);
    82     psFree(covar);
    8380
    8481    // record the effective area and significance scaling factor
    8582    float effArea = 8.0 * M_PI * PS_SQR(SIGMA_SMTH);
    86     psMetadataAddF32(recipe, PS_LIST_TAIL, "EFFECTIVE_AREA", PS_META_REPLACE, "Effective Area", effArea);
    87     psMetadataAddF32(recipe, PS_LIST_TAIL, "SIGNIFICANCE_SCALE_FACTOR", PS_META_REPLACE,
    88                      "Signicance scale factor", factor);
     83    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "EFFECTIVE_AREA", PS_META_REPLACE, "Effective Area", effArea);
     84    psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "SIGNIFICANCE_SCALE_FACTOR", PS_META_REPLACE, "Signicance scale factor", factor);
    8985
    9086    // XXX multithread this if needed
  • branches/tap_branches/psphot/src/psphotSkyReplace.c

    r21183 r27838  
    11# include "psphotInternal.h"
     2
     3bool psphotSkyReplace (pmConfig *config, const pmFPAview *view)
     4{
     5    bool status = true;
     6
     7    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     8    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     9
     10    // skip the chisq image (optionally?)
     11    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     12    if (!status) chisqNum = -1;
     13
     14    // loop over the available readouts
     15    for (int i = 0; i < num; i++) {
     16        if (i == chisqNum) continue; // skip chisq image
     17        if (!psphotSkyReplaceReadout (config, view, "PSPHOT.INPUT", i)) {
     18            psError (PSPHOT_ERR_CONFIG, false, "failed to replace sky for PSPHOT.INPUT entry %d", i);
     19            return false;
     20        }
     21    }
     22    return true;
     23}
    224
    325// XXX make this an option?
    426// in order to  successfully replace the sky, we must define a corresponding file...
    5 bool psphotSkyReplace (pmConfig *config, const pmFPAview *view) {
     27bool psphotSkyReplaceReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index) {
    628
    729    psTimerStart ("psphot.skyreplace");
    830
    931    // find the currently selected readout
    10     pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");
    11     if (readout == NULL) psAbort("input not defined");
     32    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     33    psAssert (file, "missing file?");
     34
     35    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     36    psAssert (readout, "missing readout?");
    1237
    1338    // select background pixels, from output background file, or create
  • branches/tap_branches/psphot/src/psphotSourceFits.c

    r25755 r27838  
    219219    double chiTrend;
    220220    pmModel *ONE = NULL;
     221    pmSource *tmpSrc = NULL;
     222    pmModel *EXT = NULL;
     223    psArray *DBL = NULL;
    221224
    222225    // skip the source if we don't think it is extended
     
    232235    // at this stage, skip Gaussian windowing, and do not clip pixels by S/N
    233236    // this uses the footprint to judge both radius and aperture?
    234     if (!pmSourceMoments (source, radius, 0.0, 0.0)) return false;
     237    if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) return false;
    235238
    236239    psTrace ("psphot", 5, "trying blob...\n");
     
    240243
    241244    // this temporary source is used as a place-holder by the psphotEval functions below
    242     pmSource *tmpSrc = pmSourceAlloc ();
     245    tmpSrc = pmSourceAlloc ();
    243246
    244247    // XXX need to handle failures better here
    245     pmModel *EXT = psphotFitEXT (readout, source, modelTypeEXT, maskVal, markVal);
    246     if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) psAbort("nan in fit");
     248    EXT = psphotFitEXT (readout, source, modelTypeEXT, maskVal, markVal);
     249    if (!EXT) goto escape;
     250    if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape;
    247251
    248252    okEXT = psphotEvalEXT (tmpSrc, EXT);
     
    250254
    251255    // DBL will always be defined, but DBL->data[n] might not
    252     psArray *DBL = psphotFitDBL (readout, source, maskVal, markVal);
     256    DBL = psphotFitDBL (readout, source, maskVal, markVal);
     257    if (!DBL) goto escape;
     258    if (!DBL->n) goto escape;
     259
    253260    okDBL  = psphotEvalDBL (tmpSrc, DBL->data[0]);
    254261    okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]);
     
    362369    psFree (DBL);
    363370    return true;
     371
     372escape:
     373    psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
     374    psFree (tmpSrc);
     375    psFree (EXT);
     376    psFree (DBL);
     377    return false;
    364378}
    365379
     
    425439    // use the source moments, etc to guess basic model parameters
    426440    pmModel *EXT = pmSourceModelGuess (source, modelType);
    427     PS_ASSERT (EXT, NULL);
     441    if (!EXT) {
     442        psTrace ("psphot", 5, "failed to generate a model for source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy);
     443        return NULL;
     444    }
    428445
    429446    if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) {
  • branches/tap_branches/psphot/src/psphotSourceFreePixels.c

    r12792 r27838  
    11# include "psphotInternal.h"
    22
    3 void psphotSourceFreePixels (psArray *sources) {
     3bool psphotSourceFreePixels (pmConfig *config, const pmFPAview *view)
     4{
     5    bool status = true;
    46
    5     if (!sources) return;
     7    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     8    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     9
     10    // loop over the available readouts
     11    for (int i = 0; i < num; i++) {
     12        if (!psphotSourceFreePixelsReadout (config, view, "PSPHOT.INPUT", i)) {
     13            psError (PSPHOT_ERR_CONFIG, false, "failed to free source pixels for PSPHOT.INPUT entry %d", i);
     14            return false;
     15        }
     16    }
     17    return true;
     18}
     19
     20bool psphotSourceFreePixelsReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index) {
     21
     22    bool status;
     23
     24    // find the currently selected readout
     25    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     26    psAssert (file, "missing file?");
     27
     28    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     29    psAssert (readout, "missing readout?");
     30
     31    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     32    psAssert (detections, "missing detections?");
     33
     34    psArray *sources = detections->allSources;
     35    psAssert (sources, "missing sources?");
    636
    737    for (int i = 0; i < sources->n; i++) {
     
    939        pmSourceFreePixels (source);
    1040    }
    11     return;
     41    return true;
    1242}
  • branches/tap_branches/psphot/src/psphotSourceSize.c

    r25852 r27838  
    1313    float soft;
    1414    int grow;
     15    int xtest, ytest;
     16    bool apply; // apply CR mask?
    1517} psphotSourceSizeOptions;
    1618
     19// local functions:
    1720bool psphotSourceSizePSF (psphotSourceSizeOptions *options, psArray *sources, pmPSF *psf);
    1821bool psphotSourceClass (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options);
    1922bool psphotSourceClassRegion (psRegion *region, pmPSFClump *psfClump, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options);
    2023bool psphotSourceSizeCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options);
    21 bool psphotMaskCosmicRay (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask);
    22 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask);
     24bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal);
     25bool psphotMaskCosmicRayFootprintCheck (psArray *sources);
     26int  psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh);
    2327
    2428// we need to call this function after sources have been fitted to the PSF model and
     
    2832// deviation from the psf model at the r = FWHM/2 position
    2933
    30 // XXX use an internal flag to mark sources which have already been measured
    31 bool psphotSourceSize(pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, long first)
     34// for now, let's store the detections on the readout->analysis for each readout
     35bool psphotSourceSize (pmConfig *config, const pmFPAview *view, bool getPSFsize)
     36{
     37    bool status = true;
     38
     39    // select the appropriate recipe information
     40    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     41    psAssert (recipe, "missing recipe?");
     42
     43    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     44    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     45
     46    // skip the chisq image (optionally?)
     47    int chisqNum = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.CHISQ.NUM");
     48    if (!status) chisqNum = -1;
     49
     50    // loop over the available readouts
     51    for (int i = 0; i < num; i++) {
     52        if (i == chisqNum) continue; // skip chisq image
     53        if (!psphotSourceSizeReadout (config, view, "PSPHOT.INPUT", i, recipe, getPSFsize)) {
     54            psError (PSPHOT_ERR_CONFIG, false, "failed on source size analysis for PSPHOT.INPUT entry %d", i);
     55            return false;
     56        }
     57    }
     58    return true;
     59}
     60
     61// this function use an internal flag to mark sources which have already been measured
     62bool psphotSourceSizeReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool getPSFsize)
    3263{
    3364    bool status;
     
    3667    psTimerStart ("psphot.size");
    3768
     69    // find the currently selected readout
     70    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     71    psAssert (file, "missing file?");
     72
     73    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     74    psAssert (readout, "missing readout?");
     75
     76    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     77    psAssert (detections, "missing detections?");
     78
     79    psArray *sources = detections->allSources;
     80    psAssert (sources, "missing sources?");
     81
     82    if (!sources->n) {
     83        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source size");
     84        return true;
     85    }
     86
     87    pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.PSF");
     88    psAssert (psf, "missing psf?");
     89
    3890    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
    3991    options.maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
     
    55107    // XXX recipe name is not great
    56108    options.nSigmaMoments = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.MOMENTS");
     109    assert (status);
     110
     111    // XXX recipe name is not great
     112    options.xtest = psMetadataLookupS32 (&status, recipe, "PSPHOT.CRMASK.XTEST");
     113    options.ytest = psMetadataLookupS32 (&status, recipe, "PSPHOT.CRMASK.YTEST");
    57114    assert (status);
    58115
     
    69126    }
    70127
     128    options.apply = psMetadataLookupBool(&status, recipe, "PSPHOT.CRMASK.APPLY"); // Growth size for CRs
     129    if (!status) {
     130        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSPHOT.CRMASK.APPLY is not defined.");
     131        return false;
     132    }
     133
    71134    // We are using the value psfMag - 2.5*log10(moment.Sum) as a measure of the extendedness
    72     // of and object.  We need to model this distribution for the PSF stars before we can test
     135    // of an object.  We need to model this distribution for the PSF stars before we can test
    73136    // the significance for a specific object
    74137    // XXX move this to the code that generates the PSF?
    75138    // XXX store the results on pmPSF?
    76     psphotSourceSizePSF (&options, sources, psf);
     139
     140    // XXX this should only be done on the first pass (ie, if we have newSources or allSources?)
     141    if (getPSFsize) {
     142        psphotSourceSizePSF (&options, sources, psf);
     143    }
    77144
    78145    // classify the sources based on ApResid and Moments (extended sources)
     146    // NOTE: only sources not already measured !(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)
    79147    psphotSourceClass(readout, sources, recipe, psf, &options);
    80148
     149    // NOTE: only sources not already measured !(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)
    81150    psphotSourceSizeCR (readout, sources, &options);
    82151
    83     psLogMsg ("psphot.size", PS_LOG_INFO, "measure source sizes for %ld sources: %f sec\n", sources->n - first, psTimerMark ("psphot.size"));
     152    // XXX fix this (was source->n  - first)
     153    psLogMsg ("psphot.size", PS_LOG_INFO, "measure source sizes for %ld sources: %f sec\n", sources->n, psTimerMark ("psphot.size"));
    84154
    85155    psphotVisualPlotSourceSize (recipe, readout->analysis, sources);
    86156    psphotVisualShowSourceSize (readout, sources);
    87157    psphotVisualPlotApResid (sources, options.ApResid, options.ApSysErr);
     158    psphotVisualShowSatStars (recipe, psf, sources);
    88159
    89160    return true;
    90161}
    91162
    92 bool psphotMaskCosmicRay (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {
     163// model the apmifit distribution for the psf stars:
     164bool psphotSourceSizePSF (psphotSourceSizeOptions *options, psArray *sources, pmPSF *psf) {
     165
     166    // select stats from the psf stars
     167    psVector *Ap = psVectorAllocEmpty (100, PS_TYPE_F32);
     168    psVector *ApErr = psVectorAllocEmpty (100, PS_TYPE_F32);
     169
     170    psImageMaskType maskVal = options->maskVal | options->markVal;
     171
     172    // XXX  why PHOT_WEIGHT??
     173    pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_WEIGHT;
     174
     175    int num = 0;                        // Number of sources measured
     176    for (int i = 0; i < sources->n; i++) {
     177        pmSource *source = sources->data[i];
     178        if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
     179        num++;
     180
     181        // replace object in image
     182        if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) {
     183            pmSourceAdd (source, PM_MODEL_OP_FULL, options->maskVal);
     184        }
     185
     186        // clear the mask bit and set the circular mask pixels
     187        psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
     188        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", options->markVal);
     189
     190        // XXX can we test if psfMag is set and calculate only if needed?
     191        pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
     192
     193        // clear the mask bit
     194        psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
     195
     196        // re-subtract the object, leave local sky
     197        pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal);
     198
     199        float apMag = -2.5*log10(source->moments->Sum);
     200        float dMag = source->psfMag - apMag;
     201
     202        psVectorAppend (Ap, dMag);
     203        psVectorAppend (ApErr, source->errMag);
     204    }
     205    if (num == 0) {
     206        // Not raising an error, because errors aren't being checked elsewhere in this function
     207        psFree(Ap);
     208        psFree(ApErr);
     209        return false;
     210    }
     211
     212    // model the distribution as a mean or median value and a systematic error from that value:
     213    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
     214    psVectorStats (stats, Ap, NULL, NULL, 0);
     215
     216    psVector *dAp = psVectorAlloc (Ap->n, PS_TYPE_F32);
     217    for (int i = 0; i < Ap->n; i++) {
     218        dAp->data.F32[i] = Ap->data.F32[i] - stats->robustMedian;
     219    }
     220
     221    options->ApResid = stats->robustMedian;
     222    options->ApSysErr = psVectorSystematicError(dAp, ApErr, 0.05);
     223    // XXX this is quite arbitrary...
     224    if (!isfinite(options->ApSysErr)) options->ApSysErr = 0.01;
     225    psLogMsg ("psphot", PS_LOG_DETAIL, "psf - Sum: %f +/- %f\n", options->ApResid, options->ApSysErr);
     226
     227    psFree (Ap);
     228    psFree (ApErr);
     229    psFree (stats);
     230    psFree (dAp);
     231
     232    return true;
     233}
     234
     235// classify sources based on the combination of psf-mag, Mxx, Myy
     236bool psphotSourceClass (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options) {
     237
     238    bool status;
     239    pmPSFClump psfClump;
     240    char regionName[64];
     241
     242    psLogMsg("psModules.objects", PS_LOG_INFO, "Source Size classifications: %4s %4s %4s %4s %4s %4s", "Npsf", "Next", "Nsat", "Ncr", "Nmiss", "Nskip");
     243
     244    int nRegions = psMetadataLookupS32 (&status, readout->analysis, "PSF.CLUMP.NREGIONS");
     245    for (int i = 0; i < nRegions; i ++) {
     246        snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", i);
     247        psMetadata *regionMD = psMetadataLookupPtr (&status, readout->analysis, regionName);
     248        psAssert (regionMD, "regions must be defined by earlier call to psphotRoughClassRegion");
     249
     250        psRegion *region = psMetadataLookupPtr (&status, regionMD, "REGION");
     251        psAssert (region, "regions must be defined by earlier call to psphotRoughClassRegion");
     252
     253        // pull FWHM_X,Y from the recipe, use to define psfClump.X,Y
     254        psfClump.X  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");   psAssert (status, "missing PSF.CLUMP.X");
     255        psfClump.Y  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");   psAssert (status, "missing PSF.CLUMP.Y");
     256        psfClump.dX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");  psAssert (status, "missing PSF.CLUMP.DX");
     257        psfClump.dY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");  psAssert (status, "missing PSF.CLUMP.DY");
     258
     259        if ((psfClump.X < 0) || (psfClump.Y < 0) || !psfClump.X || !psfClump.Y || isnan(psfClump.X) || isnan(psfClump.Y)) {
     260            psLogMsg ("psphot", 4, "Failed to find a valid PSF clump for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1);
     261            continue;
     262        }
     263
     264        if (!psphotSourceClassRegion (region, &psfClump, sources, recipe, psf, options)) {
     265            psLogMsg ("psphot", 4, "Failed to determine source classification for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1);
     266            continue;
     267        }
     268        // psphotVisualPlotSourceSize (recipe, readout->analysis, sources);
     269    }
     270
     271    return true;
     272}
     273
     274# define SIZE_SN_LIM 10
     275bool psphotSourceClassRegion (psRegion *region, pmPSFClump *psfClump, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options) {
     276
     277    PS_ASSERT_PTR_NON_NULL(sources, false);
     278    PS_ASSERT_PTR_NON_NULL(recipe, false);
     279
     280    int Nsat  = 0;
     281    int Next  = 0;
     282    int Npsf  = 0;
     283    int Ncr   = 0;
     284    int Nmiss = 0;
     285    int Nskip = 0;
     286
     287    pmSourceMode noMoments = PM_SOURCE_MODE_MOMENTS_FAILURE | PM_SOURCE_MODE_SKYVAR_FAILURE | PM_SOURCE_MODE_SKY_FAILURE | PM_SOURCE_MODE_BELOW_MOMENTS_SN;
     288    pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_WEIGHT;
     289
     290    psImageMaskType maskVal = options->maskVal | options->markVal;
     291
     292    for (psS32 i = 0 ; i < sources->n ; i++) {
     293
     294        pmSource *source = (pmSource *) sources->data[i];
     295
     296        // psfClumps are found for image subregions:
     297        // skip sources not in this region
     298        if (source->peak->x <  region->x0) continue;
     299        if (source->peak->x >= region->x1) continue;
     300        if (source->peak->y <  region->y0) continue;
     301        if (source->peak->y >= region->y1) continue;
     302
     303        // skip source if it was already measured
     304        if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) {
     305            psTrace("psphot", 7, "Not calculating source size since it has already been measured\n");
     306            continue;
     307        }
     308
     309        // source must have been subtracted
     310        if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) {
     311            source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED;
     312            psTrace("psphot", 7, "Not calculating source size since source is not subtracted\n");
     313            continue;
     314        }
     315
     316        // we are basically classifying by moments
     317        psAssert (source->moments, "why is this source missing moments?");
     318        if (source->mode & noMoments) {
     319            Nskip ++;
     320            continue;
     321        }
     322
     323        // convert to Mmaj, Mmin:
     324        psF32 Mxx = source->moments->Mxx;
     325        psF32 Myy = source->moments->Myy;
     326
     327        // replace object in image
     328        if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) {
     329            pmSourceAdd (source, PM_MODEL_OP_FULL, options->maskVal);
     330        }
     331
     332        // clear the mask bit and set the circular mask pixels
     333        psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
     334        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", options->markVal);
     335
     336        // XXX can we test if psfMag is set and calculate only if needed?
     337        pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
     338
     339        // clear the mask bit
     340        psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
     341
     342        // re-subtract the object, leave local sky
     343        pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal);
     344
     345        float apMag = -2.5*log10(source->moments->Sum);
     346        float dMag = source->psfMag - apMag;
     347
     348        // set nSigma to include both systematic and poisson error terms
     349        // XXX the 'poisson error' contribution for size is probably wrong...
     350        float nSigmaMAG = (dMag - options->ApResid) / hypot(source->errMag, options->ApSysErr);
     351        float nSigmaMXX = (Mxx - psfClump->X) / hypot(psfClump->dX, psfClump->X*psfClump->X*source->errMag);
     352        float nSigmaMYY = (Myy - psfClump->Y) / hypot(psfClump->dY, psfClump->Y*psfClump->Y*source->errMag);
     353
     354        // partially-masked sources are more likely to be mis-measured PSFs
     355        float sizeBias = 1.0;
     356        if (source->pixWeight < 0.9) {
     357            sizeBias = 3.0;
     358        }
     359
     360        float minMxx = psfClump->X - sizeBias*options->nSigmaMoments*psfClump->dX;
     361        float minMyy = psfClump->Y - sizeBias*options->nSigmaMoments*psfClump->dY;
     362
     363        // include MAG, MXX, and MYY?
     364        source->extNsigma = nSigmaMAG;
     365
     366        // notes to clarify the source size classification rules:
     367        // * a defect should be functionally equivalent to a cosmic ray
     368        // * CR & defect should have a faintess limit (min S/N)
     369        // * SAT stars should not be faint, but defects may?
     370
     371        // Anything within this region is a probably PSF-like object. Saturated stars may land
     372        // in this region, but are detected elsewhere on the basis of their peak value.
     373        bool isPSF = (fabs(nSigmaMAG) < options->nSigmaApResid) && (fabs(nSigmaMXX) < sizeBias*options->nSigmaMoments) && (fabs(nSigmaMYY) < sizeBias*options->nSigmaMoments);
     374        if (isPSF) {
     375          psTrace("psphotSourceClassRegion.PSF",4,"CLASS: %g %g\t%g %g  %g %g  %g %g\t%g %g\t%g PSF\t%g %g\n",
     376                  source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG,
     377                  options->nSigmaApResid,sizeBias*options->nSigmaMoments);
     378          source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
     379          Npsf ++;
     380          continue;
     381        }
     382
     383        // Defects may not always match CRs from peak curvature analysis
     384        // Defects may also be marked as SATSTAR -- XXX deactivate this flag?
     385        // XXX this rule is not great
     386        // XXX only accept brightish detections as CRs
     387        // (nSigmaMAG < -options->nSigmaApResid) ||
     388        bool isCR = isCR = (source->errMag < 1.0 / SIZE_SN_LIM) && ((Mxx < minMxx) || (Myy < minMyy));
     389        if (isCR) {
     390            psTrace("psphotSourceClassRegion.CR",4,"CLASS: %g %g %f\t%g %g  %g %g  %g %g\t%g %g\t%g CR\t%g %g\n",
     391                    source->peak->xf,source->peak->yf,source->pixWeight,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG,
     392                    options->nSigmaApResid,sizeBias*options->nSigmaMoments);
     393            source->mode |= PM_SOURCE_MODE_DEFECT;
     394            source->tmpFlags |= PM_SOURCE_TMPF_SIZE_CR_CANDIDATE;
     395            Ncr ++;
     396            continue;
     397        }
     398
     399        // saturated star (determined in PSF fit).  These may also be saturated galaxies, or
     400        // just large saturated regions.
     401        if (source->mode & PM_SOURCE_MODE_SATSTAR) {
     402            psTrace("psphotSourceClassRegion.SAT",4,"CLASS: %g %g\t%g %g  %g %g  %g %g\t%g %g\t%g SAT\t%g %g\n",
     403                    source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG,
     404                    options->nSigmaApResid,sizeBias*options->nSigmaMoments);
     405            source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
     406            Nsat ++;
     407            continue;
     408        }
     409
     410        // XXX allow the Mxx, Myy to be less than psfClump->X,Y (by some nSigma)?
     411        bool isEXT = (nSigmaMAG > options->nSigmaApResid) || (Mxx > minMxx) || (Myy > minMyy);
     412        if (isEXT) {
     413          psTrace("psphotSourceClassRegion.EXT",4,"CLASS: %g %g\t%g %g  %g %g  %g %g\t%g %g\t%g Ext\t%g %g\n",
     414                  source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG,
     415                  options->nSigmaApResid,sizeBias*options->nSigmaMoments);
     416
     417            source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
     418            source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
     419            Next ++;
     420            continue;
     421        }
     422        psTrace("psphotSourceClassRegion.MISS",4,"CLASS: %g %g\t%g %g  %g %g  %g %g\t%g %g\t%g Unk\t%g %g\n",
     423                source->peak->xf,source->peak->yf,Mxx,Myy,psfClump->X,psfClump->Y,psfClump->dX,psfClump->dY,apMag,dMag,nSigmaMAG,
     424                options->nSigmaApResid,sizeBias*options->nSigmaMoments);
     425
     426        // sources that reach here are probably too faint for a reasonable source size measurement
     427        // psWarning ("sourse size was missed for %f,%f : %f %f -- %f\n", source->peak->xf, source->peak->yf, Mxx, Myy, nSigmaMAG);
     428        source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
     429        Nmiss ++;
     430    }
     431
     432    psLogMsg("psModules.objects", PS_LOG_INFO, "Source Size classifications: %4d %4d %4d %4d %4d %4d", Npsf, Next, Nsat, Ncr, Nmiss, Nskip);
     433
     434    return true;
     435}
     436
     437// given an object suspected to be a defect, generate a pixel mask using the Lapacian transform
     438// if enough of the object is detected as 'sharp', consider the object a cosmic ray
     439bool psphotSourceSizeCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) {
     440
     441    psTimerStart ("psphot.cr");
     442
     443    int nMasked = 0;
     444    for (int i = 0; i < sources->n; i++) {
     445        pmSource *source = sources->data[i];
     446
     447        // skip source if it was already measured
     448        if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) {
     449            psTrace("psphot", 7, "Not calculating source size since it has already been measured\n");
     450            continue;
     451        }
     452
     453        // only check candidates marked above
     454        if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_CR_CANDIDATE)) {
     455            psTrace("psphot", 7, "Not calculating source size since it has already been measured\n");
     456            continue;
     457        }
     458
     459        // skip unless this source is thought to be a cosmic ray.  flag the detection and mask the pixels
     460        // XXX this may be degenerate with the above test
     461        if (!(source->mode & PM_SOURCE_MODE_DEFECT)) continue;
     462
     463        // Integer position of peak
     464        int xPeak = source->peak->xf - source->pixels->col0 + 0.5;
     465        int yPeak = source->peak->yf - source->pixels->row0 + 0.5;
     466
     467        // Skip sources which are too close to a boundary.  These are mostly caught as DEFECT
     468        if (xPeak < 1 || xPeak > source->pixels->numCols - 2 ||
     469            yPeak < 1 || yPeak > source->pixels->numRows - 2) {
     470            psTrace("psphot", 7, "Not calculating crNsigma due to edge\n");
     471            continue;
     472        }
     473
     474        // XXX for testing, only CRMASK a single source:
     475        if (options->xtest && (fabs(source->peak->xf - options->xtest) > 5)) continue;
     476        if (options->ytest && (fabs(source->peak->yf - options->ytest) > 5)) continue;
     477
     478        // replace object in image
     479        if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) {
     480            pmSourceAdd (source, PM_MODEL_OP_FULL, options->maskVal);
     481        }
     482
     483        // XXX this is running slowly and is too agressive, but it more-or-less works
     484        psTrace("psphot", 6, "mask cosmic ray at %f, %f\n", source->peak->xf, source->peak->yf);
     485        if (options->apply) {
     486            psphotMaskCosmicRay(readout, source, options->crMask);
     487        } else {
     488            source->mode |= PM_SOURCE_MODE_CR_LIMIT;
     489        }
     490        nMasked ++;
     491
     492        // re-subtract the object, leave local sky
     493        pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal);
     494    }
     495
     496    // now that we have masked pixels associated with CRs, we can grow the mask
     497    if (options->grow > 0) {
     498        bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading for psImageConvolveMask
     499        psImage *newMask = psImageConvolveMask(NULL, readout->mask, options->crMask, options->crMask, -options->grow, options->grow, -options->grow, options->grow);
     500        psImageConvolveSetThreads(oldThreads);
     501        if (!newMask) {
     502            psError(PS_ERR_UNKNOWN, false, "Unable to grow CR mask");
     503            return false;
     504        }
     505        psFree(readout->mask);
     506        readout->mask = newMask;
     507    }
     508
     509    psLogMsg ("psphot.cr", PS_LOG_INFO, "mask CR: %d masked in %f sec\n", nMasked, psTimerMark ("psphot.cr"));
     510
     511    // XXX test : save the mask image
     512    if (0) {
     513        psphotSaveImage (NULL, readout->mask,   "mask.fits");
     514    }
     515
     516    return true;
     517}
     518
     519# define DUMPPICS 0
     520# define LIMIT_XRANGE(X, IMAGE) { X = PS_MIN(PS_MAX(0, X), IMAGE->numCols); }
     521# define LIMIT_YRANGE(Y, IMAGE) { Y = PS_MIN(PS_MAX(0, Y), IMAGE->numRows); }
     522
     523// Comments by CZW 20091209 : Mechanics of how to identify CR pixels taken from "Cosmic-Ray
     524// Rejection by Laplacian Edge Detection" by Pieter van Dokkum, arXiv:astro-ph/0108003.  This
     525// does no repair or recovery of the CR pixels, it only masks them out.  My test code can be
     526// found at /data/ipp031.0/watersc1/psphot.20091209/algo_check.c
     527bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal) {
     528
     529    // Get the actual images and information about the peak.
     530    psImage *mask = readout->mask;
     531    pmPeak *peak = source->peak;
     532    pmFootprint *footprint = peak->footprint;
     533
     534    // Bounding boxes are inclusive of final pixel
     535    int xs = footprint->bbox.x0;
     536    int xe = footprint->bbox.x1 + 1;
     537    int ys = footprint->bbox.y0;
     538    int ye = footprint->bbox.y1 + 1;
     539
     540    LIMIT_XRANGE(xs, mask);
     541    LIMIT_XRANGE(xe, mask);
     542    LIMIT_YRANGE(ys, mask);
     543    LIMIT_YRANGE(ye, mask);
     544
     545    int dx = xe - xs;
     546    int dy = ye - ys;
     547
     548    psImage *image= readout->image;
     549    psImage *variance = readout->variance;
     550
     551    int binning = 2;
     552    float sigma_thresh = 3.0;
     553    int max_iter = 1; // XXX with isophot masking, we only want to do a single pass
     554
     555    // Temporary images.
     556    psImage *mypix  = psImageAlloc(dx,dy,image->type.type);
     557    psImage *myfix  = psImageAlloc(dx,dy,image->type.type);
     558    psImage *myvar  = psImageAlloc(dx,dy,image->type.type);
     559    psImage *binned = psImageAlloc(dx * binning,dy * binning,image->type.type);
     560    psImage *conved = psImageAlloc(dx * binning,dy * binning,image->type.type);
     561    psImage *edges  = psImageAlloc(dx,dy,image->type.type);
     562    psImage *mymask = psImageAlloc(dx,dy,PS_TYPE_IMAGE_MASK);
     563
     564    // Load my copy of things.
     565    for (int y = 0; y < dy; y++) {
     566        for (int x = 0; x < dx; x++) {
     567            mypix->data.F32[y][x] = image->data.F32[y+ys][x+xs];
     568            myvar->data.F32[y][x] = variance->data.F32[y+ys][x+xs];
     569            mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0x00;
     570        }
     571    }
     572    // Mask so I can see on the output image where the footprint is.
     573    for (int i = 0; i < footprint->spans->n; i++) {
     574        pmSpan *sp = footprint->spans->data[i];
     575        for (int j = sp->x0; j <= sp->x1; j++) {
     576            int y = sp->y - ys;
     577            int x = j - xs;
     578            mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= 0x01;
     579        }
     580    }
     581
     582    int nCRpix = 1; // force at least one pass...
     583    for (int iteration = 0; (iteration < max_iter) && (nCRpix > 0); iteration++) {
     584        nCRpix = 0;
     585        psImageInit (binned, 0.0);
     586        psImageInit (conved, 0.0);
     587        psImageInit (edges, 0.0);
     588
     589        // Make subsampled image. Maybe this should be called "unbinned" or something
     590        for (int y = 0; y < binning * dy; y++) {
     591            int yraw = y / binning;
     592            for (int x = 0; x < binning * dx; x++) {
     593                int xraw = x / binning;
     594                binned->data.F32[y][x] = mypix->data.F32[yraw][xraw];
     595            }
     596        }
     597
     598        // Apply Laplace transform (kernel = [[0 -0.25 0][-0.25 1 -0.25][0 -0.25 0]]), clipping at zero
     599        for (int y = 1; y < binning * dy - 1; y++) {
     600            for (int x = 1; x < binning * dx - 1; x++) {
     601                float value = binned->data.F32[y][x] - 0.25 *
     602                    (binned->data.F32[y+0][x-1] + binned->data.F32[y+0][x+1] +
     603                     binned->data.F32[y-1][x+0] + binned->data.F32[y+1][x+0]);
     604                value = PS_MAX(0.0, value);
     605
     606                conved->data.F32[y][x] = value;
     607            }
     608        }
     609
     610        // Create an edge map by rebinning
     611        for (int y = 0; y < binning * dy; y++) {
     612            int yraw = y / binning;
     613            for (int x = 0; x < binning * dx; x++) {
     614                int xraw = x / binning;
     615                edges->data.F32[yraw][xraw] += conved->data.F32[y][x];
     616            }
     617        }
     618
     619        // coordinate of peak in subimage pixels:
     620        int xPeak = peak->x - xs;
     621        int yPeak = peak->y - ys;
     622
     623        // Modify my mask if we're above the significance threshold, but only for connected pixels
     624        nCRpix = psphotMaskCosmicRayConnected (xPeak, yPeak, mymask, myvar, edges, binning, sigma_thresh);
     625
     626# if DUMPPICS
     627        psphotSaveImage (NULL, mypix,   "crmask.pix.fits");
     628# endif
     629
     630// XXX do not repair the pixels in isophot version
     631# if 0
     632        // "Repair" Masked pixels for the next round.
     633        for (int y = 1; y < dy - 1; y++) {
     634            for (int x = 1; x < dx - 1; x++) {
     635                if (!(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40)) {
     636                    myfix->data.F32[y][x] = mypix->data.F32[y][x];
     637                    continue;
     638                }
     639                myfix->data.F32[y][x] = 0.25 *
     640                    (mypix->data.F32[y+0][x-1] + mypix->data.F32[y+0][x+1] +
     641                     mypix->data.F32[y-1][x+0] + mypix->data.F32[y+1][x+0]);
     642            }
     643        }
     644
     645        // "Repair" Masked pixels for the next round.
     646        for (int y = 1; y < dy - 1; y++) {
     647            for (int x = 1; x < dx - 1; x++) {
     648                mypix->data.F32[y][x] = myfix->data.F32[y][x];
     649            }
     650        }
     651# endif
     652
     653# if DUMPPICS
     654        fprintf (stderr, "CRMASK %d %d %d %d %d\n", xs, ys, dx, dy, iteration);
     655        psphotSaveImage (NULL, mypix,   "crmask.fix.fits");
     656        psphotSaveImage (NULL, myvar,   "crmask.var.fits");
     657        psphotSaveImage (NULL, binned,  "crmask.binn.fits");
     658        psphotSaveImage (NULL, conved,  "crmask.conv.fits");
     659        psphotSaveImage (NULL, edges,   "crmask.edge.fits");
     660        psphotSaveImage (NULL, mymask,  "crmask.mask.fits");
     661# endif
     662        psTrace("psphot.czw",2,"Iter: %d Count: %d",iteration, nCRpix);
     663    }
     664
     665# if 0
     666    // A solitary masked pixel is likely a lie. Remove those
     667    // XXX can't we use nCRpix == 1 to test for these?
     668    for (int x = 0; x < dx; x++) {
     669        for (int y = 0; y < dy; y++) {
     670            if (!(mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40)) continue;
     671            if ((x-1 >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x-1] & 0x40)) {
     672                continue;
     673            }
     674            if ((y-1 >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y-1][x] & 0x40)) {
     675                continue;
     676            }
     677            if ((x+1 < dx) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x+1] & 0x40)) {
     678                continue;
     679            }
     680            if ((y+1 < dy) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y+1][x] & 0x40)) {
     681                continue;
     682            }
     683            mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] ^= 0x40;
     684        }
     685    }
     686# endif
     687
     688    // transfer temporary mask to real mask & count masked pixels
     689    nCRpix = 0;
     690    for (int x = 0; x < dx; x++) {
     691        for (int y = 0; y < dy; y++) {
     692            if (mymask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & 0x40) {
     693                mask->data.PS_TYPE_IMAGE_MASK_DATA[y+ys+mask->row0][x+xs+mask->col0] |= maskVal;
     694                nCRpix ++;
     695            }
     696        }
     697    }
     698
     699    // XXX if we decide this REALLY is a cosmic ray, set the CR_LIMIT bit
     700    if (nCRpix > 1) {
     701        source->mode |= PM_SOURCE_MODE_CR_LIMIT;
     702        source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
     703    }
     704    // fprintf (stderr, "CRMASK %d %d %d %d %d\n", peak->x, peak->y, dx, dy, nCRpix);
     705
     706    psFree(mypix);
     707    psFree(myfix);
     708    psFree(myvar);
     709    psFree(binned);
     710    psFree(conved);
     711    psFree(edges);
     712    psFree(mymask);
     713
     714    return true;
     715}
     716
     717bool psphotMaskCosmicRayFootprintCheck (psArray *sources) {
     718
     719    for (int i = 0; i < sources->n; i++) {
     720        pmSource *source = sources->data[i];
     721        pmPeak *peak = source->peak;
     722        pmFootprint *footprint = peak->footprint;
     723        if (!footprint) continue;
     724        for (int j = 0; j < footprint->spans->n; j++) {
     725            pmSpan *sp = footprint->spans->data[j];
     726            psAssert (sp, "missing span");
     727        }
     728    }
     729    return true;
     730}
     731
     732/**** ------ old versions of cosmic ray masking ----- ****/
     733
     734bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask);
     735
     736// This attempt to mask the cosmic rays used the isophotal boundary
     737bool psphotMaskCosmicRay_V1 (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {
    93738
    94739    // replace the source flux
     
    103748    pmFootprint *footprint = peak->footprint;
    104749    if (!footprint) {
     750      psTrace("psphot.czw",2,"Using isophot CR mask code.");
     751
    105752        // if we have not footprint, use the old code to mask by isophot
    106753        psphotMaskCosmicRayIsophot (source, maskVal, crMask);
     
    109756
    110757    if (!footprint->spans) {
     758      psTrace("psphot.czw",2,"Using isophot CR mask code.");
     759
    111760        // if we have no footprint, use the old code to mask by isophot
    112761        psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    113762        return true;
    114763    }
    115 
     764    psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    116765    // mask all of the pixels covered by the spans of the footprint
    117766    for (int j = 1; j < footprint->spans->n; j++) {
     
    127776    }
    128777    return true;
     778}
     779
     780# define VERBOSE 0
     781int psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh) {
     782
     783    int xLo, xRo;
     784    int nCRpix = 0;
     785
     786    float noise_factor = 5.0 / 4.0;  // Intrinsic to the Laplacian making noise spikes spikier.
     787
     788    // mark the pixels in this row to the left, then the right. stay within footprint
     789    int xL = xPeak; // find the range of valid pixels in this row
     790    int xR = xPeak;
     791    for (int ix = xPeak; (ix >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[yPeak][ix] & 0x01); ix--) {
     792        float noise = binning * sqrt(noise_factor * myvar->data.F32[yPeak][ix]);
     793        float value = edges->data.F32[yPeak][ix] / noise;
     794        if (value < sigma_thresh ) break;
     795        mymask->data.PS_TYPE_IMAGE_MASK_DATA[yPeak][ix] |= 0x40;
     796        xL = ix;
     797        nCRpix ++;
     798        if (VERBOSE) fprintf (stderr, "mark %d,%d (%d) : %d - %d\n", ix, yPeak, nCRpix, xL, xR);
     799    }
     800    for (int ix = xPeak; (ix < mymask->numCols) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[yPeak][ix] & 0x01); ix++) {
     801        float noise = binning * sqrt(noise_factor * myvar->data.F32[yPeak][ix]);
     802        float value = edges->data.F32[yPeak][ix] / noise;
     803        if (value < sigma_thresh ) break;
     804        mymask->data.PS_TYPE_IMAGE_MASK_DATA[yPeak][ix] |= 0x40;
     805        xR = ix;
     806        nCRpix ++;
     807        if (VERBOSE) fprintf (stderr, "mark %d,%d (%d) : %d - %d\n", ix, yPeak, nCRpix, xL, xR);
     808    }
     809    // xL and xR mark the first and last valid pixel in the row
     810
     811    // for each of the neighboring rows, mark the high pixels if they touch the range xL to xR
     812    xLo = PS_MAX(xL - 1, 0);
     813    xRo = PS_MIN(xR + 1, mymask->numCols);
     814
     815    // first go down:
     816    for (int iy = yPeak - 1; iy >= 0; iy--) {
     817
     818        int xLn = -1;
     819        int xRn = -1;
     820        int newPix = 0;
     821
     822        // mark the pixels in the good range
     823        for (int ix = xLo; ix < xRo; ix++) {
     824            if (!(mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01)) continue; // only use pixels in the footprint
     825            float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]);
     826            float value = edges->data.F32[iy][ix] / noise;
     827            if (value < sigma_thresh ) continue;
     828            mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40;
     829            if (xLn == -1) xLn = ix; // first valid pixel in this row
     830            xRn = ix;                // last valid pixel in this row
     831            nCRpix ++;
     832            newPix ++;
     833            if (VERBOSE) fprintf (stderr, "mark C %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn);
     834        }
     835
     836        // mark the pixels to the left of the good range
     837        for (int ix = xLo; (ix >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01); ix--) {
     838            float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]);
     839            float value = edges->data.F32[iy][ix] / noise;
     840            if (value < sigma_thresh ) break;
     841            mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40;
     842            if (xRn == -1) xRn = ix; // last valid pixel in this row
     843            xLn = ix;
     844            nCRpix ++;
     845            newPix ++;
     846            if (VERBOSE) fprintf (stderr, "mark L %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn);
     847        }
     848
     849        // mark the pixels to the right of the good range
     850        for (int ix = xRo; (ix < mymask->numCols) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01); ix++) {
     851            float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]);
     852            float value = edges->data.F32[iy][ix] / noise;
     853            if (value < sigma_thresh ) break;
     854            mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40;
     855            if (xLn == -1) xLn = ix; // first valid pixel in this row
     856            xRn = ix;
     857            nCRpix ++;
     858            newPix ++;
     859            if (VERBOSE) fprintf (stderr, "mark R %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn);
     860        }
     861        if (newPix == 0) break;
     862        xLo = PS_MAX(xLn - 1, 0);
     863        xRo = PS_MIN(xRn + 1, mymask->numCols);
     864    }
     865
     866    xLo = PS_MAX(xL - 1, 0);
     867    xRo = PS_MIN(xR + 1, mymask->numCols);
     868
     869    // next go up:
     870    for (int iy = yPeak + 1; iy < mymask->numRows; iy++) {
     871
     872        int xLn = -1;
     873        int xRn = -1;
     874        int newPix = 0;
     875
     876        // mark the pixels in the good range
     877        for (int ix = xLo; ix < xRo; ix++) {
     878            if (!(mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01)) continue; // only use pixels in the footprint
     879            float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]);
     880            float value = edges->data.F32[iy][ix] / noise;
     881            if (value < sigma_thresh ) continue;
     882            mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40;
     883            if (xLn == -1) xLn = ix; // first valid pixel in this row
     884            xRn = ix;                // last valid pixel in this row
     885            nCRpix ++;
     886            newPix ++;
     887            if (VERBOSE) fprintf (stderr, "mark C %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn);
     888        }
     889
     890        // mark the pixels to the left of the good range
     891        for (int ix = xLo; (ix >= 0) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01); ix--) {
     892            float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]);
     893            float value = edges->data.F32[iy][ix] / noise;
     894            if (value < sigma_thresh ) break;
     895            mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40;
     896            if (xRn == -1) xRn = ix; // last valid pixel in this row
     897            xLn = ix;
     898            nCRpix ++;
     899            newPix ++;
     900            if (VERBOSE) fprintf (stderr, "mark L %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn);
     901        }
     902
     903        // mark the pixels to the right of the good range
     904        for (int ix = xRo; (ix < mymask->numCols) && (mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & 0x01); ix++) {
     905            float noise = binning * sqrt(noise_factor * myvar->data.F32[iy][ix]);
     906            float value = edges->data.F32[iy][ix] / noise;
     907            if (value < sigma_thresh ) break;
     908            mymask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= 0x40;
     909            if (xLn == -1) xLn = ix; // first valid pixel in this row
     910            xRn = ix;
     911            nCRpix ++;
     912            newPix ++;
     913            if (VERBOSE) fprintf (stderr, "mark R %d,%d (%d) : %d - %d | %d - %d | %d - %d \n", ix, iy, nCRpix, xL, xR, xLo, xRo, xLn, xRn);
     914        }
     915        if (newPix == 0) break;
     916        xLo = PS_MAX(xLn - 1, 0);
     917        xRo = PS_MIN(xRn + 1, mymask->numCols);
     918    }
     919
     920    return nCRpix;
    129921}
    130922
     
    192984        }
    193985    }
    194     return true;
    195 }
    196 
    197 // model the apmifit distribution for the psf stars:
    198 bool psphotSourceSizePSF (psphotSourceSizeOptions *options, psArray *sources, pmPSF *psf) {
    199 
    200     // select stats from the psf stars
    201     psVector *Ap = psVectorAllocEmpty (100, PS_TYPE_F32);
    202     psVector *ApErr = psVectorAllocEmpty (100, PS_TYPE_F32);
    203 
    204     psImageMaskType maskVal = options->maskVal | options->markVal;
    205 
    206     // XXX  why PHOT_WEIGHT??
    207     pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_WEIGHT;
    208 
    209     for (int i = 0; i < sources->n; i++) {
    210         pmSource *source = sources->data[i];
    211         if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue;
    212 
    213         // replace object in image
    214         if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) {
    215             pmSourceAdd (source, PM_MODEL_OP_FULL, options->maskVal);
    216         }
    217 
    218         // clear the mask bit and set the circular mask pixels
    219         psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
    220         psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", options->markVal);
    221 
    222         // XXX can we test if psfMag is set and calculate only if needed?
    223         pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
    224 
    225         // clear the mask bit
    226         psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
    227 
    228         // re-subtract the object, leave local sky
    229         pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal);
    230 
    231         float apMag = -2.5*log10(source->moments->Sum);
    232         float dMag = source->psfMag - apMag;
    233 
    234         psVectorAppend (Ap, 100, dMag);
    235         psVectorAppend (ApErr, 100, source->errMag);
    236     }
    237 
    238     // model the distribution as a mean or median value and a systematic error from that value:
    239     psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN);
    240     psVectorStats (stats, Ap, NULL, NULL, 0);
    241 
    242     psVector *dAp = psVectorAlloc (Ap->n, PS_TYPE_F32);
    243     for (int i = 0; i < Ap->n; i++) {
    244         dAp->data.F32[i] = Ap->data.F32[i] - stats->robustMedian;
    245     }
    246 
    247     options->ApResid = stats->robustMedian;
    248     options->ApSysErr = psVectorSystematicError(dAp, ApErr, 0.05);
    249     psLogMsg ("psphot", PS_LOG_DETAIL, "psf - Sum: %f +/- %f\n", options->ApResid, options->ApSysErr);
    250 
    251     psFree (Ap);
    252     psFree (ApErr);
    253     psFree (stats);
    254     psFree (dAp);
    255 
    256     return true;
    257 }
    258 
    259 // classify sources based on the combination of psf-mag, Mxx, Myy
    260 bool psphotSourceClass (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options) {
    261 
    262     bool status;
    263     pmPSFClump psfClump;
    264     char regionName[64];
    265 
    266     psLogMsg("psModules.objects", PS_LOG_INFO, "Source Size classifications: %4s %4s %4s %4s %4s %4s", "Npsf", "Next", "Nsat", "Ncr", "Nmiss", "Nskip");
    267 
    268     int nRegions = psMetadataLookupS32 (&status, readout->analysis, "PSF.CLUMP.NREGIONS");
    269     for (int i = 0; i < nRegions; i ++) {
    270         snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", i);
    271         psMetadata *regionMD = psMetadataLookupPtr (&status, readout->analysis, regionName);
    272         psAssert (regionMD, "regions must be defined by earlier call to psphotRoughClassRegion");
    273 
    274         psRegion *region = psMetadataLookupPtr (&status, regionMD, "REGION");
    275         psAssert (region, "regions must be defined by earlier call to psphotRoughClassRegion");
    276 
    277         // pull FWHM_X,Y from the recipe, use to define psfClump.X,Y
    278         psfClump.X  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");   psAssert (status, "missing PSF.CLUMP.X");
    279         psfClump.Y  = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y");   psAssert (status, "missing PSF.CLUMP.Y");
    280         psfClump.dX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX");  psAssert (status, "missing PSF.CLUMP.DX");
    281         psfClump.dY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY");  psAssert (status, "missing PSF.CLUMP.DY");
    282 
    283         if ((psfClump.X < 0) || (psfClump.Y < 0) || !psfClump.X || !psfClump.Y || isnan(psfClump.X) || isnan(psfClump.Y)) {
    284             psLogMsg ("psphot", 4, "Failed to find a valid PSF clump for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1);
    285             continue;
    286         }
    287 
    288         if (!psphotSourceClassRegion (region, &psfClump, sources, recipe, psf, options)) {
    289             psLogMsg ("psphot", 4, "Failed to determine source classification for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1);
    290             continue;
    291         }
    292     }
    293 
    294     return true;
    295 }
    296 
    297 bool psphotSourceClassRegion (psRegion *region, pmPSFClump *psfClump, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options) {
    298 
    299     PS_ASSERT_PTR_NON_NULL(sources, false);
    300     PS_ASSERT_PTR_NON_NULL(recipe, false);
    301 
    302     int Nsat  = 0;
    303     int Next  = 0;
    304     int Npsf  = 0;
    305     int Ncr   = 0;
    306     int Nmiss = 0;
    307     int Nskip = 0;
    308 
    309     pmSourceMode noMoments = PM_SOURCE_MODE_MOMENTS_FAILURE | PM_SOURCE_MODE_SKYVAR_FAILURE | PM_SOURCE_MODE_SKY_FAILURE | PM_SOURCE_MODE_BELOW_MOMENTS_SN;
    310     pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_WEIGHT;
    311 
    312     psImageMaskType maskVal = options->maskVal | options->markVal;
    313 
    314     for (psS32 i = 0 ; i < sources->n ; i++) {
    315 
    316         pmSource *source = (pmSource *) sources->data[i];
    317 
    318         // psfClumps are found for image subregions:
    319         // skip sources not in this region
    320         if (source->peak->x <  region->x0) continue;
    321         if (source->peak->x >= region->x1) continue;
    322         if (source->peak->y <  region->y0) continue;
    323         if (source->peak->y >= region->y1) continue;
    324 
    325         // skip source if it was already measured
    326         if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) {
    327             psTrace("psphot", 7, "Not calculating source size since it has already been measured\n");
    328             continue;
    329         }
    330 
    331         // source must have been subtracted
    332         if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) {
    333             source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED;
    334             psTrace("psphot", 7, "Not calculating source size since source is not subtracted\n");
    335             continue;
    336         }
    337 
    338         // we are basically classifying by moments; use the default if not found
    339         psAssert (source->moments, "why is this source missing moments?");
    340         if (source->mode & noMoments) {
    341             Nskip ++;
    342             continue;
    343         }
    344 
    345         psF32 Mxx = source->moments->Mxx;
    346         psF32 Myy = source->moments->Myy;
    347 
    348         // replace object in image
    349         if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) {
    350             pmSourceAdd (source, PM_MODEL_OP_FULL, options->maskVal);
    351         }
    352 
    353         // clear the mask bit and set the circular mask pixels
    354         psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
    355         psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", options->markVal);
    356 
    357         // XXX can we test if psfMag is set and calculate only if needed?
    358         pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal
    359 
    360         // clear the mask bit
    361         psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal));
    362 
    363         // re-subtract the object, leave local sky
    364         pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal);
    365 
    366         float apMag = -2.5*log10(source->moments->Sum);
    367         float dMag = source->psfMag - apMag;
    368         float nSigma = (dMag - options->ApResid) / hypot(source->errMag, options->ApSysErr);
    369 
    370         source->extNsigma = nSigma;
    371         source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
    372 
    373         // Anything within this region is a probably PSF-like object. Saturated stars may land
    374         // in this region, but are detected elsewhere on the basis of their peak value.
    375         bool isPSF = (fabs(nSigma) < options->nSigmaApResid) && (fabs(Mxx - psfClump->X) < options->nSigmaMoments*psfClump->dX) && (fabs(Myy - psfClump->Y) < options->nSigmaMoments*psfClump->dY);
    376         if (isPSF) {
    377             Npsf ++;
    378             continue;
    379         }
    380 
    381         // Defects may not always match CRs from peak curvature analysis
    382         // Defects may also be marked as SATSTAR -- XXX deactivate this flag?
    383         // XXX this rule is not great
    384         if ((Mxx < psfClump->X) || (Myy < psfClump->Y)) {
    385             source->mode |= PM_SOURCE_MODE_DEFECT;
    386             Ncr ++;
    387             continue;
    388         }
    389 
    390         // saturated star (determined in PSF fit).  These may also be saturated galaxies, or
    391         // just large saturated regions.
    392         if (source->mode & PM_SOURCE_MODE_SATSTAR) {
    393             Nsat ++;
    394             continue;
    395         }
    396 
    397         // XXX allow the Mxx, Myy to be less than psfClump->X,Y (by some nSigma)?
    398         bool isEXT = (nSigma > options->nSigmaApResid) || ((Mxx > psfClump->X) && (Myy > psfClump->Y));
    399         if (isEXT) {
    400             source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
    401             Next ++;
    402             continue;
    403         }
    404 
    405         psWarning ("sourse size was missed for %f,%f : %f %f -- %f\n", source->peak->xf, source->peak->yf, Mxx, Myy, nSigma);
    406         Nmiss ++;
    407     }
    408 
    409     psLogMsg("psModules.objects", PS_LOG_INFO, "Source Size classifications: %4d %4d %4d %4d %4d %4d", Npsf, Next, Nsat, Ncr, Nmiss, Nskip);
    410 
    411986    return true;
    412987}
     
    4861061}
    4871062
    488 bool psphotSourceSizeCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) {
     1063// this was an old attempt to identify cosmic rays based on the peak curvature
     1064bool psphotSourcePeakCurvature (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) {
    4891065
    4901066    // classify the sources based on the CR test (place this in a function?)
     
    6181194    return true;
    6191195}
     1196
  • branches/tap_branches/psphot/src/psphotSourceStats.c

    r25852 r27838  
    11# include "psphotInternal.h"
    22
    3 bool psphotSetMomentsWindow (psMetadata *recipe, psMetadata *analysis, psArray *sources);
    4 
    5 psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections, bool setWindow) {
     3// convert detections to sources and measure their basic properties (moments, local sky, sky
     4// variance) Note: this function only generates sources for the new peaks (peak->assigned).
     5// The new sources are added to any existing sources on detections->newSources.  The sources
     6// on detections->allSources are ignored.
     7bool psphotSourceStats (pmConfig *config, const pmFPAview *view, bool setWindow)
     8{
     9    bool status = true;
     10
     11    // select the appropriate recipe information
     12    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     13    psAssert (recipe, "missing recipe?");
     14
     15    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     16    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     17
     18    // loop over the available readouts
     19    for (int i = 0; i < num; i++) {
     20        if (!psphotSourceStatsReadout (config, view, "PSPHOT.INPUT", i, recipe, setWindow)) {
     21            psError (PSPHOT_ERR_CONFIG, false, "failed to find initial detections for PSPHOT.INPUT entry %d", i);
     22            return false;
     23        }
     24    }
     25    return true;
     26}
     27
     28bool psphotSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool setWindow) {
    629
    730    bool status = false;
     
    1033    psTimerStart ("psphot.stats");
    1134
    12     // select the appropriate recipe information
    13     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    14     assert (recipe);
     35    // find the currently selected readout
     36    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     37    psAssert (file, "missing file?");
     38
     39    pmReadout *readout = pmFPAviewThisReadout(view, file->fpa);
     40    psAssert (readout, "missing readout?");
     41
     42    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
     43    psAssert (detections, "missing detections?");
     44
     45    // XXX TEST:
     46    if (detections->allSources) {
     47        psphotMaskCosmicRayFootprintCheck(detections->allSources);
     48    }
     49    if (detections->newSources) {
     50        psphotMaskCosmicRayFootprintCheck(detections->newSources);
     51    }
    1552
    1653    // determine the number of allowed threads
     
    2158
    2259    // determine properties (sky, moments) of initial sources
    23     float OUTER    = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
    24     if (!status) return NULL;
    25 
     60    float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
     61    psAssert (status, "missing SKY_OUTER_RADIUS in recipe?");
     62
     63    // XXX this seems like an arbitrary number...
    2664    OUTER = PS_MAX(OUTER, 20.0); // XXX Guarantee that we can encompass the max moments radius
    2765
    2866    char *breakPt  = psMetadataLookupStr (&status, recipe, "BREAK_POINT");
    29     if (!status) return NULL;
     67    psAssert (status, "missing BREAK_POINT?");
     68
     69    float INNER        = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS"); psAssert (status, "missing SKY_INNER_RADIUS");
     70    float MIN_SN       = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); psAssert (status, "missing MOMENTS_SN_MIN");
     71
     72    // bit-masks to test for good/bad pixels
     73    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT");
     74    psAssert (maskVal, "missing MASK.PSPHOT");
     75
     76    // bit-mask to mark pixels not used in analysis
     77    psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT");
     78    psAssert (markVal, "missing MARK.PSPHOT");
    3079
    3180    psArray *peaks = detections->peaks;
    3281    if (!peaks) {
    3382        psError(PS_ERR_UNEXPECTED_NULL, false, "No peaks found!");
    34         return NULL;
     83        return false;
    3584    }
    3685
    3786    // generate the array of sources, define the associated pixel
    38     sources = psArrayAllocEmpty (peaks->n);
     87    if (!detections->newSources) {
     88        detections->newSources = psArrayAllocEmpty (peaks->n);
     89    }
     90    sources = detections->newSources;
     91
     92    // if there are no peaks, we save the empty source array and return
     93    if (!peaks->n) {
     94        return true;
     95    }
    3996
    4097    for (int i = 0; i < peaks->n; i++) {
     
    45102        // create a new source
    46103        pmSource *source = pmSourceAlloc();
     104        source->imageID = index;
    47105
    48106        // add the peak
     
    58116        psArrayAdd (sources, 100, source);
    59117        psFree (source);
     118    }
     119
     120    if (!strcasecmp (breakPt, "PEAKS")) {
     121        psLogMsg ("psphot", PS_LOG_INFO, "%ld sources : %f sec\n", sources->n, psTimerMark ("psphot.stats"));
     122        psLogMsg ("psphot", PS_LOG_INFO, "break point PEAKS, skipping MOMENTS\n");
     123        psphotVisualShowMoments (sources);
     124        return true;
     125    }
     126
     127    if (setWindow) {
     128        if (!psphotSetMomentsWindow(recipe, readout->analysis, sources)) {
     129            psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!");
     130            psFree(detections->newSources);
     131            return false;
     132        }
     133    }
     134
     135    // if we have measured the window, we will be saving the modified version of these recipe values on readout->analysis
     136    float SIGMA = psMetadataLookupF32 (&status, readout->analysis, "MOMENTS_GAUSS_SIGMA");
     137    if (!status) {
     138        SIGMA = psMetadataLookupF32 (&status, recipe, "MOMENTS_GAUSS_SIGMA");
     139    }
     140    float RADIUS = psMetadataLookupF32 (&status, readout->analysis, "PSF_MOMENTS_RADIUS");
     141    if (!status) {
     142        RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS");
     143    }
     144
     145    // threaded measurement of the source magnitudes
     146    int Nfail = 0;
     147    int Nmoments = 0;
     148    int Nfaint = 0;
     149
     150    // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts)
     151    int Cx = 1, Cy = 1;
     152    psphotChooseCellSizes (&Cx, &Cy, readout, nThreads);
     153
     154    psArray *cellGroups = psphotAssignSources (Cx, Cy, sources);
     155
     156    for (int i = 0; i < cellGroups->n; i++) {
     157
     158        psArray *cells = cellGroups->data[i];
     159
     160        for (int j = 0; j < cells->n; j++) {
     161
     162            // allocate a job -- if threads are not defined, this just runs the job
     163            psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS");
     164
     165            psArrayAdd(job->args, 1, cells->data[j]); // sources
     166
     167            PS_ARRAY_ADD_SCALAR(job->args, INNER,   PS_TYPE_F32);
     168            PS_ARRAY_ADD_SCALAR(job->args, MIN_SN,  PS_TYPE_F32);
     169            PS_ARRAY_ADD_SCALAR(job->args, RADIUS,  PS_TYPE_F32);
     170            PS_ARRAY_ADD_SCALAR(job->args, SIGMA,   PS_TYPE_F32);
     171
     172            PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK);
     173            PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK);
     174
     175            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nmoments
     176            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfail
     177            PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nfaint
     178
     179            if (!psThreadJobAddPending(job)) {
     180                psError(PS_ERR_UNKNOWN, false, "Unable to launch thread job PSPHOT_SOURCE_STATS");
     181                psFree (job);
     182                psFree(detections->newSources);
     183                return false;
     184            }
     185            psFree(job);
     186        }
     187
     188        // wait for the threads to finish and manage results
     189        if (!psThreadPoolWait (false)) {
     190            psError(PS_ERR_UNKNOWN, false, "Failure in thread job PSPHOT_SOURCE_STATS");
     191            psFree(detections->newSources);
     192            return false;
     193        }
     194
     195        // we have only supplied one type of job, so we can assume the types here
     196        psThreadJob *job = NULL;
     197        while ((job = psThreadJobGetDone()) != NULL) {
     198            if (job->args->n < 1) {
     199                fprintf (stderr, "error with job\n");
     200            } else {
     201                psScalar *scalar = NULL;
     202                scalar = job->args->data[7];
     203                Nmoments += scalar->data.S32;
     204                scalar = job->args->data[8];
     205                Nfail += scalar->data.S32;
     206                scalar = job->args->data[9];
     207                Nfaint += scalar->data.S32;
     208            }
     209            psFree(job);
     210        }
     211    }
     212
     213    psFree (cellGroups);
     214
     215    psLogMsg ("psphot", PS_LOG_INFO, "%ld sources, %d moments, %d faint, %d failed: %f sec\n", sources->n, Nmoments, Nfaint, Nfail, psTimerMark ("psphot.stats"));
     216
     217    psphotVisualShowMoments (sources);
     218
     219    if (detections->allSources) {
     220        psphotMaskCosmicRayFootprintCheck(detections->allSources);
     221    }
     222    if (detections->newSources) {
     223        psphotMaskCosmicRayFootprintCheck(detections->newSources);
     224    }
     225
     226    return true;
     227}
     228
     229// this function is currently only called by psphotCheckExtSources
     230bool psphotSourceStatsUpdate (psArray *sources, pmConfig *config, pmReadout *readout) {
     231
     232    bool status = false;
     233
     234    psTimerStart ("psphot.stats");
     235
     236    // select the appropriate recipe information
     237    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     238    assert (recipe);
     239
     240    // determine the number of allowed threads
     241    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
     242    if (!status) {
     243        nThreads = 0;
     244    }
     245
     246    // determine properties (sky, moments) of initial sources
     247    float OUTER    = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS");
     248    if (!status) return false;
     249
     250    OUTER = PS_MAX(OUTER, 20.0); // XXX Guarantee that we can encompass the max moments radius
     251
     252    char *breakPt  = psMetadataLookupStr (&status, recipe, "BREAK_POINT");
     253    if (!status) return false;
     254
     255    for (int i = 0; i < sources->n; i++) {
     256
     257        pmSource *source = sources->data[i];
     258        if (!source->peak) continue; // XXX how can we have a peak-less source?
     259
     260        // allocate space for moments
     261        if (!source->moments) {
     262            source->moments = pmMomentsAlloc();
     263        }
     264
     265        // allocate image, weight, mask arrays for each peak (square of radius OUTER)
     266        pmSourceDefinePixels (source, readout, source->peak->x, source->peak->y, OUTER);
     267        source->peak->assigned = true;
    60268    }
    61269
     
    67275    }
    68276
    69     if (setWindow) {
    70         if (!psphotSetMomentsWindow(recipe, readout->analysis, sources)) {
    71             psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!");
    72             return NULL;
    73         }
     277    // XXX how else could we get the window size in?
     278    if (!psphotSetMomentsWindow(recipe, readout->analysis, sources)) {
     279        psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!");
     280        return NULL;
    74281    }
    75282
     
    94301            psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS");
    95302
     303            // XXX: this must match the above
    96304            psArrayAdd(job->args, 1, cells->data[j]); // sources
    97305            psArrayAdd(job->args, 1, recipe);
     
    148356
    149357    psArray *sources                = job->args->data[0];
    150     psMetadata *recipe              = job->args->data[1];
    151 
    152     float INNER        = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS");
    153     if (!status) return false;
    154     float MIN_SN       = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN");
    155     if (!status) return false;
    156     float RADIUS       = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS");
    157     if (!status) return false;
    158     float SIGMA        = psMetadataLookupF32 (&status, recipe, "MOMENTS_GAUSS_SIGMA");
    159     if (!status) return false;
    160 
    161     // bit-masks to test for good/bad pixels
    162     psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT");
    163     assert (maskVal);
    164 
    165     // bit-mask to mark pixels not used in analysis
    166     psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT");
    167     assert (markVal);
     358
     359    float INNER                     = PS_SCALAR_VALUE(job->args->data[1],F32);
     360    float MIN_SN                    = PS_SCALAR_VALUE(job->args->data[2],F32);
     361    float RADIUS                    = PS_SCALAR_VALUE(job->args->data[3],F32);
     362    float SIGMA                     = PS_SCALAR_VALUE(job->args->data[4],F32);
     363
     364    psImageMaskType maskVal         = PS_SCALAR_VALUE(job->args->data[5],PS_TYPE_IMAGE_MASK_DATA);
     365    psImageMaskType markVal         = PS_SCALAR_VALUE(job->args->data[6],PS_TYPE_IMAGE_MASK_DATA);
    168366
    169367    // maskVal is used to test for rejected pixels, and must include markVal
     
    176374    for (int i = 0; i < sources->n; i++) {
    177375        pmSource *source = sources->data[i];
     376
     377        if (source->tmpFlags & PM_SOURCE_TMPF_MOMENTS_MEASURED) continue;
     378        source->tmpFlags |= PM_SOURCE_TMPF_MOMENTS_MEASURED;
    178379
    179380        // skip faint sources for moments measurement
     
    205406
    206407        // measure basic source moments (no S/N clipping on input pixels)
    207         status = pmSourceMoments (source, RADIUS, SIGMA, 0.0);
     408        status = pmSourceMoments (source, RADIUS, SIGMA, 0.0, maskVal);
    208409        if (status) {
    209410            Nmoments ++;
     
    215416        BIG_RADIUS = PS_MIN (INNER, 3*RADIUS);
    216417        psTrace ("psphot", 4, "retrying moments for %d, %d\n", source->peak->x, source->peak->y);
    217         status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, 0.0);
     418        status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, 0.0, maskVal);
    218419        if (status) {
    219420            source->mode |= PM_SOURCE_MODE_BIG_RADIUS;
     
    229430
    230431    // change the value of a scalar on the array (wrap this and put it in psArray.h)
    231     scalar = job->args->data[2];
     432    scalar = job->args->data[7];
    232433    scalar->data.S32 = Nmoments;
    233434
    234     scalar = job->args->data[3];
     435    scalar = job->args->data[8];
    235436    scalar->data.S32 = Nfail;
    236437
    237     scalar = job->args->data[4];
     438    scalar = job->args->data[9];
    238439    scalar->data.S32 = Nfaint;
    239440
     
    242443
    243444// this function attempts to iteratively determine the best value for sigma of the moments weighting Gaussian
     445// this function modifies the recipe values MOMENTS_SX_MAX, MOMENTS_SY_MAX, and PSF_CLUMP_GRID_SCALE, used by pmSourcePSFClump
    244446bool psphotSetMomentsWindow (psMetadata *recipe, psMetadata *analysis, psArray *sources) {
    245447
    246448    bool status;
    247449
    248     float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN");
    249     if (!status) return false;
     450    float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); psAssert (status, "missing MOMENTS_SN_MIN");
     451    float PSF_SN_LIM = psMetadataLookupF32(&status, recipe, "PSF_SN_LIM"); psAssert (status, "missing PSF_SN_LIM");
     452    psF32 MOMENTS_AR_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_AR_MAX"); psAssert (status, "missing MOMENTS_AR_MAX");
    250453
    251454    // XXX move this to a config file?
    252     float sigma[4] = {1.0, 2.0, 3.0, 4.5};
    253     float Sout[4];
     455    # define NSIGMA 8
     456    float sigma[NSIGMA] = {1.0, 2.0, 3.0, 4.5, 6.0, 9.0, 12.0, 18.0};
     457    float Sout[NSIGMA];
    254458
    255459    // this sorts by peak->SN
     
    257461
    258462    // loop over radii:
    259     for (int i = 0; i < 4; i++) {
     463    for (int i = 0; i < NSIGMA; i++) {
    260464
    261465        // XXX move max source number to config
     
    272476
    273477            // measure basic source moments (no S/N clipping on input pixels)
    274             status = pmSourceMoments (source, 4*sigma[i], sigma[i], 0.0);
     478            status = pmSourceMoments (source, 4*sigma[i], sigma[i], 0.0, 0xffff);
    275479        }
    276480
    277481        // choose a grid scale that is a fixed fraction of the psf sigma^2
    278         psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_CLUMP_GRID_SCALE", PS_META_REPLACE, "clump grid", 0.1*PS_SQR(sigma[i]));
    279         psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SX_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(sigma[i]));
    280         psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SY_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(sigma[i]));
     482        float PSF_CLUMP_GRID_SCALE = 0.1*PS_SQR(sigma[i]);
     483        float MOMENTS_SX_MAX = 2.0*PS_SQR(sigma[i]);
     484        float MOMENTS_SY_MAX = 2.0*PS_SQR(sigma[i]);
    281485
    282486        // determine the PSF parameters from the source moment values
    283         pmPSFClump psfClump = pmSourcePSFClump (NULL, sources, recipe);
     487        pmPSFClump psfClump = pmSourcePSFClump (NULL, NULL, sources, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_AR_MAX);
    284488        psLogMsg ("psphot", 3, "radius %.1f, nStars: %d, nSigma: %5.2f, X,  Y: %f, %f (%f, %f)\n", sigma[i], psfClump.nStars, psfClump.nSigma, psfClump.X, psfClump.Y, sqrt(psfClump.X) / sigma[i], sqrt(psfClump.Y) / sigma[i]);
    285489
     
    296500        psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY);
    297501
    298         // psphotVisualPlotMoments (recipe, sources);
     502        psphotVisualPlotMoments (recipe, analysis, sources);
    299503
    300504        Sout[i] = sqrt(0.5*(psfClump.X + psfClump.Y)) / sigma[i];
     
    302506
    303507    // we are looking for sigma for which Sout = 0.65 (or some other value)
    304 
    305508    float Sigma = NAN;
    306509    float minS = Sout[0];
    307510    float maxS = Sout[0];
    308     for (int i = 0; i < 4; i++) {
     511    for (int i = 0; i < NSIGMA; i++) {
    309512        minS = PS_MIN(Sout[i], minS);
    310513        maxS = PS_MAX(Sout[i], maxS);
    311514    }
    312     if (minS > 0.65) Sigma = sigma[3];
     515    if (minS > 0.65) Sigma = sigma[NSIGMA-1];
    313516    if (maxS < 0.65) Sigma = sigma[0];
    314517
    315     for (int i = 0; i < 3; i++) {
     518    for (int i = 0; i < NSIGMA - 1 && isnan(Sigma); i++) {
     519        if (!isfinite(Sout[i]) || !isfinite(Sout[i+1])) continue;
    316520        if ((Sout[i] > 0.65) && (Sout[i+1] > 0.65)) continue;
    317521        if ((Sout[i] < 0.65) && (Sout[i+1] < 0.65)) continue;
     
    321525
    322526    // choose a grid scale that is a fixed fraction of the psf sigma^2
    323     psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_CLUMP_GRID_SCALE", PS_META_REPLACE, "clump grid", 0.1*PS_SQR(Sigma));
    324     psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SX_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma));
    325     psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SY_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma));
    326     psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_GAUSS_SIGMA", PS_META_REPLACE, "moments limit", Sigma);
    327     psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_MOMENTS_RADIUS", PS_META_REPLACE, "moments limit", 4.0*Sigma);
     527    psMetadataAddF32(analysis, PS_LIST_TAIL, "PSF_CLUMP_GRID_SCALE", PS_META_REPLACE, "clump grid", 0.1*PS_SQR(Sigma));
     528    psMetadataAddF32(analysis, PS_LIST_TAIL, "MOMENTS_SX_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma));
     529    psMetadataAddF32(analysis, PS_LIST_TAIL, "MOMENTS_SY_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma));
     530    psMetadataAddF32(analysis, PS_LIST_TAIL, "MOMENTS_GAUSS_SIGMA", PS_META_REPLACE, "moments limit", Sigma);
     531    psMetadataAddF32(analysis, PS_LIST_TAIL, "PSF_MOMENTS_RADIUS", PS_META_REPLACE, "moments limit", 4.0*Sigma);
    328532
    329533    psLogMsg ("psphot", 3, "using window function with sigma = %f\n", Sigma);
    330534    return true;
    331535}
     536
     537// if we use the footprints, the output peaks list contains both old and new peaks,
     538// otherwise it only contains the new peaks.
     539
  • branches/tap_branches/psphot/src/psphotSubtractBackground.c

    r23287 r27838  
    44// generate the median in NxN boxes, clipping heavily
    55// linear interpolation to generate full-scale model
    6 bool psphotSubtractBackground (pmConfig *config, const pmFPAview *view, const char *filename)
     6bool psphotSubtractBackgroundReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe)
    77{
    88    bool status = true;
     
    1313
    1414    // find the currently selected readout
    15     pmFPAfile *file = psMetadataLookupPtr (&status, config->files, filename);
     15    pmFPAfile *file = pmFPAfileSelectSingle(config->files, filename, index); // File of interest
     16
    1617    pmFPA *inFPA = file->fpa;
    1718    pmReadout *readout = pmFPAviewThisReadout (view, inFPA);
     
    1920    psImage *mask  = readout->mask;
    2021
    21     // find the currently selected readout
    22     pmReadout *model = pmFPAfileThisReadout (config->files, view, "PSPHOT.BACKMDL");
     22    // find the currently selected readout (XXX note that the model is saved on PSPHOT.BACKMDL regardless of 'filename'
     23    pmFPAfile *modelFile = pmFPAfileSelectSingle(config->files, "PSPHOT.BACKMDL", index); // File of interest
     24    assert (modelFile);
     25
     26    pmReadout *model = NULL;
     27    if (modelFile->mode == PM_FPA_MODE_INTERNAL) {
     28        model = modelFile->readout;
     29    } else {
     30        model = pmFPAviewThisReadout (view, modelFile->fpa);
     31    }
    2332    assert (model);
    24 
    25     // select the appropriate recipe information
    26     psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
    27     assert (recipe);
    2833
    2934    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     
    3540
    3641    // select background pixels, from output background file, or create
     42    // XXX for now, we will only allow a single background image to be generated
    3743    file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKGND");
    3844    if (file) {
     
    6672
    6773    // back-sub image pixels, from output background file (don't create if not requested)
     74    // XXX for now, we will only allow a single background-subtracted image to be generated
    6875    file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKSUB");
    6976    if (file) {
     
    109116    // the pmReadout selected in this function are all view on entries in config->files
    110117
     118    // display the backsub and backgnd images
     119    // move this inthe the subtract background loop
     120    psphotVisualShowBackground (config, view, readout);
     121
    111122    npass ++;
    112123    return true;
    113124}
     125
     126bool psphotSubtractBackground (pmConfig *config, const pmFPAview *view)
     127{
     128    bool status = false;
     129
     130    // select the appropriate recipe information
     131    psMetadata *recipe  = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);
     132    psAssert (recipe, "missing recipe?");
     133
     134    int num = psMetadataLookupS32 (&status, config->arguments, "PSPHOT.INPUT.NUM");
     135    psAssert (status, "programming error: must define PSPHOT.INPUT.NUM");
     136
     137    // loop over the available readouts
     138    for (int i = 0; i < num; i++) {
     139        if (!psphotSubtractBackgroundReadout (config, view, "PSPHOT.INPUT", i, recipe)) {
     140            psError (PSPHOT_ERR_CONFIG, false, "failed to subtract background for PSPHOT.INPUT entry %d", i);
     141            return false;
     142        }
     143    }
     144    return true;
     145}
  • branches/tap_branches/psphot/src/psphotVisual.c

    r25852 r27838  
    6060}
    6161
     62bool psphotVisualEraseOverlays (int channel, char *overlay) {
     63
     64    int myKapa = psphotKapaChannel (channel);
     65    if (!(strcasecmp (overlay, "all"))) {
     66      KiiEraseOverlay (myKapa, "red");
     67      KiiEraseOverlay (myKapa, "green");
     68      KiiEraseOverlay (myKapa, "blue");
     69      KiiEraseOverlay (myKapa, "yellow");
     70      return true;
     71    }
     72    KiiEraseOverlay (myKapa, overlay);
     73    return true;
     74}
     75
    6276bool psphotVisualShowMask (int kapaFD, psImage *inImage, const char *name, int channel) {
    6377
     
    106120}
    107121
    108 bool psphotVisualScaleImage (int kapaFD, psImage *inImage, const char *name, int channel) {
     122bool psphotVisualScaleImage (int kapaFD, psImage *inImage, psImage *inMask, const char *name, int channel) {
    109123
    110124    KiiImage image;
     
    116130    psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    117131    psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
    118     if (!psImageBackground(stats, NULL, inImage, NULL, 0, rng)) {
     132    if (!psImageBackground(stats, NULL, inImage, inMask, 0xffff, rng)) {
    119133        fprintf (stderr, "failed to get background values\n");
    120134        return false;
     
    171185    if (kapa == -1) return false;
    172186
    173     // psphotVisualShowMask (kapa, readout->mask, "mask", 2);
    174     psphotVisualScaleImage (kapa, readout->variance, "variance", 1);
    175     psphotVisualScaleImage (kapa, readout->image, "image", 0);
     187    psphotVisualShowMask (kapa, readout->mask, "mask", 2);
     188    psphotVisualScaleImage (kapa, readout->variance, readout->mask, "variance", 1);
     189    psphotVisualScaleImage (kapa, readout->image, readout->mask, "image", 0);
    176190
    177191    pmVisualAskUser(NULL);
     
    197211    }
    198212
    199     psphotVisualScaleImage (kapa, backgnd->image, "backgnd", 2);
    200     psphotVisualScaleImage (kapa, readout->image, "backsub", 0);
     213    psphotVisualScaleImage (kapa, backgnd->image, readout->mask, "backgnd", 2);
     214    psphotVisualScaleImage (kapa, readout->image, readout->mask, "backsub", 0);
    201215
    202216    pmVisualAskUser(NULL);
     
    204218}
    205219
    206 bool psphotVisualShowSignificance (psImage *image) {
     220bool psphotVisualShowSignificance (psImage *image, float min, float max) {
    207221
    208222    if (!pmVisualIsVisual()) return true;
     
    211225    if (kapa == -1) return false;
    212226
    213     psphotVisualRangeImage (kapa, image, "signif", 2, -1.0, 25.0*25.0);
     227    psphotVisualRangeImage (kapa, image, "signif", 2, min, max);
    214228
    215229    pmVisualAskUser(NULL);
     
    247261        overlay[Noverlay].text = NULL;
    248262        Noverlay ++;
    249 
    250 # if (0)
    251         overlay[Noverlay].type = KII_OVERLAY_BOX;
    252         overlay[Noverlay].x = peak->x;
    253         overlay[Noverlay].y = peak->y;
    254         overlay[Noverlay].dx = 1.0;
    255         overlay[Noverlay].dy = 1.0;
    256         overlay[Noverlay].angle = 0.0;
    257         overlay[Noverlay].text = NULL;
    258         Noverlay ++;
    259 
    260         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    261         overlay[Noverlay].x = peak->xf;
    262         overlay[Noverlay].y = peak->yf;
    263         overlay[Noverlay].dx = 2.0;
    264         overlay[Noverlay].dy = 2.0;
    265         overlay[Noverlay].angle = 0.0;
    266         overlay[Noverlay].text = NULL;
    267         Noverlay ++;
    268 # endif
    269     }
    270 
    271 # if (1)
    272     overlay[Noverlay].type = KII_OVERLAY_BOX;
    273     overlay[Noverlay].x = 10.0;
    274     overlay[Noverlay].y = 10.0;
    275     overlay[Noverlay].dx = 1.0;
    276     overlay[Noverlay].dy = 1.0;
    277     overlay[Noverlay].angle = 0.0;
    278     overlay[Noverlay].text = NULL;
    279     Noverlay ++;
    280 # endif
     263    }
    281264
    282265    KiiLoadOverlay (kapa, overlay, Noverlay, "red");
     
    463446    KapaSetFont (myKapa, "courier", 14);
    464447
     448    section.bg = KapaColorByName ("none"); // XXX probably should be 'none'
     449
    465450    float SN_LIM = psMetadataLookupF32(&status, recipe, "PSF_SN_LIM");
    466451
     
    494479    Xmin = PS_MAX(Xmin, -0.1);
    495480    Ymin = PS_MAX(Ymin, -0.1);
     481
     482    // XXX test: hardwire plot limits
     483    // Xmin = -0.1; Ymin = -0.1;
     484    // Xmax = 20.1; Ymax = 20.1;
    496485
    497486    // storage vectors for data to be plotted
     
    551540    KapaSetLimits (myKapa, &graphdata);
    552541
     542    graphdata.padXm = NAN;
     543    graphdata.padYm = NAN;
     544    graphdata.padXp = 0.5;
     545    graphdata.padYp = 0.5;
    553546    KapaBox (myKapa, &graphdata);
     547
    554548    KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM);
    555549    KapaSendLabel (myKapa, "M_yy| (pixels)", KAPA_LABEL_YM);
     
    560554    graphdata.style = 2;
    561555    KapaPrepPlot (myKapa, nF, &graphdata);
     556
    562557    KapaPlotVector (myKapa, nF, xFaint->data.F32, "x");
    563558    KapaPlotVector (myKapa, nF, yFaint->data.F32, "y");
     
    575570    section.dy = 0.25;
    576571    section.x  = 0.00;
    577     section.y  = 0.80;
     572    section.y  = 0.75;
    578573    section.name = psStringCopy ("MagMyy");
    579574    KapaSetSection (myKapa, &section);
     
    587582    KapaSetLimits (myKapa, &graphdata);
    588583
     584    graphdata.padXm = 0.5;
     585    graphdata.padYm = NAN;
     586    graphdata.padXp = NAN;
     587    graphdata.padYp = 0.5;
    589588    strcpy (graphdata.labels, "0210");
    590589    KapaBox (myKapa, &graphdata);
     
    611610    section.dx = 0.25;
    612611    section.dy = 0.75;
    613     section.x  = 0.80;
     612    section.x  = 0.75;
    614613    section.y  = 0.00;
    615614    section.name = psStringCopy ("MagMxx");
     
    624623    KapaSetLimits (myKapa, &graphdata);
    625624
     625    graphdata.padXm = NAN;
     626    graphdata.padYm = 0.5;
     627    graphdata.padXp = 0.5;
     628    graphdata.padYp = NAN;
    626629    strcpy (graphdata.labels, "2001");
    627630    KapaBox (myKapa, &graphdata);
     
    654657
    655658        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    656         float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, analysis, "PSF_CLUMP_NSIGMA");
     659        float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
    657660
    658661        graphdata.color = KapaColorByName ("blue");
     
    11071110    }
    11081111
    1109     psphotVisualScaleImage (myKapa, outsat, "satstar", 2);
     1112    psphotVisualScaleImage (myKapa, outsat, NULL, "satstar", 2);
    11101113
    11111114    pmVisualAskUser(NULL);
    11121115    psFree (outsat);
    11131116    return true;
     1117}
     1118
     1119static void plotline (int myKapa, Graphdata *graphdata, float x0, float y0, float x1, float y1)
     1120{
     1121    float x[2], y[2];
     1122    x[0] = x0;
     1123    x[1] = x1;
     1124    y[0] = y0;
     1125    y[1] = y1;
     1126    KapaPrepPlot   (myKapa, 2, graphdata);
     1127    KapaPlotVector (myKapa, 2, x, "x");
     1128    KapaPlotVector (myKapa, 2, y, "y");
    11141129}
    11151130
     
    11511166    }
    11521167
     1168    // generate model profiles (major and minor axis):
     1169    // create a model with theta = 0.0 so major and minor axes are equiv to x and y:
     1170    psEllipseShape rawShape, rotShape;
     1171
     1172    rawShape.sx  = source->modelPSF->params->data.F32[PM_PAR_SXX] / M_SQRT2;
     1173    rawShape.sy  = source->modelPSF->params->data.F32[PM_PAR_SYY] / M_SQRT2;
     1174    rawShape.sxy = source->modelPSF->params->data.F32[PM_PAR_SXY];
     1175
     1176    psEllipseAxes axes = psEllipseShapeToAxes (rawShape, 20.0);
     1177
     1178    axes.theta = 0.0;
     1179
     1180    rotShape = psEllipseAxesToShape (axes);
     1181
     1182    psVector *params = psVectorAlloc(source->modelPSF->params->n, PS_TYPE_F32);
     1183    for (int i = 0; i < source->modelPSF->params->n; i++) {
     1184        params->data.F32[i] = source->modelPSF->params->data.F32[i];
     1185    }
     1186    params->data.F32[PM_PAR_SXX] = rotShape.sx * M_SQRT2;
     1187    params->data.F32[PM_PAR_SYY] = rotShape.sy * M_SQRT2;
     1188    params->data.F32[PM_PAR_SXY] = rotShape.sxy;
     1189    params->data.F32[PM_PAR_XPOS] = 0.0;
     1190    params->data.F32[PM_PAR_YPOS] = 0.0;
     1191
     1192    psVector *rmod = psVectorAlloc(300, PS_TYPE_F32);
     1193    psVector *fmaj = psVectorAlloc(300, PS_TYPE_F32);
     1194    psVector *fmin = psVectorAlloc(300, PS_TYPE_F32);
     1195
     1196    psVector *coord = psVectorAlloc(2, PS_TYPE_F32);
     1197
     1198    float r = 0.0;
     1199    for (int i = 0; i < rmod->n; i++) {
     1200        r = i*0.1;
     1201        rmod->data.F32[i] = r;
     1202
     1203        coord->data.F32[1] = r;
     1204        coord->data.F32[0] = 0.0;
     1205        fmaj->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord));
     1206
     1207        coord->data.F32[0] = r;
     1208        coord->data.F32[1] = 0.0;
     1209        fmin->data.F32[i] = log10(source->modelPSF->modelFunc (NULL, params, coord));
     1210    }
     1211    psFree (coord);
     1212    psFree (params);
     1213
     1214    float FWHM_MAJOR = 2.0*source->modelPSF->modelRadius (source->modelPSF->params, 0.5*source->modelPSF->params->data.F32[PM_PAR_I0]);
     1215    float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
     1216    if (FWHM_MAJOR < FWHM_MINOR) PS_SWAP (FWHM_MAJOR, FWHM_MINOR);
     1217
     1218    psEllipseMoments emoments;
     1219    emoments.x2 = source->moments->Mxx;
     1220    emoments.xy = source->moments->Mxy;
     1221    emoments.y2 = source->moments->Myy;
     1222    axes = psEllipseMomentsToAxes (emoments, 20.0);
     1223    float MOMENTS_MAJOR = 2.355*axes.major;
     1224    float MOMENTS_MINOR = 2.355*axes.minor;
     1225
     1226    float logHM = log10(0.5*source->modelPSF->params->data.F32[PM_PAR_I0]);
     1227
    11531228    // reset source Add/Sub state to recorded
    11541229    if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     
    11871262    KapaPlotVector (myKapa, nb, fb->data.F32, "y");
    11881263
     1264    graphdata.color = KapaColorByName ("blue");
     1265    graphdata.ptype = 0;
     1266    graphdata.size = 0.0;
     1267    graphdata.style = 0;
     1268    KapaPrepPlot   (myKapa, rmod->n, &graphdata);
     1269    KapaPlotVector (myKapa, rmod->n, rmod->data.F32, "x");
     1270    KapaPlotVector (myKapa, rmod->n, fmin->data.F32, "y");
     1271    plotline (myKapa, &graphdata, 0.0, logHM, 30.0, logHM);
     1272    plotline (myKapa, &graphdata, 0.5*FWHM_MINOR, 0.0, 0.5*FWHM_MINOR, 5.0);
     1273    graphdata.ltype = 1;
     1274    plotline (myKapa, &graphdata, 0.5*MOMENTS_MINOR, 0.0, 0.5*MOMENTS_MINOR, 5.0);
     1275    graphdata.ltype = 0;
     1276       
     1277    graphdata.color = KapaColorByName ("green");
     1278    graphdata.ptype = 0;
     1279    graphdata.size = 0.0;
     1280    graphdata.style = 0;
     1281    KapaPrepPlot   (myKapa, rmod->n, &graphdata);
     1282    KapaPlotVector (myKapa, rmod->n, rmod->data.F32, "x");
     1283    KapaPlotVector (myKapa, rmod->n, fmaj->data.F32, "y");
     1284    plotline (myKapa, &graphdata, 0.5*FWHM_MAJOR, 0.0, 0.5*FWHM_MAJOR, 5.0);
     1285    graphdata.ltype = 1;
     1286    plotline (myKapa, &graphdata, 0.5*MOMENTS_MAJOR, 0.0, 0.5*MOMENTS_MAJOR, 5.0);
     1287    graphdata.ltype = 0;
     1288       
     1289    for (int i = 0; i < rmod->n; i++) {
     1290        rmod->data.F32[i] = log10(rmod->data.F32[i]);
     1291    }
     1292
    11891293    // ** loglog **
    11901294    KapaSelectSection (myKapa, "loglog");
     
    11951299    graphdata.ymin = -0.05;
    11961300    graphdata.ymax = +5.05;
     1301    graphdata.color = KapaColorByName ("black");
    11971302    KapaSetLimits (myKapa, &graphdata);
    11981303
     
    12171322    KapaPlotVector (myKapa, nb, Rb->data.F32, "x");
    12181323    KapaPlotVector (myKapa, nb, fb->data.F32, "y");
     1324
     1325    graphdata.color = KapaColorByName ("blue");
     1326    graphdata.ptype = 0;
     1327    graphdata.size = 0.0;
     1328    graphdata.style = 0;
     1329    KapaPrepPlot   (myKapa, rmod->n, &graphdata);
     1330    KapaPlotVector (myKapa, rmod->n, rmod->data.F32, "x");
     1331    KapaPlotVector (myKapa, rmod->n, fmin->data.F32, "y");
     1332
     1333    graphdata.color = KapaColorByName ("green");
     1334    graphdata.ptype = 0;
     1335    graphdata.size = 0.0;
     1336    graphdata.style = 0;
     1337    KapaPrepPlot   (myKapa, rmod->n, &graphdata);
     1338    KapaPlotVector (myKapa, rmod->n, rmod->data.F32, "x");
     1339    KapaPlotVector (myKapa, rmod->n, fmaj->data.F32, "y");
     1340
     1341    psFree (rmod);
     1342    psFree (fmin);
     1343    psFree (fmaj);
    12191344
    12201345    psFree (rg);
     
    12401365    psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels
    12411366    assert (maskVal);
     1367
     1368    section.bg  = KapaColorByName ("none"); // XXX probably should be 'none'
    12421369
    12431370    KapaClearPlots (myKapa);
     
    14051532        if (source == NULL) continue;
    14061533
    1407         // if (source->type != type) continue;
    14081534        if (mode) {
    14091535            if (keep) {
     
    14781604    KapaSetFont (myKapa, "courier", 14);
    14791605
     1606    section.bg  = KapaColorByName ("none"); // XXX probably should be 'none'
     1607
    14801608    // select the max psfX,Y values for the plot limits
    14811609    float Xmin = 1000.0, Xmax = 0.0;
     
    15291657    psVector *sDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
    15301658
     1659    psVector *xLOW = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
     1660    psVector *yLOW = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
     1661    psVector *mLOW = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
     1662    psVector *sLOW = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
     1663
    15311664    psVector *xCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
    15321665    psVector *yCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
     
    15391672    int nPSF = 0;
    15401673    int nDEF = 0;
     1674    int nLOW = 0;
    15411675    int nCR  = 0;
    15421676    for (int i = 0; i < sources->n; i++) {
    15431677        pmSource *source = sources->data[i];
    15441678        if (source->moments == NULL) continue;
     1679
     1680        // only plot the measured sources...
     1681        if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)) continue;
    15451682
    15461683        if (source->mode & PM_SOURCE_MODE_CR_LIMIT) {
     
    15741711            continue;
    15751712        }
    1576         if ((source->mode & PM_SOURCE_MODE_CR_LIMIT) || (source->mode & PM_SOURCE_MODE_SATSTAR)) {
     1713        if (source->errMag > 0.1) {
     1714            xLOW->data.F32[nLOW] = source->moments->Mxx;
     1715            yLOW->data.F32[nLOW] = source->moments->Myy;
     1716            mLOW->data.F32[nLOW] = -2.5*log10(source->moments->Sum);
     1717            sLOW->data.F32[nLOW] = source->extNsigma;
     1718            nLOW++;
    15771719            continue;
    15781720        }
     
    15831725        nPSF++;
    15841726    }
     1727
    15851728    xSAT->n = nSAT;
    15861729    ySAT->n = nSAT;
     
    16071750    mDEF->n = nDEF;
    16081751    sDEF->n = nDEF;
     1752
     1753    xLOW->n = nLOW;
     1754    yLOW->n = nLOW;
     1755    mLOW->n = nLOW;
     1756    sLOW->n = nLOW;
    16091757
    16101758    // four sections: MxxMyy, MagMxx, MagMyy, MagSigma
     
    16261774    KapaSetLimits (myKapa, &graphdata);
    16271775
     1776    graphdata.padXm = NAN;
     1777    graphdata.padYm = NAN;
     1778    graphdata.padXp = 0.5;
     1779    graphdata.padYp = 0.5;
    16281780    KapaBox (myKapa, &graphdata);
    16291781    KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM);
     
    16691821    KapaPlotVector (myKapa, nSAT, xSAT->data.F32, "x");
    16701822    KapaPlotVector (myKapa, nSAT, ySAT->data.F32, "y");
     1823
     1824    graphdata.color = KapaColorByName ("black");
     1825    graphdata.ptype = 7;
     1826    graphdata.size = 1.0;
     1827    graphdata.style = 2;
     1828    KapaPrepPlot   (myKapa, nLOW, &graphdata);
     1829    KapaPlotVector (myKapa, nLOW, xLOW->data.F32, "x");
     1830    KapaPlotVector (myKapa, nLOW, yLOW->data.F32, "y");
    16711831
    16721832    // second section: MagMyy
     
    16811841    graphdata.color = KapaColorByName ("black");
    16821842    graphdata.xmin = -17.1;
    1683     graphdata.xmax =  -7.9;
     1843    graphdata.xmax =  -6.9;
    16841844    graphdata.ymin = Ymin;
    16851845    graphdata.ymax = Ymax;
    16861846    KapaSetLimits (myKapa, &graphdata);
    16871847
     1848    graphdata.padXm = 0.5;
     1849    graphdata.padYm = NAN;
     1850    graphdata.padXp = NAN;
     1851    graphdata.padYp = 0.5;
    16881852    strcpy (graphdata.labels, "0210");
    16891853    KapaBox (myKapa, &graphdata);
     
    17341898    section.dx = 0.25;
    17351899    section.dy = 0.60;
    1736     section.x  = 0.80;
     1900    section.x  = 0.75;
    17371901    section.y  = 0.00;
    17381902    section.name = psStringCopy ("MagMxx");
     
    17431907    graphdata.xmin = Xmin;
    17441908    graphdata.xmax = Xmax;
    1745     graphdata.ymin =  -7.9;
     1909    graphdata.ymin =  -6.9;
    17461910    graphdata.ymax = -17.1;
    17471911    KapaSetLimits (myKapa, &graphdata);
    17481912
     1913    graphdata.padXm = NAN;
     1914    graphdata.padYm = 0.5;
     1915    graphdata.padXp = 0.5;
     1916    graphdata.padYp = NAN;
    17491917    strcpy (graphdata.labels, "2001");
    17501918    KapaBox (myKapa, &graphdata);
     
    17941962    // fourth section: MagSigma
    17951963    section.dx = 0.75;
    1796     section.dy = 0.15;
     1964    section.dy = 0.20;
    17971965    section.x  = 0.00;
    1798     section.y  = 0.65;
     1966    section.y  = 0.60;
    17991967    section.name = psStringCopy ("MagSigma");
    18001968    KapaSetSection (myKapa, &section);
     
    18021970
    18031971    graphdata.color = KapaColorByName ("black");
    1804     graphdata.xmax =  -7.9;
     1972    graphdata.xmax =  -6.9;
    18051973    graphdata.xmin = -17.1;
    18061974    graphdata.ymin = -20.1;
     
    18081976    KapaSetLimits (myKapa, &graphdata);
    18091977
     1978    graphdata.padXm = 0.5;
     1979    graphdata.padYm = NAN;
     1980    graphdata.padXp = 0.5;
     1981    graphdata.padYp = 0.5;
    18101982    strcpy (graphdata.labels, "0100");
    18111983    KapaBox (myKapa, &graphdata);
     
    18622034
    18632035        int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS");
    1864         float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, analysis, "PSF_CLUMP_NSIGMA");
     2036        float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");
    18652037
    18662038        graphdata.color = KapaColorByName ("blue");
     
    19012073    psFree (ySAT);
    19022074    psFree (mSAT);
     2075    psFree (sSAT);
    19032076
    19042077    psFree (xEXT);
    19052078    psFree (yEXT);
    19062079    psFree (mEXT);
     2080    psFree (sEXT);
    19072081
    19082082    psFree (xPSF);
    19092083    psFree (yPSF);
    19102084    psFree (mPSF);
     2085    psFree (sPSF);
    19112086
    19122087    psFree (xDEF);
    19132088    psFree (yDEF);
    19142089    psFree (mDEF);
     2090    psFree (sDEF);
     2091
     2092    psFree (xLOW);
     2093    psFree (yLOW);
     2094    psFree (mLOW);
     2095    psFree (sLOW);
    19152096
    19162097    psFree (xCR);
    19172098    psFree (yCR);
    19182099    psFree (mCR);
     2100    psFree (sCR);
    19192101
    19202102    pmVisualAskUser(NULL);
     
    19292111    if (myKapa == -1) return false;
    19302112
    1931     psphotVisualScaleImage (myKapa, readout->image, "resid", 1);
     2113    psphotVisualScaleImage (myKapa, readout->image, readout->mask, "resid", 1);
    19322114
    19332115    pmVisualAskUser(NULL);
     
    20542236}
    20552237
     2238bool psphotVisualPlotChisq (psArray *sources) {
     2239
     2240    Graphdata graphdata;
     2241
     2242    if (!pmVisualIsVisual()) return true;
     2243
     2244    int myKapa = psphotKapaChannel (2);
     2245    if (myKapa == -1) return false;
     2246
     2247    KapaClearPlots (myKapa);
     2248    KapaInitGraph (&graphdata);
     2249
     2250    psVector *x = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
     2251    psVector *y = psVectorAllocEmpty (sources->n, PS_TYPE_F32);
     2252
     2253    graphdata.xmin = +32.0;
     2254    graphdata.xmax = -32.0;
     2255    graphdata.ymin = +32.0;
     2256    graphdata.ymax = -32.0;
     2257
     2258    FILE *f = fopen ("chisq.dat", "w");
     2259
     2260    // construct the plot vectors
     2261    int n = 0;
     2262    for (int i = 0; i < sources->n; i++) {
     2263        pmSource *source = sources->data[i];
     2264        if (!source) continue;
     2265        if (source->type != PM_SOURCE_TYPE_STAR) continue;
     2266        if (!source->moments) continue;
     2267        if (!isfinite(source->moments->Sum)) continue;
     2268        if (!source->modelPSF) continue;
     2269        if (!isfinite(source->modelPSF->chisq)) continue;
     2270
     2271        x->data.F32[n] = -2.5*log10(source->moments->Sum);
     2272        y->data.F32[n] = source->modelPSF->chisq / source->modelPSF->nDOF;
     2273        graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]);
     2274        graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]);
     2275        graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[n]);
     2276        graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[n]);
     2277
     2278        fprintf (f, "%d %d %f %f\n", i, n, x->data.F32[n], y->data.F32[n]);
     2279
     2280        n++;
     2281    }
     2282    x->n = y->n = n;
     2283    fclose (f);
     2284
     2285    float range;
     2286    range = graphdata.xmax - graphdata.xmin;
     2287    graphdata.xmax += 0.05*range;
     2288    graphdata.xmin -= 0.05*range;
     2289    range = graphdata.ymax - graphdata.ymin;
     2290    graphdata.ymax += 0.05*range;
     2291    graphdata.ymin -= 0.05*range;
     2292
     2293    // XXX test
     2294    graphdata.xmin = -17.0;
     2295    graphdata.xmax =  -3.0;
     2296    graphdata.ymin =  -0.1;
     2297    graphdata.ymax = +10.1;
     2298
     2299    KapaSetLimits (myKapa, &graphdata);
     2300
     2301    KapaSetFont (myKapa, "helvetica", 14);
     2302    KapaBox (myKapa, &graphdata);
     2303    KapaSendLabel (myKapa, "PSF Mag", KAPA_LABEL_XM);
     2304    KapaSendLabel (myKapa, "ChiSq", KAPA_LABEL_YM);
     2305
     2306    graphdata.color = KapaColorByName ("black");
     2307    graphdata.ptype = 2;
     2308    graphdata.size = 0.5;
     2309    graphdata.style = 2;
     2310    KapaPrepPlot (myKapa, n, &graphdata);
     2311    KapaPlotVector (myKapa, n, x->data.F32, "x");
     2312    KapaPlotVector (myKapa, n, y->data.F32, "y");
     2313
     2314    psFree (x);
     2315    psFree (y);
     2316
     2317    pmVisualAskUser(NULL);
     2318    return true;
     2319}
     2320
    20562321bool psphotVisualShowPetrosians (psArray *sources) {
    20572322
     
    20732338        if (!source) continue;
    20742339        if (!source->extpars) continue;
    2075         if (!source->extpars->profile) continue;
    2076         if (!source->extpars->petrosian_80) continue;
    2077 
    2078         pmSourceRadialProfile *profile = source->extpars->profile;
    2079         pmSourceExtendedFlux *petrosian = source->extpars->petrosian_80;
     2340        if (!source->extpars->petProfile) continue;
     2341
     2342        float petrosianRadius = source->extpars->petrosianRadius;
     2343        psEllipseAxes *axes = &source->extpars->axes;
    20802344
    20812345        overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    20822346        overlay[Noverlay].x = source->peak->xf;
    20832347        overlay[Noverlay].y = source->peak->yf;
    2084         overlay[Noverlay].dx = 2.0*petrosian->radius;
    2085         overlay[Noverlay].dy = 2.0*petrosian->radius*profile->axes.minor/profile->axes.major;
    2086         overlay[Noverlay].angle = profile->axes.theta * PS_DEG_RAD;
     2348        overlay[Noverlay].dx = 1.0*petrosianRadius;
     2349        overlay[Noverlay].dy = 1.0*petrosianRadius*axes->minor/axes->major;
     2350        overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
    20872351        overlay[Noverlay].text = NULL;
    20882352        Noverlay ++;
    20892353        CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    20902354
    2091         overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
    2092         overlay[Noverlay].x = source->peak->xf;
    2093         overlay[Noverlay].y = source->peak->yf;
    2094         overlay[Noverlay].dx = 4.0*petrosian->radius;
    2095         overlay[Noverlay].dy = 4.0*petrosian->radius*profile->axes.minor/profile->axes.major;
    2096         overlay[Noverlay].angle = profile->axes.theta * PS_DEG_RAD;
    2097         overlay[Noverlay].text = NULL;
    2098         Noverlay ++;
    2099         CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
     2355        // overlay[Noverlay].type = KII_OVERLAY_CIRCLE;
     2356        // overlay[Noverlay].x = source->peak->xf;
     2357        // overlay[Noverlay].y = source->peak->yf;
     2358        // overlay[Noverlay].dx = 2.0*petrosianRadius;
     2359        // overlay[Noverlay].dy = 2.0*petrosianRadius*axes->minor/axes->major;
     2360        // overlay[Noverlay].angle = axes->theta * PS_DEG_RAD;
     2361        // overlay[Noverlay].text = NULL;
     2362        // Noverlay ++;
     2363        // CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100);
    21002364    }
    21012365
Note: See TracChangeset for help on using the changeset viewer.