Changeset 27840 for branches/simtest_nebulous_branches/psphot/src
- Timestamp:
- May 3, 2010, 8:50:52 AM (16 years ago)
- Location:
- branches/simtest_nebulous_branches
- Files:
-
- 62 edited
- 29 copied
-
. (modified) (1 prop)
-
psphot (modified) (1 prop)
-
psphot/src (modified) (1 prop)
-
psphot/src/Makefile.am (modified) (5 diffs)
-
psphot/src/psphot.h (modified) (7 diffs)
-
psphot/src/psphotAddNoise.c (modified) (7 diffs)
-
psphot/src/psphotApResid.c (modified) (17 diffs)
-
psphot/src/psphotArguments.c (modified) (2 diffs)
-
psphot/src/psphotBasicDeblend.c (modified) (2 diffs)
-
psphot/src/psphotBlendFit.c (modified) (6 diffs)
-
psphot/src/psphotChoosePSF.c (modified) (17 diffs)
-
psphot/src/psphotCleanup.c (modified) (1 diff)
-
psphot/src/psphotCullPeaks.c (modified) (2 diffs)
-
psphot/src/psphotDeblendSatstars.c (modified) (3 diffs)
-
psphot/src/psphotDefineFiles.c (modified) (1 diff)
-
psphot/src/psphotDiagnosticPlots.c (modified) (2 diffs)
-
psphot/src/psphotEfficiency.c (copied) (copied from trunk/psphot/src/psphotEfficiency.c )
-
psphot/src/psphotEllipticalContour.c (copied) (copied from trunk/psphot/src/psphotEllipticalContour.c )
-
psphot/src/psphotEllipticalProfile.c (copied) (copied from trunk/psphot/src/psphotEllipticalProfile.c )
-
psphot/src/psphotErrorCodes.dat (modified) (1 diff)
-
psphot/src/psphotExtendedSourceAnalysis.c (modified) (8 diffs)
-
psphot/src/psphotExtendedSourceFits.c (modified) (5 diffs)
-
psphot/src/psphotFake.c (copied) (copied from trunk/psphot/src/psphotFake.c )
-
psphot/src/psphotFindDetections.c (modified) (5 diffs)
-
psphot/src/psphotFindFootprints.c (modified) (6 diffs)
-
psphot/src/psphotFindPeaks.c (modified) (2 diffs)
-
psphot/src/psphotFitSourcesLinear.c (modified) (13 diffs)
-
psphot/src/psphotFitSourcesLinearStack.c (modified) (10 diffs)
-
psphot/src/psphotForced.c (copied) (copied from trunk/psphot/src/psphotForced.c )
-
psphot/src/psphotForcedArguments.c (copied) (copied from trunk/psphot/src/psphotForcedArguments.c )
-
psphot/src/psphotForcedImageLoop.c (copied) (copied from trunk/psphot/src/psphotForcedImageLoop.c )
-
psphot/src/psphotForcedReadout.c (copied) (copied from trunk/psphot/src/psphotForcedReadout.c )
-
psphot/src/psphotGuessModels.c (modified) (7 diffs)
-
psphot/src/psphotImageLoop.c (modified) (2 diffs)
-
psphot/src/psphotImageQuality.c (modified) (16 diffs)
-
psphot/src/psphotKernelFromPSF.c (modified) (2 diffs)
-
psphot/src/psphotLoadPSF.c (modified) (1 diff)
-
psphot/src/psphotLoadSRCTEXT.c (copied) (copied from trunk/psphot/src/psphotLoadSRCTEXT.c )
-
psphot/src/psphotMagnitudes.c (modified) (6 diffs)
-
psphot/src/psphotMakeFluxScale.c (modified) (1 diff)
-
psphot/src/psphotMakePSF.c (copied) (copied from trunk/psphot/src/psphotMakePSF.c )
-
psphot/src/psphotMakePSFArguments.c (copied) (copied from trunk/psphot/src/psphotMakePSFArguments.c )
-
psphot/src/psphotMakePSFImageLoop.c (copied) (copied from trunk/psphot/src/psphotMakePSFImageLoop.c )
-
psphot/src/psphotMakePSFReadout.c (copied) (copied from trunk/psphot/src/psphotMakePSFReadout.c )
-
psphot/src/psphotMakeResiduals.c (modified) (8 diffs)
-
psphot/src/psphotMaskReadout.c (modified) (4 diffs)
-
psphot/src/psphotMergeSources.c (modified) (9 diffs)
-
psphot/src/psphotModelBackground.c (modified) (11 diffs)
-
psphot/src/psphotModelGroupInit.c (modified) (3 diffs)
-
psphot/src/psphotModelTest.c (modified) (1 diff)
-
psphot/src/psphotMomentsStudy.c (modified) (1 diff)
-
psphot/src/psphotOutput.c (modified) (5 diffs)
-
psphot/src/psphotPSFConvModel.c (modified) (2 diffs)
-
psphot/src/psphotParseCamera.c (modified) (1 diff)
-
psphot/src/psphotPetrosian.c (modified) (1 diff)
-
psphot/src/psphotPetrosianAnalysis.c (copied) (copied from trunk/psphot/src/psphotPetrosianAnalysis.c )
-
psphot/src/psphotPetrosianProfile.c (copied) (copied from trunk/psphot/src/psphotPetrosianProfile.c )
-
psphot/src/psphotPetrosianRadialBins.c (copied) (copied from trunk/psphot/src/psphotPetrosianRadialBins.c )
-
psphot/src/psphotPetrosianStats.c (copied) (copied from trunk/psphot/src/psphotPetrosianStats.c )
-
psphot/src/psphotPetrosianStudy.c (copied) (copied from trunk/psphot/src/psphotPetrosianStudy.c )
-
psphot/src/psphotPetrosianVisual.c (copied) (copied from trunk/psphot/src/psphotPetrosianVisual.c )
-
psphot/src/psphotRadialBins.c (copied) (copied from trunk/psphot/src/psphotRadialBins.c )
-
psphot/src/psphotRadialProfile.c (modified) (2 diffs)
-
psphot/src/psphotRadialProfileByAngles.c (copied) (copied from trunk/psphot/src/psphotRadialProfileByAngles.c )
-
psphot/src/psphotRadiiFromProfiles.c (copied) (copied from trunk/psphot/src/psphotRadiiFromProfiles.c )
-
psphot/src/psphotRadiusChecks.c (modified) (7 diffs)
-
psphot/src/psphotReadout.c (modified) (6 diffs)
-
psphot/src/psphotReadoutCleanup.c (modified) (5 diffs)
-
psphot/src/psphotReadoutFindPSF.c (modified) (2 diffs)
-
psphot/src/psphotReadoutKnownSources.c (modified) (2 diffs)
-
psphot/src/psphotReadoutMinimal.c (modified) (2 diffs)
-
psphot/src/psphotReplaceUnfit.c (modified) (6 diffs)
-
psphot/src/psphotRoughClass.c (modified) (4 diffs)
-
psphot/src/psphotSetThreads.c (modified) (2 diffs)
-
psphot/src/psphotSignificanceImage.c (modified) (3 diffs)
-
psphot/src/psphotSkyReplace.c (modified) (1 diff)
-
psphot/src/psphotSourceFits.c (modified) (21 diffs)
-
psphot/src/psphotSourceFreePixels.c (modified) (2 diffs)
-
psphot/src/psphotSourceMatch.c (copied) (copied from trunk/psphot/src/psphotSourceMatch.c )
-
psphot/src/psphotSourcePlots.c (modified) (3 diffs)
-
psphot/src/psphotSourceSize.c (modified) (7 diffs)
-
psphot/src/psphotSourceStats.c (modified) (13 diffs)
-
psphot/src/psphotStack.c (copied) (copied from trunk/psphot/src/psphotStack.c )
-
psphot/src/psphotStackArguments.c (copied) (copied from trunk/psphot/src/psphotStackArguments.c )
-
psphot/src/psphotStackChisqImage.c (copied) (copied from trunk/psphot/src/psphotStackChisqImage.c )
-
psphot/src/psphotStackImageLoop.c (copied) (copied from trunk/psphot/src/psphotStackImageLoop.c )
-
psphot/src/psphotStackParseCamera.c (copied) (copied from trunk/psphot/src/psphotStackParseCamera.c )
-
psphot/src/psphotStackReadout.c (copied) (copied from trunk/psphot/src/psphotStackReadout.c )
-
psphot/src/psphotSubtractBackground.c (modified) (6 diffs)
-
psphot/src/psphotVersion.c (modified) (1 diff)
-
psphot/src/psphotVisual.c (modified) (69 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/simtest_nebulous_branches
- Property svn:mergeinfo changed
-
branches/simtest_nebulous_branches/psphot
-
Property svn:mergeinfo
set to (toggle deleted branches)
/trunk/psphot merged eligible /branches/eam_branches/stackphot.20100406/psphot 27622-27655 /branches/pap_delete/psphot 27530-27595
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
branches/simtest_nebulous_branches/psphot/src
- Property svn:ignore
-
old new 18 18 psphotVersionDefinitions.h 19 19 psphotMomentsStudy 20 psphotPetrosianStudy 21 psphotForced 22 psphotMakePSF 23 psphotStack
-
- Property svn:ignore
-
branches/simtest_nebulous_branches/psphot/src/Makefile.am
r24586 r27840 25 25 libpsphot_la_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 26 26 27 bin_PROGRAMS = psphot psphotTest psphotMomentsStudy 27 bin_PROGRAMS = psphot psphotForced psphotMakePSF psphotStack 28 # bin_PROGRAMS = psphotPetrosianStudy psphotTest psphotMomentsStudy 28 29 29 30 psphot_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) … … 31 32 psphot_LDADD = libpsphot.la 32 33 33 psphotTest_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) 34 psphotTest_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 35 psphotTest_LDADD = libpsphot.la 36 37 psphotMomentsStudy_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) 38 psphotMomentsStudy_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 39 psphotMomentsStudy_LDADD = libpsphot.la 40 34 psphotForced_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) 35 psphotForced_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 36 psphotForced_LDADD = libpsphot.la 37 38 psphotMakePSF_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) 39 psphotMakePSF_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 40 psphotMakePSF_LDADD = libpsphot.la 41 42 psphotStack_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) 43 psphotStack_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 44 psphotStack_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 49 50 # psphotPetrosianStudy_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) 51 # psphotPetrosianStudy_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 52 # psphotPetrosianStudy_LDADD = libpsphot.la 53 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 41 59 psphot_SOURCES = \ 42 60 psphot.c \ 43 61 psphotArguments.c \ 44 psphot Cleanup.c\62 psphotParseCamera.c \ 45 63 psphotImageLoop.c \ 46 64 psphotMosaicChip.c \ 47 psphotParseCamera.c 48 49 psphotDetect_SOURCES = \ 50 psphotDetect.c \ 51 psphotDetectArguments.c \ 52 psphotDetectParseCamera.c \ 53 psphotDetectImageLoop.c \ 54 psphotDetectReadout.c \ 55 psphotMosaicChip.c \ 56 psphotCleanup.c 57 58 psphotTest_SOURCES = \ 59 psphotTest.c 60 61 psphotMomentsStudy_SOURCES = \ 62 psphotMomentsStudy.c 65 psphotCleanup.c 66 67 # forced photometry of specified positions given a specified psf 68 psphotForced_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 78 psphotMakePSF_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 88 psphotStack_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 # 117 # psphotPetrosianStudy_SOURCES = \ 118 # psphotPetrosianStudy.c 63 119 64 120 libpsphot_la_SOURCES = \ … … 104 160 psphotExtendedSourceAnalysis.c \ 105 161 psphotExtendedSourceFits.c \ 106 psphotRadialProfile.c \107 psphotPetrosian.c \108 psphotIsophotal.c \109 psphotAnnuli.c \110 psphotKron.c \111 162 psphotKernelFromPSF.c \ 112 163 psphotPSFConvModel.c \ 113 psphotModelTest.c \114 164 psphotFitSet.c \ 115 165 psphotSourceFreePixels.c \ … … 117 167 psphotMergeSources.c \ 118 168 psphotLoadPSF.c \ 169 psphotLoadSRCTEXT.c \ 119 170 psphotReadoutCleanup.c \ 120 171 psphotSourcePlots.c \ … … 128 179 psphotCheckStarDistribution.c \ 129 180 psphotThreadTools.c \ 130 psphotAddNoise.c 131 132 # dropped? psphotGrowthCurve.c 181 psphotAddNoise.c \ 182 psphotRadialProfile.c \ 183 psphotRadialProfileByAngles.c \ 184 psphotRadiiFromProfiles.c \ 185 psphotEllipticalContour.c \ 186 psphotEllipticalProfile.c \ 187 psphotRadialBins.c \ 188 psphotPetrosian.c \ 189 psphotPetrosianRadialBins.c \ 190 psphotPetrosianStats.c \ 191 psphotPetrosianVisual.c \ 192 psphotEfficiency.c 193 194 # XXX need to fix this for the new apis 195 # psphotModelTest.c 196 197 # re-instate these 198 # psphotIsophotal.c \ 199 # psphotAnnuli.c \ 200 # psphotKron.c \ 201 # 202 203 # test versions 204 # psphotPetrosianProfile.c \ 205 # psphotPetrosianAnalysis.c \ 206 # 133 207 134 208 include_HEADERS = \ -
branches/simtest_nebulous_branches/psphot/src/psphot.h
r24890 r27840 12 12 13 13 #define PSPHOT_RECIPE_PSF_FAKE_ALLOW "PSF.FAKE.ALLOW" // Name for recipe component permitting fake PSFs 14 15 // pmPCMData : PSF Convolved Model data storage structure 16 typedef struct { 17 psImage *model; 18 psArray *dmodels; 19 psImage *modelConv; 20 psArray *dmodelsConv; 21 } pmPCMData; 14 22 15 23 // top-level psphot functions … … 29 37 bool psphotReadoutMinimal(pmConfig *config, const pmFPAview *view); 30 38 31 bool psphotReadoutCleanup (pmConfig *config, pmReadout *readout, psMetadata *recipe, pmDetections *detections, pmPSF *psf, psArray *sources); 39 bool psphotReadoutCleanup (pmConfig *config, const pmFPAview *view); 40 bool psphotReadoutCleanupReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 41 32 42 bool psphotDefineFiles (pmConfig *config, pmFPAfile *input); 33 43 void psphotFilesActivate(pmConfig *config, bool state); … … 38 48 // XXX test functions 39 49 psArray *psphotFakeSources (void); 50 bool psphotMaskCosmicRayFootprintCheck (psArray *sources); 40 51 41 52 // 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, psMetadata *recipe, pmPSF *psf, bool final); 52 bool psphotReplaceUnfitSources (psArray *sources, psImageMaskType maskVal); 53 54 bool psphotReplaceAllSources (psArray *sources, psMetadata *recipe); 55 bool psphotRemoveAllSources (psArray *sources, psMetadata *recipe); 56 57 bool psphotBlendFit (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf); 53 bool psphotAddPhotcode (pmConfig *config, const pmFPAview *view); 54 bool psphotAddPhotcodeReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index); 55 56 bool psphotSetMaskAndVariance (pmConfig *config, const pmFPAview *view); 57 bool psphotSetMaskAndVarianceReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 58 59 bool psphotModelBackground (pmConfig *config, const pmFPAview *view); 60 bool psphotModelBackgroundReadoutFileIndex (pmConfig *config, const pmFPAview *view, const char *filename, int index); 61 62 bool psphotSubtractBackground (pmConfig *config, const pmFPAview *view); 63 bool psphotSubtractBackgroundReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 64 65 bool psphotFindDetections (pmConfig *config, const pmFPAview *view, bool firstPass); 66 bool psphotFindDetectionsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool firstPass); 67 68 bool psphotSourceStats (pmConfig *config, const pmFPAview *view, bool setWindow); 69 bool psphotSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool setWindow); 70 71 bool psphotDeblendSatstars (pmConfig *config, const pmFPAview *view); 72 bool psphotDeblendSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index); 73 74 bool psphotBasicDeblend (pmConfig *config, const pmFPAview *view); 75 bool psphotBasicDeblendReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index); 76 77 bool psphotRoughClass (pmConfig *config, const pmFPAview *view); 78 bool psphotRoughClassReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 79 bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *analysis, psMetadata *recipe, const bool havePSF); 80 81 bool psphotImageQuality (pmConfig *config, const pmFPAview *view); 82 bool psphotImageQualityReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 83 84 bool psphotChoosePSF (pmConfig *config, const pmFPAview *view); 85 bool psphotChoosePSFReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 86 87 bool psphotGuessModels (pmConfig *config, const pmFPAview *view); 88 bool psphotGuessModelsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index); 89 90 bool psphotMergeSources (pmConfig *config, const pmFPAview *view); 91 bool psphotMergeSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index); 92 93 bool psphotFitSourcesLinear (pmConfig *config, const pmFPAview *view, bool final); 94 bool psphotFitSourcesLinearReadout (psMetadata *recipe, pmReadout *readout, psArray *sources, pmPSF *psf, bool final); 95 96 bool psphotSourceSize (pmConfig *config, const pmFPAview *view, bool getPSFsize); 97 bool psphotSourceSizeReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool getPSFsize); 98 99 bool psphotBlendFit (pmConfig *config, const pmFPAview *view); 100 bool psphotBlendFitReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 58 101 bool psphotBlendFit_Threaded (psThreadJob *job); 59 102 60 psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections); 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, pmPSF *psf); 103 bool psphotReplaceAllSources (pmConfig *config, const pmFPAview *view); 104 bool psphotReplaceAllSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 105 106 bool psphotAddNoise (pmConfig *config, const pmFPAview *view); 107 bool psphotSubNoise (pmConfig *config, const pmFPAview *view); 108 bool psphotAddOrSubNoise (pmConfig *config, const pmFPAview *view, bool add); 109 bool psphotAddOrSubNoiseReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool add); 110 111 bool psphotExtendedSourceAnalysis (pmConfig *config, const pmFPAview *view); 112 bool psphotExtendedSourceAnalysisReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 113 114 bool psphotExtendedSourceFits (pmConfig *config, const pmFPAview *view); 115 bool psphotExtendedSourceFitsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 116 117 bool psphotApResid (pmConfig *config, const pmFPAview *view); 118 bool psphotApResidReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 119 120 bool psphotMagnitudes (pmConfig *config, const pmFPAview *view); 121 bool psphotMagnitudesReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, pmReadout *readout, psArray *sources, pmPSF *psf); 67 122 bool psphotMagnitudes_Threaded (psThreadJob *job); 123 124 bool psphotEfficiency (pmConfig *config, const pmFPAview *view); 125 bool psphotEfficiencyReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe); 68 126 69 127 bool psphotPSFWeights(pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources); 70 128 bool psphotPSFWeights_Threaded (psThreadJob *job); 71 129 72 bool psphotApResid (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf);73 bool psphotApResidMags_Threaded (psThreadJob *job);74 75 130 bool psphotSkyReplace (pmConfig *config, const pmFPAview *view); 76 bool psphotExtendedSourceAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe); 77 bool psphotExtendedSourceFits (pmReadout *readout, psArray *sources, psMetadata *recipe); 131 bool psphotSkyReplaceReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index); 132 133 bool psphotSourceFreePixels (pmConfig *config, const pmFPAview *view); 134 bool psphotSourceFreePixelsReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index); 135 136 // in psphotSourceStats.c: 137 bool psphotSourceStats_Threaded (psThreadJob *job); 138 bool psphotSourceStatsUpdate (psArray *sources, pmConfig *config, pmReadout *readout); 139 bool psphotSetMomentsWindow (psMetadata *recipe, psMetadata *analysis, psArray *sources); 140 141 // in psphotChoosePSF.c: 142 bool psphotPSFstats (pmReadout *readout, pmPSF *psf); 143 bool psphotMomentsStats (pmReadout *readout, psArray *sources); 144 145 // in psphotGuessModel.c 146 bool psphotGuessModel_Threaded (psThreadJob *job); 147 148 // in psphotMergeSources.c: 149 bool psphotLoadExtSources (pmConfig *config, const pmFPAview *view); 150 psArray *psphotLoadPSFSources (pmConfig *config, const pmFPAview *view); 151 bool psphotRepairLoadedSources (pmConfig *config, const pmFPAview *view); 152 bool psphotCheckExtSources (pmConfig *config, const pmFPAview *view); 153 154 // generate the detection structure for the supplied array of sources 155 bool psphotDetectionsFromSources (pmConfig *config, const pmFPAview *view, psArray *sources); 156 157 // generate the detection structure for the supplied array of sources 158 bool 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. 162 psImage *psphotModelBackgroundReadoutNoFile(pmReadout *readout, const pmConfig *config); 163 psImageBinning *psphotBackgroundBinning(const psImage *image, const pmConfig *config); 164 165 // in psphotReplaceUnfit.c: 166 bool psphotRemoveAllSources (const psArray *sources, const psMetadata *recipe); 167 bool psphotReplaceUnfitSources (psArray *sources, psImageMaskType maskVal); 78 168 79 169 // thread-related: … … 86 176 psImage *psphotSignificanceImage (pmReadout *readout, psMetadata *recipe, const int pass, psImageMaskType maskVal); 87 177 psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax); 88 bool psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, 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 95 bool psphotMagErrorScale (float *errorScale, float *errorFloor, psVector *dMag, psVector *dap, psVector *mask, int nGroup); 96 bool psphotApResidTrend (pmReadout *readout, pmPSF *psf, int Npsf, int scale, float *errorScale, float *errorFloor, psVector *mask, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag); 178 bool psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int pass, psImageMaskType maskVal); 179 psErrorCode psphotCullPeaks(const pmReadout *readout, const psMetadata *recipe, psArray *footprints); 180 181 // in psphotApResid.c: 182 pmTrend2D *psphotApResidTrend (float *apResidSysErr, pmReadout *readout, int Nx, int Ny, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag); 183 bool psphotApResidMags_Threaded (psThreadJob *job); 97 184 98 185 // basic support functions 99 186 void psphotModelClassInit (void); 100 187 bool psphotGrowthCurve (pmReadout *readout, pmPSF *psf, bool ignore, psImageMaskType maskVal); 101 bool psphotSetMaskAndVariance (pmConfig *config, pmReadout *readout, psMetadata *recipe);102 void psphotSourceFreePixels (psArray *sources);103 188 104 189 // functions to set the correct source pixels 105 bool psphotInitRadiusPSF (const psMetadata *recipe, const pmModelType type); 190 bool psphotInitRadiusPSF(const psMetadata *recipe, const psMetadata *analysis, const pmModelType type); 191 106 192 bool psphotCheckRadiusPSF (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal); 107 193 bool psphotCheckRadiusPSFBlend (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal, float dR); 108 194 bool psphotInitRadiusEXT (psMetadata *recipe, pmModelType type); 109 195 bool psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal); 110 111 // output functions 112 bool psphotAddPhotcode (psMetadata *recipe, pmConfig *config, const pmFPAview *view, const char *filerule); 196 float psphotSetRadiusEXT (pmReadout *readout, pmSource *source, psImageMaskType markVal); 197 113 198 bool psphotDumpMoments (psMetadata *recipe, psArray *sources); 114 199 psMetadata *psphotDefineHeader (psMetadata *recipe); … … 141 226 bool psphotFitSummary (void); 142 227 143 bool psphotMergeSources (psArray *oldSources, psArray *newSources); 144 bool psphotLoadExtSources (pmConfig *config, const pmFPAview *view, psArray *sources); 145 psArray *psphotLoadPSFSources (pmConfig *config, const pmFPAview *view); 146 147 pmPSF *psphotLoadPSF (pmConfig *config, const pmFPAview *view, psMetadata *recipe); 228 bool psphotLoadPSF (pmConfig *config, const pmFPAview *view); 229 bool psphotLoadPSFReadout (pmConfig *config, const pmFPAview *view, const char *outFilename, const char *inFilename, int index); 230 148 231 bool psphotSetHeaderNstars (psMetadata *recipe, psArray *sources); 149 bool psphotAddNoise (pmReadout *readout, psArray *sources, psMetadata *recipe);150 bool psphotSubNoise (pmReadout *readout, psArray *sources, psMetadata *recipe);151 bool psphotAddOrSubNoise (pmReadout *readout, psArray *sources, psMetadata *recipe, bool add);152 232 bool psphotRadialPlot (int *kapa, const char *filename, pmSource *source); 153 233 bool psphotSourcePlots (pmReadout *readout, psArray *sources, psMetadata *recipe); 154 234 bool psphotMosaicSubimage (psImage *outImage, pmSource *source, int Xo, int Yo, int DX, int DY, bool normalize); 155 235 156 bool psphotAddWithTest (pmSource *source, bool useState, psImageMaskType maskVal);157 bool psphotSubWithTest (pmSource *source, bool useState, psImageMaskType maskVal);158 bool psphotSetState (pmSource *source, bool curState, psImageMaskType maskVal);159 bool psphotDeblendSatstars (pmReadout *readout, psArray *sources, psMetadata *recipe);160 bool psphotSourceSize (pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, long first);161 162 236 bool psphotMakeResiduals (psArray *sources, psMetadata *recipe, pmPSF *psf, psImageMaskType maskVal); 163 237 … … 166 240 psKernel *psphotKernelFromPSF (pmSource *source, int nPix); 167 241 168 bool psphotRadialProfile (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 169 bool psphotPetrosian (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 170 bool psphotIsophotal (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 171 bool psphotAnnuli (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 172 bool psphotKron (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 242 // functions related to extended source analysis 243 bool psphotRadialProfile (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal); 244 bool psphotRadialProfilesByAngles (pmSource *source, int Nsec, float Rmax); 245 float psphotRadiusFromProfile (pmSource *source, psVector *radius, psVector *flux, float fluxMin, float fluxMax); 246 bool psphotRadiiFromProfiles (pmSource *source, float fluxMin, float fluxMax); 247 bool psphotEllipticalProfile (pmSource *source, bool RAW_RADIUS); 248 bool psphotEllipticalContour (pmSource *source); 173 249 174 250 // psphotVisual functions 175 bool psphotVisualShowImage (pmReadout *readout); 176 bool psphotVisualShowBackground (pmConfig *config, const pmFPAview *view, pmReadout *readout); 177 bool psphotVisualShowSignificance (psImage *image); 178 bool psphotVisualShowPeaks (pmDetections *detections); 179 bool psphotVisualShowFootprints (pmDetections *detections); 180 bool psphotVisualShowMoments (psArray *sources); 181 bool psphotVisualPlotMoments (psMetadata *recipe, psArray *sources); 182 bool psphotVisualShowRoughClass (psArray *sources); 183 bool psphotVisualShowPSFStars (psMetadata *recipe, pmPSF *psf, psArray *sources); 184 bool psphotVisualShowSatStars (psMetadata *recipe, pmPSF *psf, psArray *sources); 185 bool psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf); 186 bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal); 187 bool psphotVisualPlotRadialProfiles (psMetadata *recipe, psArray *sources); 188 bool psphotVisualShowFlags (psArray *sources); 189 bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources); 190 bool psphotVisualShowResidualImage (pmReadout *readout); 191 bool psphotVisualPlotApResid (psArray *sources); 192 bool psphotVisualPlotSourceSize (psArray *sources); 193 194 bool psphotImageQuality (psMetadata *recipe, psArray *sources); 251 bool psphotVisualShowImage (pmReadout *readout); 252 bool psphotVisualShowBackground (pmConfig *config, const pmFPAview *view, pmReadout *readout); 253 bool psphotVisualShowSignificance (psImage *image, float min, float max); 254 bool psphotVisualShowPeaks (pmDetections *detections); 255 bool psphotVisualShowFootprints (pmDetections *detections); 256 bool psphotVisualShowMoments (psArray *sources); 257 bool psphotVisualPlotMoments (psMetadata *recipe, psMetadata *analysis, psArray *sources); 258 bool psphotVisualShowRoughClass (psArray *sources); 259 bool psphotVisualShowPSFStars (psMetadata *recipe, pmPSF *psf, psArray *sources); 260 bool psphotVisualShowSatStars (psMetadata *recipe, pmPSF *psf, psArray *sources); 261 bool psphotVisualShowPSFModel (pmReadout *readout, pmPSF *psf); 262 bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal); 263 bool psphotVisualPlotRadialProfiles (psMetadata *recipe, psArray *sources); 264 bool psphotVisualShowFlags (psArray *sources); 265 bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources); 266 bool psphotVisualShowResidualImage (pmReadout *readout); 267 bool psphotVisualPlotApResid (psArray *sources, float mean, float error); 268 bool psphotVisualPlotChisq (psArray *sources); 269 bool psphotVisualPlotSourceSize (psMetadata *recipe, psMetadata *analysis, psArray *sources); 270 bool psphotVisualShowPetrosians (psArray *sources); 271 bool psphotVisualEraseOverlays (int channel, char *overlay); 272 273 bool psphotPetrosian (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal); 274 bool psphotPetrosianRadialBins (pmSource *source, float radiusMax, float skynoise); 275 bool psphotPetrosianStats (pmSource *source); 276 277 // currently disabled: 278 // bool psphotIsophotal (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 279 // bool psphotAnnuli (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 280 // bool psphotKron (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 281 282 // XXX visualization functions related to radial profiles (disabled) 283 bool psphotPetrosianVisualProfileByAngle (psVector *radius, psVector *flux); 284 bool psphotPetrosianVisualProfileRadii (psVector *radius, psVector *flux, psVector *radiusBin, psVector *fluxBin, float peakFlux, float RadiusRef); 285 bool psphotPetrosianVisualEllipticalContour (pmSourceRadialFlux *radFlux, pmSourceExtendedPars *extpars); 286 bool 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 292 bool psphotRadialBins (psMetadata *recipe, pmSource *source, float radiusMax, float skynoise); 195 293 196 294 // structures & functions to support psf-convolved model fitting 197 198 // pmPCMData : PSF Convolved Model data storage structure199 typedef struct {200 psImage *model;201 psArray *dmodels;202 psImage *modelConv;203 psArray *dmodelsConv;204 } pmPCMData;205 206 295 207 296 // psf-convolved model fitting … … 241 330 bool psphotDumpPSFStars (pmReadout *readout, pmPSFtry *try, float radius, psImageMaskType maskVal, psImageMaskType markVal); 242 331 332 bool psphotLoadSRCTEXT (pmFPA *fpa, pmConfig *config); 333 243 334 bool psphotCheckStarDistribution (psArray *sources, psArray *stars, pmPSFOptions *options); 244 335 int psphotSupplementStars (psArray *stars, psArray *sources, psImageBinning *binning, int ix, int iy); 245 336 246 247 // Create a background model for a readout 248 // Essentially identical to psphotModelBackground, but with a more convenient API for outsiders. 249 psImage *psphotBackgroundModel(pmReadout *ro, // Readout for which to generate background model 250 const pmConfig *config // Configuration 251 ); 252 337 pmConfig *psphotForcedArguments(int argc, char **argv); 338 bool psphotForcedImageLoop (pmConfig *config); 339 bool psphotForcedReadout(pmConfig *config, const pmFPAview *view); 340 341 pmConfig *psphotMakePSFArguments(int argc, char **argv); 342 bool psphotMakePSFImageLoop (pmConfig *config); 343 bool psphotMakePSFReadout(pmConfig *config, const pmFPAview *view); 344 345 /**** psphotStack prototypes ****/ 346 347 pmConfig *psphotStackArguments(int argc, char **argv); 348 bool psphotStackParseCamera (pmConfig *config); 349 bool psphotStackImageLoop (pmConfig *config); 350 bool psphotStackReadout (pmConfig *config, const pmFPAview *view); 351 bool psphotStackChisqImage (pmConfig *config, const pmFPAview *view); 352 bool psphotStackChisqImageAddReadout(const pmConfig *config, // Configuration 353 const pmFPAview *view, 354 pmReadout **chiReadout, 355 char *filename, 356 int index); 357 358 bool psphotStackRemoveChisqFromInputs (pmConfig *config); 359 bool pmFPAfileRemoveSingle(psMetadata *files, const char *name, int num); 360 361 psArray *psphotMatchSources (pmConfig *config, const pmFPAview *view); 362 bool psphotMatchSourcesReadout (psArray *objects, pmConfig *config, const pmFPAview *view, char *filename, int index); 363 bool psphotMatchSourcesToObjects (psArray *objects, psArray *sources, float RADIUS); 364 365 bool psphotFitSourcesLinearStack (pmConfig *config, psArray *objects, bool final); 366 int pmPhotObjSortBySN (const void **a, const void **b); 367 int pmPhotObjSortByX (const void **a, const void **b); 253 368 254 369 #endif -
branches/simtest_nebulous_branches/psphot/src/psphotAddNoise.c
r21519 r27840 1 1 # include "psphotInternal.h" 2 2 3 bool psphotAddNoise (pm Readout *readout, psArray *sources, psMetadata *recipe) {4 return psphotAddOrSubNoise (readout, sources, recipe, true);3 bool psphotAddNoise (pmConfig *config, const pmFPAview *view) { 4 return psphotAddOrSubNoise (config, view, true); 5 5 } 6 6 7 bool psphotSubNoise (pm Readout *readout, psArray *sources, psMetadata *recipe) {8 return psphotAddOrSubNoise (readout, sources, recipe, false);7 bool psphotSubNoise (pmConfig *config, const pmFPAview *view) { 8 return psphotAddOrSubNoise (config, view, false); 9 9 } 10 10 11 bool psphotAddOrSubNoise (pmReadout *readout, psArray *sources, psMetadata *recipe, bool add) { 11 // for now, let's store the detections on the readout->analysis for each readout 12 bool 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 33 bool psphotAddOrSubNoiseReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool add) { 12 34 13 35 bool status = false; … … 16 38 psEllipseAxes axes; 17 39 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?"); 21 54 22 55 psTimerStart ("psphot.noise"); … … 24 57 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 25 58 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 26 assert (maskVal);59 psAssert (maskVal, "missing mask value?"); 27 60 28 61 // increase variance by factor*(object noise): … … 42 75 PS_ASSERT (status, false); 43 76 if (isfinite(GAIN)) { 44 FACTOR /= GAIN;77 FACTOR /= GAIN; 45 78 } 46 79 … … 50 83 51 84 // skip sources which were not subtracted 85 // NOTE: this bit is not modified when pmSourceOp applies to noise 52 86 if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) continue; 53 87 … … 70 104 oldshape.sxy = PAR[PM_PAR_SXY]; 71 105 72 // XXX can this be done more intelligently?73 if (oldI0 == 0.0) continue;74 if (!isfinite(oldI0)) continue;106 // XXX can this be done more intelligently? 107 if (oldI0 == 0.0) continue; 108 if (!isfinite(oldI0)) continue; 75 109 76 110 // increase size and height of source … … 79 113 axes.minor *= SIZE; 80 114 newshape = psEllipseAxesToShape (axes); 81 PAR[PM_PAR_I0] = FACTOR* PS_SQR(oldI0);115 PAR[PM_PAR_I0] = FACTOR*oldI0; 82 116 PAR[PM_PAR_SXX] = newshape.sx; 83 117 PAR[PM_PAR_SYY] = newshape.sy; -
branches/simtest_nebulous_branches/psphot/src/psphotApResid.c
r24878 r27840 4 4 // measure the aperture residual statistics and 2D variations 5 5 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 7 bool 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 33 bool psphotApResidReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) 7 34 { 8 35 int Nfail = 0; … … 13 40 pmSource *source; 14 41 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 20 42 psTimerStart ("psphot.apresid"); 21 43 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?"); 25 64 26 65 // determine the number of allowed threads … … 33 72 if (!measureAptrend) { 34 73 // save nan values since these were not calculated 35 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYBIAS", PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias", NAN); 36 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYSAT", PS_DATA_F32 | PS_META_REPLACE, "aperture-determined saturation", NAN); 37 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN); 38 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN); 39 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN); 40 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0); 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); 41 78 return true; 42 79 } … … 53 90 maskVal |= markVal; 54 91 55 // S/N limit to perform full non-linear fits 92 // clipping for extreme outliers 93 // XXX this is not currently defined in the recipe 56 94 float MAX_AP_OFFSET = psMetadataLookupF32 (&status, recipe, "MAX_AP_OFFSET"); 57 95 58 // this is the smallest radius allowed: need to at least extend growth curve down to this... 96 // options for how the photometry is calculated 97 // XXX are these sensible? 59 98 bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH"); 60 99 bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP"); … … 100 139 PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32); 101 140 PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK); 141 PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK); 102 142 103 143 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nskip … … 110 150 } 111 151 psFree(job); 112 113 # if (0)114 int nskip = 0;115 int nfail = 0;116 117 if (!psphotApResidMags_Unthreaded (&nskip, &nfail, sources, psf, photMode, maskVal)) {118 psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");119 return false;120 }121 Nskip += nskip;122 Nfail += nfail;123 # endif124 125 152 } 126 153 … … 138 165 } else { 139 166 psScalar *scalar = NULL; 140 scalar = job->args->data[ 4];167 scalar = job->args->data[5]; 141 168 Nskip += scalar->data.S32; 142 scalar = job->args->data[ 5];169 scalar = job->args->data[6]; 143 170 Nfail += scalar->data.S32; 144 171 } … … 150 177 151 178 // gather the stats to assess the aperture residuals 152 psVector *mask = psVectorAllocEmpty (300, PS_TYPE_VECTOR_MASK);153 179 psVector *mag = psVectorAllocEmpty (300, PS_TYPE_F32); 154 180 psVector *xPos = psVectorAllocEmpty (300, PS_TYPE_F32); … … 158 184 Npsf = 0; 159 185 186 # ifdef DEBUG 187 FILE *f = fopen ("apresid.dat", "w"); 188 psAssert (f, "failed open"); 189 # endif 190 160 191 for (int i = 0; i < sources->n; i++) { 161 192 source = sources->data[i]; … … 170 201 if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) SKIPSTAR ("EXTENDED"); 171 202 if (source->mode & PM_SOURCE_MODE_CR_LIMIT) SKIPSTAR ("COSMIC RAY"); 203 if (source->mode & PM_SOURCE_MODE_DEFECT) SKIPSTAR ("DEFECT"); 172 204 173 205 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 174 206 continue; 175 207 } 208 209 // XXX make this user-configurable? 210 if (source->errMag > 0.01) continue; 176 211 177 212 // aperture residual for this source … … 185 220 } 186 221 187 mag->data.F32[Npsf] = source->psfMag; 188 apResid->data.F32[Npsf] = dap; 189 xPos->data.F32[Npsf] = model->params->data.F32[PM_PAR_XPOS]; 190 yPos->data.F32[Npsf] = model->params->data.F32[PM_PAR_YPOS]; 191 192 mask->data.PS_TYPE_VECTOR_MASK_DATA[Npsf] = 0; 193 194 dMag->data.F32[Npsf] = model->dparams->data.F32[PM_PAR_I0] / model->params->data.F32[PM_PAR_I0]; 195 196 psVectorExtend (mag, 100, 1); 197 psVectorExtend (mask, 100, 1); 198 psVectorExtend (xPos, 100, 1); 199 psVectorExtend (yPos, 100, 1); 200 psVectorExtend (dMag, 100, 1); 201 psVectorExtend (apResid, 100, 1); 222 # ifdef DEBUG 223 fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f\n", 224 source->peak->xf, source->peak->yf, 225 source->modelPSF->params->data.F32[PM_PAR_XPOS], source->modelPSF->params->data.F32[PM_PAR_YPOS], 226 source->psfMag, source->apMag, source->errMag, 227 source->modelPSF->params->data.F32[PM_PAR_I0], 228 source->modelPSF->params->data.F32[PM_PAR_SXX], source->modelPSF->params->data.F32[PM_PAR_SXY], source->modelPSF->params->data.F32[PM_PAR_SYY], 229 source->modelPSF->params->data.F32[PM_PAR_7]); 230 # endif 231 if (!isfinite(source->psfMag)) psAbort ("nan in psfMag"); 232 if (!isfinite(source->errMag)) psAbort ("nan in errMag"); 233 if (!isfinite(source->apMag)) psAbort ("nan in apMag"); 234 if (!isfinite(model->params->data.F32[PM_PAR_XPOS])) psAbort ("nan in xPos"); 235 if (!isfinite(model->params->data.F32[PM_PAR_YPOS])) psAbort ("nan in yPos"); 236 237 psVectorAppend (mag, source->psfMag); 238 psVectorAppend (dMag,source->errMag); 239 psVectorAppend (apResid, dap); 240 psVectorAppend (xPos, model->params->data.F32[PM_PAR_XPOS]); 241 psVectorAppend (yPos, model->params->data.F32[PM_PAR_YPOS]); 202 242 Npsf ++; 203 243 } … … 205 245 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "measure aperture residuals for %d objects (%d skipped, %d failed, %ld invalid)\n", 206 246 Npsf, Nskip, Nfail, sources->n - Npsf - Nskip - Nfail); 247 248 # ifdef DEBUG 249 fclose (f); 250 # endif 207 251 208 252 // XXX choose a better value here? … … 212 256 } 213 257 214 // XXX deprecating the old code which allowed the ApResid to be fitted as a function of flux and r^2/flux 215 // XXX is this asymmetric clipping still needed? this analysis should come after neighbors are subtracted... 216 // 3hi/1lo sigma clipping on the rflux vs metric fit 217 // systematic error information 218 float errorScale = 0.0; 219 float errorFloor = 0.0; 220 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); 275 276 psFree (psf->ApTrend); 277 psf->ApTrend = NULL; 221 278 float errorFloorMin = FLT_MAX; 222 int entryMin = -1; 223 224 // Fit out the dap vs mag trend, iterate over spatial scale until error Floor increases. 225 // Stop if Npsf / (Nx * Ny) < 3 279 280 // as we loop over orders, we need to refer to the initial selection, but we modify the 281 // option values to match the current guess: save the max values here: 282 int NX = readout->image->numCols; 283 int NY = readout->image->numRows; 226 284 for (int i = 1; i <= APTREND_ORDER_MAX; i++) { 227 228 if (!psphotApResidTrend (readout, psf, Npsf, i, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag)) { 229 break; 230 } 231 232 // store the resulting errorFloor values and the scales, redo the best 285 286 int Nx, Ny; 287 if (NX > NY) { 288 Nx = i; 289 Ny = PS_MAX (1, (int)(i * (NY / (float)(NX)) + 0.5)); 290 } else { 291 Ny = i; 292 Nx = PS_MAX (1, (int)(i * (NX / (float)(NY)) + 0.5)); 293 } 294 295 float errorFloor; 296 pmTrend2D *apTrend = psphotApResidTrend (&errorFloor, readout, Nx, Ny, xPos, yPos, apResid, dMag); 297 if (!apTrend) { 298 continue; 299 } 300 301 // apply ApTrend results 302 // float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5; 303 // float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5; 304 // float ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center 305 // if (!isfinite(ApResid)) psAbort("nan apresid @ center"); 306 307 // store the minimum errorFloor and best ApTrend to keep 233 308 if (errorFloor < errorFloorMin) { 234 309 errorFloorMin = errorFloor; 235 entryMin = i; 310 psFree (psf->ApTrend); 311 psf->ApTrend = psMemIncrRefCounter(apTrend); 236 312 } 237 } 238 if (entryMin == -1) { 313 psFree (apTrend); 314 } 315 if (psf->ApTrend == NULL) { 239 316 psWarning("Failed to find a valid aperture residual value"); 240 317 goto escape; 241 318 } 242 319 243 // XXX catch error condition 244 psphotApResidTrend (readout, psf, Npsf, entryMin, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag); 320 // apply ApTrend results 321 float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5; 322 float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5; 323 324 psf->ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center 325 psf->dApResid = errorFloorMin; 326 psf->nApResid = Npsf; 327 328 // save results for later output 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); 333 334 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid); 335 psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d sources: %f sec\n", Npsf, psTimerMark ("psphot.apresid")); 336 337 psFree (xPos); 338 psFree (yPos); 339 psFree (apResid); 340 psFree (mag); 341 psFree (dMag); 342 343 psphotVisualPlotApResid (sources, psf->ApResid, psf->dApResid); 344 345 return true; 346 347 escape: 348 // save nan values since these were not calculated 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); 353 354 psFree (xPos); 355 psFree (yPos); 356 psFree (apResid); 357 psFree (mag); 358 psFree (dMag); 359 return true; 360 // this is a quality error, not a programming error 361 } 362 363 pmTrend2D *psphotApResidTrend (float *apResidSysErr, pmReadout *readout, int Nx, int Ny, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) { 364 365 // the mask marks the values not used to calculate the ApTrend 366 psVector *mask = psVectorAlloc(xPos->n, PS_TYPE_VECTOR_MASK); 367 psVectorInit (mask, 0); 368 369 // XXX allow user to set this optionally? 370 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 371 372 // measure Trend2D for the current spatial scale 373 pmTrend2D *apTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats); 374 375 // XXX somewhat arbitrary: soften the errors so the few bright stars do not totally dominate: 376 // XXX use this or not? probably not, since this is the point of the systematic error analysis 377 psVector *dMagSoft = psVectorAlloc (dMag->n, PS_TYPE_F32); 378 for (int i = 0; i < dMag->n; i++) { 379 dMagSoft->data.F32[i] = hypot(dMag->data.F32[i], 0.005); 380 } 381 382 // XXX test for errors here 383 if (!pmTrend2DFit (apTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft)) { 384 psWarning("Failed to fit trend for %d x %d map", Nx, Ny); 385 psFree (apTrend); 386 return NULL; 387 } 388 if (apTrend->mode == PM_TREND_MAP) { 389 // p_psImagePrint (2, apTrend->map->map, "ApTrend Before"); // XXX TEST: 390 psImageMapRepair (apTrend->map->map); 391 // p_psImagePrint (2, apTrend->map->map, "ApTrend After"); // XXX TEST: 392 } 245 393 246 394 // construct the fitted values and the residuals 247 psVector *apResidFit = pmTrend2DEvalVector ( psf->ApTrend, mask, 0xff, xPos, yPos);395 psVector *apResidFit = pmTrend2DEvalVector (apTrend, mask, 0xff, xPos, yPos); 248 396 psVector *apResidRes = (psVector *) psBinaryOp (NULL, (void *) apResid, "-", (void *) apResidFit); 249 psVector *dMagSys = (psVector *) psBinaryOp (NULL, (void *) dMag, "*", (void *) psScalarAlloc(errorScale, PS_TYPE_F32)); 250 251 if (psTraceGetLevel("psphot") >= 2) { 252 FILE *dumpFile = fopen ("apresid.dat", "w"); 397 398 // measure systematic error 399 *apResidSysErr = psVectorSystematicError (apResidRes, dMag, 0.10); 400 if (!isfinite(*apResidSysErr)) { 401 psWarning("Failed to find systematic error for %d x %d map", Nx, Ny); 402 psFree (apTrend); 403 return NULL; 404 } 405 406 psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid\n", Nx, Ny); 407 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *apResidSysErr); 408 409 if (psTraceGetLevel("psphot") >= 4) { 410 char filename[64]; 411 snprintf (filename, 64, "apresid.%dx%d.dat", Nx, Ny); 412 FILE *dumpFile = fopen (filename, "w"); 253 413 for (int i = 0; i < xPos->n; i++) { 254 fprintf (dumpFile, "%f %f %f %f %f%f %f %x\n",414 fprintf (dumpFile, "%f %f %f %f %f %f %x\n", 255 415 xPos->data.F32[i], yPos->data.F32[i], 256 mag->data.F32[i], dMag->data.F32[i], dMagSys->data.F32[i],416 dMag->data.F32[i], hypot(dMag->data.F32[i], *apResidSysErr), 257 417 apResid->data.F32[i], apResidRes->data.F32[i], 258 418 mask->data.PS_TYPE_VECTOR_MASK_DATA[i]); … … 261 421 } 262 422 263 // apply ApTrend results264 float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5;265 float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5;266 267 psf->ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center268 psf->dApResid = errorFloor;269 psf->nApResid = Npsf;270 271 // save results for later output272 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYBIAS", PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias", 0.0);273 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYSAT", PS_DATA_F32 | PS_META_REPLACE, "aperture-determined saturation", 0.0);274 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", psf->ApResid);275 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid);276 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth->apLoss);277 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid);278 279 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid);280 psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d sources: %f sec\n", Npsf, psTimerMark ("psphot.apresid"));281 282 psFree (mag);283 423 psFree (mask); 284 psFree (xPos);285 psFree (yPos);286 287 psFree (apResid);288 psFree (apResidFit);289 psFree (apResidRes);290 291 psFree (dMagSys);292 psFree (dMag);293 294 psphotVisualPlotApResid (sources);295 296 return true;297 298 escape:299 // save nan values since these were not calculated300 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYBIAS", PS_DATA_F32 | PS_META_REPLACE, "aperture sky bias", NAN);301 psMetadataAdd (recipe, PS_LIST_TAIL, "SKYSAT", PS_DATA_F32 | PS_META_REPLACE, "aperture-determined saturation", NAN);302 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN);303 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN);304 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN);305 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0);306 307 psFree (mag);308 psFree (mask);309 psFree (xPos);310 psFree (yPos);311 psFree (apResid);312 psFree (dMag);313 return false;314 }315 316 /*317 (aprMag' - fitMag) = rflux*skyBias + ApTrend(x,y)318 (aprMag - rflux*skyBias) - fitMag = ApTrend(x,y)319 (aprMag - rflux*skyBias) = fitMag + ApTrend(x,y)320 */321 322 // XXX this still sucks... need a better way to estimate the error floor...323 bool psphotMagErrorScale (float *errorScale, float *errorFloor, psVector *dMag, psVector *dap, psVector *mask, int nGroup) {324 325 psStats *statsS = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);326 psStats *statsM = psStatsAlloc (PS_STAT_SAMPLE_MEAN);327 328 // measure the trend in bins with 10 values each; if < 10 total, use them all329 int nBin = PS_MAX (dMag->n / nGroup, 1);330 331 // output vectors for ApResid trend332 psVector *dSo = psVectorAlloc (nBin, PS_TYPE_F32);333 psVector *dMo = psVectorAlloc (nBin, PS_TYPE_F32);334 psVector *dRo = psVectorAlloc (nBin, PS_TYPE_F32);335 336 // use dMag to group the dMag and dap vectors337 psVector *index = psVectorSortIndex (NULL, dMag);338 339 // subset vectors for dMag and dap values within the given range340 psVector *dMSubset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);341 psVector *dASubset = psVectorAllocEmpty (nGroup, PS_TYPE_F32);342 psVector *mkSubset = psVectorAllocEmpty (nGroup, PS_TYPE_VECTOR_MASK);343 344 int n = 0;345 for (int i = 0; i < dMo->n; i++) {346 int j;347 for (j = 0; (j < nGroup) && (n < dMag->n); j++, n++) {348 int N = index->data.U32[n];349 dMSubset->data.F32[j] = dMag->data.F32[N];350 dASubset->data.F32[j] = dap->data.F32[N];351 mkSubset->data.PS_TYPE_VECTOR_MASK_DATA[j] = mask->data.PS_TYPE_VECTOR_MASK_DATA[N];352 }353 dMSubset->n = j;354 dASubset->n = j;355 mkSubset->n = j;356 357 psStatsInit (statsS);358 psStatsInit (statsM);359 360 if (j > 2) {361 if (!psVectorStats (statsS, dASubset, NULL, mkSubset, 0xff)) {362 psError(PS_ERR_UNKNOWN, false, "failure to measure stats");363 return false;364 }365 if (!psVectorStats (statsM, dMSubset, NULL, mkSubset, 0xff)) {366 psError(PS_ERR_UNKNOWN, false, "failure to measure stats");367 return false;368 }369 dSo->data.F32[i] = statsS->robustStdev;370 dMo->data.F32[i] = statsM->sampleMean;371 dRo->data.F32[i] = statsS->robustStdev / statsM->sampleMean;372 } else {373 dSo->data.F32[i] = NAN;374 dMo->data.F32[i] = NAN;375 dRo->data.F32[i] = NAN;376 }377 }378 psFree (dMSubset);379 psFree (dASubset);380 psFree (mkSubset);381 382 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);383 if (!psVectorStats (stats, dRo, NULL, NULL, 0)) {384 psError(PS_ERR_UNKNOWN, false, "failure to measure stats");385 return false;386 }387 388 *errorScale = stats->sampleMedian;389 for (int i = 0; i < dSo->n; i++) {390 *errorFloor = dSo->data.F32[i];391 if (fabs(*errorFloor) <= FLT_EPSILON) continue;392 if (isfinite(*errorFloor)) break;393 }394 395 psFree (stats);396 psFree (index);397 398 psFree (dRo);399 psFree (dMo);400 psFree (dSo);401 402 psFree (statsS);403 psFree (statsM);404 405 return true;406 }407 408 bool psphotApResidTrend (pmReadout *readout, pmPSF *psf, int Npsf, int scale, float *errorScale, float *errorFloor, psVector *mask, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) {409 410 int Nx, Ny;411 412 if (readout->image->numCols > readout->image->numRows) {413 Nx = scale;414 float AR = readout->image->numRows / (float) readout->image->numCols;415 Ny = (int) (Nx * AR + 0.5);416 Ny = PS_MAX (1, Ny);417 } else {418 Ny = scale;419 float AR = readout->image->numRows / (float) readout->image->numCols;420 Nx = (int) (Ny * AR + 0.5);421 Nx = PS_MAX (1, Nx);422 }423 424 // require at least 10 stars per spatial bin425 if (Npsf < 10*Nx*Ny) {426 return false;427 }428 429 // the mask marks the values not used to calculate the ApTrend430 psVectorInit (mask, 0);431 432 // XXX stats structure for use by ApTrend : make parameters user setable433 psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);434 stats->min = 2.0;435 stats->max = 3.0;436 437 // measure Trend2D for the current spatial scale438 psFree (psf->ApTrend);439 psf->ApTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats);440 441 // XXX somewhat arbitrary: soften the errors so the few bright stars do not totally dominate:442 psVector *dMagSoft = psVectorAlloc (dMag->n, PS_TYPE_F32);443 for (int i = 0; i < dMag->n; i++) {444 dMagSoft->data.F32[i] = hypot(dMag->data.F32[i], 0.01);445 }446 447 // XXX test for errors here448 pmTrend2DFit (psf->ApTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft);449 450 // construct the fitted values and the residuals451 psVector *apResidFit = pmTrend2DEvalVector (psf->ApTrend, mask, 0xff, xPos, yPos);452 psVector *apResidRes = (psVector *) psBinaryOp (NULL, (void *) apResid, "-", (void *) apResidFit);453 454 // measure systematic errorFloor & systematic / photon scale factor455 // XXX this is a bit arbitrary, but it forces ~3 stars from the bright bin per spatial bin456 int nGroup = PS_MAX (3*Nx*Ny, 10);457 psphotMagErrorScale (errorScale, errorFloor, dMag, apResidRes, mask, nGroup);458 459 psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid (%d stars per bin)\n", Nx, Ny, nGroup);460 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic error / photon error: %f\n", *errorScale);461 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *errorFloor);462 463 424 psFree (stats); 464 425 psFree (dMagSoft); … … 466 427 psFree (apResidRes); 467 428 468 return true;429 return apTrend; 469 430 } 470 431 … … 480 441 pmSourcePhotometryMode photMode = PS_SCALAR_VALUE(job->args->data[2],S32); 481 442 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3],PS_TYPE_IMAGE_MASK_DATA); 443 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA); 482 444 483 445 for (int i = 0; i < sources->n; i++) { … … 490 452 if (source->mode & PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR"); 491 453 492 if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) { 493 Nskip ++; 494 psTrace ("psphot", 3, "skip : bad source mag"); 495 continue; 454 // replace object in image 455 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 456 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 496 457 } 497 458 498 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 499 Nfail ++; 500 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag); 501 continue; 502 } 503 source->mode |= PM_SOURCE_MODE_AP_MAGS; 459 // clear the mask bit and set the circular mask pixels 460 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 461 psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal); 462 463 bool status = pmSourceMagnitudes (source, psf, photMode, maskVal); 464 465 // clear the mask bit 466 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 467 468 // re-subtract the object, leave local sky 469 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 470 471 if (!status) { 472 Nskip ++; 473 psTrace ("psphot", 3, "skip : bad source mag"); 474 continue; 475 } 476 477 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 478 Nfail ++; 479 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag); 480 continue; 481 } 482 source->mode |= PM_SOURCE_MODE_AP_MAGS; 504 483 } 505 484 506 485 // change the value of a scalar on the array (wrap this and put it in psArray.h) 507 scalar = job->args->data[ 4];486 scalar = job->args->data[5]; 508 487 scalar->data.S32 = Nskip; 509 488 510 scalar = job->args->data[ 5];489 scalar = job->args->data[6]; 511 490 scalar->data.S32 = Nfail; 512 491 513 492 return true; 514 493 } 515 516 # if (0)517 bool psphotApResidMags_Unthreaded (int *nskip, int *nfail, psArray *sources, pmPSF *psf, pmSourcePhotometryMode photMode, psImageMaskType maskVal) {518 519 int Nskip = 0;520 int Nfail = 0;521 522 for (int i = 0; i < sources->n; i++) {523 pmSource *source = (pmSource *) sources->data[i];524 525 if (source->type != PM_SOURCE_TYPE_STAR) SKIPSTAR ("NOT STAR");526 if (source->mode & PM_SOURCE_MODE_SATSTAR) SKIPSTAR ("SATSTAR");527 if (source->mode & PM_SOURCE_MODE_BLEND) SKIPSTAR ("BLEND");528 if (source->mode & PM_SOURCE_MODE_FAIL) SKIPSTAR ("FAIL STAR");529 if (source->mode & PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR");530 531 if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) {532 Nskip ++;533 psTrace ("psphot", 3, "skip : bad source mag");534 continue;535 }536 537 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) {538 Nfail ++;539 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag);540 continue;541 }542 }543 544 // change the value of a scalar on the array (wrap this and put it in psArray.h)545 *nskip = Nskip;546 *nfail = Nfail;547 548 return true;549 }550 # endif -
branches/simtest_nebulous_branches/psphot/src/psphotArguments.c
r24587 r27840 218 218 // override any configuration-specified source for these files 219 219 // 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"); 224 224 225 225 if (argc == 1) { … … 228 228 } 229 229 230 if (psArgumentGet(argc, argv, "-help") 231 ||psArgumentGet(argc, argv, "-h"))230 if (psArgumentGet(argc, argv, "-help") || 231 psArgumentGet(argc, argv, "-h")) 232 232 writeHelpInfo(argv[0], config, stdout); 233 233 -
branches/simtest_nebulous_branches/psphot/src/psphotBasicDeblend.c
r20453 r27840 1 1 # include "psphotInternal.h" 2 2 3 bool psphotBasicDeblend (psArray *sources, psMetadata *recipe) { 3 // for now, let's store the detections on the readout->analysis for each readout 4 bool 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 21 bool psphotBasicDeblendReadout (pmConfig *config, const pmFPAview *view, const char *filename, int fileIndex) { 4 22 5 23 int N; … … 8 26 pmSource *source, *testSource; 9 27 28 psTimerStart ("psphot.deblend.basic"); 29 10 30 int Nblend = 0; 11 31 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?"); 13 53 14 54 float FRACTION = psMetadataLookupF32 (&status, recipe, "DEBLEND_PEAK_FRACTION"); -
branches/simtest_nebulous_branches/psphot/src/psphotBlendFit.c
r24029 r27840 1 1 # include "psphotInternal.h" 2 2 3 // for now, let's store the detections on the readout->analysis for each readout 4 bool 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 3 25 // XXX I don't like this name 4 bool psphotBlendFit (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf) {26 bool psphotBlendFitReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) { 5 27 6 28 int Nfit = 0; … … 12 34 psTimerStart ("psphot.fit.nonlinear"); 13 35 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?"); 17 56 18 57 // determine the number of allowed threads … … 40 79 psphotInitLimitsPSF (recipe, readout); 41 80 psphotInitLimitsEXT (recipe); 42 psphotInitRadiusPSF (recipe, psf->type);81 psphotInitRadiusPSF (recipe, readout->analysis, psf->type); 43 82 44 83 // starts the timer, sets up the array of fitSets … … 47 86 // source analysis is done in S/N order (brightest first) 48 87 sources = psArraySort (sources, pmSourceSortBySN); 88 if (!sources->n) { 89 psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping blend"); 90 return true; 91 } 49 92 50 93 // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts) … … 254 297 pmSourceCacheModel (source, maskVal); 255 298 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 256 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;257 299 } 258 300 … … 273 315 } 274 316 275 # if (0)276 bool psphotBlendFit_Unthreaded (int *nfit, int *npsf, int *next, int *nfail, pmReadout *readout, psMetadata *recipe, psArray *sources, pmPSF *psf, psArray *newSources) {277 278 bool status = false;279 int Nfit = 0;280 int Npsf = 0;281 int Next = 0;282 int Nfail = 0;283 284 // bit-masks to test for good/bad pixels285 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT");286 assert (maskVal);287 288 // bit-mask to mark pixels not used in analysis289 psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT");290 assert (markVal);291 292 // maskVal is used to test for rejected pixels, and must include markVal293 maskVal |= markVal;294 295 // S/N limit to perform full non-linear fits296 float FIT_SN_LIM = psMetadataLookupF32 (&status, recipe, "FULL_FIT_SN_LIM");297 298 // option to limit analysis to a specific region299 char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION");300 psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region));301 if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined");302 303 for (int i = 0; i < sources->n; i++) {304 pmSource *source = sources->data[i];305 306 // skip non-astronomical objects (very likely defects)307 if (source->mode & PM_SOURCE_MODE_BLEND) continue;308 if (source->mode & PM_SOURCE_MODE_CR_LIMIT) continue;309 if (source->type == PM_SOURCE_TYPE_DEFECT) continue;310 if (source->type == PM_SOURCE_TYPE_SATURATED) continue;311 312 // skip DBL second sources (ie, added by psphotFitBlob)313 if (source->mode & PM_SOURCE_MODE_PAIR) continue;314 315 // limit selection to some SN limit316 if (source->peak->SN < FIT_SN_LIM) continue;317 318 // exclude sources outside optional analysis region319 if (source->peak->xf < AnalysisRegion.x0) continue;320 if (source->peak->yf < AnalysisRegion.y0) continue;321 if (source->peak->xf > AnalysisRegion.x1) continue;322 if (source->peak->yf > AnalysisRegion.y1) continue;323 324 // if model is NULL, we don't have a starting guess325 if (source->modelPSF == NULL) continue;326 327 // skip sources which are insignificant flux?328 // XXX this is somewhat ad-hoc329 if (source->modelPSF->params->data.F32[1] < 0.1) {330 psTrace ("psphot", 5, "skipping near-zero source: %f, %f : %f\n",331 source->modelPSF->params->data.F32[1],332 source->modelPSF->params->data.F32[2],333 source->modelPSF->params->data.F32[3]);334 continue;335 }336 337 // replace object in image338 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) {339 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);340 }341 Nfit ++;342 343 // try fitting PSFs or extended sources depending on source->mode344 // these functions subtract the resulting fitted source345 if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {346 if (psphotFitBlob (readout, source, newSources, psf, maskVal, markVal)) {347 source->type = PM_SOURCE_TYPE_EXTENDED;348 psTrace ("psphot", 5, "source at %7.1f, %7.1f is ext", source->peak->xf, source->peak->yf);349 Next ++;350 continue;351 }352 } else {353 if (psphotFitBlend (readout, source, psf, maskVal, markVal)) {354 source->type = PM_SOURCE_TYPE_STAR;355 psTrace ("psphot", 5, "source at %7.1f, %7.1f is psf", source->peak->xf, source->peak->yf);356 Npsf ++;357 continue;358 }359 }360 361 psTrace ("psphot", 5, "source at %7.1f, %7.1f failed", source->peak->xf, source->peak->yf);362 Nfail ++;363 364 // re-subtract the object, leave local sky365 pmSourceCacheModel (source, maskVal);366 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);367 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;368 }369 370 // change the value of a scalar on the array (wrap this and put it in psArray.h)371 *nfit = Nfit;372 *npsf = Npsf;373 *next = Next;374 *nfail = Nfail;375 376 return true;377 }378 # endif -
branches/simtest_nebulous_branches/psphot/src/psphotChoosePSF.c
r23989 r27840 1 1 # include "psphotInternal.h" 2 2 3 void psphotCountPSFStars (psArray *sources) { 4 5 int nPSF = 0; 6 7 // select the candidate PSF stars (pointers to original sources) 8 for (int i = 0; i < sources->n; i++) { 9 pmSource *source = sources->data[i]; 10 if (source->mode & PM_SOURCE_MODE_PSFSTAR) { 11 nPSF ++; 12 } 13 } 14 15 fprintf (stderr, "N PSF: %d\n", nPSF); 3 // generate a PSF model for inputs without PSF models already loaded 4 bool 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; 16 28 } 17 29 18 30 // try PSF models and select best option 19 pmPSF *psphotChoosePSF (pmReadout *readout, psArray *sources, psMetadata *recipe) {31 bool psphotChoosePSFReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) { 20 32 21 33 bool status; 22 34 23 35 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 } 24 60 25 61 // bit-masks to test for good/bad pixels 26 62 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); 27 assert (maskVal);63 psAssert (maskVal, "missing mask value?"); 28 64 29 65 // bit-mask to mark pixels not used in analysis 30 66 psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); 31 assert (markVal);67 psAssert (markVal, "missing mark value?"); 32 68 33 69 // maskVal is used to test for rejected pixels, and must include markVal … … 73 109 // get the fixed PSF fit radius 74 110 // XXX check that PSF_FIT_RADIUS < SKY_OUTER_RADIUS 75 options->radius = psMetadataLookupF32 (&status, recipe, "PSF_FIT_RADIUS"); 76 assert (status); 77 78 // XXX ROBUST seems to be too agressive given the small numbers. 79 // options->stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 80 options->stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 111 // options->radius = psMetadataLookupF32 (&status, recipe, "PSF_FIT_RADIUS"); 112 // assert (status); 113 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 } 120 float fitScale = psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS_SCALE"); 121 float apScale = psMetadataLookupF32(&status, recipe, "PSF_APERTURE_SCALE"); 122 options->fitRadius = (int)(fitScale*gaussSigma); 123 options->apRadius = (int)(apScale*gaussSigma); 124 125 // XXX use the same radii for standard analysis as for the PSF creation 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); 81 128 82 129 // dimensions of the field for which the PSF is defined … … 99 146 100 147 psArray *stars = psArrayAllocEmpty (sources->n); 101 102 // psphotCountPSFStars (sources);103 148 104 149 // select the candidate PSF stars (pointers to original sources) … … 115 160 } 116 161 117 // psphotCountPSFStars (sources);118 119 162 // check that the identified psf stars sufficiently cover the region; if not, extend the 120 163 // limits somewhat 121 164 psphotCheckStarDistribution (stars, sources, options); 122 165 123 // psphotCountPSFStars (sources);124 125 166 psLogMsg ("psphot.pspsf", PS_LOG_DETAIL, "selected candidate %ld PSF objects\n", stars->n); 167 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 } 126 174 127 175 // get the list pointers for the PSF_MODEL entries … … 164 212 bool status = true; 165 213 status &= psphotMakeFluxScale (readout->image, recipe, psf); 166 status &= psphotPSFstats (readout, recipe,psf);214 status &= psphotPSFstats (readout, psf); 167 215 if (!status) { 168 216 psError(PSPHOT_ERR_PSF, false, "Failed to fit any models when choosing PSF"); … … 239 287 bool status = true; 240 288 status &= psphotMakeFluxScale (readout->image, recipe, psf); 241 status &= psphotPSFstats (readout, recipe,psf);289 status &= psphotPSFstats (readout, psf); 242 290 if (!status) { 243 291 psError(PSPHOT_ERR_PSF, false, "Failed to fit any models when choosing PSF"); … … 289 337 // XXX test dump of psf star data and psf-subtracted image 290 338 if (psTraceGetLevel("psphot.psfstars") > 5) { 291 psphotDumpPSFStars (readout, try, options-> radius, maskVal, markVal);339 psphotDumpPSFStars (readout, try, options->fitRadius, maskVal, markVal); 292 340 } 293 341 294 342 // save only the best model; 295 // XXX we are not saving the fitted sources296 // XXX do we want to keep them so we may optionally write them out?297 343 pmPSF *psf = psMemIncrRefCounter(try->psf); 298 344 psFree (models); 299 345 300 if (!psphotPSFstats (readout, recipe,psf)) {346 if (!psphotPSFstats (readout, psf)) { 301 347 psError(PSPHOT_ERR_PSF, false, "cannot measure PSF shape terms"); 302 348 psFree(options); … … 305 351 } 306 352 307 // psphotCountPSFStars (sources);308 309 353 char *modelName = pmModelClassGetName (psf->type); 310 354 psLogMsg ("psphot.pspsf", PS_LOG_INFO, "select psf model: %f sec\n", psTimerMark ("psphot.choose.psf")); … … 312 356 313 357 psFree (options); 314 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; 315 370 } 316 371 317 372 // measure average parameters of the PSF model 318 bool psphotPSFstats (pmReadout *readout, p sMetadata *recipe, pmPSF *psf) {373 bool psphotPSFstats (pmReadout *readout, pmPSF *psf) { 319 374 320 375 psEllipseShape shape; … … 322 377 323 378 PS_ASSERT_PTR_NON_NULL(readout, false); 324 PS_ASSERT_PTR_NON_NULL(recipe, false);325 379 PS_ASSERT_PTR_NON_NULL(psf, false); 326 380 … … 341 395 // create modelPSF from this model 342 396 pmModel *modelPSF = pmModelFromPSFforXY (psf, xc, yc, 1.0); 343 if (!modelPSF) continue; 397 if (!modelPSF) { 398 fprintf (stderr, "?"); 399 continue; 400 } 344 401 345 402 // get the model full-width at half-max … … 354 411 355 412 float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major); 356 if (!isfinite(FWHM_MAJOR) || !isfinite(FWHM_MINOR)) continue; 413 if (!isfinite(FWHM_MAJOR) || !isfinite(FWHM_MINOR)) { 414 fprintf (stderr, "!"); 415 continue; 416 } 357 417 psVectorAppend (fwhmMajor, FWHM_MAJOR); 358 418 psVectorAppend (fwhmMinor, FWHM_MINOR); … … 366 426 } 367 427 368 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_MAJ", PS_META_REPLACE, "PSF FWHM Major axis (mean)", stats->sampleMean); 369 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_SG", PS_META_REPLACE, "PSF FWHM Major axis (sigma)", stats->sampleStdev); 370 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_LQ", PS_META_REPLACE, "PSF FWHM Major axis (lower quartile)", stats->sampleLQ); 371 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 372 434 373 435 if (!psVectorStats (stats, fwhmMinor, NULL, NULL, 0)) { … … 375 437 return false; 376 438 } 377 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_MIN", PS_META_REPLACE, "PSF FWHM Minor axis (mean)", stats->sampleMean); 378 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_SG", PS_META_REPLACE, "PSF FWHM Minor axis (sigma)", stats->sampleStdev); 379 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_LQ", PS_META_REPLACE, "PSF FWHM Minor axis (lower quartile)", stats->sampleLQ); 380 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_UQ", PS_META_REPLACE, "PSF FWHM Minor axis (upper quartile)", stats->sampleUQ); 381 382 psMetadataAddF32 (recipe, PS_LIST_TAIL, "ANGLE", PS_META_REPLACE, "PSF angle", axes.theta); 383 psMetadataAddS32 (recipe, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", psf->nPSFstars); 384 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); 385 455 386 456 psFree (fwhmMajor); … … 391 461 392 462 // determine approximate PSF shape parameters based on the moments 393 bool psphotMomentsStats (pmReadout *readout, ps Metadata *recipe, psArray *sources) {463 bool psphotMomentsStats (pmReadout *readout, psArray *sources) { 394 464 395 465 // without the PSF model, we can only rely on the source->moments … … 405 475 406 476 PS_ASSERT_PTR_NON_NULL(readout, false); 407 PS_ASSERT_PTR_NON_NULL(recipe, false);408 477 PS_ASSERT_PTR_NON_NULL(sources, false); 409 478 … … 433 502 FWHM_T /= FWHM_N; 434 503 435 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_MAJ", PS_META_REPLACE, "PSF FWHM Major axis (mean)", FWHM_X); 436 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_SG", PS_META_REPLACE, "PSF FWHM Major axis (sigma)", 0); 437 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_LQ", PS_META_REPLACE, "PSF FWHM Major axis (lower quartile)", 0); 438 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MJ_UQ", PS_META_REPLACE, "PSF FWHM Major axis (upper quartile)", 0); 439 440 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FWHM_MIN", PS_META_REPLACE, "PSF FWHM Minor axis (mean)", FWHM_Y); 441 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_SG", PS_META_REPLACE, "PSF FWHM Minor axis (sigma)", 0); 442 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_LQ", PS_META_REPLACE, "PSF FWHM Minor axis (lower quartile)", 0); 443 psMetadataAddF32 (recipe, PS_LIST_TAIL, "FW_MN_UQ", PS_META_REPLACE, "PSF FWHM Minor axis (upper quartile)", 0); 444 445 psMetadataAddF32 (recipe, PS_LIST_TAIL, "ANGLE", PS_META_REPLACE, "PSF angle", FWHM_T); 446 psMetadataAddS32 (recipe, PS_LIST_TAIL, "NPSFSTAR", PS_META_REPLACE, "Number of stars used to make PSF", 0); 447 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); 448 522 449 523 return true; -
branches/simtest_nebulous_branches/psphot/src/psphotCleanup.c
r24144 r27840 14 14 psFree (config); 15 15 16 psThreadPoolFinalize ();17 psTimerStop ();18 16 psMemCheckCorruption (stderr, true); 19 17 pmModelClassCleanup (); 20 psTimeFinalize ();21 18 pmSourceFitSetDone (); 22 19 pmConceptsDone (); -
branches/simtest_nebulous_branches/psphot/src/psphotCullPeaks.c
r24877 r27840 5 5 */ 6 6 psErrorCode 7 psphotCullPeaks(const psImage *image, // the image wherein lives the footprint 8 const psImage *weight, // corresponding variance image 7 psphotCullPeaks(const pmReadout *readout, // the image wherein lives the footprint 9 8 const psMetadata *recipe, 10 9 psArray *footprints) { // array of pmFootprints 10 11 11 bool status = false; 12 12 13 float nsigma_delta = psMetadataLookupF32(&status, recipe, "FOOTPRINT_CULL_NSIGMA_DELTA"); 13 14 if (!status) { … … 22 23 fPadding = 0; 23 24 } 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 25 28 const float min_threshold = nsigma_min*skyStdev; 26 29 27 30 for (int i = 0; i < footprints->n; i++) { 31 // if (i % 50 == 0) fprintf (stderr, "cull %d\n", i); 28 32 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) { 30 38 return psError(PS_ERR_UNKNOWN, false, "Culling pmFootprint %d", fp->id); 31 39 } 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 } 32 44 } 33 34 45 return PS_ERR_NONE; 35 46 } 47 48 // psLogMsg ("psphot", PS_LOG_INFO, "%ld peaks, %ld total footprints: %f sec\n", detections->peaks->n, detections->footprints->n, -
branches/simtest_nebulous_branches/psphot/src/psphotDeblendSatstars.c
r24889 r27840 1 1 # include "psphotInternal.h" 2 2 3 bool psphotDeblendSatstars (pmReadout *readout, psArray *sources, psMetadata *recipe) { 3 // for now, let's store the detections on the readout->analysis for each readout 4 bool 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 21 bool psphotDeblendSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int fileIndex) { 4 22 5 23 int N; 6 24 pmSource *source; 25 bool status; 7 26 8 27 psTimerStart ("psphot.deblend.sat"); … … 11 30 float SAT_MIN_RADIUS = 5.0; 12 31 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 14 54 pmCell *cell = readout->parent; 15 55 float SATURATION = 0.75*psMetadataLookupF32 (&status, cell->concepts, "CELL.SATURATION"); … … 49 89 psVector *xVec = contour->data[0]; 50 90 psVector *yVec = contour->data[1]; 51 if (xVec->n < 5) continue; 91 if (xVec->n < 5) { 92 psFree(contour); 93 continue; 94 } 52 95 53 96 // find the center of the contour (let's just use mid[x,y]) -
branches/simtest_nebulous_branches/psphot/src/psphotDefineFiles.c
r23688 r27840 126 126 } 127 127 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 128 137 if (psMetadataLookupPtr(NULL, config->arguments, "PSPHOT.PSF")) { 129 138 pmFPAfileBindFromArgs(&status, input, config, "PSPHOT.PSF.LOAD", "PSPHOT.PSF"); -
branches/simtest_nebulous_branches/psphot/src/psphotDiagnosticPlots.c
r23989 r27840 68 68 if (!psVectorStats (stats, histogram->nums, NULL, NULL, 0)) { 69 69 psError(PS_ERR_UNKNOWN, false, "failure to measure stats for histogram"); 70 psFree(histogram); 70 71 return false; 71 72 } … … 108 109 if (!psVectorStats (stats, histogram->nums, NULL, NULL, 0)) { 109 110 psError(PS_ERR_UNKNOWN, false, "failure to measure stats for histogram"); 111 psFree(histogram); 110 112 return false; 111 113 } -
branches/simtest_nebulous_branches/psphot/src/psphotErrorCodes.dat
r11308 r27840 2 2 # This file is used to generate psphotErrorClasses.h 3 3 # 4 BASE = 3000 First value we use 4 5 UNKNOWN Unknown PM error code 5 6 NOT_IMPLEMENTED Desired feature is not yet implemented -
branches/simtest_nebulous_branches/psphot/src/psphotExtendedSourceAnalysis.c
r21519 r27840 1 1 # include "psphotInternal.h" 2 2 3 // for now, let's store the detections on the readout->analysis for each readout 4 bool 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 3 31 // aperture-like measurements for extended sources 4 bool psphotExtendedSourceAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe) {32 bool psphotExtendedSourceAnalysisReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) { 5 33 6 34 bool status; … … 11 39 int Nkron = 0; 12 40 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 13 61 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 14 62 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 15 63 assert (maskVal); 16 64 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 } 65 // XXX require petrosian analysis for non-linear fits? 22 66 23 // option to limit analysis to a specific region 24 char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION"); 25 psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region)); 26 if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined"); 67 // XXX temporary user-supplied systematic sky noise measurement (derive from background model) 68 float skynoise = psMetadataLookupF32 (&status, recipe, "SKY.NOISE"); 27 69 28 70 // S/N limit to perform full non-linear fits … … 35 77 bool doKron = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_KRON"); 36 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 85 37 86 // source analysis is done in S/N order (brightest first) 38 87 sources = psArraySort (sources, pmSourceSortBySN); 39 88 40 // XXX some init functions for the extended source recipe options? 89 // option to limit analysis to a specific region 90 char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION"); 91 psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region)); 92 if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined"); 41 93 42 94 // choose the sources of interest … … 49 101 if (source->type == PM_SOURCE_TYPE_DEFECT) continue; 50 102 if (source->type == PM_SOURCE_TYPE_SATURATED) continue; 103 if (source->mode & PM_SOURCE_MODE_DEFECT) continue; 104 if (source->mode & PM_SOURCE_MODE_SATSTAR) continue; 105 if (!(source->mode & PM_SOURCE_MODE_EXT_LIMIT)) continue; 51 106 52 107 // limit selection to some SN limit … … 66 121 Next ++; 67 122 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 68 130 // if we request any of these measurements, we require the radial profile 69 131 if (doPetrosian || doIsophotal || doAnnuli || doKron) { 70 if (!psphotRadialProfile (source, recipe, maskVal)) {132 if (!psphotRadialProfile (source, recipe, skynoise, maskVal)) { 71 133 // all measurements below require the radial profile; skip them all 72 134 // re-subtract the object, leave local sky 73 135 psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My); 74 136 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 75 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;76 137 continue; 77 138 } … … 79 140 } 80 141 142 // Petrosian Mags 143 if (doPetrosian) { 144 if (!psphotPetrosian (source, recipe, skynoise, maskVal)) { 145 psTrace ("psphot", 5, "FAILED petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My); 146 } else { 147 psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My); 148 Npetro ++; 149 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS; 150 } 151 } 152 153 # if (0) 81 154 // Isophotal Mags 82 155 if (doIsophotal) { … … 89 162 } 90 163 } 91 92 // Petrosian Mags93 if (doPetrosian) {94 if (!psphotPetrosian (source, recipe, maskVal)) {95 psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);96 } else {97 psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);98 Npetro ++;99 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS;100 }101 }102 103 164 // Kron Mags 104 165 if (doKron) { … … 111 172 } 112 173 } 113 114 // Radial Annuli 115 if (doAnnuli) { 116 if (!psphotAnnuli (source, recipe, maskVal)) { 117 psError(PSPHOT_ERR_UNKNOWN, false, "failure in Annuli analysis"); 118 return false; 119 } 120 psTrace ("psphot", 5, "measured annuli for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My); 121 Nannuli ++; 122 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS; 123 } 174 # endif 124 175 125 176 // re-subtract the object, leave local sky 126 177 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 127 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED; 178 179 if (source->extpars) { 180 psFree(source->extpars->radFlux); 181 psFree(source->extpars->ellipticalFlux); 182 } 128 183 } 129 184 130 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); 131 186 psLogMsg ("psphot", PS_LOG_INFO, " %d petrosian\n", Npetro); 132 187 psLogMsg ("psphot", PS_LOG_INFO, " %d isophotal\n", Nisophot); 133 188 psLogMsg ("psphot", PS_LOG_INFO, " %d annuli\n", Nannuli); 134 189 psLogMsg ("psphot", PS_LOG_INFO, " %d kron\n", Nkron); 190 191 psphotVisualShowResidualImage (readout); 192 193 if (doPetrosian) { 194 psphotVisualShowPetrosians (sources); 195 } 196 135 197 return true; 136 198 } -
branches/simtest_nebulous_branches/psphot/src/psphotExtendedSourceFits.c
r21519 r27840 1 1 # include "psphotInternal.h" 2 2 3 // for now, let's store the detections on the readout->analysis for each readout 4 bool 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 3 31 // non-linear model fitting for extended sources 4 bool psphotExtendedSourceFits (pmReadout *readout, psArray *sources, psMetadata *recipe) {32 bool psphotExtendedSourceFitsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) { 5 33 6 34 bool status; … … 12 40 bool savePics = false; 13 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 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 14 60 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 15 61 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels … … 21 67 // maskVal is used to test for rejected pixels, and must include markVal 22 68 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 }29 69 30 70 // select the collection of desired models … … 226 266 227 267 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 228 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;229 268 230 269 psFree (modelFluxes); … … 253 292 // subtract the best fit from the object, leave local sky 254 293 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 255 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;256 294 257 295 // the initial model flux is no longer needed -
branches/simtest_nebulous_branches/psphot/src/psphotFindDetections.c
r21183 r27840 1 1 # include "psphotInternal.h" 2 2 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) 6 bool 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 3 27 // smooth the image, search for peaks, optionally define footprints based on the peaks 4 pmDetections *psphotFindDetections (pmDetections *detections, pmReadout *readout, psMetadata *recipe) {28 bool psphotFindDetectionsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool firstPass) { 5 29 6 30 bool status; … … 9 33 int NMAX = 0; 10 34 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 11 42 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 12 43 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 13 assert (maskVal);44 psAssert (maskVal, "missing mask value?"); 14 45 15 46 // Use the new pmFootprints approach? 16 47 const bool useFootprints = psMetadataLookupBool(NULL, recipe, "USE_FOOTPRINTS"); 17 48 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 19 51 if (!detections) { 52 // create the container 20 53 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) { 21 65 pass = 1; 22 66 NSIGMA_PEAK = psMetadataLookupF32 (&status, recipe, "PEAKS_NSIGMA_LIMIT"); PS_ASSERT (status, NULL); … … 30 74 float threshold = PS_SQR(NSIGMA_PEAK); 31 75 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 34 82 assert (detections->oldPeaks == NULL); 35 83 detections->oldPeaks = detections->peaks; … … 39 87 psImage *significance = psphotSignificanceImage (readout, recipe, pass, maskVal); 40 88 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 } 43 98 44 99 // detect the peaks in the significance image 45 100 detections->peaks = psphotFindPeaks (significance, readout, recipe, threshold, NMAX); 46 psMetadataAddF32 (re cipe, 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); 47 102 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; 50 108 } 51 109 52 110 // optionally merge peaks into footprints 53 111 if (useFootprints) { 54 psphotFindFootprints (detections, significance, readout, recipe, pass, maskVal);112 psphotFindFootprints (detections, significance, readout, recipe, threshold, pass, maskVal); 55 113 } 56 114 … … 61 119 psphotVisualShowFootprints (detections); 62 120 63 return detections; 121 psFree (detections); 122 123 return true; 64 124 } 65 125 -
branches/simtest_nebulous_branches/psphot/src/psphotFindFootprints.c
r24274 r27840 1 1 # include "psphotInternal.h" 2 2 3 bool psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psImageMaskType maskVal) {3 bool psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int pass, psImageMaskType maskVal) { 4 4 5 5 bool status; … … 9 9 int npixMin = psMetadataLookupS32(&status, recipe, "FOOTPRINT_NPIXMIN"); 10 10 PS_ASSERT (status, false); 11 12 float FOOTPRINT_NSIGMA_LIMIT;13 if (pass == 1) {14 FOOTPRINT_NSIGMA_LIMIT = psMetadataLookupS32(&status, recipe, "FOOTPRINT_NSIGMA_LIMIT");15 } else {16 FOOTPRINT_NSIGMA_LIMIT = psMetadataLookupS32(&status, recipe, "FOOTPRINT_NSIGMA_LIMIT_2");17 }18 PS_ASSERT (status, false);19 20 // XXX do we need to use the same threshold here as for peaks? does it make sense for21 // these to be different?22 23 float threshold = PS_SQR(FOOTPRINT_NSIGMA_LIMIT);24 11 25 12 int growRadius = 0; … … 54 41 if (pass == 2) { 55 42 // merge in old peaks; 56 const int includePeaks = 0x0 | 0x2; // i.e. just from newFootprints 57 58 // 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 59 44 60 45 psArray *mergedFootprints = pmFootprintArraysMerge(detections->footprints, footprints, includePeaks); … … 63 48 psFree(footprints); 64 49 psFree(detections->footprints); 50 51 // replace the merged footprints on the detection structure 65 52 detections->footprints = mergedFootprints; 66 53 } else { … … 68 55 } 69 56 70 psphotCullPeaks(readout ->image, readout->variance, recipe, detections->footprints);57 psphotCullPeaks(readout, recipe, detections->footprints); 71 58 detections->peaks = pmFootprintArrayToPeaks(detections->footprints); 72 59 psLogMsg ("psphot", PS_LOG_INFO, "%ld peaks, %ld total footprints: %f sec\n", detections->peaks->n, detections->footprints->n, psTimerMark ("psphot.footprints")); … … 74 61 return detections; 75 62 } 63 64 bool 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/simtest_nebulous_branches/psphot/src/psphotFindPeaks.c
r21519 r27840 13 13 psArray *peaks = pmPeaksInImage (significance, threshold); 14 14 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) { 17 22 // XXX do we need to set something in the readout->analysis to indicate that 18 23 // 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; 21 26 } 22 27 … … 31 36 peak->SN = sqrt(peak->value); 32 37 peak->flux = readout->image->data.F32[peak->y-row0][peak->x-col0]; 38 // if (peak->flux / peak->value > 5.0/12.0) { 39 // psWarning ("odd peak levels (1)"); 40 // } 41 // if (peak->value / peak->flux > 5*12.0) { 42 // psWarning ("odd peak levels (2)"); 43 // } 33 44 if (readout->variance && isfinite (peak->dx)) { 34 45 peak->dx *= sqrt(readout->variance->data.F32[peak->y-row0][peak->x-col0]); -
branches/simtest_nebulous_branches/psphot/src/psphotFitSourcesLinear.c
r23445 r27840 12 12 static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, int SKY_FIT_ORDER, psImageMaskType markVal); 13 13 14 bool psphotFitSourcesLinear (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, bool final) { 14 // for now, let's store the detections on the readout->analysis for each readout 15 bool 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 53 bool psphotFitSourcesLinearReadout (psMetadata *recipe, pmReadout *readout, psArray *sources, pmPSF *psf, bool final) { 15 54 16 55 bool status; … … 18 57 float y; 19 58 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 } 21 64 22 65 psTimerStart ("psphot.linear"); … … 59 102 } 60 103 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 61 111 // select the sources which will be used for the fitting analysis 62 112 for (int i = 0; i < sources->n; i++) { … … 76 126 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) continue; 77 127 } else { 78 if (source->mode & PM_SOURCE_MODE_BLEND) continue;128 // if (source->mode & PM_SOURCE_MODE_BLEND) continue; 79 129 } 80 130 … … 120 170 121 171 // 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); 123 173 psSparseMatrixElement (sparse, i, i, f); 124 174 125 175 // the formal error depends on the weighting scheme 126 176 if (CONSTANT_PHOTOMETRIC_WEIGHTS) { 127 float var = pmSourceModelDotModel (SRCi, SRCi, false );177 float var = pmSourceModelDotModel (SRCi, SRCi, false, covarFactor); 128 178 errors->data.F32[i] = 1.0 / sqrt(var); 129 179 } else { … … 133 183 134 184 // find the image x model value 135 f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS );185 f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor); 136 186 psSparseVectorElement (sparse, i, f); 137 187 … … 139 189 switch (SKY_FIT_ORDER) { 140 190 case 1: 141 f = pmSourceModelWeight (SRCi, 1, CONSTANT_PHOTOMETRIC_WEIGHTS );191 f = pmSourceModelWeight (SRCi, 1, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor); 142 192 psSparseBorderElementB (border, i, 1, f); 143 f = pmSourceModelWeight (SRCi, 2, CONSTANT_PHOTOMETRIC_WEIGHTS );193 f = pmSourceModelWeight (SRCi, 2, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor); 144 194 psSparseBorderElementB (border, i, 2, f); 145 195 146 196 case 0: 147 f = pmSourceModelWeight (SRCi, 0, CONSTANT_PHOTOMETRIC_WEIGHTS );197 f = pmSourceModelWeight (SRCi, 0, CONSTANT_PHOTOMETRIC_WEIGHTS, covarFactor); 148 198 psSparseBorderElementB (border, i, 0, f); 149 199 break; … … 165 215 166 216 // 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); 168 218 psSparseMatrixElement (sparse, j, i, f); 169 219 } … … 186 236 if (SKY_FIT_LINEAR) { 187 237 psSparseBorderSolve (&norm, &skyfit, constraint, border, 5); 188 fprintf (stderr, "skyfit: %f\n", skyfit->data.F32[0]);238 psLogMsg ("psphot", PS_LOG_MINUTIA, "skyfit: %f\n", skyfit->data.F32[0]); 189 239 } else { 190 240 norm = psSparseSolve (NULL, constraint, sparse, 5); … … 215 265 // subtract object 216 266 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 217 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;218 267 } 219 268 psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "sub models: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem); 220 269 221 270 // measure chisq for each source 222 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++) { 223 273 pmSource *source = fitSources->data[i]; 224 274 if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) continue; 225 275 pmModel *model = pmSourceGetModel (NULL, source); 226 pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal );276 pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal, covarFactor); 227 277 } 228 278 psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "get chisqs: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem); … … 239 289 240 290 psphotVisualShowResidualImage (readout); 241 psphotVisualShowFlags (sources); 291 psphotVisualPlotChisq (sources); 292 // 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); 242 297 243 298 return true; … … 245 300 246 301 // XXX do we need this? 302 // XXX disallow the simultaneous sky fit and remove this code... 247 303 248 304 // Calculate the weight terms for the sky fit component of the matrix. This function operates … … 264 320 float x = model->params->data.F32[PM_PAR_XPOS]; 265 321 float y = model->params->data.F32[PM_PAR_YPOS]; 266 psImageMaskCircle (source->maskView, x, y, model-> radiusFit, "AND", PS_NOT_IMAGE_MASK(markVal));322 psImageMaskCircle (source->maskView, x, y, model->fitRadius, "AND", PS_NOT_IMAGE_MASK(markVal)); 267 323 } 268 324 -
branches/simtest_nebulous_branches/psphot/src/psphotFitSourcesLinearStack.c
r24584 r27840 1 1 # include "psphotInternal.h" 2 // XXX need array of covar factors for each image 3 // XXX define the 'good' / 'bad' flags? 2 4 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 6 6 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) { 7 bool psphotFitSourcesLinearStack (pmConfig *config, psArray *objects, bool final) { 15 8 16 9 bool status; 17 float x;18 float y;19 10 float f; 20 // float r; 11 12 // select the appropriate recipe information 13 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE); 14 assert (recipe); 21 15 22 16 psTimerStart ("psphot.linear"); … … 33 27 maskVal |= markVal; 34 28 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); 37 32 38 33 // storage array for fitSources 39 psArray *fitSources = psArrayAllocEmpty ( sources->n);34 psArray *fitSources = psArrayAllocEmpty (objects->n); 40 35 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); 46 42 47 43 // 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; 50 48 51 // turn this bit off and turn it on again if we pass this test52 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; 53 51 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; 57 55 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; 60 58 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 } 66 63 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 } 74 67 } 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); 76 69 77 70 if (fitSources->n == 0) { … … 83 76 psVector *errors = psVectorAlloc (fitSources->n, PS_TYPE_F32); 84 77 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 87 79 psSparse *sparse = psSparseAlloc (fitSources->n, 100); 88 psSparseBorder *border = psSparseBorderAlloc (sparse, 1);89 80 90 81 // fill out the sparse matrix elements and border elements (B) … … 95 86 96 87 // 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); 98 89 psSparseMatrixElement (sparse, i, i, f); 99 90 100 91 // the formal error depends on the weighting scheme 101 92 if (CONSTANT_PHOTOMETRIC_WEIGHTS) { 102 float var = pmSourceModelDotModel (SRCi, SRCi, false );93 float var = pmSourceModelDotModel (SRCi, SRCi, false, COVAR_FACTOR); 103 94 errors->data.F32[i] = 1.0 / sqrt(var); 104 95 } else { … … 106 97 } 107 98 108 109 99 // find the image x model value 110 f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS );100 f = pmSourceDataDotModel (SRCi, SRCi, CONSTANT_PHOTOMETRIC_WEIGHTS, COVAR_FACTOR); 111 101 psSparseVectorElement (sparse, i, f); 112 113 f = pmSourceModelWeight (SRCi, 0, CONSTANT_PHOTOMETRIC_WEIGHTS);114 psSparseBorderElementB (border, i, 0, f);115 102 116 103 // loop over all other stars following this one … … 118 105 pmSource *SRCj = fitSources->data[j]; 119 106 107 // we only need to generate dot terms for source on the same image 108 if (SRCj->imageID != SRCi->imageID) { continue; } 109 120 110 // skip over disjoint source images, break after last possible overlap 121 if (SRC i->pixels->row0 + SRCi->pixels->numRows < SRCj->pixels->row0) break;122 if (SRC j->pixels->row0 + SRCj->pixels->numRows < SRCi->pixels->row0) continue;123 if (SRC i->pixels->col0 + SRCi->pixels->numCols < SRCj->pixels->col0) continue;124 if (SRC j->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)] 125 115 126 116 // 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); 128 118 psSparseMatrixElement (sparse, j, i, f); 129 119 } … … 133 123 psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "built matrix: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem); 134 124 135 // set the sky, sky_x, sky_y components of border matrix136 SetBorderMatrixElements (border, readout, fitSources, CONSTANT_PHOTOMETRIC_WEIGHTS, SKY_FIT_ORDER, markVal);137 138 125 psSparseConstraint constraint; 139 126 constraint.paramMin = 0.0; … … 142 129 143 130 // 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); 146 133 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 for152 // extended sources, the shape errors153 134 154 135 // adjust I0 for fitSources and subtract … … 164 145 model->params->data.F32[PM_PAR_I0] = norm->data.F32[i]; 165 146 model->dparams->data.F32[PM_PAR_I0] = errors->data.F32[i]; 166 // XXX is the value of 'errors' modified by the sky fit?167 147 168 148 // subtract object 169 149 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 170 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;171 150 } 172 151 psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "sub models: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem); 173 152 174 153 // measure chisq for each source 175 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++) { 176 156 pmSource *source = fitSources->data[i]; 177 157 if (source->mode & PM_SOURCE_MODE_NONLINEAR_FIT) continue; 178 158 pmModel *model = pmSourceGetModel (NULL, source); 179 pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal );159 pmSourceChisq (model, source->pixels, source->maskObj, source->variance, maskVal, COVAR_FACTOR); 180 160 } 181 161 psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "get chisqs: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem); … … 186 166 psFree (norm); 187 167 psFree (errors); 188 psFree (border);189 168 190 169 psLogMsg ("psphot.ensemble", PS_LOG_INFO, "measure ensemble of PSFs: %f sec\n", psTimerMark ("psphot.linear")); 191 192 psphotVisualShowResidualImage (readout);193 psphotVisualShowFlags (sources);194 170 195 171 return true; 196 172 } 197 173 198 // Calculate the weight terms for the sky fit component of the matrix. This function operates 199 // on the pixels which correspond to all of the sources of interest. These elements fill in 200 // the border matrix components in the sparse matrix equation. 201 static bool SetBorderMatrixElements (psSparseBorder *border, pmReadout *readout, psArray *sources, bool constant_weights, psImageMaskType markVal) { 174 // sort by X (ascending) 175 int pmPhotObjSortByX (const void **a, const void **b) 176 { 177 pmPhotObj *objA = *(pmPhotObj **)a; 178 pmPhotObj *objB = *(pmPhotObj **)b; 202 179 203 // generate the image-wide weight terms 204 // turn on MARK for all image pixels 205 psRegion fullArray = psRegionSet (0, 0, 0, 0); 206 fullArray = psRegionForImage (readout->mask, fullArray); 207 psImageMaskRegion (readout->mask, fullArray, "OR", markVal); 180 psF32 fA = objA->x; 181 psF32 fB = objB->x; 208 182 209 // turn off MARK for all object pixels 210 for (int i = 0; i < sources->n; i++) { 211 pmSource *source = sources->data[i]; 212 pmModel *model = pmSourceGetModel (NULL, source); 213 if (model == NULL) continue; 214 float x = model->params->data.F32[PM_PAR_XPOS]; 215 float y = model->params->data.F32[PM_PAR_YPOS]; 216 psImageMaskCircle (source->maskView, x, y, model->radiusFit, "AND", PS_NOT_IMAGE_MASK(markVal)); 217 } 218 219 // accumulate the image statistics from the masked regions 220 psF32 **image = readout->image->data.F32; 221 psF32 **variance = readout->variance->data.F32; 222 psImageMaskType **mask = readout->mask->data.PS_TYPE_IMAGE_MASK_DATA; 223 224 double w, x, y, x2, xy, y2, xc, yc, wt, f, fo, fx, fy; 225 w = x = y = x2 = xy = y2 = fo = fx = fy = 0; 226 227 int col0 = readout->image->col0; 228 int row0 = readout->image->row0; 229 230 for (int j = 0; j < readout->image->numRows; j++) { 231 for (int i = 0; i < readout->image->numCols; i++) { 232 if (mask[j][i]) continue; 233 if (constant_weights) { 234 wt = 1.0; 235 } else { 236 wt = variance[j][i]; 237 } 238 f = image[j][i]; 239 w += 1/wt; 240 fo += f/wt; 241 } 242 } 243 244 // turn off MARK for all image pixels 245 psImageMaskRegion (readout->mask, fullArray, "AND", PS_NOT_IMAGE_MASK(markVal)); 246 247 // set the Border T elements 248 psSparseBorderElementG (border, 0, fo); 249 psSparseBorderElementT (border, 0, 0, w); 250 251 return true; 183 psF32 diff = fA - fB; 184 if (diff > FLT_EPSILON) return (+1); 185 if (diff < FLT_EPSILON) return (-1); 186 return (0); 252 187 } -
branches/simtest_nebulous_branches/psphot/src/psphotGuessModels.c
r24876 r27840 3 3 // XXX : the threading here is not great. this may be due to blocks between elements, but 4 4 // 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 6 6 // 2) loop over the sources once and associate them with their cell 7 7 // 3) define the threaded function to work with sources for a given cell 8 8 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 10 bool 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) 33 bool psphotGuessModelsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index) { 11 34 12 35 bool status; 13 36 14 37 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?"); 15 59 16 60 // select the appropriate recipe information … … 21 65 int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads 22 66 if (!status) { 23 nThreads = 0;67 nThreads = 0; 24 68 } 25 69 … … 36 80 37 81 // setup the PSF fit radius details 38 psphotInitRadiusPSF (recipe, psf->type);82 psphotInitRadiusPSF (recipe, readout->analysis, psf->type); 39 83 40 84 // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts) … … 46 90 for (int i = 0; i < cellGroups->n; i++) { 47 91 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 job53 psThreadJob *job = psThreadJobAlloc ("PSPHOT_GUESS_MODEL");54 psArrayAdd(job->args, 1, readout);55 psArrayAdd(job->args, 1, cells->data[j]); // sources56 psArrayAdd(job->args, 1, psf);57 58 // XXX change these to use abstract mask type info59 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 results71 // wait here for the threaded jobs to finish72 // 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 here79 psThreadJob *job = NULL;80 while ((job = psThreadJobGetDone()) != NULL) {81 // we have no returned data from this operation82 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 } 87 131 } 88 132 … … 90 134 int nMiss = 0; 91 135 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 ++; 97 141 } 98 142 psAssert (nMiss == 0, "failed to attempt to build models for %d objects\n", nMiss); … … 110 154 psArray *sources = job->args->data[1]; 111 155 pmPSF *psf = job->args->data[2]; 112 156 113 157 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3],PS_TYPE_IMAGE_MASK_DATA); 114 158 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA); … … 117 161 118 162 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 that122 // 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 the136 // peak and the position from the moments. Use the peak position if (a) there are no137 // moments and (b) the sources is not saturated138 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 moments142 useMoments = (useMoments && source->moments->nPixels); // can't if the moments were not measured143 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 model175 // this function affects the mask pixels176 psphotCheckRadiusPSF (readout, source, modelPSF, markVal);177 178 // set the source PSF model179 source->modelPSF = modelPSF;180 source->modelPSF->residuals = psf->residuals;181 182 pmSourceCacheModel (source, maskVal); // ALLOC x14 (!) 183 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 (!) 184 228 } 185 229 -
branches/simtest_nebulous_branches/psphot/src/psphotImageLoop.c
r23957 r27840 67 67 68 68 // Update the header 69 { 70 pmHDU *hdu = pmHDUGetHighest(input->fpa, chip, cell); 71 if (hdu && hdu != lastHDU) { 72 psphotVersionHeaderFull(hdu->header); 73 lastHDU = hdu; 74 } 69 pmHDU *hdu = pmHDUGetHighest(input->fpa, chip, cell); 70 if (hdu && hdu != lastHDU) { 71 psphotVersionHeaderFull(hdu->header); 72 lastHDU = hdu; 75 73 } 76 74 77 psImageMaskType maskSat = pmConfigMaskGet("SAT", config); // Mask value for saturated pixels 78 if (!pmReadoutMaskNonfinite(readout, maskSat)) { 79 psError(psErrorCodeLast(), false, "Unable to mask non-finite pixels."); 80 psFree(view); 81 return false; 82 } 75 // if an external mask is supplied, ensure that NAN pixels are also masked 76 if (readout->mask) { 77 psImageMaskType maskSat = pmConfigMaskGet("SAT", config); // Mask value for saturated pixels 78 if (!pmReadoutMaskNonfinite(readout, maskSat)) { 79 psError(psErrorCodeLast(), false, "Unable to mask non-finite pixels."); 80 psFree(view); 81 return false; 82 } 83 } 83 84 84 85 // run the actual photometry analysis on this chip/cell/readout … … 90 91 } 91 92 92 status = true; 93 status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL"); 94 status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKMDL.STDEV"); 95 status &= pmFPAfileDropInternal (config->files, "PSPHOT.BACKGND"); 96 if (!status) { 97 psError(PSPHOT_ERR_PROG, false, "trouble dropping internal files"); 98 psFree (view); 99 return false; 100 } 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 } 101 103 } 102 103 104 // save output which is saved at the chip level 104 105 if (!pmFPAfileIOChecks (config, view, PM_FPA_AFTER)) ESCAPE ("failed output for Chip in psphot."); -
branches/simtest_nebulous_branches/psphot/src/psphotImageQuality.c
r23989 r27840 4 4 // XXX Lots of code duplication here 5 5 6 // for now, let's store the detections on the readout->analysis for each readout 7 bool 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 6 33 // 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)34 bool psphotImageQualityReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) 8 35 { 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 9 61 psVector *FWHM_MAJOR = psVectorAllocEmpty(100, PS_TYPE_F32); 10 62 psVector *FWHM_MINOR = psVectorAllocEmpty(100, PS_TYPE_F32); … … 81 133 82 134 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); 89 140 90 141 // XXX make this a recipe option … … 98 149 99 150 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); 104 153 105 154 if (!psVectorStats(stats, FWHM_MINOR, NULL, NULL, 0)) { … … 108 157 } 109 158 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); 114 161 115 162 if (!psVectorStats(stats, M2, NULL, NULL, 0)) { … … 119 166 float vM2 = stats->sampleMean; 120 167 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); 129 172 130 173 if (!psVectorStats(stats, M2c, NULL, NULL, 0)) { … … 132 175 goto FAIL; 133 176 } 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); 142 181 143 182 if (!psVectorStats(stats, M2s, NULL, NULL, 0)) { … … 145 184 goto FAIL; 146 185 } 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); 155 190 156 191 if (!psVectorStats(stats, M3, NULL, NULL, 0)) { … … 160 195 float vM3 = stats->sampleMean; 161 196 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); 170 201 171 202 if (!psVectorStats(stats, M4, NULL, NULL, 0)) { … … 175 206 float vM4 = stats->sampleMean; 176 207 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); 185 212 186 213 #else … … 192 219 } 193 220 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); 198 223 199 224 if (!psVectorStats(stats, FWHM_MINOR, NULL, NULL, 0)) { … … 202 227 } 203 228 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); 208 231 209 232 if (!psVectorStats(stats, M2, NULL, NULL, 0)) { … … 213 236 float vM2 = stats->robustMedian; 214 237 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); 223 242 224 243 if (!psVectorStats(stats, M2c, NULL, NULL, 0)) { … … 226 245 goto FAIL; 227 246 } 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); 236 251 237 252 if (!psVectorStats(stats, M2s, NULL, NULL, 0)) { … … 239 254 goto FAIL; 240 255 } 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); 249 260 250 261 if (!psVectorStats(stats, M3, NULL, NULL, 0)) { … … 254 265 float vM3 = stats->robustMedian; 255 266 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); 264 271 265 272 if (!psVectorStats(stats, M4, NULL, NULL, 0)) { … … 269 276 float vM4 = stats->robustMedian; 270 277 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); 279 282 #endif 280 283 281 psLogMsg ("psphot", PS_LOG_INFO, "Image Quality Stats from %ld psf stars : FWHM (major, minor) : %f, %f\n",284 psLogMsg ("psphot", PS_LOG_INFO, "Image Quality Stats from %ld psf stars : FWHM (major, minor) [pixels]: %f, %f\n", 282 285 M2->n, fwhm_major, fwhm_minor); 283 286 284 psLogMsg ("psphot", PS_LOG_INFO, "M_2 : %f +/- %f, M_3 : %f +/- %f, M_4 : %f +/- %f \n",287 psLogMsg ("psphot", PS_LOG_INFO, "M_2 : %f +/- %f, M_3 : %f +/- %f, M_4 : %f +/- %f [pixels^n]\n", 285 288 vM2, dM2, vM3, dM3, vM4, dM4); 286 289 -
branches/simtest_nebulous_branches/psphot/src/psphotKernelFromPSF.c
r17396 r27840 4 4 5 5 assert (source); 6 assert (source->psf Flux); // XXX build if needed?6 assert (source->psfImage); // XXX build if needed? 7 7 8 int x0 = source->peak->xf - source->psf Flux->col0;9 int y0 = source->peak->yf - source->psf Flux->row0;8 int x0 = source->peak->xf - source->psfImage->col0; 9 int y0 = source->peak->yf - source->psfImage->row0; 10 10 11 11 // need to decide on the size: dynamically? statically? … … 17 17 // if the realized PSF for this object does not cover the full kernel, give up for now 18 18 if (x0 + psf->xMin < 0) goto escape; 19 if (x0 + psf->xMax >= source->psf Flux->numCols) goto escape;19 if (x0 + psf->xMax >= source->psfImage->numCols) goto escape; 20 20 if (y0 + psf->yMin < 0) goto escape; 21 if (y0 + psf->yMax >= source->psf Flux->numRows) goto escape;21 if (y0 + psf->yMax >= source->psfImage->numRows) goto escape; 22 22 23 23 double sum = 0.0; 24 24 for (int j = psf->yMin; j <= psf->yMax; j++) { 25 25 for (int i = psf->xMin; i <= psf->xMax; i++) { 26 double value = source->psf Flux->data.F32[y0 + j][x0 + i];26 double value = source->psfImage->data.F32[y0 + j][x0 + i]; 27 27 psf->kernel[j][i] = value; 28 28 sum += value; -
branches/simtest_nebulous_branches/psphot/src/psphotLoadPSF.c
r18002 r27840 1 1 # include "psphotInternal.h" 2 2 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 3 12 // load an externally supplied psf model 4 pmPSF *psphotLoadPSF (pmConfig *config, const pmFPAview *view, psMetadata *recipe) { 13 bool 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 } 5 30 6 31 // find the currently selected chip 7 pmChip *chip = pmFPA fileThisChip (config->files, view, "PSPHOT.PSF.LOAD");8 if (!chip) return NULL;32 pmChip *chip = pmFPAviewThisChip (view, inFile->fpa); 33 if (!chip) return false; 9 34 10 35 // find the currently selected readout 11 pmReadout *readout = pmFPA fileThisReadout (config->files, view, "PSPHOT.PSF.LOAD");12 if (!readout) return NULL;36 pmReadout *readout = pmFPAviewThisReadout (view, outFile->fpa); 37 if (!readout) return false; 13 38 14 39 // 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"); 16 41 if (psf == NULL) { 17 42 psLogMsg ("psphot", 3, "no psf supplied for this chip"); 18 return NULL;43 return true; 19 44 } 20 45 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 } 22 49 23 50 psLogMsg ("psphot", 3, "using externally supplied PSF model for this readout"); 24 51 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; 28 59 } 60 61 bool 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/simtest_nebulous_branches/psphot/src/psphotMagnitudes.c
r23349 r27840 1 1 # include "psphotInternal.h" 2 2 3 bool psphotMagnitudes(pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources, pmPSF *psf) { 3 bool 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 46 bool psphotMagnitudesReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, pmReadout *readout, psArray *sources, pmPSF *psf) { 4 47 5 48 bool status = false; 6 49 int Nap = 0; 7 50 51 if (!sources->n) { 52 psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping source magnitudes"); 53 return true; 54 } 55 8 56 psTimerStart ("psphot.mags"); 9 10 // select the appropriate recipe information11 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);12 assert (recipe);13 57 14 58 // determine the number of allowed threads … … 41 85 } 42 86 43 bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH");87 bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH"); 44 88 bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP"); 89 bool DIFF_STATS = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP"); 45 90 46 91 pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_APCORR | PM_SOURCE_PHOT_WEIGHT; 47 92 if (!IGNORE_GROWTH) photMode |= PM_SOURCE_PHOT_GROWTH; 48 93 if (INTERPOLATE_AP) photMode |= PM_SOURCE_PHOT_INTERP; 94 if (DIFF_STATS) photMode |= PM_SOURCE_PHOT_DIFFSTATS; 49 95 50 96 // choose Cx, Cy (see psphotThreadTools.c for overview of the concepts) … … 71 117 PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32); 72 118 PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK); 119 PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK); 73 120 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for nAp 74 121 … … 102 149 fprintf (stderr, "error with job\n"); 103 150 } else { 104 psScalar *scalar = job->args->data[ 7];151 psScalar *scalar = job->args->data[8]; 105 152 Nap += scalar->data.S32; 106 153 } … … 127 174 pmSourcePhotometryMode photMode = PS_SCALAR_VALUE(job->args->data[5],S32); 128 175 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[6],PS_TYPE_IMAGE_MASK_DATA); 176 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[7],PS_TYPE_IMAGE_MASK_DATA); 129 177 130 178 for (int i = 0; i < sources->n; i++) { 131 179 pmSource *source = (pmSource *) sources->data[i]; 132 status = pmSourceMagnitudes (source, psf, photMode, maskVal); 180 181 // replace object in image 182 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 183 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 184 } 185 186 // clear the mask bit and set the circular mask pixels 187 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 188 psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal); 189 190 status = pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal 133 191 if (status && isfinite(source->apMag)) Nap ++; 192 193 // clear the mask bit 194 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 195 196 // re-subtract the object, leave local sky 197 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 134 198 135 199 if (backModel) { … … 155 219 156 220 // change the value of a scalar on the array (wrap this and put it in psArray.h) 157 psScalar *scalar = job->args->data[ 7];221 psScalar *scalar = job->args->data[8]; 158 222 scalar->data.S32 = Nap; 159 223 160 224 return true; 161 225 } 162 163 # if (0)164 bool psphotMagnitudes_Unthreaded (int *nap, psArray *sources, pmPSF *psf, psImageBinning *binning, pmReadout *backModel, pmReadout *backStdev, pmSourcePhotometryMode photMode, psImageMaskType maskVal) {165 166 bool status;167 int Nap = 0;168 169 for (int i = 0; i < sources->n; i++) {170 pmSource *source = (pmSource *) sources->data[i];171 status = pmSourceMagnitudes (source, psf, photMode, maskVal);172 if (status && isfinite(source->apMag)) Nap ++;173 174 if (backModel) {175 psAssert (binning, "if backModel is defined, so should binning be");176 source->sky = psImageUnbinPixel(source->peak->x, source->peak->y, backModel->image, binning);177 if (isnan(source->sky) && false) {178 psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "error setting pmSource.sky");179 }180 } else {181 source->sky = NAN;182 }183 184 if (backStdev) {185 psAssert (binning, "if backStdev is defined, so should binning be");186 source->skyErr = psImageUnbinPixel(source->peak->x, source->peak->y, backStdev->image, binning);187 if (isnan(source->skyErr) && false) {188 psLogMsg ("psphot.magnitudes", PS_LOG_DETAIL, "error setting pmSource.skyErr");189 }190 } else {191 source->skyErr = NAN;192 }193 }194 195 // change the value of a scalar on the array (wrap this and put it in psArray.h)196 *nap = Nap;197 198 return true;199 }200 # endif201 226 202 227 bool psphotPSFWeights(pmConfig *config, pmReadout *readout, const pmFPAview *view, psArray *sources) { -
branches/simtest_nebulous_branches/psphot/src/psphotMakeFluxScale.c
r20453 r27840 60 60 goto DONE; 61 61 } 62 if (trend->mode == PM_TREND_MAP) { 63 // p_psImagePrint (2, trend->map->map, "FluxScale Before"); // XXX TEST: 64 psImageMapRepair (trend->map->map); 65 // p_psImagePrint (2, trend->map->map, "FluxScale After"); // XXX TEST: 66 } 62 67 63 68 // XXX do something useful to measure residual statistics -
branches/simtest_nebulous_branches/psphot/src/psphotMakeResiduals.c
r23989 r27840 1 1 # include "psphotInternal.h" 2 3 # define RESIDUAL_SOFTENING 0.005 2 4 3 5 bool psphotMakeResiduals (psArray *sources, psMetadata *recipe, pmPSF *psf, psImageMaskType maskVal) { … … 31 33 32 34 float pixelSN = psMetadataLookupF32(&status, recipe, "PSF.RESIDUALS.PIX.SN"); 35 PS_ASSERT (status, false); 36 37 float radiusMax = psMetadataLookupF32(&status, recipe, "PSF.RESIDUALS.RADIUS"); 33 38 PS_ASSERT (status, false); 34 39 … … 171 176 bool offImage = false; 172 177 if (psImageInterpolate (&flux, &dflux, &mflux, ix, iy, interp) == PS_INTERPOLATE_STATUS_OFF) { 173 // fprintf (stderr, "off image: %f %f : %f %f\n", ix, iy, flux, dflux);174 178 // This pixel is off the image 175 179 offImage = true; … … 179 183 } 180 184 fluxes->data.F32[i] = flux; 181 dfluxes->data.F32[i] = dflux;185 dfluxes->data.F32[i] = hypot(dflux, RESIDUAL_SOFTENING); 182 186 if (isnan(flux)) { 187 fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i] = badMask; 188 } 189 if (isnan(dflux)) { 183 190 fmasks->data.PS_TYPE_VECTOR_MASK_DATA[i] = badMask; 184 191 } … … 234 241 } 235 242 243 float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows)); 244 if (radius > radiusMax) { 245 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 246 continue; 247 } 248 236 249 resid->Ro->data.F32[oy][ox] = psStatsGetValue(fluxStats, statOption); 237 250 resid->Rx->data.F32[oy][ox] = resid->Ry->data.F32[oy][ox] = 0.0; … … 248 261 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 249 262 } 250 251 // fprintf (stderr, "res: %2d %2d : %6.4f %6.4f %6.4f %3d %1d\n", ox, oy, resid->Ro->data.F32[oy][ox], fluxStats->sampleStdev, fluxStats->sampleStdev/sqrt(nKeep), nKeep, resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox]);252 253 263 } else { 254 264 assert (SPATIAL_ORDER == 1); 265 266 float radius = hypot((ox - 0.5*resid->Ro->numCols), (oy - 0.5*resid->Ro->numRows)); 267 if (radius > radiusMax) { 268 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 269 continue; 270 } 271 255 272 psImageInit(A, 0.0); 256 273 psVectorInit(B, 0.0); … … 275 292 276 293 if (!psMatrixGJSolve(A, B)) { 277 psError(PSPHOT_ERR_PSF, false, "Singular matrix solving for (y,x) = (%d,%d)'s residuals", 278 oy, ox); 279 psFree(resid); resid = NULL; 280 break; 294 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 295 psWarning("Singular matrix solving for (y,x) = (%d,%d)'s residuals, masking", oy, ox); 296 continue; 281 297 } 282 298 … … 286 302 287 303 float dRo = sqrt(A->data.F32[0][0]); 288 // fprintf (stderr, "res: %2d %2d : %6.4f %6.4f %6.4f %3d %1d\n",289 // ox, oy, resid->Ro->data.F32[oy][ox], dRo, dRo/sqrt(nKeep), nKeep, resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox]);290 304 291 305 if (fabs(resid->Ro->data.F32[oy][ox]) < pixelSN*dRo/sqrt(nKeep)) { 292 306 resid->mask->data.PM_TYPE_RESID_MASK_DATA[oy][ox] = 1; 293 } 294 //resid->variance->data.F32[oy][ox] = XXX; 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; 310 } 295 311 } 296 312 } -
branches/simtest_nebulous_branches/psphot/src/psphotMaskReadout.c
r24484 r27840 1 1 # include "psphotInternal.h" 2 2 3 bool 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 3 26 // generate mask and variance if not defined, additional mask for restricted subregion 4 bool psphotSetMaskAndVariance (pmConfig *config, pmReadout *readout, psMetadata *recipe) {27 bool psphotSetMaskAndVarianceReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) { 5 28 6 29 bool status; 7 30 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) 11 39 psImageMaskType maskSat = pmConfigMaskGet("SAT", config); // Mask value for saturated pixels 12 40 psMetadataAddImageMask (recipe, PS_LIST_TAIL, "MASK.SAT", PS_META_REPLACE, "user-defined mask", maskSat); … … 14 42 psImageMaskType maskBad = pmConfigMaskGet("LOW", config); // Mask value for low pixels 15 43 if (!maskBad) { 16 // XXX:for backward compatability look up old name44 // for backward compatability look up old name 17 45 maskBad = pmConfigMaskGet("BAD", config); 18 46 } … … 33 61 } 34 62 63 bool softenVariance = psMetadataLookupBool (&status, recipe, "SOFTEN.VARIANCE"); 64 float softenFraction = psMetadataLookupF32 (&status, recipe, "SOFTEN.VARIANCE.FRACTION"); 65 35 66 // make this an option via the recipe 36 if ( 0) {67 if (softenVariance) { 37 68 psImage *im = readout->image; 38 69 psImage *wt = readout->variance; 39 psImage *mk = readout->mask;40 70 for (int j = 0; j < im->numRows; j++) { 41 71 for (int i = 0; i < im->numCols; i++) { 42 if (isfinite(im->data.F32[j][i]) && isfinite(wt->data.F32[j][i])) continue; 43 mk->data.PS_TYPE_IMAGE_MASK_DATA[j][i] |= maskBad; 72 if (!isfinite(im->data.F32[j][i])) continue; 73 if (!isfinite(wt->data.F32[j][i])) continue; 74 float sysError = softenFraction * im->data.F32[j][i]; 75 wt->data.F32[j][i] += PS_SQR(sysError); 44 76 } 45 77 } … … 69 101 } 70 102 103 // display the image, weight, mask (ch 1,2,3) 104 psphotVisualShowImage (readout); 105 71 106 return true; 72 107 } -
branches/simtest_nebulous_branches/psphot/src/psphotMergeSources.c
r21519 r27840 5 5 PM_SOURCE_MODE_CR_LIMIT | PM_SOURCE_MODE_EXT_LIMIT) // Mask to apply for PSF sources 6 6 7 // for now, let's store the detections on the readout->analysis for each readout 8 bool 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 7 25 // add newly selected sources to the existing list of sources 8 bool psphotMergeSources (psArray *oldSources, psArray *newSources) { 26 bool 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; 9 55 10 56 for (int i = 0; i < newSources->n; i++) { 11 57 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 73 bool 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 128 loadTXT: 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 151 finish: 152 153 psFree (detections); 154 155 if (!extCMF && !extSourcesTXT) { 30 156 psLogMsg ("psphot", 3, "no external sources for this readout"); 31 157 return true; 32 158 } 33 159 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); 55 165 return true; 56 166 } 57 167 58 168 // 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 59 170 psArray *psphotLoadPSFSources (pmConfig *config, const pmFPAview *view) { 171 172 bool status; 60 173 61 174 // find the currently selected readout … … 66 179 } 67 180 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; 69 188 if (!sources) { 70 189 psLogMsg ("psphot", 3, "no psf sources for this readout"); 190 return NULL; 71 191 } 72 192 … … 74 194 } 75 195 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. 199 bool 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 76 227 // 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 229 bool 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?"); 78 237 79 238 pmDetections *detections = pmDetectionsAlloc(); … … 88 247 float snMin = psMetadataLookupF32(NULL, recipe, "MOMENTS_SN_MIN"); 89 248 if (!isfinite(snMin)) { 90 return NULL;249 return false; 91 250 } 92 251 … … 96 255 97 256 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); 98 264 continue; 99 265 } … … 108 274 peak->flux = flux; // this are being set wrong, but does it matter? 109 275 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 } 115 281 116 282 psArrayAdd (detections->peaks, 100, peak); … … 120 286 psLogMsg ("psphot", 3, "%ld PSF sources loaded", detections->peaks->n); 121 287 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; 123 295 } 124 296 … … 149 321 peak->flux = flux; // this are being set wrong, but does it matter? 150 322 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 } 156 328 157 329 source->peak = peak; … … 162 334 return true; 163 335 } 336 337 bool 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/simtest_nebulous_branches/psphot/src/psphotModelBackground.c
r24188 r27840 5 5 // Determine the binning characteristics for the background model 6 6 // 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 model7 psImageBinning *psphotBackgroundBinning(const psImage *image, // Image for which to generate a bg model 8 8 const pmConfig *config // Configuration 9 9 ) … … 28 28 } 29 29 30 30 31 // 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 39 static 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 ) 38 46 { 39 47 psTimerStart ("psphot.background"); … … 137 145 138 146 // 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); 141 148 142 149 psF32 **modelData = model->data.F32; … … 144 151 145 152 // XXXX we can thread this here by running blocks in parallel 153 154 int nFailures = 0; 155 psImageBackgroundInit(); 146 156 147 157 // measure clipped median for subimages … … 211 221 stats->options = PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV; 212 222 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 ++; 216 229 modelData[iy][ix] = modelStdevData[iy][ix] = NAN; 217 230 } else { … … 232 245 psFree (submask); 233 246 } 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)); 234 251 } 235 252 … … 293 310 psLogMsg ("psphot", PS_LOG_INFO, "built background image: %f sec\n", psTimerMark ("psphot.background")); 294 311 295 psMetadataAddF32(re cipe, PS_LIST_TAIL, "SKY_MEAN", PS_META_REPLACE, "sky mean", Value);296 psMetadataAddF32(re cipe, 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); 297 314 psLogMsg ("psphot", PS_LOG_INFO, "image sky : mean %f stdev %f", Value, ValueStdev); 298 315 … … 303 320 PS_STAT_MAX); 304 321 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); 317 328 psLogMsg ("psphot", PS_LOG_INFO, "background sky : min %f mean %f max %f stdev %f", 318 329 statsBck->min, statsBck->sampleMean, statsBck->max, statsBck->sampleStdev); … … 327 338 } 328 339 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 341 psImage *psphotModelBackgroundReadoutNoFile(pmReadout *readout, const pmConfig *config) 332 342 { 333 PM_ASSERT_READOUT_NON_NULL(r o, NULL);334 PM_ASSERT_READOUT_IMAGE(r o, NULL);343 PM_ASSERT_READOUT_NON_NULL(readout, NULL); 344 PM_ASSERT_READOUT_IMAGE(readout, NULL); 335 345 PS_ASSERT_PTR_NON_NULL(config, NULL); 336 346 337 psImageBinning *binning = backgroundBinning(ro->image, config); // Image binning parameters347 psImageBinning *binning = psphotBackgroundBinning(readout->image, config); // Image binning parameters 338 348 psImage *model = psImageAlloc(binning->nXruff, binning->nYruff, PS_TYPE_F32); // Background model 339 349 psImage *modelStdev = psImageAlloc(binning->nXruff, binning->nYruff, PS_TYPE_F32); // Standard deviation 340 350 341 if (! backgroundModel(model, modelStdev, ro->analysis, ro, binning, config)) {351 if (!psphotModelBackgroundReadout(model, modelStdev, readout->analysis, readout, binning, config)) { 342 352 psFree(model); 343 353 psFree(modelStdev); … … 345 355 return NULL; 346 356 } 347 348 357 psFree(modelStdev); 349 350 358 return model; 351 359 } 352 360 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 362 bool psphotModelBackgroundReadoutFileIndex (pmConfig *config, const pmFPAview *view, const char *filename, int index) 357 363 { 358 bool status = true;359 360 364 // 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 362 368 pmFPA *inFPA = file->fpa; 363 369 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)) { 370 377 psError(PS_ERR_UNKNOWN, false, "Unable to generate background model"); 371 378 return false; … … 375 382 return true; 376 383 } 384 385 // XXX supply filename or keep PSPHOT.INPUT fixed? 386 bool 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/simtest_nebulous_branches/psphot/src/psphotModelGroupInit.c
r14655 r27840 1 1 # include "psphotInternal.h" 2 2 3 // Add locally-defined models here. As these mature, they can be moved to 3 // Add locally-defined models here. As these mature, they can be moved to 4 4 // psModule/src/objects/models 5 5 … … 8 8 9 9 static pmModelClass userModels[] = { 10 {"PS_MODEL_TEST1", 7, pmModelFunc_TEST1, pmModelFlux_TEST1, pmModelRadius_TEST1, pmModelLimits_TEST1, pmModelGuess_TEST1, pmModelFromPSF_TEST1, pmModelParamsFromPSF_TEST1, pmModelFitStatus_TEST1 },11 {"PS_MODEL_STRAIL", 9, pmModelFunc_STRAIL, pmModelFlux_STRAIL, pmModelRadius_STRAIL, pmModelLimits_STRAIL, pmModelGuess_STRAIL, pmModelFromPSF_STRAIL, pmModelParamsFromPSF_STRAIL, pmModelFitStatus_STRAIL },10 {"PS_MODEL_TEST1", 7, pmModelFunc_TEST1, pmModelFlux_TEST1, pmModelRadius_TEST1, pmModelLimits_TEST1, pmModelGuess_TEST1, pmModelFromPSF_TEST1, pmModelParamsFromPSF_TEST1, pmModelFitStatus_TEST1, NULL}, 11 {"PS_MODEL_STRAIL", 9, pmModelFunc_STRAIL, pmModelFlux_STRAIL, pmModelRadius_STRAIL, pmModelLimits_STRAIL, pmModelGuess_STRAIL, pmModelFromPSF_STRAIL, pmModelParamsFromPSF_STRAIL, pmModelFitStatus_STRAIL, NULL}, 12 12 }; 13 13 14 void psphotModelClassInit (void) 15 { 14 void psphotModelClassInit (void) 15 { 16 16 17 17 // if pmModelClassInit returns false, we have already init'ed … … 20 20 int Nmodels = sizeof (userModels) / sizeof (pmModelClass); 21 21 for (int i = 0; i < Nmodels; i++) { 22 pmModelClassAdd (&userModels[i]);22 pmModelClassAdd (&userModels[i]); 23 23 } 24 24 return; -
branches/simtest_nebulous_branches/psphot/src/psphotModelTest.c
r24588 r27840 139 139 140 140 // get the source moments 141 status = pmSourceMoments (source, mRADIUS, 0.0, 1.0 );141 status = pmSourceMoments (source, mRADIUS, 0.0, 1.0, maskVal); 142 142 if (!status) psAbort("psSourceMoments error"); 143 143 source->peak->value = source->moments->Peak; -
branches/simtest_nebulous_branches/psphot/src/psphotMomentsStudy.c
r24585 r27840 148 148 pmSourceAdd(source, PM_MODEL_OP_FUNC, 0); 149 149 150 pmSourceMoments (source, 32.0, sigWindow, 0.0 );150 pmSourceMoments (source, 32.0, sigWindow, 0.0, 0xffff); 151 151 // fprintf (stderr, "sigOut : %f\n", sqrt(source->moments->Mxx)); 152 152 -
branches/simtest_nebulous_branches/psphot/src/psphotOutput.c
r21366 r27840 31 31 } 32 32 return background; 33 } 34 35 // dump source stats for psf stars 36 bool psphotDumpStats (psArray *sources, char *stage) { 37 38 char filename[64]; 39 snprintf (filename, 64, "psf.%s.dat", stage); 40 FILE *f = fopen (filename, "w"); 41 for (int i = 0; i < sources->n; i++) { 42 pmSource *source = sources->data[i]; 43 if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue; 44 45 pmModel *model = source->modelPSF; 46 if (!model) continue; 47 48 // int xc = source->peak->x - source->pixels->col0; 49 // int yc = source->peak->y - source->pixels->row0; 50 // float mcore = source->modelFlux ? source->modelFlux->data.F32[yc][xc] : NAN; 51 // float mpeak = model ? model->params->data.F32[PM_PAR_I0] : NAN; 52 // bool subtracted = source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED; 53 // fprintf (stderr, "%d %d : %d : %f %f : %f %f\n", source->peak->x, source->peak->y, subtracted, source->peak->flux, source->pixels->data.F32[yc][xc], mcore, mpeak); 54 55 fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f\n", 56 source->peak->xf, source->peak->yf, 57 model->params->data.F32[PM_PAR_XPOS], model->params->data.F32[PM_PAR_YPOS], 58 source->psfMag, source->apMag, source->errMag, 59 model->params->data.F32[PM_PAR_I0], 60 model->params->data.F32[PM_PAR_SXX], model->params->data.F32[PM_PAR_SXY], model->params->data.F32[PM_PAR_SYY], 61 model->params->data.F32[PM_PAR_7]); 62 } 63 fclose (f); 64 return true; 33 65 } 34 66 … … 94 126 } 95 127 96 bool psphotAddPhotcode (psMetadata *recipe, pmConfig *config, const pmFPAview *view, const char *filerule) { 97 98 bool status; 99 100 pmFPAfile *input = psMetadataLookupPtr (&status, config->files, filerule); 101 PS_ASSERT (status, false); 102 103 // determine PHOTCODE from fpa & view, overwrite in recipe 104 char *photcode = pmConceptsPhotcodeForView (input, view); 128 bool 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 145 bool 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); 105 154 PS_ASSERT (photcode, false); 106 155 107 psMetadataAddStr (re cipe, 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); 108 157 psLogMsg ("psphot", 3, "PHOTCODE is %s", photcode); 109 158 … … 112 161 } 113 162 114 bool psphotSetHeaderNstars (psMetadata * recipe, psArray *sources) {163 bool psphotSetHeaderNstars (psMetadata *header, psArray *sources) { 115 164 116 165 int nSrc = 0; … … 141 190 } 142 191 143 psMetadataAddS32 (recipe, PS_LIST_TAIL, "NSTARS", PS_META_REPLACE, "Number of sources", nSrc); 144 psMetadataAddS32 (recipe, PS_LIST_TAIL, "NDET_EXT", PS_META_REPLACE, "Number of extended sources", nEXT); 145 psMetadataAddS32 (recipe, PS_LIST_TAIL, "NDET_CR", PS_META_REPLACE, "Number of cosmic rays", nCR); 146 return true; 147 } 148 149 // these values are saved in an output header stub - they are added to either the 150 // PHU header (CMP) or the MEF table header (CMF) 151 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 201 psMetadata *psphotDefineHeader (psMetadata *analysis) { 202 203 bool status = true; 152 204 153 205 psMetadata *header = psMetadataAlloc (); 154 206 155 207 // write necessary information to output header 156 psMetadataItemSupplement (header, recipe, "ZERO_PT"); 157 psMetadataItemSupplement (header, recipe, "PHOTCODE"); 158 159 psMetadataItemSupplement (header, recipe, "APMIFIT"); 160 psMetadataItemSupplement (header, recipe, "DAPMIFIT"); 161 psMetadataItemSupplement (header, recipe, "NAPMIFIT"); 162 psMetadataItemSupplement (header, recipe, "SKYBIAS"); 163 psMetadataItemSupplement (header, recipe, "SKYSAT"); 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"); 164 214 165 215 // PSF model parameters (shape values for image center) 166 psMetadataItemSupplement ( header, recipe, "NPSFSTAR");167 psMetadataItemSupplement ( header, recipe, "APLOSS");168 169 psMetadataItemSupplement ( header, recipe, "FWHM_MAJ");170 psMetadataItemSupplement ( header, recipe, "FW_MJ_SG");171 psMetadataItemSupplement ( header, recipe, "FW_MJ_LQ");172 psMetadataItemSupplement ( header, recipe, "FW_MJ_UQ");173 174 psMetadataItemSupplement ( header, recipe, "FWHM_MIN");175 psMetadataItemSupplement ( header, recipe, "FW_MN_SG");176 psMetadataItemSupplement ( header, recipe, "FW_MN_LQ");177 psMetadataItemSupplement ( header, recipe, "FW_MN_UQ");178 179 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"); 180 230 181 231 // Image Quality measurements 182 psMetadataItemSupplement ( header, recipe, "IQ_NSTAR");183 184 psMetadataItemSupplement ( header, recipe, "IQ_FW1");185 psMetadataItemSupplement ( header, recipe, "IQ_FW1_E");186 psMetadataItemSupplement ( header, recipe, "IQ_FW2");187 psMetadataItemSupplement ( header, recipe, "IQ_FW2_E");188 189 psMetadataItemSupplement ( header, recipe, "IQ_M2");190 psMetadataItemSupplement ( header, recipe, "IQ_M2_ER");191 psMetadataItemSupplement ( header, recipe, "IQ_M2_LQ");192 psMetadataItemSupplement ( header, recipe, "IQ_M2_UQ");193 194 psMetadataItemSupplement ( header, recipe, "IQ_M2C");195 psMetadataItemSupplement ( header, recipe, "IQ_M2C_E");196 psMetadataItemSupplement ( header, recipe, "IQ_M2C_L");197 psMetadataItemSupplement ( header, recipe, "IQ_M2C_U");198 199 psMetadataItemSupplement ( header, recipe, "IQ_M2S");200 psMetadataItemSupplement ( header, recipe, "IQ_M2S_E");201 psMetadataItemSupplement ( header, recipe, "IQ_M2S_L");202 psMetadataItemSupplement ( header, recipe, "IQ_M2S_U");203 204 psMetadataItemSupplement ( header, recipe, "IQ_M3");205 psMetadataItemSupplement ( header, recipe, "IQ_M3_ER");206 psMetadataItemSupplement ( header, recipe, "IQ_M3_LQ");207 psMetadataItemSupplement ( header, recipe, "IQ_M3_UQ");208 209 psMetadataItemSupplement ( header, recipe, "IQ_M4");210 psMetadataItemSupplement ( header, recipe, "IQ_M4_ER");211 psMetadataItemSupplement ( header, recipe, "IQ_M4_LQ");212 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"); 213 263 214 264 // XXX these need to be defined from elsewhere 215 265 psMetadataAdd (header, PS_LIST_TAIL, "FSATUR", PS_DATA_F32 | PS_META_REPLACE, "SATURATION MAG", 0.0); 216 266 psMetadataAdd (header, PS_LIST_TAIL, "FLIMIT", PS_DATA_F32 | PS_META_REPLACE, "COMPLETENESS MAG", 0.0); 217 psMetadataItemSupplement ( header, recipe, "NSTARS");218 219 psMetadataItemSupplement ( header, recipe, "NDET_EXT");220 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"); 221 271 222 272 // sky background model statistics 223 psMetadataItemSupplement ( header, recipe, "MSKY_MN");224 psMetadataItemSupplement ( header, recipe, "MSKY_SIG");225 psMetadataItemSupplement ( header, recipe, "MSKY_MIN");226 psMetadataItemSupplement ( header, recipe, "MSKY_MAX");227 psMetadataItemSupplement ( header, recipe, "MSKY_NX");228 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"); 229 279 230 280 psMetadataAddF32 (header, PS_LIST_TAIL, "DT_PHOT", PS_META_REPLACE, "elapsed psphot time", psTimerMark ("psphotReadout")); 231 232 // XXX : don't require any of these about values to exist233 psErrorClear ();234 281 235 282 return header; … … 256 303 psImageKeepCircle (source->maskObj, x, y, radius, "OR", markVal); 257 304 pmModelSub (source->pixels, source->maskObj, source->modelPSF, PM_MODEL_OP_FULL, maskVal); 258 psImage KeepCircle (source->maskObj, x, y, radius, "AND", PS_NOT_IMAGE_MASK(markVal));305 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 259 306 } 260 307 -
branches/simtest_nebulous_branches/psphot/src/psphotPSFConvModel.c
r21183 r27840 37 37 } 38 38 39 // adjust the pixels based on the footprint 40 float radius = psphotSetRadiusEXT (readout, source, markVal); 41 if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) return false; 42 39 43 // XXX test : modify the Io, SXX, SYY terms based on the psf SXX, SYY terms: 40 44 psEllipseShape psfShape; … … 67 71 psVector *params = modelConv->params; 68 72 psVector *dparams = modelConv->dparams; 69 70 psphotCheckRadiusEXT (readout, source, modelConv, markVal);71 73 72 74 // create the minimization constraints -
branches/simtest_nebulous_branches/psphot/src/psphotParseCamera.c
r21458 r27840 39 39 return NULL; 40 40 } 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); 41 43 42 44 // define the additional input/output files associated with psphot -
branches/simtest_nebulous_branches/psphot/src/psphotPetrosian.c
r21183 r27840 1 1 # include "psphotInternal.h" 2 2 3 bool psphotPetrosian (pmSource *source, psMetadata *recipe, psImageMaskType maskVal) {3 bool psphotPetrosian (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal) { 4 4 5 bool status; 5 // XXX these need to go into recipe values 6 float Rmax = 200; 6 7 7 assert (source->extpars); 8 assert (source->extpars->profile); 9 assert (source->extpars->profile->radius); 10 assert (source->extpars->profile->flux); 8 psAssert (source->extpars, "need to run psphotRadialProfile first"); 9 psAssert (source->extpars->ellipticalFlux, "need to run psphotRadialProfile first"); 11 10 12 psVector *radius = source->extpars->profile->radius; 13 psVector *flux = source->extpars->profile->flux; 11 // integrate the radial profile for radial bins defined for the petrosian measurement: 12 // SB_i (r_i) where \alpha r_i < r < \beta r_i 13 if (!psphotPetrosianRadialBins (source, Rmax, skynoise)) { 14 psError (PS_ERR_UNKNOWN, false, "failed to generate elliptical profile"); 15 return false; 16 } 17 18 // use the SB_i from above to calculate the petrosian radius and the flux within that radius 19 if (!psphotPetrosianStats (source)) { 20 psError (PS_ERR_UNKNOWN, false, "failed to generate elliptical profile"); 21 return false; 22 } 23 24 psTrace ("psphot", 3, "source at %f,%f: petrosian radius: %f, flux: %f, axis ratio: %f, angle: %f", 25 source->peak->xf, source->peak->yf, 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); 14 30 15 // flux at which to measure isophotal parameters 16 float PETROSIAN_R0 = psMetadataLookupF32 (&status, recipe, "PETROSIAN_R0"); 17 float PETROSIAN_RF = psMetadataLookupF32 (&status, recipe, "PETROSIAN_FLUX_RATIO"); 18 assert (status); 19 20 // first find flux at R0 21 int firstAbove = -1; 22 int lastBelow = -1; 23 for (int i = 0; i < radius->n; i++) { 24 if (radius->data.F32[i] < PETROSIAN_R0) lastBelow = i; 25 if ((firstAbove < 0) && (radius->data.F32[i] > PETROSIAN_R0)) firstAbove = i; 26 } 27 // if we don't go out far enough, we have a problem... 28 if (lastBelow == radius->n - 1) { 29 psTrace ("psphot", 5, "did not go out far enough to reach petrosian reference radius..."); 30 // XXX skip object? raise a flag ? 31 return false; 32 } 33 if (firstAbove < 0) { 34 psTrace ("psphot", 5, "did not go out far enough to bound petrosian reference radius"); 35 // XXX raise a flag ? 36 return false; 37 } 38 39 // average flux in this range 40 float fluxR0 = 0.0; 41 int fluxRn = 0; 42 for (int i = PS_MIN(firstAbove, lastBelow); i <= PS_MAX(firstAbove, lastBelow); i++) { 43 fluxR0 += flux->data.F32[i]; 44 fluxRn ++; 45 } 46 fluxR0 /= (float)(fluxRn); 47 48 // target flux for petrosian radius 49 float fluxRP = fluxR0 * PETROSIAN_RF; 50 51 // find the first bin below the flux level and the last above the level 52 // XXX can this be done faster with bisection? 53 // XXX do I need to worry about crazy outliers? 54 // XXX should i be smoothing or fitting the curve? 55 int firstBelow = -1; 56 int lastAbove = -1; 57 for (int i = 0; i < flux->n; i++) { 58 if (flux->data.F32[i] > fluxRP) lastAbove = i; 59 if ((firstBelow < 0) && (flux->data.F32[i] < fluxRP)) firstBelow = i; 60 } 61 // if we don't go out far enough, we have a problem... 62 if (lastAbove == radius->n - 1) { 63 psTrace ("psphot", 5, "did not go out far enough to reach petrosian radius..."); 64 // XXX skip object? raise a flag ? 65 return false; 66 } 67 if (firstBelow < 0) { 68 psTrace ("psphot", 5, "did not go out far enough to bound petrosian radius"); 69 // XXX raise a flag ? 70 return false; 71 } 72 73 // need to examine pixels in this vicinity 74 float fluxFirst = 0; 75 float fluxLast = 0; 76 for (int i = 0; i <= PS_MAX(firstBelow, lastAbove); i++) { 77 if (i <= firstBelow) { 78 fluxFirst += flux->data.F32[i]; 79 } 80 if (i <= lastAbove) { 81 fluxLast += flux->data.F32[i]; 82 } 83 } 84 float fluxRPSum = 0.5*(fluxLast + fluxFirst); 85 float fluxRPSumErr = 0.5*fabs(fluxLast - fluxFirst); 86 // XXX need to use the weight appropriately here... 87 88 float rad = 0.5*(radius->data.F32[firstBelow] + radius->data.F32[lastAbove]); 89 float radErr = 0.5*fabs(radius->data.F32[firstBelow] - radius->data.F32[lastAbove]); 90 91 if (!source->extpars->petrosian) { 92 source->extpars->petrosian = pmSourcePetrosianValuesAlloc (); 93 } 94 95 // these are uncalibrated: instrumental mags and pixel units 96 source->extpars->petrosian->mag = -2.5*log10(fluxRPSum); 97 source->extpars->petrosian->magErr = fluxRPSumErr / fluxRPSum; 98 99 source->extpars->petrosian->rad = rad; 100 source->extpars->petrosian->radErr = radErr; 101 102 psTrace ("psphot", 5, "Petrosian flux:%f +/- %f @ %f +/- %f for %f, %f\n", 103 source->extpars->petrosian->mag, source->extpars->petrosian->magErr, 104 source->extpars->petrosian->rad, source->extpars->petrosian->radErr, 105 source->peak->xf, source->peak->yf); 106 107 return true; 108 31 return true; 109 32 } -
branches/simtest_nebulous_branches/psphot/src/psphotRadialProfile.c
r21366 r27840 1 1 # include "psphotInternal.h" 2 2 3 # define COMPARE_RADIUS(A,B) (radius->data.F32[A] < radius->data.F32[B]) 4 # define SWAP_RADIUS(TYPE,A,B) { \ 5 float tmp; \ 6 if (A != B) { \ 7 tmp = radius->data.F32[A]; \ 8 radius->data.F32[A] = radius->data.F32[B]; \ 9 radius->data.F32[B] = tmp; \ 10 tmp = flux->data.F32[A]; \ 11 flux->data.F32[A] = flux->data.F32[B]; \ 12 flux->data.F32[B] = tmp; \ 13 tmp = variance->data.F32[A]; \ 14 variance->data.F32[A] = variance->data.F32[B]; \ 15 variance->data.F32[B] = tmp; \ 16 } \ 17 } 3 bool psphotRadialProfile (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal) { 18 4 19 bool psphotRadialProfile (pmSource *source, psMetadata *recipe, psImageMaskType maskVal) { 5 bool status; 20 6 21 7 // allocate pmSourceExtendedParameters, if not already defined … … 24 10 } 25 11 26 if (!source->extpars->profile) { 27 source->extpars->profile = pmSourceRadialProfileAlloc (); 12 // XXX these need to go into recipe values 13 int Nsec = 24; 14 float Rmax = 200; 15 float fluxMin = 0.0; 16 float fluxMax = source->peak->flux; 17 18 bool RAW_RADIUS = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_RAW_RADIUS"); 19 20 // generate a series of radial profiles at Nsec evenly spaced angles. the profile flux 21 // is measured by interpolation for small radii; for large radii, the pixels in a box 22 // are averaged to increase the S/N 23 if (!psphotRadialProfilesByAngles (source, Nsec, Rmax)) { 24 psError (PS_ERR_UNKNOWN, false, "failed to measure radial profile for petrosian"); 25 return false; 28 26 } 29 27 30 int nPts = source->pixels->numRows * source->pixels->numCols; 31 source->extpars->profile->radius = psVectorAllocEmpty (nPts, PS_TYPE_F32); 32 source->extpars->profile->flux = psVectorAllocEmpty (nPts, PS_TYPE_F32); 33 source->extpars->profile->variance = psVectorAllocEmpty (nPts, PS_TYPE_F32); 28 // use the radial profiles to determine the radius of a given isophote. this isophote 29 // is used to determine the elliptical shape of the object, so it has a relatively high 30 // value (nominally 25% of the peak) 31 if (!psphotRadiiFromProfiles (source, fluxMin, fluxMax)) { 32 psError (PS_ERR_UNKNOWN, false, "failed to measure isophotal radii from profiles"); 33 return false; 34 } 34 35 35 psVector *radius = source->extpars->profile->radius; 36 psVector *flux = source->extpars->profile->flux; 37 psVector *variance = source->extpars->profile->variance; 38 39 // XXX use the extended source model here for Xo, Yo? 40 // XXX define a radius scaled to the elliptical contour? 41 42 int n = 0; 43 44 float Xo = 0.0; 45 float Yo = 0.0; 46 47 if (source->modelEXT) { 48 Xo = source->modelEXT->params->data.F32[PM_PAR_XPOS] - source->pixels->col0; 49 Yo = source->modelEXT->params->data.F32[PM_PAR_YPOS] - source->pixels->row0; 50 } else { 51 Xo = source->peak->xf - source->pixels->col0; 52 Yo = source->peak->yf - source->pixels->row0; 36 // convert the isophotal radius vs angle measurements to an elliptical contour 37 if (!psphotEllipticalContour (source)) { 38 psLogMsg ("psphot", 3, "failed to measure elliptical contour"); 39 return false; 53 40 } 54 for (int iy = 0; iy < source->pixels->numRows; iy++) { 55 for (int ix = 0; ix < source->pixels->numCols; ix++) { 56 if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) continue; 57 radius->data.F32[n] = hypot (ix - Xo, iy - Yo) ; 58 flux->data.F32[n] = source->pixels->data.F32[iy][ix]; 59 variance->data.F32[n] = source->variance->data.F32[iy][ix]; 60 n++; 61 } 41 42 // generate a single, normalized radial profile following the elliptical contours. 43 // the radius is normalized by the axis ratio so that on the major axis, 1 pixel = 1 pixel 44 if (!psphotEllipticalProfile (source, RAW_RADIUS)) { 45 psError (PS_ERR_UNKNOWN, false, "failed to generate elliptical profile"); 46 return false; 62 47 } 63 radius->n = n;64 variance->n = n;65 flux->n = n;66 67 // sort the vector set by the radius 68 PSSORT (radius->n, COMPARE_RADIUS, SWAP_RADIUS, NONE);69 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"); 52 return false; 53 } 54 70 55 return true; 71 56 } -
branches/simtest_nebulous_branches/psphot/src/psphotRadiusChecks.c
r21183 r27840 4 4 static float PSF_FIT_NSIGMA; 5 5 static float PSF_FIT_PADDING; 6 static float PSF_APERTURE = 0; // radius to use in PSF aperture mags 6 7 static float PSF_FIT_RADIUS = 0; // radius to use in fitting (ignored if <= 0, 7 8 // and a per-object radius is calculated) 8 9 9 bool psphotInitRadiusPSF(const psMetadata *recipe, const p mModelType type) {10 bool psphotInitRadiusPSF(const psMetadata *recipe, const psMetadata *analysis, const pmModelType type) { 10 11 11 12 bool status = true; 12 13 13 PSF_FIT_NSIGMA = psMetadataLookupF32(&status, recipe, "PSF_FIT_NSIGMA");14 PSF_FIT_NSIGMA = psMetadataLookupF32(&status, recipe, "PSF_FIT_NSIGMA"); 14 15 PSF_FIT_PADDING = psMetadataLookupF32(&status, recipe, "PSF_FIT_PADDING"); 15 PSF_FIT_RADIUS = psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS"); 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 } 16 26 17 27 return true; … … 34 44 radiusFit = model->modelRadius(model->params, 1.0); 35 45 } 46 model->fitRadius = (RADIUS_TYPE)(radiusFit + PSF_FIT_PADDING); 47 } else { 48 model->fitRadius = radiusFit; 36 49 } 37 model->radiusFit = (RADIUS_TYPE)(radiusFit + PSF_FIT_PADDING); 38 39 if (isnan(model->radiusFit)) psAbort("error in radius"); 50 if (isnan(model->fitRadius)) psAbort("error in radius"); 40 51 41 52 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 42 model-> radiusFit*= 2;53 model->fitRadius *= 2; 43 54 } 44 55 45 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit); 56 // radius used to measure aperture photometry 57 source->apRadius = PSF_APERTURE; 58 59 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius); 46 60 47 61 // set the mask to flag the excluded pixels 48 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model-> radiusFit, "OR", markVal);62 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius, "OR", markVal); 49 63 return status; 50 64 } … … 58 72 59 73 // set the fit radius based on the object flux limit and the model 60 model->radiusFit = (RADIUS_TYPE) (model->modelRadius (model->params, PSF_FIT_NSIGMA*moments->dSky) + dR + PSF_FIT_PADDING); 61 if (isnan(model->radiusFit)) psAbort("error in radius"); 62 74 float radiusFit = PSF_FIT_RADIUS; 75 if (radiusFit <= 0) { // use fixed radius 76 if (moments == NULL) { 77 radiusFit = model->modelRadius(model->params, PSF_FIT_NSIGMA*moments->dSky); 78 } else { 79 radiusFit = model->modelRadius(model->params, 1.0); 80 } 81 model->fitRadius = (RADIUS_TYPE)(radiusFit + PSF_FIT_PADDING); 82 } else { 83 model->fitRadius = radiusFit; 84 } 85 if (isnan(model->fitRadius)) psAbort("error in radius"); 86 87 // above sets a radius for a single star, bump by blend separation 88 model->fitRadius += dR; 89 63 90 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 64 model-> radiusFit*= 2;91 model->fitRadius *= 2; 65 92 } 66 93 67 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit); 94 // radius used to measure aperture photometry 95 source->apRadius = PSF_APERTURE; 96 97 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius); 68 98 69 99 // set the mask to flag the excluded pixels 70 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model-> radiusFit, "OR", markVal);100 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius, "OR", markVal); 71 101 return status; 72 102 } … … 74 104 static float EXT_FIT_NSIGMA; 75 105 static float EXT_FIT_PADDING; 106 static float EXT_FIT_MAX_RADIUS; 76 107 77 108 bool psphotInitRadiusEXT (psMetadata *recipe, pmModelType type) { … … 79 110 bool status; 80 111 81 EXT_FIT_NSIGMA = psMetadataLookupF32 (&status, recipe, "EXT_FIT_NSIGMA"); 82 EXT_FIT_PADDING = psMetadataLookupF32 (&status, recipe, "EXT_FIT_PADDING"); 112 EXT_FIT_NSIGMA = psMetadataLookupF32 (&status, recipe, "EXT_FIT_NSIGMA"); 113 EXT_FIT_PADDING = psMetadataLookupF32 (&status, recipe, "EXT_FIT_PADDING"); 114 EXT_FIT_MAX_RADIUS = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MAX_RADIUS"); 83 115 84 116 return true; … … 86 118 87 119 // call this function whenever you (re)-define the EXT model 120 float psphotSetRadiusEXT (pmReadout *readout, pmSource *source, psImageMaskType markVal) { 121 122 psAssert (source, "source not defined??"); 123 psAssert (source->peak, "peak not defined??"); 124 125 pmPeak *peak = source->peak; 126 127 // set the radius based on the footprint: 128 if (!peak->footprint) goto escape; 129 pmFootprint *footprint = peak->footprint; 130 if (!footprint->spans) goto escape; 131 if (footprint->spans->n < 1) goto escape; 132 133 // find the max radius 134 float radius = 0.0; 135 for (int j = 0; j < footprint->spans->n; j++) { 136 pmSpan *span = footprint->spans->data[j]; 137 138 float dY = span->y - peak->yf; 139 float dX0 = span->x0 - peak->xf; 140 float dX1 = span->x1 - peak->xf; 141 142 radius = PS_MAX (radius, hypot(dY, dX0)); 143 radius = PS_MAX (radius, hypot(dY, dX1)); 144 } 145 146 radius += EXT_FIT_PADDING; 147 if (isnan(radius)) psAbort("error in radius"); 148 149 radius = PS_MIN (radius, EXT_FIT_MAX_RADIUS); 150 151 // redefine the pixels if needed 152 pmSourceRedefinePixels (source, readout, peak->xf, peak->yf, radius); 153 154 // set the mask to flag the excluded pixels 155 psImageKeepCircle (source->maskObj, peak->xf, peak->yf, radius, "OR", markVal); 156 return radius; 157 158 escape: 159 return NAN; 160 // bool result = psphotCheckRadiusEXT (readout, source, model, markVal); 161 // return result; 162 } 163 164 // alternative EXT radius based on model guess (for use without footprints) 88 165 bool psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal) { 166 167 psAbort ("do not use this function"); 89 168 90 169 psF32 *PAR = model->params->data.F32; … … 96 175 float rawRadius = model->modelRadius (model->params, EXT_FIT_NSIGMA*moments->dSky); 97 176 98 model-> radiusFit= rawRadius + EXT_FIT_PADDING;99 if (isnan(model-> radiusFit)) psAbort("error in radius");177 model->fitRadius = rawRadius + EXT_FIT_PADDING; 178 if (isnan(model->fitRadius)) psAbort("error in radius"); 100 179 101 180 // redefine the pixels if needed 102 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model-> radiusFit);181 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius); 103 182 104 183 // set the mask to flag the excluded pixels 105 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model-> radiusFit, "OR", markVal);184 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius, "OR", markVal); 106 185 return status; 107 186 } -
branches/simtest_nebulous_branches/psphot/src/psphotReadout.c
r24890 r27840 3 3 // this should be called by every program that links against libpsphot 4 4 bool psphotInit (void) { 5 6 5 psphotErrorRegister(); // register our error codes/messages 7 6 psphotModelClassInit (); // load implementation-specific models … … 12 11 bool psphotReadout(pmConfig *config, const pmFPAview *view) { 13 12 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. 18 15 psTimerStart ("psphotReadout"); 16 17 pmModelClassSetLimits(PM_MODEL_LIMITS_LAX); 19 18 20 19 // select the current recipe … … 24 23 return false; 25 24 } 25 // optional break-point for processing 26 char *breakPt = psMetadataLookupStr (NULL, recipe, "BREAK_POINT"); 27 psAssert (breakPt, "configuration error: set BREAK_POINT"); 26 28 27 29 // set the photcode for this image 28 if (!psphotAddPhotcode ( recipe, config, view, "PSPHOT.INPUT")) {30 if (!psphotAddPhotcode (config, view)) { 29 31 psError (PSPHOT_ERR_CONFIG, false, "trouble defining the photcode"); 30 32 return false; 31 33 } 32 34 33 // find the currently selected readout34 pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");35 PS_ASSERT_PTR_NON_NULL (readout, false);36 37 // optional break-point for processing38 char *breakPt = psMetadataLookupStr (NULL, recipe, "BREAK_POINT");39 PS_ASSERT_PTR_NON_NULL (breakPt, false);40 41 35 // Generate the mask and weight images, including the user-defined analysis region of interest 42 psphotSetMaskAndVariance (config, readout, recipe); 36 if (!psphotSetMaskAndVariance (config, view)) { 37 return psphotReadoutCleanup(config, view); 38 } 43 39 if (!strcasecmp (breakPt, "NOTHING")) { 44 return psphotReadoutCleanup(config, readout, recipe, NULL, NULL, NULL); 45 } 46 47 // display the image, weight, mask (ch 1,2,3) 48 psphotVisualShowImage (readout); 40 return psphotReadoutCleanup(config, view); 41 } 49 42 50 43 // generate a background model (median, smoothed image) 51 if (!psphotModelBackground (config, view , "PSPHOT.INPUT")) {52 return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);53 } 54 if (!psphotSubtractBackground (config, view , "PSPHOT.INPUT")) {55 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); 56 49 } 57 50 if (!strcasecmp (breakPt, "BACKMDL")) { 58 return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL); 59 } 60 61 // display the backsub and backgnd images 62 psphotVisualShowBackground (config, view, readout); 63 64 // run a single-model test if desired (exits from here if test is run) 65 psphotModelTest (config, view, recipe); 66 67 // load the psf model, if suppled. FWHM_X,FWHM_Y,etc are saved in the recipe 68 pmPSF *psf = psphotLoadPSF (config, view, recipe); 69 70 // several functions below behave differently if we have a PSF model already 71 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 } 72 60 73 61 // find the detections (by peak and/or footprint) in the image. 74 pmDetections *detections = psphotFindDetections (NULL, readout, recipe); 75 if (!detections) { 76 psLogMsg ("psphot", 3, "unable to find detections in this image"); 77 return psphotReadoutCleanup (config, readout, recipe, detections, psf, NULL); 78 } 79 80 // construct sources and measure basic stats 81 psArray *sources = psphotSourceStats (config, readout, detections); 82 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 } 83 73 if (!strcasecmp (breakPt, "PEAKS")) { 84 return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources); 85 } 86 87 // find blended neighbors of very saturated stars 88 // XXX merge this with Basic Deblend? 89 psphotDeblendSatstars (readout, sources, recipe); 90 91 // mark blended peaks PS_SOURCE_BLEND 92 if (!psphotBasicDeblend (sources, recipe)) { 93 psLogMsg ("psphot", 3, "failed on deblend analysis"); 94 return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources); 95 } 96 97 // classify sources based on moments, brightness 98 if (!psphotRoughClass (readout, sources, recipe, havePSF)) { 99 psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image"); 100 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); 101 99 } 102 100 if (!strcasecmp (breakPt, "MOMENTS")) { 103 return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources); 104 } 105 106 if (!havePSF && !psphotImageQuality (recipe, sources)) { 107 psLogMsg("psphot", 3, "failed to measure image quality"); 108 return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources); 109 } 110 111 // if we were not supplied a PSF, choose one here 112 if (psf == NULL) { 113 // use bright stellar objects to measure PSF 114 // XXX if we do not have enough stars to generate the PSF, build one 115 // from the SEEING guess and model class 116 psf = psphotChoosePSF (readout, sources, recipe); 117 if (psf == NULL) { 118 psLogMsg ("psphot", 3, "failure to construct a psf model"); 119 return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources); 120 } 121 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); 122 109 } 123 110 if (!strcasecmp (breakPt, "PSFMODEL")) { 124 return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources); 125 } 126 127 psphotVisualShowPSFModel (readout, psf); 111 return psphotReadoutCleanup (config, view); 112 } 128 113 129 114 // include externally-supplied sources 130 psphotLoadExtSources (config, view, sources); 131 132 // construct an initial model for each object 133 psphotGuessModels (config, readout, sources, psf); 134 135 // XXX test output of models 136 // psphotTestSourceOutput (readout, sources, recipe, psf); 137 138 // linear PSF fit to source peaks 139 psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE); 140 141 // We have to place these visualizations here because the models are not realized until 142 // psphotGuessModels or fitted until psphotFitSourcesLinear. 143 psphotVisualShowPSFStars (recipe, psf, sources); 144 psphotVisualShowSatStars (recipe, psf, sources); 145 146 // identify CRs and extended sources 147 psphotSourceSize (config, readout, sources, recipe, 0); 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); 125 126 // linear PSF fit to source peaks, subtract the models from the image (in PSF mask) 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) 148 131 if (!strcasecmp (breakPt, "ENSEMBLE")) { 149 132 goto finish; … … 151 134 152 135 // non-linear PSF and EXT fit to brighter sources 153 psphotBlendFit (config, readout, sources, psf); 136 // replace model flux, adjust mask as needed, fit, subtract the models (full stamp) 137 psphotBlendFit (config, view); // pass 1 (detections->allSources) 154 138 155 139 // replace all sources 156 psphotReplaceAllSources (sources, recipe); 157 158 // linear fit to include all sources 159 psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE); 140 psphotReplaceAllSources (config, view); // pass 1 (detections->allSources) 141 142 // linear fit to include all sources (subtract again) 143 // NOTE : apply to ALL sources (extended + psf) 144 psphotFitSourcesLinear (config, view, true); // pass 2 (detections->allSources) 160 145 161 146 // if we only do one pass, skip to extended source analysis 162 if (!strcasecmp (breakPt, "PASS1")) { 163 goto pass1finish; 164 } 165 166 // XXX for the moment, drop the re-calc of the background (prove this works) 167 // replace background in residual image 168 // psphotSkyReplace (config, view); 169 // re-measure background model (median, smoothed image) 170 // psphotImageMedian (config, view); 147 if (!strcasecmp (breakPt, "PASS1")) goto pass1finish; 148 149 // NOTE: possibly re-measure background model here with objects subtracted / or masked 171 150 172 151 // add noise for subtracted objects 173 psphotAddNoise (readout, sources, recipe); 174 175 // find fainter sources (pass 2) 176 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) 177 157 178 158 // remove noise for subtracted objects (ie, return to normal noise level) 179 psphotSubNoise (readout, sources, recipe); 159 // NOTE: this needs to operate only on the OLD sources 160 psphotSubNoise (config, view); // pass 1 (detections->allSources) 180 161 181 162 // define new sources based on only the new peaks 182 psArray *newSources = psphotSourceStats (config, readout, detections); 163 // NOTE: new sources are saved on detections->newSources 164 psphotSourceStats (config, view, false); // pass 2 (detections->newSources) 183 165 184 166 // set source type 185 if (!psphotRoughClass (readout, newSources, recipe, havePSF)) { 167 // NOTE: apply only to detections->newSources 168 if (!psphotRoughClass (config, view)) { // pass 2 (detections->newSources) 186 169 psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image"); 187 return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources); 188 } 189 190 // create full input models 191 psphotGuessModels (config, readout, newSources, psf); 170 return psphotReadoutCleanup (config, view); 171 } 172 173 // create full input models, set the radius to fitRadius, set circular fit mask 174 // NOTE: apply only to detections->newSources 175 psphotGuessModels (config, view); // pass 2 (detections->newSources) 192 176 193 177 // replace all sources so fit below applies to all at once 194 psphotReplaceAllSources (sources, recipe); 178 // NOTE: apply only to OLD sources (which have been subtracted) 179 psphotReplaceAllSources (config, view); // pass 2 195 180 196 181 // merge the newly selected sources into the existing list 197 psphotMergeSources (sources, newSources); 198 psFree (newSources); 199 200 // linear fit to all sources 201 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) 202 188 203 189 pass1finish: 204 190 205 191 // measure source size for the remaining sources 206 psphotSourceSize (config, readout, sources, recipe, 0);207 208 psphotExtendedSourceAnalysis (readout, sources, recipe); 209 210 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) 211 197 212 198 finish: … … 216 202 217 203 // measure aperture photometry corrections 218 if (!psphotApResid (config, readout, sources, psf)) {204 if (!psphotApResid (config, view)) { // pass 1 (detections->allSources) 219 205 psLogMsg ("psphot", 3, "failed on psphotApResid"); 220 return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);206 return psphotReadoutCleanup (config, view); 221 207 } 222 208 223 209 // calculate source magnitudes 224 psphotMagnitudes(config, readout, view, sources, psf); 210 psphotMagnitudes(config, view); // pass 1 (detections->allSources) 211 212 if (!psphotEfficiency(config, view)) { // pass 1 213 psErrorStackPrint(stderr, "Unable to determine detection efficiencies from fake sources"); 214 psErrorClear(); 215 } 225 216 226 217 // replace failed sources? … … 228 219 229 220 // replace background in residual image 230 psphotSkyReplace (config, view); 221 psphotSkyReplace (config, view); // pass 1 231 222 232 223 // drop the references to the image pixels held by each source 233 psphotSourceFreePixels ( sources);224 psphotSourceFreePixels (config, view); // pass 1 234 225 235 226 // create the exported-metadata and free local data 236 return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);227 return psphotReadoutCleanup(config, view); 237 228 } 238 -
branches/simtest_nebulous_branches/psphot/src/psphotReadoutCleanup.c
r24203 r27840 1 1 # include "psphotInternal.h" 2 2 3 // psphotReadoutCleanup is called on exit from psphotReadout. If the last raised error is4 // 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 4 bool psphotReadoutCleanup (pmConfig *config, const pmFPAview *view) 5 { 6 bool status = true; 7 7 8 8 // remove internal pmFPAfiles, if created … … 12 12 } 13 13 if (psErrorCodeLast() != PS_ERR_NONE) { 14 psFree (psf);15 psFree (sources);16 psFree (detections);17 14 return false; 18 15 } 19 16 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 41 bool 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 20 58 // use the psf-model to measure FWHM stats 21 59 if (psf) { 22 if (!psphotPSFstats (readout, recipe,psf)) {60 if (!psphotPSFstats (readout, psf)) { 23 61 psError(PSPHOT_ERR_PROG, false, "Failed to measure PSF shape parameters"); 24 psFree (psf);25 psFree (sources);26 psFree (detections);27 62 return false; 28 63 } … … 30 65 // otherwise, use the source moments to measure FWHM stats 31 66 if (!psf && sources) { 32 if (!psphotMomentsStats (readout, recipe,sources)) {67 if (!psphotMomentsStats (readout, sources)) { 33 68 psError(PSPHOT_ERR_PROG, false, "Failed to measure Moment shape parameters"); 34 psFree (psf);35 psFree (sources);36 psFree (detections);37 69 return false; 38 70 } … … 40 72 41 73 // 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) { 43 76 bool mdok; // Status of MD lookup 44 77 int nIQ = psMetadataLookupS32(&mdok, recipe, "IQ_NSTAR"); // Number of stars for IQ measurement 45 78 if (!mdok || nIQ <= 0) { 46 79 psError(PSPHOT_ERR_DATA, false, "Unable to measure image quality"); 47 psFree (psf);48 psFree (sources);49 psFree (detections);50 80 return false; 51 81 } 52 82 } 53 83 84 // create an output header with stats results currently saved on readout->analysis 85 psMetadata *header = psphotDefineHeader (readout->analysis); 54 86 55 87 // 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); 60 89 61 90 // save the results of the analysis 91 // this should happen way up stream (when needed?) 62 92 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 66 94 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. 67 97 // save the psf for possible output. if there was already an entry, it was loaded from external sources 68 98 // the new one may have been updated or modified, so replace the existing entry. We … … 79 109 } 80 110 81 // XXX move this to top of loop?82 pmKapaClose ();83 84 psFree (detections);85 psFree (psf);86 111 psFree (header); 87 psFree (sources);88 89 112 return true; 90 113 } -
branches/simtest_nebulous_branches/psphot/src/psphotReadoutFindPSF.c
r23442 r27840 7 7 psTimerStart ("psphotReadout"); 8 8 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)) { 18 11 psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode"); 19 12 return false; 20 13 } 21 14 22 // find the currently selected readout23 pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");24 PS_ASSERT_PTR_NON_NULL (readout, false);25 26 15 // 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); 31 17 32 18 // Note that in this implementation, we do NOT model the background and we do not … … 34 20 35 21 // 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)) { 38 24 psError(PSPHOT_ERR_ARGUMENTS, true, "Can't find PSF stars"); 39 return psphotReadoutCleanup(config, readout, recipe, detections, NULL, NULL);25 return psphotReadoutCleanup(config, view); 40 26 } 41 27 42 // construct sources and measure basic stats (moments, local sky) 43 psArray *sources = psphotSourceStats(config, readout, detections); 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 } 45 33 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; 51 38 } 52 39 53 40 // classify sources based on moments, brightness (psf is not known) 54 if (!psphotRoughClass ( readout, sources, recipe, false)) {55 ps LogMsg ("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); 57 44 } 58 45 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)) { 61 52 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); 64 54 } 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 66 75 67 76 // drop the references to the image pixels held by each source 68 psphotSourceFreePixels(sources); 69 psFree(sources); 77 psphotSourceFreePixels(config, view); 70 78 71 79 // create the exported-metadata and free local data 72 return psphotReadoutCleanup(config, readout, recipe, detections, psf, NULL);80 return psphotReadoutCleanup(config, view); 73 81 } -
branches/simtest_nebulous_branches/psphot/src/psphotReadoutKnownSources.c
r23442 r27840 1 1 # include "psphotInternal.h" 2 2 3 // in this psphotReadout-variant, we are only measuring the photometry for known sources, 4 // using a PSF generated from this observationthose sources3 // in this psphotReadout-variant, we are only measuring the photometry for known sources, using 4 // a PSF generated for this observation from those sources 5 5 bool psphotReadoutKnownSources(pmConfig *config, const pmFPAview *view, psArray *inSources) { 6 6 7 7 psTimerStart ("psphotReadout"); 8 8 9 // select the current recipe10 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 9 // set the photcode for this image 17 if (!psphotAddPhotcode( recipe, config, view, "PSPHOT.INPUT")) {10 if (!psphotAddPhotcode(config, view)) { 18 11 psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode"); 19 12 return false; 20 13 } 21 14 22 // find the currently selected readout23 pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT");24 PS_ASSERT_PTR_NON_NULL (readout, false);25 26 15 // 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); 31 17 32 18 // Note that in this implementation, we do NOT model the background and we do not … … 34 20 35 21 // 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)) { 38 23 psError(PSPHOT_ERR_ARGUMENTS, true, "Can't find PSF stars"); 39 return psphotReadoutCleanup(config, readout, recipe, detections, NULL, NULL);24 return psphotReadoutCleanup(config, view); 40 25 } 41 26 42 27 // construct sources and measure basic stats 43 psArray *sources = psphotSourceStats (config, readout, detections); 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 } 45 32 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; 51 37 } 52 38 53 39 // classify sources based on moments, brightness (psf is not known) 54 if (!psphotRoughClass ( readout, sources, recipe, false)) {55 ps LogMsg ("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); 57 43 } 58 44 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); 63 48 } 64 psphotVisualShowPSFModel (readout, psf);65 49 66 50 // 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); 68 56 69 57 // 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); 76 59 77 60 // measure aperture photometry corrections 78 if (!psphotApResid (config, readout, sources, psf)) {61 if (!psphotApResid (config, view)) { 79 62 psLogMsg ("psphot", 3, "failed on psphotApResid"); 80 return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);63 return psphotReadoutCleanup(config, view); 81 64 } 82 65 83 66 // calculate source magnitudes 84 psphotMagnitudes(config, readout, view, sources, psf);67 psphotMagnitudes(config, view); 85 68 86 69 // drop the references to the image pixels held by each source 87 psphotSourceFreePixels ( sources);70 psphotSourceFreePixels (config, view); 88 71 89 72 // create the exported-metadata and free local data 90 return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);73 return psphotReadoutCleanup(config, view); 91 74 } -
branches/simtest_nebulous_branches/psphot/src/psphotReadoutMinimal.c
r24890 r27840 1 1 # include "psphotInternal.h" 2 2 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 being5 // 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. 6 6 7 7 // NOTE: ppSub needs to perform extended source analysis for comets and trails. … … 15 15 psTimerStart ("psphotReadout"); 16 16 17 // select the current recipe 18 psMetadata *recipe = psMetadataLookupPtr (NULL, config->recipes, PSPHOT_RECIPE); 19 if (!recipe) { 20 psError(PSPHOT_ERR_CONFIG, false, "missing recipe %s", PSPHOT_RECIPE); 21 return false; 22 } 17 pmModelClassSetLimits(PM_MODEL_LIMITS_LAX); 23 18 24 19 // set the photcode for this image 25 if (!psphotAddPhotcode( recipe, config, view, "PSPHOT.INPUT")) {20 if (!psphotAddPhotcode(config, view)) { 26 21 psError(PSPHOT_ERR_CONFIG, false, "trouble defining the photcode"); 27 22 return false; 28 23 } 29 24 30 // find the currently selected readout 31 pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT"); 32 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); 33 27 34 // Generate the mask and weight images, including the user-defined analysis region of interest 35 psphotSetMaskAndVariance (config, readout, recipe); 36 37 // display the image, weight, mask (ch 1,2,3) 38 psphotVisualShowImage (readout); 39 40 // load the psf model, if suppled. FWHM_X,FWHM_Y,etc are saved in the recipe 41 pmPSF *psf = psphotLoadPSF (config, view, recipe); 42 if (!psf) { 28 // load the psf model, if suppled. FWHM_X,FWHM_Y,etc are saved on readout->analysis 29 if (!psphotLoadPSF (config, view)) { 43 30 psError (PSPHOT_ERR_CONFIG, false, "missing psf model"); 44 return psphotReadoutCleanup (config, readout, recipe, NULL, NULL, NULL);31 return psphotReadoutCleanup (config, view); 45 32 } 46 33 47 // find the detections (by peak and/or footprint) in the image. 48 pmDetections *detections = pmDetectionsAlloc(); // New detections; allocated to ensure pass=2 49 detections = psphotFindDetections(detections, readout, recipe); 50 if (!detections) { 51 psLogMsg ("psphot", 3, "unable to find detections in this image"); 52 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); 53 38 } 54 39 55 // construct sources and measure basic stats 56 psArray *sources = psphotSourceStats (config, readout, detections); 57 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 } 58 45 59 46 // find blended neighbors of very saturated stars 60 // XXX merge this with Basic Deblend? 61 psphotDeblendSatstars (readout, sources, recipe); 47 psphotDeblendSatstars (config, view); 62 48 63 49 // mark blended peaks PS_SOURCE_BLEND 64 if (!psphotBasicDeblend ( sources, recipe)) {50 if (!psphotBasicDeblend (config, view)) { 65 51 psLogMsg ("psphot", 3, "failed on deblend analysis"); 66 return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);52 return psphotReadoutCleanup (config, view); 67 53 } 68 54 69 55 // classify sources based on moments, brightness (use supplied psf shape parameters) 70 if (!psphotRoughClass ( readout, sources, recipe, true)) {56 if (!psphotRoughClass (config, view)) { 71 57 psLogMsg ("psphot", 3, "failed to find a valid PSF clump for image"); 72 return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources);58 return psphotReadoutCleanup (config, view); 73 59 } 74 60 75 61 // construct an initial model for each object 76 psphotGuessModels (config, readout, sources, psf); 62 psphotGuessModels (config, view); 63 64 // merge the newly selected sources into the existing list 65 psphotMergeSources (config, view); 77 66 78 67 // linear PSF fit to source peaks 79 psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE); 80 81 // We have to place these visualizations here because the models are not realized until 82 // psphotGuessModels or fitted until psphotFitSourcesLinear. 83 psphotVisualShowPSFStars (recipe, psf, sources); 84 psphotVisualShowSatStars (recipe, psf, sources); 68 psphotFitSourcesLinear (config, view, false); 85 69 86 70 // XXX eventually, add the extended source fits here 87 71 # if (0) 88 72 // measure source size for the remaining sources 89 psphotSourceSize (config, readout, sources, recipe, 0);73 psphotSourceSize (config, view); 90 74 91 psphotExtendedSourceAnalysis ( readout, sources, recipe);75 psphotExtendedSourceAnalysis (config, view); 92 76 93 psphotExtendedSourceFits ( readout, sources, recipe);77 psphotExtendedSourceFits (config, view); 94 78 # endif 95 79 96 80 // calculate source magnitudes 97 psphotMagnitudes(config, readout, view, sources, psf); 81 psphotMagnitudes(config, view); 82 83 // XXX ensure this is measured if the analysis succeeds (even if quality is low) 84 if (!psphotEfficiency(config, view)) { 85 psErrorStackPrint(stderr, "Unable to determine detection efficiencies from fake sources"); 86 psErrorClear(); 87 } 98 88 99 89 // drop the references to the image pixels held by each source 100 psphotSourceFreePixels ( sources);90 psphotSourceFreePixels (config, view); 101 91 102 92 // create the exported-metadata and free local data 103 return psphotReadoutCleanup(config, readout, recipe, detections, psf, sources);93 return psphotReadoutCleanup(config, view); 104 94 } -
branches/simtest_nebulous_branches/psphot/src/psphotReplaceUnfit.c
r21519 r27840 17 17 replace: 18 18 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 19 source->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;20 19 } 21 20 psLogMsg ("psphot.replace", 3, "replace unfitted models: %f sec (%ld objects)\n", psTimerMark ("psphot.replace"), sources->n); … … 23 22 } 24 23 25 bool psphotReplaceAllSources (psArray *sources, psMetadata *recipe) { 24 // for now, let's store the detections on the readout->analysis for each readout 25 bool 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 46 bool psphotReplaceAllSourcesReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) { 26 47 27 48 bool status; … … 30 51 psTimerStart ("psphot.replace"); 31 52 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 32 66 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 33 67 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 34 assert (maskVal);68 psAssert (maskVal, "missing mask value?"); 35 69 36 70 for (int i = 0; i < sources->n; i++) { … … 41 75 42 76 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 43 source->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;44 77 } 45 78 psLogMsg ("psphot.replace", PS_LOG_INFO, "replaced models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.replace")); … … 47 80 } 48 81 49 bool psphotRemoveAllSources ( psArray *sources,psMetadata *recipe) {82 bool psphotRemoveAllSources (const psArray *sources, const psMetadata *recipe) { 50 83 51 84 bool status; … … 64 97 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) continue; 65 98 66 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 67 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED; 99 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 68 100 } 69 101 psLogMsg ("psphot.replace", PS_LOG_INFO, "replaced models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.replace")); 70 102 return true; 71 103 } 72 73 // add source, if the source has been subtracted; do not modify state74 bool psphotAddWithTest (pmSource *source, bool useState, psImageMaskType maskVal) {75 76 // what is current state? (true : add; false : sub)77 bool state = !(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);78 if (state && useState) return true;79 80 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);81 return true;82 }83 84 // sub source, if the source has been added; do not modify state85 bool psphotSubWithTest (pmSource *source, bool useState, psImageMaskType maskVal) {86 87 // what is current state? (true : sub; false : add)88 bool state = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);89 if (state && useState) return true;90 91 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);92 return true;93 }94 95 // add or sub source to match recorded state: supply current state as true (add) or false (sub)96 bool psphotSetState (pmSource *source, bool curState, psImageMaskType maskVal) {97 98 // what is desired state? (true : add; false : sub)99 bool newState = !(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);100 if (curState == newState) return true;101 102 if (curState && !newState) {103 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);104 }105 if (newState && !curState) {106 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);107 }108 return true;109 } -
branches/simtest_nebulous_branches/psphot/src/psphotRoughClass.c
r23989 r27840 1 1 # include "psphotInternal.h" 2 2 3 # define CHECK_STATUS(S,MSG) { \4 if (!status) {\5 psError(PSPHOT_ERR_CONFIG, false, "missing PSF Clump entry: %s\n", MSG); \6 return false;\7 } }3 # define CHECK_STATUS(S,MSG) { \ 4 if (!status) { \ 5 psError(PSPHOT_ERR_CONFIG, false, "missing PSF Clump entry: %s\n", MSG); \ 6 return false; \ 7 } } 8 8 9 bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *recipe, const bool havePSF); 9 // for now, let's store the detections on the readout->analysis for each readout 10 bool psphotRoughClass (pmConfig *config, const pmFPAview *view) 11 { 12 bool status = true; 10 13 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 36 bool psphotRoughClassReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) { 13 37 14 38 bool status; 15 39 16 40 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 } 17 65 18 66 // we make this measurement on a NxM grid of regions across the readout … … 24 72 int nRegion = 0; 25 73 for (int ix = 0; ix < NX; ix ++) { 26 for (int iy = 0; iy < NY; iy ++) {74 for (int iy = 0; iy < NY; iy ++) { 27 75 28 psRegion region = psRegionSet (ix*dX, (ix + 1)*dX, iy*dY, (iy + 1)*dY); 29 if (!psphotRoughClassRegion (nRegion, ®ion, sources, recipe, havePSF)) { 30 psLogMsg ("psphot", 4, "Failed to determine rough classification for region %f,%f - %f,%f\n", 31 region.x0, region.y0, region.x1, region.y1); 32 continue; 33 } 34 35 nRegion ++; 36 } 76 psRegion *region = psRegionAlloc (ix*dX, (ix + 1)*dX, iy*dY, (iy + 1)*dY); 77 if (!psphotRoughClassRegion (nRegion, region, sources, readout->analysis, recipe, havePSF)) { 78 psLogMsg ("psphot", 4, "Failed to determine rough classification for region %f,%f - %f,%f\n", 79 region->x0, region->y0, region->x1, region->y1); 80 psFree (region); 81 continue; 82 } 83 psFree (region); 84 nRegion ++; 85 } 37 86 } 38 psMetadataAddS32 (re cipe, 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); 39 88 40 89 // optional printout of source moments only … … 43 92 psLogMsg ("psphot.roughclass", PS_LOG_INFO, "rough classification: %f sec\n", psTimerMark ("psphot.rough")); 44 93 45 psphotVisualPlotMoments (recipe, sources);94 psphotVisualPlotMoments (recipe, readout->analysis, sources); 46 95 psphotVisualShowRoughClass (sources); 47 psphotVisualShowFlags (sources);96 // XXX better visualization: psphotVisualShowFlags (sources); 48 97 49 98 return true; 50 99 } 51 100 52 bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata * recipe, const bool havePSF) {101 bool psphotRoughClassRegion (int nRegion, psRegion *region, psArray *sources, psMetadata *analysis, psMetadata *recipe, const bool havePSF) { 53 102 54 103 bool status; … … 60 109 assert (maskSat); 61 110 111 // the regions are saved on the readout->analysis metadata folder (passed to us as analysis) 62 112 snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", nRegion); 63 psMetadata *regionMD = psMetadataLookupPtr (&status, recipe, regionName);113 psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName); 64 114 if (!regionMD) { 65 regionMD = psMetadataAlloc(); 66 psMetadataAddMetadata (recipe, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD); 67 psFree (regionMD); 115 // allocate the region metadata folder and add this region to it. 116 regionMD = psMetadataAlloc(); 117 psMetadataAddMetadata (analysis, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD); 118 psFree (regionMD); 68 119 } 120 psMetadataAddPtr (regionMD, PS_LIST_TAIL, "REGION", PS_DATA_REGION | PS_META_REPLACE, "psf clump region", region); 69 121 70 122 if (!havePSF) { 71 // determine the PSF parameters from the source moment values 72 psfClump = pmSourcePSFClump (region, sources, recipe); 73 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X", PS_META_REPLACE, "psf clump center", psfClump.X); 74 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y", PS_META_REPLACE, "psf clump center", psfClump.Y); 75 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX); 76 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY); 123 // determine the PSF parameters from the source moment values 124 // XXX why not save the psfClump as a PTR? 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 147 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X", PS_META_REPLACE, "psf clump center", psfClump.X); 148 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y", PS_META_REPLACE, "psf clump center", psfClump.Y); 149 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX); 150 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY); 77 151 } else { 78 // pull FWHM_X,Y from the recipe, use to define psfClump.X,Y79 psfClump.X = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); 80 if (!status) {81 psLogMsg ("psphot", 4, "No PSF clump defined for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1);82 return false;83 } 84 psfClump.Y = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y"); psAssert (status, "missing PSF.CLUMP.Y");85 psfClump.dX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX"); psAssert (status, "missing PSF.CLUMP.DX");86 psfClump.dY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY"); psAssert (status, "missing PSF.CLUMP.DY");152 // pull FWHM_X,Y from the recipe, use to define psfClump.X,Y 153 psfClump.X = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); 154 if (!status) { 155 psLogMsg ("psphot", 4, "No PSF clump defined for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1); 156 return false; 157 } 158 psfClump.Y = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y"); psAssert (status, "missing PSF.CLUMP.Y"); 159 psfClump.dX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX"); psAssert (status, "missing PSF.CLUMP.DX"); 160 psfClump.dY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY"); psAssert (status, "missing PSF.CLUMP.DY"); 87 161 } 88 162 89 163 if (psfClump.X < 0) { 90 psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourcePSFClump");91 return false;164 psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourcePSFClump"); 165 return false; 92 166 } 93 167 if (!psfClump.X || !psfClump.Y || isnan(psfClump.X) || isnan(psfClump.Y)) { 94 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);95 return false;168 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); 169 return false; 96 170 } 97 171 psLogMsg ("psphot", 3, "psf clump X, Y: %f, %f\n", psfClump.X, psfClump.Y); 98 172 psLogMsg ("psphot", 3, "psf clump DX, DY: %f, %f\n", psfClump.dX, psfClump.dY); 99 173 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 100 178 // group into STAR, COSMIC, EXTENDED, SATURATED, etc. 101 if (!pmSourceRoughClass (region, sources, recipe, psfClump, maskSat)) {102 psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourceRoughClass");103 return false;179 if (!pmSourceRoughClass (region, sources, PSF_SN_LIM, PSF_CLUMP_NSIGMA, psfClump, maskSat)) { 180 psError(PSPHOT_ERR_PROG, false, "programming error calling pmSourceRoughClass"); 181 return false; 104 182 } 105 183 -
branches/simtest_nebulous_branches/psphot/src/psphotSetThreads.c
r23218 r27840 10 10 psFree(task); 11 11 12 task = psThreadTaskAlloc("PSPHOT_MAGNITUDES", 8);12 task = psThreadTaskAlloc("PSPHOT_MAGNITUDES", 9); 13 13 task->function = &psphotMagnitudes_Threaded; 14 14 psThreadTaskAdd(task); … … 20 20 psFree(task); 21 21 22 task = psThreadTaskAlloc("PSPHOT_APRESID_MAGS", 6);22 task = psThreadTaskAlloc("PSPHOT_APRESID_MAGS", 7); 23 23 task->function = &psphotApResidMags_Threaded; 24 24 psThreadTaskAdd(task); 25 25 psFree(task); 26 26 27 task = psThreadTaskAlloc("PSPHOT_SOURCE_STATS", 5);27 task = psThreadTaskAlloc("PSPHOT_SOURCE_STATS", 10); 28 28 task->function = &psphotSourceStats_Threaded; 29 29 psThreadTaskAdd(task); -
branches/simtest_nebulous_branches/psphot/src/psphotSignificanceImage.c
r21407 r27840 22 22 } 23 23 24 bool status_x, status_y; 25 float FWHM_X = psMetadataLookupF32 (&status_x, recipe, "FWHM_X"); 26 float FWHM_Y = psMetadataLookupF32 (&status_y, recipe, "FWHM_Y"); 27 if (status_x && status_y) { 28 // if we know the FHWM, use that to set the smoothing kernel (XXX allow an optional override?) 29 SIGMA_SMTH = 0.5*(FWHM_X + FWHM_Y) / (2.0*sqrt(2.0*log(2.0))); 30 NSIGMA_SMTH = psMetadataLookupF32 (&status, recipe, "PEAKS_SMOOTH_NSIGMA"); 31 guess = false; 24 // if we have already determined the PSF model, then we have a better idea how to smooth this image 25 bool statusMajor, statusMinor; 26 float fwhmMajor = psMetadataLookupF32(&statusMajor, readout->analysis, "FWHM_MAJ"); 27 float fwhmMinor = psMetadataLookupF32(&statusMinor, readout->analysis, "FWHM_MIN"); 28 if (statusMajor && statusMinor) { 29 // if we know the FHWM, use that to set the smoothing kernel (XXX allow an optional override?) 30 if (!isfinite(fwhmMajor) || !isfinite(fwhmMinor) || fwhmMajor == 0.0 || fwhmMinor == 0.0) { 31 psWarning("fwhmMajor (%f) or fwhmMinor (%f) is bad!", fwhmMajor, fwhmMinor); 32 } 33 SIGMA_SMTH = 0.5*(fwhmMajor + fwhmMinor) / (2.0*sqrt(2.0*log(2.0))); 34 NSIGMA_SMTH = psMetadataLookupF32 (&status, recipe, "PEAKS_SMOOTH_NSIGMA"); 35 guess = false; 32 36 } else { 33 // if we do not know the FWHM, use the guess smoothing kernel supplied.34 // it is a configuration error if these are not supplied35 SIGMA_SMTH = psMetadataLookupF32 (&status, recipe, "PEAKS_SMOOTH_SIGMA");36 PS_ASSERT (status, NULL);37 NSIGMA_SMTH = psMetadataLookupF32 (&status, recipe, "PEAKS_SMOOTH_NSIGMA");38 PS_ASSERT (status, NULL);39 guess = true;37 // if we do not know the FWHM, use the guess smoothing kernel supplied. 38 // it is a configuration error if these are not supplied 39 SIGMA_SMTH = psMetadataLookupF32 (&status, recipe, "PEAKS_SMOOTH_SIGMA"); 40 PS_ASSERT (status, NULL); 41 NSIGMA_SMTH = psMetadataLookupF32 (&status, recipe, "PEAKS_SMOOTH_NSIGMA"); 42 PS_ASSERT (status, NULL); 43 guess = true; 40 44 } 41 45 // record the actual smoothing sigma 42 psMetadataAddF32(recipe, PS_LIST_TAIL, "SIGMA_SMOOTH", PS_META_REPLACE, "Smoothing sigma for detections", 43 SIGMA_SMTH); 46 psMetadataAddF32(readout->analysis, PS_LIST_TAIL, "SIGMA_SMOOTH", PS_META_REPLACE, "Smoothing sigma for detections", SIGMA_SMTH); 44 47 45 48 // smooth the image, applying the mask as we go … … 56 59 // effective per-pixel variance is maintained. 57 60 psImage *smooth_wt = psImageCopy(NULL, readout->variance, PS_TYPE_F32); 58 psImageSmoothMask_Threaded(smooth_wt, smooth_wt, readout->mask, maskVal, SIGMA_SMTH * M_SQRT1_2, 59 NSIGMA_SMTH, minGauss); 61 psImageSmoothMask_Threaded(smooth_wt, smooth_wt, readout->mask, maskVal, SIGMA_SMTH * M_SQRT1_2, NSIGMA_SMTH, minGauss); 60 62 psLogMsg("psphot", PS_LOG_MINUTIA, "smooth variance: %f sec\n", psTimerMark("psphot.smooth")); 61 63 … … 74 76 // Calculate correction factor for the covariance produced by the (potentially multiple) smoothing 75 77 psKernel *kernel = psImageSmoothKernel(SIGMA_SMTH, NSIGMA_SMTH); // Kernel used for smoothing 76 psKernel *covar = psImageCovarianceCalculate(kernel, readout->covariance); // Covariance matrix78 float factor = 1.0 / psImageCovarianceCalculateFactor(kernel, readout->covariance); 77 79 psFree(kernel); 78 float factor = 1.0 / psImageCovarianceFactor(covar);79 psFree(covar);80 80 81 81 // record the effective area and significance scaling factor 82 82 float effArea = 8.0 * M_PI * PS_SQR(SIGMA_SMTH); 83 psMetadataAddF32(recipe, PS_LIST_TAIL, "EFFECTIVE_AREA", PS_META_REPLACE, "Effective Area", effArea); 84 psMetadataAddF32(recipe, PS_LIST_TAIL, "SIGNIFICANCE_SCALE_FACTOR", PS_META_REPLACE, 85 "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); 86 85 87 86 // XXX multithread this if needed -
branches/simtest_nebulous_branches/psphot/src/psphotSkyReplace.c
r21183 r27840 1 1 # include "psphotInternal.h" 2 3 bool 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 } 2 24 3 25 // XXX make this an option? 4 26 // in order to successfully replace the sky, we must define a corresponding file... 5 bool psphotSkyReplace (pmConfig *config, const pmFPAview *view) {27 bool psphotSkyReplaceReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index) { 6 28 7 29 psTimerStart ("psphot.skyreplace"); 8 30 9 31 // 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?"); 12 37 13 38 // select background pixels, from output background file, or create -
branches/simtest_nebulous_branches/psphot/src/psphotSourceFits.c
r24592 r27840 90 90 psphotCheckRadiusPSFBlend (readout, source, PSF, markVal, dR); 91 91 92 // fit PSF model (set/unset the pixel mask)92 // fit PSF model 93 93 pmSourceFitSet (source, modelSet, PM_SOURCE_FIT_PSF, maskVal); 94 95 // clear the circular mask 96 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 97 98 if (!isfinite(PSF->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 94 99 95 100 // correct model chisq for flux trend … … 101 106 pmSource *blend = sourceSet->data[i]; 102 107 pmModel *model = modelSet->data[i]; 108 109 if (!isfinite(model->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 103 110 104 111 // correct model chisq for flux trend … … 120 127 pmSourceCacheModel (blend, maskVal); 121 128 pmSourceSub (blend, PM_MODEL_OP_FULL, maskVal); 122 blend->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;123 129 blend->mode |= PM_SOURCE_MODE_BLEND_FIT; 124 130 } … … 144 150 pmSourceCacheModel (source, maskVal); 145 151 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 146 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;147 152 source->mode |= PM_SOURCE_MODE_BLEND_FIT; 148 153 return true; … … 167 172 // fit PSF model (set/unset the pixel mask) 168 173 pmSourceFitModel (source, PSF, PM_SOURCE_FIT_PSF, maskVal); 174 175 if (!isfinite(PSF->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 176 177 // clear the circular mask 178 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 169 179 170 180 // correct model chisq for flux trend … … 186 196 pmSourceCacheModel (source, maskVal); 187 197 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 188 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED; 189 return true; 190 } 191 192 static float EXT_MIN_SN; 193 static float EXT_MOMENTS_RAD; 198 return true; 199 } 200 194 201 static pmModelType modelTypeEXT; 195 202 … … 197 204 198 205 bool status; 199 200 // extended source model parameters201 EXT_MIN_SN = psMetadataLookupF32 (&status, recipe, "EXT_MIN_SN");202 EXT_MOMENTS_RAD = psMetadataLookupF32 (&status, recipe, "EXT_MOMENTS_RADIUS");203 206 204 207 // extended source model descriptions … … 216 219 double chiTrend; 217 220 pmModel *ONE = NULL; 221 pmSource *tmpSrc = NULL; 222 pmModel *EXT = NULL; 223 psArray *DBL = NULL; 218 224 219 225 // skip the source if we don't think it is extended … … 221 227 if (source->type == PM_SOURCE_TYPE_DEFECT) return false; 222 228 if (source->type == PM_SOURCE_TYPE_SATURATED) return false; 223 if (source->peak->SN < EXT_MIN_SN) return false; 224 229 230 // set the radius based on the footprint (also sets the mask pixels) 231 float radius = psphotSetRadiusEXT (readout, source, markVal); 232 233 // XXX note that this changes the source moments that are published... 225 234 // recalculate the source moments using the larger extended-source moments radius 226 235 // at this stage, skip Gaussian windowing, and do not clip pixels by S/N 227 if (!pmSourceMoments (source, EXT_MOMENTS_RAD, 0.0, 0.0)) return false; 236 // this uses the footprint to judge both radius and aperture? 237 if (!pmSourceMoments (source, radius, 0.0, 0.0, maskVal)) return false; 228 238 229 239 psTrace ("psphot", 5, "trying blob...\n"); … … 233 243 234 244 // this temporary source is used as a place-holder by the psphotEval functions below 235 pmSource *tmpSrc = pmSourceAlloc ();245 tmpSrc = pmSourceAlloc (); 236 246 237 247 // XXX need to handle failures better here 238 pmModel *EXT = psphotFitEXT (readout, source, modelTypeEXT, maskVal, markVal); 248 EXT = psphotFitEXT (readout, source, modelTypeEXT, maskVal, markVal); 249 if (!EXT) goto escape; 250 if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) goto escape; 251 239 252 okEXT = psphotEvalEXT (tmpSrc, EXT); 240 253 chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN; 241 254 242 255 // DBL will always be defined, but DBL->data[n] might not 243 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 244 260 okDBL = psphotEvalDBL (tmpSrc, DBL->data[0]); 245 261 okDBL &= psphotEvalDBL (tmpSrc, DBL->data[1]); 246 262 // XXX should I keep / save the flags set in the eval functions? 263 264 // clear the circular mask 265 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 247 266 248 267 // correct first model chisqs for flux trend … … 250 269 ONE = DBL->data[0]; 251 270 if (ONE) { 271 if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 252 272 chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]); 253 273 ONE->chisqNorm = ONE->chisq / chiTrend; … … 258 278 ONE = DBL->data[1]; 259 279 if (ONE) { 280 if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 260 281 chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]); 261 282 ONE->chisqNorm = ONE->chisq / chiTrend; … … 277 298 278 299 // both models failed; reject them both 300 // XXX -- change type flags to psf in this case and keep original moments? 279 301 psFree (EXT); 280 302 psFree (DBL); … … 287 309 // save new model 288 310 source->modelEXT = EXT; 311 source->modelEXT->fitRadius = radius; 289 312 source->type = PM_SOURCE_TYPE_EXTENDED; 290 313 source->mode |= PM_SOURCE_MODE_EXTMODEL; … … 293 316 pmSourceCacheModel (source, maskVal); 294 317 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 295 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED; 318 319 # if (PS_TRACE_ON) 296 320 psTrace ("psphot", 5, "blob as EXT: %f %f\n", EXT->params->data.F32[PM_PAR_XPOS], EXT->params->data.F32[PM_PAR_YPOS]); 321 if (psTraceGetLevel("psphot") >= 6) { 322 psLogMsg ("psphot", 1, "source 2:\n"); 323 for (int i = 0; i < source->modelEXT->params->n; i++) { 324 psLogMsg ("psphot", 1, "PAR %d : %f +/- %f\n", i, source->modelEXT->params->data.F32[i], source->modelEXT->dparams->data.F32[i]); 325 } 326 } 327 # endif 328 297 329 return true; 298 330 … … 304 336 psFree (source->modelPSF); 305 337 source->modelPSF = psMemIncrRefCounter (DBL->data[0]); 306 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;307 338 source->mode |= PM_SOURCE_MODE_PAIR; 339 source->modelPSF->fitRadius = radius; 308 340 309 341 // copy most data from the primary source (modelEXT, blends stay NULL) 310 // XXX use pmSourceCopy?311 342 pmSource *newSrc = pmSourceCopy (source); 312 343 newSrc->modelPSF = psMemIncrRefCounter (DBL->data[1]); 344 newSrc->modelPSF->fitRadius = radius; 313 345 314 346 // build cached models and subtract … … 317 349 pmSourceCacheModel (newSrc, maskVal); 318 350 pmSourceSub (newSrc, PM_MODEL_OP_FULL, maskVal); 351 352 # if (PS_TRACE_ON) 319 353 psTrace ("psphot", 5, "blob as DBL: %f %f\n", ONE->params->data.F32[PM_PAR_XPOS], ONE->params->data.F32[PM_PAR_YPOS]); 354 if (psTraceGetLevel("psphot") >= 6) { 355 psLogMsg ("psphot", 1, "source 1:\n"); 356 for (int i = 0; i < newSrc->modelPSF->params->n; i++) { 357 psLogMsg ("psphot", 1, "PAR %d : %f +/- %f\n", i, newSrc->modelPSF->params->data.F32[i], newSrc->modelPSF->dparams->data.F32[i]); 358 } 359 psLogMsg ("psphot", 1, "source 2:\n"); 360 for (int i = 0; i < source->modelPSF->params->n; i++) { 361 psLogMsg ("psphot", 1, "PAR %d : %f +/- %f\n", i, source->modelPSF->params->data.F32[i], source->modelPSF->dparams->data.F32[i]); 362 } 363 psphotVisualShowResidualImage (readout); 364 } 365 # endif 320 366 321 367 psArrayAdd (newSources, 100, newSrc); … … 323 369 psFree (DBL); 324 370 return true; 371 372 escape: 373 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 374 psFree (tmpSrc); 375 psFree (EXT); 376 psFree (DBL); 377 return false; 325 378 } 326 379 … … 356 409 // save the PSF model from the Ensemble fit 357 410 PSF = source->modelPSF; 358 psphotCheckRadiusPSFBlend (readout, source, PSF, markVal, 8.0);359 411 if (isnan(PSF->params->data.F32[1])) psAbort("nan in dbl fit"); 360 412 … … 387 439 // use the source moments, etc to guess basic model parameters 388 440 pmModel *EXT = pmSourceModelGuess (source, modelType); 389 PS_ASSERT (EXT, NULL); 390 391 // if (isnan(EXT->params->data.F32[1])) psAbort("nan in ext fit"); 392 393 psphotCheckRadiusEXT (readout, source, EXT, markVal); 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 } 394 445 395 446 if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) { … … 401 452 return (EXT); 402 453 } 403 -
branches/simtest_nebulous_branches/psphot/src/psphotSourceFreePixels.c
r12792 r27840 1 1 # include "psphotInternal.h" 2 2 3 void psphotSourceFreePixels (psArray *sources) { 3 bool psphotSourceFreePixels (pmConfig *config, const pmFPAview *view) 4 { 5 bool status = true; 4 6 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 20 bool 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?"); 6 36 7 37 for (int i = 0; i < sources->n; i++) { … … 9 39 pmSourceFreePixels (source); 10 40 } 11 return ;41 return true; 12 42 } -
branches/simtest_nebulous_branches/psphot/src/psphotSourcePlots.c
r21183 r27840 111 111 if (Xo == 0) { 112 112 // place source alone on this row 113 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 113 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 114 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 114 115 psphotRadialPlot (&kapa, "radial.plots.ps", source); 115 116 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true); 116 117 117 psphotSubWithTest (source, false, maskVal); // remove source (force) 118 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 118 119 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true); 119 120 120 psphotSetState (source, false, maskVal); // replace source (has been subtracted) 121 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 122 121 123 Yo += DY; 122 124 Xo = 0; … … 126 128 Yo += dY; 127 129 Xo = 0; 128 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 130 131 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 132 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 129 133 psphotRadialPlot (&kapa, "radial.plots.ps", source); 130 134 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true); 131 135 132 psphotSubWithTest (source, false, maskVal); // remove source (force) 136 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 133 137 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true); 134 psphotSetState (source, false, maskVal); // replace source (has been subtracted) 138 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 135 139 136 140 Xo = DX; … … 139 143 } else { 140 144 // extend this row 141 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 145 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 146 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 142 147 psphotRadialPlot (&kapa, "radial.plots.ps", source); 143 148 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true); 144 149 145 psphotSubWithTest (source, false, maskVal); // remove source (force) 150 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 146 151 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true); 147 psphotSetState (source, false, maskVal); // replace source (has been subtracted) 152 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 148 153 149 154 Xo += DX; -
branches/simtest_nebulous_branches/psphot/src/psphotSourceSize.c
r21519 r27840 2 2 # include <gsl/gsl_sf_gamma.h> 3 3 4 static float psphotModelContour(const psImage *image, const psImage *variance, const psImage *mask, 5 psImageMaskType maskVal, const pmModel *model, float Ro); 6 7 bool psphotMaskCosmicRay_Old (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask); 8 bool psphotMaskCosmicRay_New (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask); 4 typedef struct { 5 psImageMaskType maskVal; 6 psImageMaskType markVal; 7 psImageMaskType crMask; 8 float ApResid; 9 float ApSysErr; 10 float nSigmaApResid; 11 float nSigmaMoments; 12 float nSigmaCR; 13 float soft; 14 int grow; 15 int xtest, ytest; 16 bool apply; // apply CR mask? 17 } psphotSourceSizeOptions; 18 19 // local functions: 20 bool psphotSourceSizePSF (psphotSourceSizeOptions *options, psArray *sources, pmPSF *psf); 21 bool psphotSourceClass (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options); 22 bool psphotSourceClassRegion (psRegion *region, pmPSFClump *psfClump, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options); 23 bool psphotSourceSizeCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options); 24 bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal); 25 bool psphotMaskCosmicRayFootprintCheck (psArray *sources); 26 int psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh); 9 27 10 28 // we need to call this function after sources have been fitted to the PSF model and … … 14 32 // deviation from the psf model at the r = FWHM/2 position 15 33 16 bool psphotSourceSize(pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, long first) 34 // for now, let's store the detections on the readout->analysis for each readout 35 bool 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 62 bool psphotSourceSizeReadout(pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool getPSFsize) 17 63 { 18 64 bool status; 65 psphotSourceSizeOptions options; 19 66 20 67 psTimerStart ("psphot.size"); 21 68 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 22 90 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) 23 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 24 assert (maskVal); 91 options.maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 92 assert (options.maskVal); 93 94 options.markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); // Mask value for bad pixels 95 assert (options.markVal); 25 96 26 97 // bit to mask the cosmic-ray pixels 27 psImageMaskTypecrMask = pmConfigMaskGet("CR", config); // Mask value for cosmic rays28 29 float CR_NSIGMA_LIMIT= psMetadataLookupF32 (&status, recipe, "PSPHOT.CR.NSIGMA.LIMIT");98 options.crMask = pmConfigMaskGet("CR", config); // Mask value for cosmic rays 99 100 options.nSigmaCR = psMetadataLookupF32 (&status, recipe, "PSPHOT.CR.NSIGMA.LIMIT"); 30 101 assert (status); 31 102 32 float EXT_NSIGMA_LIMIT = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.LIMIT"); 103 // XXX recipe name is not great 104 options.nSigmaApResid = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.LIMIT"); 33 105 assert (status); 34 106 35 int grow = psMetadataLookupS32(&status, recipe, "PSPHOT.CR.GROW"); // Growth size for CRs 36 if (!status || grow < 0) { 107 // XXX recipe name is not great 108 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"); 114 assert (status); 115 116 options.grow = psMetadataLookupS32(&status, recipe, "PSPHOT.CR.GROW"); // Growth size for CRs 117 if (!status || options.grow < 0) { 37 118 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSPHOT.CR.GROW is not positive."); 38 119 return false; 39 120 } 40 121 41 floatsoft = psMetadataLookupF32(&status, recipe, "PSPHOT.CR.NSIGMA.SOFTEN"); // Softening parameter42 if (!status || !isfinite( soft) ||soft < 0.0) {122 options.soft = psMetadataLookupF32(&status, recipe, "PSPHOT.CR.NSIGMA.SOFTEN"); // Softening parameter 123 if (!status || !isfinite(options.soft) || options.soft < 0.0) { 43 124 psWarning("PSPHOT.CR.NSIGMA.SOFTEN not set; defaulting to zero."); 44 soft = 0.0; 45 } 46 47 // loop over all source 48 for (int i = first; i < sources->n; i++) { 125 options.soft = 0.0; 126 } 127 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 134 // We are using the value psfMag - 2.5*log10(moment.Sum) as a measure of the extendedness 135 // of an object. We need to model this distribution for the PSF stars before we can test 136 // the significance for a specific object 137 // XXX move this to the code that generates the PSF? 138 // XXX store the results on pmPSF? 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 } 144 145 // classify the sources based on ApResid and Moments (extended sources) 146 // NOTE: only sources not already measured !(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) 147 psphotSourceClass(readout, sources, recipe, psf, &options); 148 149 // NOTE: only sources not already measured !(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) 150 psphotSourceSizeCR (readout, sources, &options); 151 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")); 154 155 psphotVisualPlotSourceSize (recipe, readout->analysis, sources); 156 psphotVisualShowSourceSize (readout, sources); 157 psphotVisualPlotApResid (sources, options.ApResid, options.ApSysErr); 158 psphotVisualShowSatStars (recipe, psf, sources); 159 160 return true; 161 } 162 163 // model the apmifit distribution for the psf stars: 164 bool 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++) { 49 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 236 bool 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 275 bool 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; 50 302 51 303 // skip source if it was already measured 52 if ( isfinite(source->crNsigma)) {53 psTrace("psphot", 7, "Not calculating extNsigma,crNsigma since alreadymeasured\n");304 if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) { 305 psTrace("psphot", 7, "Not calculating source size since it has already been measured\n"); 54 306 continue; 55 307 } … … 57 309 // source must have been subtracted 58 310 if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) { 59 source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED; 60 psTrace("psphot", 7, "Not calculating extNsigma,crNsigma since source is not subtracted\n"); 61 continue; 62 } 63 64 psF32 **resid = source->pixels->data.F32; 65 psF32 **variance = source->variance->data.F32; 66 psImageMaskType **mask = source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA; 67 68 // check for extendedness: measure the delta flux significance at the 1 sigma contour 69 source->extNsigma = psphotModelContour(source->pixels, source->variance, source->maskObj, maskVal, 70 source->modelPSF, 1.0); 71 72 // XXX prevent a source from being both CR and EXT? 73 if (source->extNsigma > EXT_NSIGMA_LIMIT) { 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 74 417 source->mode |= PM_SOURCE_MODE_EXT_LIMIT; 75 } 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 439 bool 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; 76 462 77 463 // Integer position of peak … … 79 465 int yPeak = source->peak->yf - source->pixels->row0 + 0.5; 80 466 81 // XXX for now, skip sources which are too close to a boundary 82 // XXX raise a flag? 467 // Skip sources which are too close to a boundary. These are mostly caught as DEFECT 83 468 if (xPeak < 1 || xPeak > source->pixels->numCols - 2 || 84 469 yPeak < 1 || yPeak > source->pixels->numRows - 2) { 85 source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED;86 470 psTrace("psphot", 7, "Not calculating crNsigma due to edge\n"); 87 471 continue; 88 472 } 89 473 90 // XXX for now, just skip any sources with masked pixels 91 // XXX raise a flag? 92 bool keep = true; 93 for (int iy = -1; (iy <= +1) && keep; iy++) { 94 for (int ix = -1; (ix <= +1) && keep; ix++) { 95 if (mask[yPeak+iy][xPeak+ix] & maskVal) { 96 keep = false; 97 } 98 } 99 } 100 if (!keep) { 101 psTrace("psphot", 7, "Not calculating crNsigma due to masked pixels\n"); 102 source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED; 103 continue; 104 } 105 106 // Compare the central pixel with those on either side, for the four possible lines through it. 107 108 // Soften variances (add systematic error) 109 float softening = soft * PS_SQR(source->peak->flux); // Softening for variances 110 111 // Across the middle: y = 0 112 float cX = 2*resid[yPeak][xPeak] - resid[yPeak+0][xPeak-1] - resid[yPeak+0][xPeak+1]; 113 float dcX = 4*variance[yPeak][xPeak] + variance[yPeak+0][xPeak-1] + variance[yPeak+0][xPeak+1]; 114 float nX = cX / sqrtf(dcX + softening); 115 116 // Up the centre: x = 0 117 float cY = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak+0] - resid[yPeak+1][xPeak+0]; 118 float dcY = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak+0] + variance[yPeak+1][xPeak+0]; 119 float nY = cY / sqrtf(dcY + softening); 120 121 // Diagonal: x = y 122 float cL = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak-1] - resid[yPeak+1][xPeak+1]; 123 float dcL = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak-1] + variance[yPeak+1][xPeak+1]; 124 float nL = cL / sqrtf(dcL + softening); 125 126 // Diagonal: x = - y 127 float cR = 2*resid[yPeak][xPeak] - resid[yPeak+1][xPeak-1] - resid[yPeak-1][xPeak+1]; 128 float dcR = 4*variance[yPeak][xPeak] + variance[yPeak+1][xPeak-1] + variance[yPeak-1][xPeak+1]; 129 float nR = cR / sqrtf(dcR + softening); 130 131 // P(chisq > chisq_obs; Ndof) = gamma_Q (Ndof/2, chisq/2) 132 // Ndof = 4 ? (four measurements, no free parameters) 133 // XXX this value is going to be biased low because of systematic errors. 134 // we need to calibrate it somehow 135 // source->psfProb = gsl_sf_gamma_inc_Q (2, 0.5*chisq); 136 137 // not strictly accurate: overcounts the chisq contribution from the center pixel (by 138 // factor of 4); also biases a bit low if any pixels are masked 139 // XXX I am not sure I want to keep this value... 140 source->psfChisq = PS_SQR(nX) + PS_SQR(nY) + PS_SQR(nL) + PS_SQR(nR); 141 142 float fCR = 0.0; 143 int nCR = 0; 144 if (nX > 0.0) { 145 fCR += nX; 146 nCR ++; 147 } 148 if (nY > 0.0) { 149 fCR += nY; 150 nCR ++; 151 } 152 if (nL > 0.0) { 153 fCR += nL; 154 nCR ++; 155 } 156 if (nR > 0.0) { 157 fCR += nR; 158 nCR ++; 159 } 160 source->crNsigma = (nCR > 0) ? fCR / nCR : 0.0; 161 if (!isfinite(source->crNsigma)) { 162 continue; 163 } 164 165 // this source is thought to be a cosmic ray. flag the detection and mask the pixels 166 if (source->crNsigma > CR_NSIGMA_LIMIT) { 167 // XXX still testing... : psphotMaskCosmicRay_New (readout->mask, source, maskVal, crMask); 168 psphotMaskCosmicRay_Old (source, maskVal, crMask); 169 } 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); 170 494 } 171 495 172 496 // now that we have masked pixels associated with CRs, we can grow the mask 173 if ( grow > 0) {497 if (options->grow > 0) { 174 498 bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading for psImageConvolveMask 175 psImage *newMask = psImageConvolveMask(NULL, readout->mask, crMask, crMask, -grow, grow, -grow,grow);499 psImage *newMask = psImageConvolveMask(NULL, readout->mask, options->crMask, options->crMask, -options->grow, options->grow, -options->grow, options->grow); 176 500 psImageConvolveSetThreads(oldThreads); 177 501 if (!newMask) { … … 183 507 } 184 508 185 psLogMsg ("psphot.size", PS_LOG_INFO, "measure source sizes for %ld sources: %f sec\n", 186 sources->n - first, psTimerMark ("psphot.size")); 187 188 psphotVisualPlotSourceSize (sources); 189 psphotVisualShowSourceSize (readout, sources); 190 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 527 bool 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 717 bool 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 734 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask); 735 736 // This attempt to mask the cosmic rays used the isophotal boundary 737 bool psphotMaskCosmicRay_V1 (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) { 738 739 // replace the source flux 740 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 741 742 // flag this as a CR 743 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 744 pmPeak *peak = source->peak; 745 psAssert (peak, "NULL peak"); 746 747 // grab the matching footprint 748 pmFootprint *footprint = peak->footprint; 749 if (!footprint) { 750 psTrace("psphot.czw",2,"Using isophot CR mask code."); 751 752 // if we have not footprint, use the old code to mask by isophot 753 psphotMaskCosmicRayIsophot (source, maskVal, crMask); 754 return true; 755 } 756 757 if (!footprint->spans) { 758 psTrace("psphot.czw",2,"Using isophot CR mask code."); 759 760 // if we have no footprint, use the old code to mask by isophot 761 psphotMaskCosmicRayIsophot (source, maskVal, crMask); 762 return true; 763 } 764 psphotMaskCosmicRayIsophot (source, maskVal, crMask); 765 // mask all of the pixels covered by the spans of the footprint 766 for (int j = 1; j < footprint->spans->n; j++) { 767 pmSpan *span1 = footprint->spans->data[j]; 768 769 int iy = span1->y; 770 int xs = span1->x0; 771 int xe = span1->x1; 772 773 for (int ix = xs; ix < xe; ix++) { 774 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask; 775 } 776 } 777 return true; 778 } 779 780 # define VERBOSE 0 781 int 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; 921 } 922 923 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) { 924 925 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 926 pmPeak *peak = source->peak; 927 psAssert (peak, "NULL peak"); 928 929 psImage *mask = source->maskView; 930 psImage *pixels = source->pixels; 931 psImage *variance = source->variance; 932 933 // XXX This should be a recipe variable 934 # define SN_LIMIT 5.0 935 936 int xo = peak->x - pixels->col0; 937 int yo = peak->y - pixels->row0; 938 939 // mark the pixels in this row to the left, then the right 940 for (int ix = xo; ix >= 0; ix--) { 941 float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]); 942 if (SN > SN_LIMIT) { 943 mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask; 944 } 945 } 946 for (int ix = xo + 1; ix < pixels->numCols; ix++) { 947 float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]); 948 if (SN > SN_LIMIT) { 949 mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask; 950 } 951 } 952 953 // for each of the neighboring rows, mark the high pixels if they have a marked neighbor 954 // first go up: 955 for (int iy = PS_MIN(yo, mask->numRows-2); iy >= 0; iy--) { 956 // mark the pixels in this row to the left, then the right 957 for (int ix = 0; ix < pixels->numCols; ix++) { 958 float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]); 959 if (SN < SN_LIMIT) continue; 960 961 bool valid = false; 962 valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix] & crMask); 963 valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix-1] & crMask) : 0; 964 valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix+1] & crMask) : 0; 965 966 if (!valid) continue; 967 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask; 968 } 969 } 970 // next go down: 971 for (int iy = PS_MIN(yo+1, mask->numRows-1); iy < pixels->numRows; iy++) { 972 // mark the pixels in this row to the left, then the right 973 for (int ix = 0; ix < pixels->numCols; ix++) { 974 float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]); 975 if (SN < SN_LIMIT) continue; 976 977 bool valid = false; 978 valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix] & crMask); 979 valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix-1] & crMask) : 0; 980 valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix+1] & crMask) : 0; 981 982 if (!valid) continue; 983 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask; 984 } 985 } 191 986 return true; 192 987 } … … 194 989 // given the PSF ellipse parameters, navigate around the 1sigma contour, return the total 195 990 // deviation in sigmas. This is measured on the residual image - should we ignore negative 196 // deviations? 197 static float psphotModelContour(const psImage *image, const psImage *variance, const psImage *mask, 198 psImageMaskType maskVal, const pmModel *model, float Ro) 991 // deviations? NOTE: This function was an early attempt to classify extended objects, and is 992 // no longer used by psphot. 993 float psphotModelContour(const psImage *image, const psImage *variance, const psImage *mask, 994 psImageMaskType maskVal, const pmModel *model, float Ro) 199 995 { 200 996 psF32 *PAR = model->params->data.F32; // Model parameters … … 265 1061 } 266 1062 267 bool psphotMaskCosmicRay_New (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) { 268 269 // replace the source flux 270 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 271 source->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED; 272 273 // flag this as a CR 274 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 275 pmPeak *peak = source->peak; 276 psAssert (peak, "NULL peak"); 277 278 // grab the matching footprint 279 pmFootprint *footprint = peak->footprint; 280 if (!footprint) { 281 // if we have not footprint, use the old code to mask by isophot 282 psphotMaskCosmicRay_Old (source, maskVal, crMask); 283 return true; 284 } 285 286 if (!footprint->spans) { 287 // if we have not footprint, use the old code to mask by isophot 288 psphotMaskCosmicRay_Old (source, maskVal, crMask); 289 return true; 290 } 291 292 // mask all of the pixels covered by the spans of the footprint 293 for (int j = 1; j < footprint->spans->n; j++) { 294 pmSpan *span1 = footprint->spans->data[j]; 295 296 int iy = span1->y; 297 int xs = span1->x0; 298 int xe = span1->x1; 299 300 for (int ix = xs; ix < xe; ix++) { 301 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask; 302 } 1063 // this was an old attempt to identify cosmic rays based on the peak curvature 1064 bool psphotSourcePeakCurvature (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) { 1065 1066 // classify the sources based on the CR test (place this in a function?) 1067 // XXX use an internal flag to mark sources which have already been measured 1068 for (int i = 0; i < sources->n; i++) { 1069 pmSource *source = sources->data[i]; 1070 1071 // skip source if it was already measured 1072 if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) { 1073 psTrace("psphot", 7, "Not calculating source size since it has already been measured\n"); 1074 continue; 1075 } 1076 1077 // source must have been subtracted 1078 if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) { 1079 source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED; 1080 psTrace("psphot", 7, "Not calculating source size since source is not subtracted\n"); 1081 continue; 1082 } 1083 1084 psF32 **resid = source->pixels->data.F32; 1085 psF32 **variance = source->variance->data.F32; 1086 psImageMaskType **mask = source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA; 1087 1088 // Integer position of peak 1089 int xPeak = source->peak->xf - source->pixels->col0 + 0.5; 1090 int yPeak = source->peak->yf - source->pixels->row0 + 0.5; 1091 1092 // Skip sources which are too close to a boundary. These are mostly caught as DEFECT 1093 if (xPeak < 1 || xPeak > source->pixels->numCols - 2 || 1094 yPeak < 1 || yPeak > source->pixels->numRows - 2) { 1095 psTrace("psphot", 7, "Not calculating crNsigma due to edge\n"); 1096 continue; 1097 } 1098 1099 // Skip sources with masked pixels. These are mostly caught as DEFECT 1100 bool keep = true; 1101 for (int iy = -1; (iy <= +1) && keep; iy++) { 1102 for (int ix = -1; (ix <= +1) && keep; ix++) { 1103 if (mask[yPeak+iy][xPeak+ix] & options->maskVal) { 1104 keep = false; 1105 } 1106 } 1107 } 1108 if (!keep) { 1109 psTrace("psphot", 7, "Not calculating crNsigma due to masked pixels\n"); 1110 continue; 1111 } 1112 1113 // Compare the central pixel with those on either side, for the four possible lines through it. 1114 1115 // Soften variances (add systematic error) 1116 float softening = options->soft * PS_SQR(source->peak->flux); // Softening for variances 1117 1118 // Across the middle: y = 0 1119 float cX = 2*resid[yPeak][xPeak] - resid[yPeak+0][xPeak-1] - resid[yPeak+0][xPeak+1]; 1120 float dcX = 4*variance[yPeak][xPeak] + variance[yPeak+0][xPeak-1] + variance[yPeak+0][xPeak+1]; 1121 float nX = cX / sqrtf(dcX + softening); 1122 1123 // Up the centre: x = 0 1124 float cY = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak+0] - resid[yPeak+1][xPeak+0]; 1125 float dcY = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak+0] + variance[yPeak+1][xPeak+0]; 1126 float nY = cY / sqrtf(dcY + softening); 1127 1128 // Diagonal: x = y 1129 float cL = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak-1] - resid[yPeak+1][xPeak+1]; 1130 float dcL = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak-1] + variance[yPeak+1][xPeak+1]; 1131 float nL = cL / sqrtf(dcL + softening); 1132 1133 // Diagonal: x = - y 1134 float cR = 2*resid[yPeak][xPeak] - resid[yPeak+1][xPeak-1] - resid[yPeak-1][xPeak+1]; 1135 float dcR = 4*variance[yPeak][xPeak] + variance[yPeak+1][xPeak-1] + variance[yPeak-1][xPeak+1]; 1136 float nR = cR / sqrtf(dcR + softening); 1137 1138 // P(chisq > chisq_obs; Ndof) = gamma_Q (Ndof/2, chisq/2) 1139 // Ndof = 4 ? (four measurements, no free parameters) 1140 // XXX this value is going to be biased low because of systematic errors. 1141 // we need to calibrate it somehow 1142 // source->psfProb = gsl_sf_gamma_inc_Q (2, 0.5*chisq); 1143 1144 // not strictly accurate: overcounts the chisq contribution from the center pixel (by 1145 // factor of 4); also biases a bit low if any pixels are masked 1146 // XXX I am not sure I want to keep this value... 1147 source->psfChisq = PS_SQR(nX) + PS_SQR(nY) + PS_SQR(nL) + PS_SQR(nR); 1148 1149 float fCR = 0.0; 1150 int nCR = 0; 1151 if (nX > 0.0) { 1152 fCR += nX; 1153 nCR ++; 1154 } 1155 if (nY > 0.0) { 1156 fCR += nY; 1157 nCR ++; 1158 } 1159 if (nL > 0.0) { 1160 fCR += nL; 1161 nCR ++; 1162 } 1163 if (nR > 0.0) { 1164 fCR += nR; 1165 nCR ++; 1166 } 1167 source->crNsigma = (nCR > 0) ? fCR / nCR : 0.0; 1168 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED; 1169 1170 if (!isfinite(source->crNsigma)) { 1171 continue; 1172 } 1173 1174 // this source is thought to be a cosmic ray. flag the detection and mask the pixels 1175 if (source->crNsigma > options->nSigmaCR) { 1176 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 1177 // XXX still testing... : psphotMaskCosmicRay (readout->mask, source, maskVal, crMask); 1178 // XXX acting strange... psphotMaskCosmicRay_Old (source, maskVal, crMask); 1179 } 1180 } 1181 1182 // now that we have masked pixels associated with CRs, we can grow the mask 1183 if (options->grow > 0) { 1184 bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading for psImageConvolveMask 1185 psImage *newMask = psImageConvolveMask(NULL, readout->mask, options->crMask, options->crMask, -options->grow, options->grow, -options->grow, options->grow); 1186 psImageConvolveSetThreads(oldThreads); 1187 if (!newMask) { 1188 psError(PS_ERR_UNKNOWN, false, "Unable to grow CR mask"); 1189 return false; 1190 } 1191 psFree(readout->mask); 1192 readout->mask = newMask; 303 1193 } 304 1194 return true; 305 1195 } 306 1196 307 bool psphotMaskCosmicRay_Old (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {308 309 source->mode |= PM_SOURCE_MODE_CR_LIMIT;310 pmPeak *peak = source->peak;311 psAssert (peak, "NULL peak");312 313 psImage *mask = source->maskView;314 psImage *pixels = source->pixels;315 psImage *variance = source->variance;316 317 // XXX This should be a recipe variable318 # define SN_LIMIT 5.0319 320 int xo = peak->x - pixels->col0;321 int yo = peak->y - pixels->row0;322 323 // mark the pixels in this row to the left, then the right324 for (int ix = xo; ix >= 0; ix--) {325 float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]);326 if (SN > SN_LIMIT) {327 mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask;328 }329 }330 for (int ix = xo + 1; ix < pixels->numCols; ix++) {331 float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]);332 if (SN > SN_LIMIT) {333 mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask;334 }335 }336 337 // for each of the neighboring rows, mark the high pixels if they have a marked neighbor338 // first go up:339 for (int iy = PS_MIN(yo, mask->numRows-2); iy >= 0; iy--) {340 // mark the pixels in this row to the left, then the right341 for (int ix = 0; ix < pixels->numCols; ix++) {342 float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]);343 if (SN < SN_LIMIT) continue;344 345 bool valid = false;346 valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix] & crMask);347 valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix-1] & crMask) : 0;348 valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix+1] & crMask) : 0;349 350 if (!valid) continue;351 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;352 }353 }354 // next go down:355 for (int iy = PS_MIN(yo+1, mask->numRows-1); iy < pixels->numRows; iy++) {356 // mark the pixels in this row to the left, then the right357 for (int ix = 0; ix < pixels->numCols; ix++) {358 float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]);359 if (SN < SN_LIMIT) continue;360 361 bool valid = false;362 valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix] & crMask);363 valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix-1] & crMask) : 0;364 valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix+1] & crMask) : 0;365 366 if (!valid) continue;367 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;368 }369 }370 return true;371 } -
branches/simtest_nebulous_branches/psphot/src/psphotSourceStats.c
r24589 r27840 1 1 # include "psphotInternal.h" 2 2 3 psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections) { 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. 7 bool 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 28 bool psphotSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe, bool setWindow) { 4 29 5 30 bool status = false; … … 8 33 psTimerStart ("psphot.stats"); 9 34 10 // select the appropriate recipe information 11 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE); 12 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 } 13 52 14 53 // determine the number of allowed threads … … 19 58 20 59 // determine properties (sky, moments) of initial sources 21 float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS"); 22 if (!status) return NULL; 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... 64 OUTER = PS_MAX(OUTER, 20.0); // XXX Guarantee that we can encompass the max moments radius 65 23 66 char *breakPt = psMetadataLookupStr (&status, recipe, "BREAK_POINT"); 24 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"); 25 79 26 80 psArray *peaks = detections->peaks; 27 81 if (!peaks) { 28 82 psError(PS_ERR_UNEXPECTED_NULL, false, "No peaks found!"); 29 return NULL;83 return false; 30 84 } 31 85 32 86 // generate the array of sources, define the associated pixel 33 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 } 34 96 35 97 for (int i = 0; i < peaks->n; i++) { … … 40 102 // create a new source 41 103 pmSource *source = pmSourceAlloc(); 104 source->imageID = index; 42 105 43 106 // add the peak … … 53 116 psArrayAdd (sources, 100, source); 54 117 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 230 bool 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; 55 268 } 56 269 … … 62 275 } 63 276 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; 281 } 282 64 283 // threaded measurement of the source magnitudes 65 284 int Nfail = 0; … … 82 301 psThreadJob *job = psThreadJobAlloc ("PSPHOT_SOURCE_STATS"); 83 302 303 // XXX: this must match the above 84 304 psArrayAdd(job->args, 1, cells->data[j]); // sources 85 305 psArrayAdd(job->args, 1, recipe); … … 136 356 137 357 psArray *sources = job->args->data[0]; 138 psMetadata *recipe = job->args->data[1]; 139 140 float INNER = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS"); 141 if (!status) return false; 142 float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); 143 if (!status) return false; 144 float RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS"); 145 if (!status) return false; 146 float MIN_PIXEL_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_MIN_PIXEL_SN"); 147 if (!status) return false; 148 float SIGMA = psMetadataLookupF32 (&status, recipe, "MOMENTS_GAUSS_SIGMA"); 149 if (!status) return false; 150 151 // bit-masks to test for good/bad pixels 152 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); 153 assert (maskVal); 154 155 // bit-mask to mark pixels not used in analysis 156 psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); 157 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); 158 366 159 367 // maskVal is used to test for rejected pixels, and must include markVal … … 166 374 for (int i = 0; i < sources->n; i++) { 167 375 pmSource *source = sources->data[i]; 376 377 if (source->tmpFlags & PM_SOURCE_TMPF_MOMENTS_MEASURED) continue; 378 source->tmpFlags |= PM_SOURCE_TMPF_MOMENTS_MEASURED; 168 379 169 380 // skip faint sources for moments measurement … … 194 405 } 195 406 196 // measure basic source moments 197 status = pmSourceMoments (source, RADIUS, SIGMA, MIN_PIXEL_SN);407 // measure basic source moments (no S/N clipping on input pixels) 408 status = pmSourceMoments (source, RADIUS, SIGMA, 0.0, maskVal); 198 409 if (status) { 199 410 Nmoments ++; … … 205 416 BIG_RADIUS = PS_MIN (INNER, 3*RADIUS); 206 417 psTrace ("psphot", 4, "retrying moments for %d, %d\n", source->peak->x, source->peak->y); 207 status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, MIN_PIXEL_SN);418 status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, 0.0, maskVal); 208 419 if (status) { 209 420 source->mode |= PM_SOURCE_MODE_BIG_RADIUS; … … 219 430 220 431 // change the value of a scalar on the array (wrap this and put it in psArray.h) 221 scalar = job->args->data[ 2];432 scalar = job->args->data[7]; 222 433 scalar->data.S32 = Nmoments; 223 434 224 scalar = job->args->data[ 3];435 scalar = job->args->data[8]; 225 436 scalar->data.S32 = Nfail; 226 437 227 scalar = job->args->data[ 4];438 scalar = job->args->data[9]; 228 439 scalar->data.S32 = Nfaint; 229 440 … … 231 442 } 232 443 233 # if (0) 234 bool psphotSourceStats_Unthreaded (int *nfail, int *nmoments, psArray *sources, psMetadata *recipe) { 235 236 bool status = false; 237 float BIG_RADIUS; 238 239 float INNER = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS"); 240 if (!status) return false; 241 float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); 242 if (!status) return false; 243 float RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS"); 244 if (!status) return false; 245 246 // bit-masks to test for good/bad pixels 247 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); 248 assert (maskVal); 249 250 // bit-mask to mark pixels not used in analysis 251 psImageMaskType markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); 252 assert (markVal); 253 254 // maskVal is used to test for rejected pixels, and must include markVal 255 maskVal |= markVal; 256 257 // threaded measurement of the sources moments 258 int Nfail = 0; 259 int Nmoments = 0; 260 for (int i = 0; i < sources->n; i++) { 261 pmSource *source = sources->data[i]; 262 263 // skip faint sources for moments measurement 264 if (source->peak->SN < MIN_SN) { 265 continue; 266 } 267 268 // measure a local sky value 269 // the local sky is now ignored; kept here for reference only 270 status = pmSourceLocalSky (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal); 271 if (!status) { 272 psErrorClear(); // XXX re-consider the errors raised here 273 Nfail ++; 274 continue; 275 } 276 277 // measure the local sky variance (needed if noise is not sqrt(signal)) 278 // XXX EAM : this should use ROBUST not SAMPLE median, but it is broken 279 status = pmSourceLocalSkyVariance (source, PS_STAT_SAMPLE_MEDIAN, INNER, maskVal, markVal); 280 if (!status) { 281 Nfail ++; 282 psErrorClear(); 283 continue; 284 } 285 286 // measure basic source moments 287 status = pmSourceMoments (source, RADIUS, SIGMA, MIN_PIXEL_SN); 288 if (status) { 289 Nmoments ++; 290 continue; 291 } 292 293 // if no valid pixels, or massive swing, likely saturated source, 294 // try a much larger box 295 BIG_RADIUS = PS_MIN (INNER, 3*RADIUS); 296 psTrace ("psphot", 4, "retrying moments for %d, %d\n", source->peak->x, source->peak->y); 297 status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, MIN_PIXEL_SN); 298 if (status) { 299 Nmoments ++; 300 continue; 301 } 302 303 Nfail ++; 304 psErrorClear(); 305 continue; 306 } 307 308 // change the value of a scalar on the array (wrap this and put it in psArray.h) 309 *nmoments = Nmoments; 310 *nfail = Nfail; 311 444 // 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 446 bool psphotSetMomentsWindow (psMetadata *recipe, psMetadata *analysis, psArray *sources) { 447 448 bool status; 449 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"); 453 454 // XXX move this to a config file? 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]; 458 459 // this sorts by peak->SN 460 sources = psArraySort (sources, pmSourceSortBySN); 461 462 // loop over radii: 463 for (int i = 0; i < NSIGMA; i++) { 464 465 // XXX move max source number to config 466 for (int j = 0; (j < sources->n) && (j < 400); j++) { 467 468 pmSource *source = sources->data[j]; 469 psAssert (source->moments, "force moments to exist"); 470 source->moments->nPixels = 0; 471 472 // skip faint sources for moments measurement 473 if (source->peak->SN < MIN_SN) { 474 continue; 475 } 476 477 // measure basic source moments (no S/N clipping on input pixels) 478 status = pmSourceMoments (source, 4*sigma[i], sigma[i], 0.0, 0xffff); 479 } 480 481 // choose a grid scale that is a fixed fraction of the psf sigma^2 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]); 485 486 // determine the PSF parameters from the source moment values 487 pmPSFClump psfClump = pmSourcePSFClump (NULL, NULL, sources, PSF_SN_LIM, PSF_CLUMP_GRID_SCALE, MOMENTS_SX_MAX, MOMENTS_SY_MAX, MOMENTS_AR_MAX); 488 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]); 489 490 psMetadataAddS32 (analysis, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS", PS_META_REPLACE, "psf clump regions", 1); 491 psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, "PSF.CLUMP.REGION.000"); 492 if (!regionMD) { 493 regionMD = psMetadataAlloc(); 494 psMetadataAddMetadata (analysis, PS_LIST_TAIL, "PSF.CLUMP.REGION.000", PS_META_REPLACE, "psf clump region", regionMD); 495 psFree (regionMD); 496 } 497 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X", PS_META_REPLACE, "psf clump center", psfClump.X); 498 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y", PS_META_REPLACE, "psf clump center", psfClump.Y); 499 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX); 500 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY); 501 502 psphotVisualPlotMoments (recipe, analysis, sources); 503 504 Sout[i] = sqrt(0.5*(psfClump.X + psfClump.Y)) / sigma[i]; 505 } 506 507 // we are looking for sigma for which Sout = 0.65 (or some other value) 508 float Sigma = NAN; 509 float minS = Sout[0]; 510 float maxS = Sout[0]; 511 for (int i = 0; i < NSIGMA; i++) { 512 minS = PS_MIN(Sout[i], minS); 513 maxS = PS_MAX(Sout[i], maxS); 514 } 515 if (minS > 0.65) Sigma = sigma[NSIGMA-1]; 516 if (maxS < 0.65) Sigma = sigma[0]; 517 518 for (int i = 0; i < NSIGMA - 1 && isnan(Sigma); i++) { 519 if (!isfinite(Sout[i]) || !isfinite(Sout[i+1])) continue; 520 if ((Sout[i] > 0.65) && (Sout[i+1] > 0.65)) continue; 521 if ((Sout[i] < 0.65) && (Sout[i+1] < 0.65)) continue; 522 Sigma = sigma[i] + (0.65 - Sout[i])*(sigma[i+1] - sigma[i])/(Sout[i+1] - Sout[i]); 523 } 524 psAssert (isfinite(Sigma), "did we miss a case?"); 525 526 // choose a grid scale that is a fixed fraction of the psf sigma^2 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); 532 533 psLogMsg ("psphot", 3, "using window function with sigma = %f\n", Sigma); 312 534 return true; 313 535 } 314 # endif 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/simtest_nebulous_branches/psphot/src/psphotSubtractBackground.c
r23287 r27840 4 4 // generate the median in NxN boxes, clipping heavily 5 5 // linear interpolation to generate full-scale model 6 bool psphotSubtractBackground (pmConfig *config, const pmFPAview *view, const char *filename)6 bool psphotSubtractBackgroundReadout (pmConfig *config, const pmFPAview *view, const char *filename, int index, psMetadata *recipe) 7 7 { 8 8 bool status = true; … … 13 13 14 14 // 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 16 17 pmFPA *inFPA = file->fpa; 17 18 pmReadout *readout = pmFPAviewThisReadout (view, inFPA); … … 19 20 psImage *mask = readout->mask; 20 21 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 } 23 32 assert (model); 24 25 // select the appropriate recipe information26 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, PSPHOT_RECIPE);27 assert (recipe);28 33 29 34 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) … … 35 40 36 41 // select background pixels, from output background file, or create 42 // XXX for now, we will only allow a single background image to be generated 37 43 file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKGND"); 38 44 if (file) { … … 66 72 67 73 // 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 68 75 file = psMetadataLookupPtr (&status, config->files, "PSPHOT.BACKSUB"); 69 76 if (file) { … … 109 116 // the pmReadout selected in this function are all view on entries in config->files 110 117 118 // display the backsub and backgnd images 119 // move this inthe the subtract background loop 120 psphotVisualShowBackground (config, view, readout); 121 111 122 npass ++; 112 123 return true; 113 124 } 125 126 bool 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/simtest_nebulous_branches/psphot/src/psphotVersion.c
r23805 r27840 30 30 psString psphotVersionLong(void) 31 31 { 32 psString version = ps LibVersion(); // Version, to return33 psString source = ps LibSource(); // Source32 psString version = psphotVersion(); // Version, to return 33 psString source = psphotSource(); // Source 34 34 35 35 psStringPrepend(&version, "psphot "); -
branches/simtest_nebulous_branches/psphot/src/psphotVisual.c
r24636 r27840 15 15 # include <kapa.h> 16 16 17 bool pmVisualLimitsFromVectors (Graphdata *graphdata, psVector *xVec, psVector *yVec); 18 17 19 // functions used to visualize the analysis as it goes 18 20 // these are invoked by the -visual options 19 21 20 static int kapa = -1;22 static int kapa1 = -1; 21 23 static int kapa2 = -1; 22 24 static int kapa3 = -1; 23 25 26 int psphotKapaChannel (int channel) { 27 28 switch (channel) { 29 case 1: 30 if (kapa1 == -1) { 31 kapa1 = KapaOpenNamedSocket ("kapa", "psphot:images"); 32 if (kapa1 == -1) { 33 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 34 pmVisualSetVisual(false); 35 } 36 } 37 return kapa1; 38 case 2: 39 if (kapa2 == -1) { 40 kapa2 = KapaOpenNamedSocket ("kapa", "psphot:plots"); 41 if (kapa2 == -1) { 42 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 43 pmVisualSetVisual(false); 44 } 45 } 46 return kapa2; 47 case 3: 48 if (kapa3 == -1) { 49 kapa3 = KapaOpenNamedSocket ("kapa", "psphot:stamps"); 50 if (kapa3 == -1) { 51 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 52 pmVisualSetVisual(false); 53 } 54 } 55 return kapa3; 56 default: 57 psAbort ("unknown kapa channel"); 58 } 59 psAbort ("unknown kapa channel"); 60 } 61 62 bool 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 } 24 75 25 76 bool psphotVisualShowMask (int kapaFD, psImage *inImage, const char *name, int channel) { … … 69 120 } 70 121 71 bool psphotVisualScaleImage (int kapaFD, psImage *inImage, const char *name, int channel) {122 bool psphotVisualScaleImage (int kapaFD, psImage *inImage, psImage *inMask, const char *name, int channel) { 72 123 73 124 KiiImage image; … … 79 130 psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 80 131 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); 81 if (!psImageBackground(stats, NULL, inImage, NULL, 0, rng)) {132 if (!psImageBackground(stats, NULL, inImage, inMask, 0xffff, rng)) { 82 133 fprintf (stderr, "failed to get background values\n"); 83 134 return false; … … 131 182 if (!pmVisualIsVisual()) return true; 132 183 133 if (kapa == -1) { 134 kapa = KapaOpenNamedSocket ("kapa", "psphot:images"); 135 if (kapa == -1) { 136 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 137 pmVisualSetVisual(false); 138 return false; 139 } 140 } 141 142 // psphotVisualShowMask (kapa, readout->mask, "mask", 2); 143 psphotVisualScaleImage (kapa, readout->variance, "variance", 1); 144 psphotVisualScaleImage (kapa, readout->image, "image", 0); 145 146 // pause and wait for user input: 147 // continue, save (provide name), ?? 148 char key[10]; 149 fprintf (stdout, "[c]ontinue? "); 150 if (!fgets(key, 8, stdin)) { 151 psWarning("Unable to read option"); 152 } 184 int kapa = psphotKapaChannel (1); 185 if (kapa == -1) return false; 186 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); 190 191 pmVisualAskUser(NULL); 153 192 return true; 154 193 } … … 160 199 if (!pmVisualIsVisual()) return true; 161 200 162 if (kapa == -1) { 163 kapa = KapaOpenNamedSocket ("kapa", "psphot:images"); 164 if (kapa == -1) { 165 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 166 pmVisualSetVisual(false); 167 return false; 168 } 169 } 201 int kapa = psphotKapaChannel (1); 202 if (kapa == -1) return false; 170 203 171 204 bool status = false; … … 178 211 } 179 212 180 psphotVisualScaleImage (kapa, backgnd->image, "backgnd", 2); 181 psphotVisualScaleImage (kapa, readout->image, "backsub", 0); 182 183 // pause and wait for user input: 184 // continue, save (provide name), ?? 185 char key[10]; 186 fprintf (stdout, "[c]ontinue? "); 187 if (!fgets(key, 8, stdin)) { 188 psWarning("Unable to read option"); 189 } 190 return true; 191 } 192 193 bool psphotVisualShowSignificance (psImage *image) { 213 psphotVisualScaleImage (kapa, backgnd->image, readout->mask, "backgnd", 2); 214 psphotVisualScaleImage (kapa, readout->image, readout->mask, "backsub", 0); 215 216 pmVisualAskUser(NULL); 217 return true; 218 } 219 220 bool psphotVisualShowSignificance (psImage *image, float min, float max) { 194 221 195 222 if (!pmVisualIsVisual()) return true; 196 223 197 if (kapa == -1) { 198 kapa = KapaOpenNamedSocket ("kapa", "psphot:images"); 199 if (kapa == -1) { 200 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 201 pmVisualSetVisual(false); 202 return false; 203 } 204 } 205 206 // XXX test: image->data.F32[10][10] = 10000; 207 psphotVisualRangeImage (kapa, image, "signif", 2, -1.0, 25.0*25.0); 208 209 // pause and wait for user input: 210 // continue, save (provide name), ?? 211 char key[10]; 212 fprintf (stdout, "[c]ontinue? "); 213 if (!fgets(key, 8, stdin)) { 214 psWarning("Unable to read option"); 215 } 224 int kapa = psphotKapaChannel (1); 225 if (kapa == -1) return false; 226 227 psphotVisualRangeImage (kapa, image, "signif", 2, min, max); 228 229 pmVisualAskUser(NULL); 216 230 return true; 217 231 } … … 224 238 if (!pmVisualIsVisual()) return true; 225 239 226 if (kapa == -1) { 227 fprintf (stderr, "kapa not opened, skipping\n"); 228 return false; 229 } 240 int kapa = psphotKapaChannel (1); 241 if (kapa == -1) return false; 230 242 231 243 psArray *peaks = detections->peaks; … … 233 245 // note: this uses the Ohana allocation tools: 234 246 // ALLOCATE (overlay, KiiOverlay, 3*peaks->n + 1); 235 ALLOCATE (overlay, KiiOverlay, peaks->n );247 ALLOCATE (overlay, KiiOverlay, peaks->n + 2); 236 248 237 249 Noverlay = 0; … … 249 261 overlay[Noverlay].text = NULL; 250 262 Noverlay ++; 251 252 # if (0) 253 overlay[Noverlay].type = KII_OVERLAY_BOX; 254 overlay[Noverlay].x = peak->x; 255 overlay[Noverlay].y = peak->y; 256 overlay[Noverlay].dx = 1.0; 257 overlay[Noverlay].dy = 1.0; 258 overlay[Noverlay].angle = 0.0; 259 overlay[Noverlay].text = NULL; 260 Noverlay ++; 261 262 overlay[Noverlay].type = KII_OVERLAY_CIRCLE; 263 overlay[Noverlay].x = peak->xf; 264 overlay[Noverlay].y = peak->yf; 265 overlay[Noverlay].dx = 2.0; 266 overlay[Noverlay].dy = 2.0; 267 overlay[Noverlay].angle = 0.0; 268 overlay[Noverlay].text = NULL; 269 Noverlay ++; 270 # endif 271 } 272 273 # if (0) 274 overlay[Noverlay].type = KII_OVERLAY_BOX; 275 overlay[Noverlay].x = 10.0; 276 overlay[Noverlay].y = 10.0; 277 overlay[Noverlay].dx = 0.5; 278 overlay[Noverlay].dy = 0.5; 279 overlay[Noverlay].angle = 0.0; 280 overlay[Noverlay].text = NULL; 281 Noverlay ++; 282 # endif 263 } 283 264 284 265 KiiLoadOverlay (kapa, overlay, Noverlay, "red"); 285 266 FREE (overlay); 286 267 287 // pause and wait for user input: 288 // continue, save (provide name), ?? 289 char key[10]; 290 fprintf (stdout, "[c]ontinue? "); 291 if (!fgets(key, 8, stdin)) { 292 psWarning("Unable to read option"); 293 } 268 pmVisualAskUser(NULL); 294 269 return true; 295 270 } … … 302 277 if (!pmVisualIsVisual()) return true; 303 278 304 if (kapa == -1) { 305 fprintf (stderr, "kapa not opened, skipping\n"); 306 return false; 307 } 279 int kapa = psphotKapaChannel (1); 280 if (kapa == -1) return false; 308 281 309 282 psArray *footprints = detections->footprints; … … 325 298 326 299 // draw the top 300 // XXX need to allow top (and bottom) to have more than one span 327 301 span = footprint->spans->data[0]; 328 302 overlay[Noverlay].type = KII_OVERLAY_LINE; … … 399 373 FREE (overlay); 400 374 401 // pause and wait for user input: 402 // continue, save (provide name), ?? 403 char key[10]; 404 fprintf (stdout, "[c]ontinue? "); 405 if (!fgets(key, 8, stdin)) { 406 psWarning("Unable to read option"); 407 } 375 pmVisualAskUser(NULL); 408 376 return true; 409 377 } … … 419 387 if (!pmVisualIsVisual()) return true; 420 388 421 if (kapa == -1) { 422 fprintf (stderr, "kapa not opened, skipping\n"); 423 return false; 424 } 389 int kapa = psphotKapaChannel (1); 390 if (kapa == -1) return false; 391 392 // XXX mark the different source classes with different color/shape dots 393 // XXX are moments S/N and peak S/N consistent? 425 394 426 395 // note: this uses the Ohana allocation tools: … … 448 417 overlay[Noverlay].dx = 2.0*axes.major; 449 418 overlay[Noverlay].dy = 2.0*axes.minor; 450 overlay[Noverlay].angle = -axes.theta * PS_DEG_RAD; // XXXXXXXX the axes angle is negative to display of object on kapa 419 420 overlay[Noverlay].angle = axes.theta * PS_DEG_RAD; 421 451 422 overlay[Noverlay].text = NULL; 452 423 Noverlay ++; … … 456 427 FREE (overlay); 457 428 458 // pause and wait for user input: 459 // continue, save (provide name), ?? 460 char key[10]; 461 fprintf (stdout, "[c]ontinue? "); 462 if (!fgets(key, 8, stdin)) { 463 psWarning("Unable to read option"); 464 } 465 466 return true; 467 } 468 469 bool psphotVisualPlotMoments (psMetadata *recipe, psArray *sources) { 429 pmVisualAskUser(NULL); 430 return true; 431 } 432 433 bool psphotVisualPlotMoments (psMetadata *recipe, psMetadata *analysis, psArray *sources) { 470 434 471 435 bool status; … … 475 439 if (!pmVisualIsVisual()) return true; 476 440 477 if (kapa3 == -1) { 478 kapa3 = KapaOpenNamedSocket ("kapa", "psphot:plots"); 479 if (kapa3 == -1) { 480 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 481 pmVisualSetVisual(false); 482 return false; 483 } 484 } 485 486 KapaClearPlots (kapa3); 441 int myKapa = psphotKapaChannel (2); 442 if (myKapa == -1) return false; 443 444 KapaClearPlots (myKapa); 487 445 KapaInitGraph (&graphdata); 488 KapaSetFont (kapa3, "courier", 14); 446 KapaSetFont (myKapa, "courier", 14); 447 448 section.bg = KapaColorByName ("none"); // XXX probably should be 'none' 489 449 490 450 float SN_LIM = psMetadataLookupF32(&status, recipe, "PSF_SN_LIM"); 491 451 492 452 // select the max psfX,Y values for the plot limits 493 float Xmin = 0.0, Xmax = 0.0;494 float Ymin = 0.0, Ymax = 0.0;453 float Xmin = 1000.0, Xmax = 0.0; 454 float Ymin = 1000.0, Ymax = 0.0; 495 455 { 496 int nRegions = psMetadataLookupS32 (&status, recipe, "PSF.CLUMP.NREGIONS");456 int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS"); 497 457 for (int n = 0; n < nRegions; n++) { 498 458 499 459 char regionName[64]; 500 460 snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n); 501 psMetadata *regionMD = psMetadataLookupPtr (&status, recipe, regionName);502 503 float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X");461 psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName); 462 463 float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); 504 464 float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y"); 505 465 float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX"); 506 466 float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY"); 507 467 508 float X0 = psfX - 4.0*psfdX; 509 float X1 = psfX + 4.0*psfdX; 510 float Y0 = psfY - 4.0*psfdY; 511 float Y1 = psfY + 4.0*psfdY; 512 513 if (isfinite(X0)) { Xmin = PS_MAX(Xmin, X0); } 514 if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); } 515 if (isfinite(Y0)) { Ymin = PS_MAX(Ymin, Y0); } 516 if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); } 517 } 518 } 468 float X0 = psfX - 4.0*psfdX; 469 float X1 = psfX + 4.0*psfdX; 470 float Y0 = psfY - 4.0*psfdY; 471 float Y1 = psfY + 4.0*psfdY; 472 473 if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); } 474 if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); } 475 if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); } 476 if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); } 477 } 478 } 479 Xmin = PS_MAX(Xmin, -0.1); 480 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; 519 485 520 486 // storage vectors for data to be plotted … … 564 530 section.y = 0.00; 565 531 section.name = psStringCopy ("MxxMyy"); 566 KapaSetSection ( kapa3, §ion);532 KapaSetSection (myKapa, §ion); 567 533 psFree (section.name); 568 534 … … 572 538 graphdata.xmax = Xmax; 573 539 graphdata.ymax = Ymax; 574 KapaSetLimits (kapa3, &graphdata); 575 576 KapaBox (kapa3, &graphdata); 577 KapaSendLabel (kapa3, "M_xx| (pixels)", KAPA_LABEL_XM); 578 KapaSendLabel (kapa3, "M_yy| (pixels)", KAPA_LABEL_YM); 540 KapaSetLimits (myKapa, &graphdata); 541 542 graphdata.padXm = NAN; 543 graphdata.padYm = NAN; 544 graphdata.padXp = 0.5; 545 graphdata.padYp = 0.5; 546 KapaBox (myKapa, &graphdata); 547 548 KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM); 549 KapaSendLabel (myKapa, "M_yy| (pixels)", KAPA_LABEL_YM); 579 550 580 551 graphdata.color = KapaColorByName ("black"); … … 582 553 graphdata.size = 0.3; 583 554 graphdata.style = 2; 584 KapaPrepPlot (kapa3, nF, &graphdata); 585 KapaPlotVector (kapa3, nF, xFaint->data.F32, "x"); 586 KapaPlotVector (kapa3, nF, yFaint->data.F32, "y"); 555 KapaPrepPlot (myKapa, nF, &graphdata); 556 557 KapaPlotVector (myKapa, nF, xFaint->data.F32, "x"); 558 KapaPlotVector (myKapa, nF, yFaint->data.F32, "y"); 587 559 588 560 graphdata.color = KapaColorByName ("red"); … … 590 562 graphdata.size = 0.5; 591 563 graphdata.style = 2; 592 KapaPrepPlot ( kapa3, nB, &graphdata);593 KapaPlotVector ( kapa3, nB, xBright->data.F32, "x");594 KapaPlotVector ( kapa3, nB, yBright->data.F32, "y");564 KapaPrepPlot (myKapa, nB, &graphdata); 565 KapaPlotVector (myKapa, nB, xBright->data.F32, "x"); 566 KapaPlotVector (myKapa, nB, yBright->data.F32, "y"); 595 567 596 568 // second section: MagMyy … … 598 570 section.dy = 0.25; 599 571 section.x = 0.00; 600 section.y = 0. 80;572 section.y = 0.75; 601 573 section.name = psStringCopy ("MagMyy"); 602 KapaSetSection ( kapa3, §ion);574 KapaSetSection (myKapa, §ion); 603 575 psFree (section.name); 604 576 … … 608 580 graphdata.ymin = Ymin; 609 581 graphdata.ymax = Ymax; 610 KapaSetLimits (kapa3, &graphdata); 611 582 KapaSetLimits (myKapa, &graphdata); 583 584 graphdata.padXm = 0.5; 585 graphdata.padYm = NAN; 586 graphdata.padXp = NAN; 587 graphdata.padYp = 0.5; 612 588 strcpy (graphdata.labels, "0210"); 613 KapaBox ( kapa3, &graphdata);614 KapaSendLabel ( kapa3, "inst mag", KAPA_LABEL_XP);615 KapaSendLabel ( kapa3, "M_yy| (pixels)", KAPA_LABEL_YM);589 KapaBox (myKapa, &graphdata); 590 KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_XP); 591 KapaSendLabel (myKapa, "M_yy| (pixels)", KAPA_LABEL_YM); 616 592 617 593 graphdata.color = KapaColorByName ("black"); … … 619 595 graphdata.size = 0.3; 620 596 graphdata.style = 2; 621 KapaPrepPlot ( kapa3, nF, &graphdata);622 KapaPlotVector ( kapa3, nF, mFaint->data.F32, "x");623 KapaPlotVector ( kapa3, nF, yFaint->data.F32, "y");597 KapaPrepPlot (myKapa, nF, &graphdata); 598 KapaPlotVector (myKapa, nF, mFaint->data.F32, "x"); 599 KapaPlotVector (myKapa, nF, yFaint->data.F32, "y"); 624 600 625 601 graphdata.color = KapaColorByName ("red"); … … 627 603 graphdata.size = 0.5; 628 604 graphdata.style = 2; 629 KapaPrepPlot ( kapa3, nB, &graphdata);630 KapaPlotVector ( kapa3, nB, mBright->data.F32, "x");631 KapaPlotVector ( kapa3, nB, yBright->data.F32, "y");605 KapaPrepPlot (myKapa, nB, &graphdata); 606 KapaPlotVector (myKapa, nB, mBright->data.F32, "x"); 607 KapaPlotVector (myKapa, nB, yBright->data.F32, "y"); 632 608 633 609 // third section: MagMxx 634 610 section.dx = 0.25; 635 611 section.dy = 0.75; 636 section.x = 0. 80;612 section.x = 0.75; 637 613 section.y = 0.00; 638 614 section.name = psStringCopy ("MagMxx"); 639 KapaSetSection ( kapa3, §ion);615 KapaSetSection (myKapa, §ion); 640 616 psFree (section.name); 641 617 … … 645 621 graphdata.ymin = -7.9; 646 622 graphdata.ymax = -17.1; 647 KapaSetLimits (kapa3, &graphdata); 648 623 KapaSetLimits (myKapa, &graphdata); 624 625 graphdata.padXm = NAN; 626 graphdata.padYm = 0.5; 627 graphdata.padXp = 0.5; 628 graphdata.padYp = NAN; 649 629 strcpy (graphdata.labels, "2001"); 650 KapaBox ( kapa3, &graphdata);651 KapaSendLabel ( kapa3, "M_xx| (pixels)", KAPA_LABEL_XM);652 KapaSendLabel ( kapa3, "inst mag", KAPA_LABEL_YP);630 KapaBox (myKapa, &graphdata); 631 KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM); 632 KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_YP); 653 633 654 634 graphdata.color = KapaColorByName ("black"); … … 656 636 graphdata.size = 0.3; 657 637 graphdata.style = 2; 658 KapaPrepPlot ( kapa3, nF, &graphdata);659 KapaPlotVector ( kapa3, nF, xFaint->data.F32, "x");660 KapaPlotVector ( kapa3, nF, mFaint->data.F32, "y");638 KapaPrepPlot (myKapa, nF, &graphdata); 639 KapaPlotVector (myKapa, nF, xFaint->data.F32, "x"); 640 KapaPlotVector (myKapa, nF, mFaint->data.F32, "y"); 661 641 662 642 graphdata.color = KapaColorByName ("red"); … … 664 644 graphdata.size = 0.5; 665 645 graphdata.style = 2; 666 KapaPrepPlot ( kapa3, nB, &graphdata);667 KapaPlotVector ( kapa3, nB, xBright->data.F32, "x");668 KapaPlotVector ( kapa3, nB, mBright->data.F32, "y");646 KapaPrepPlot (myKapa, nB, &graphdata); 647 KapaPlotVector (myKapa, nB, xBright->data.F32, "x"); 648 KapaPlotVector (myKapa, nB, mBright->data.F32, "y"); 669 649 670 650 // draw N circles to outline the clumps 671 651 { 672 KapaSelectSection ( kapa3, "MxxMyy");652 KapaSelectSection (myKapa, "MxxMyy"); 673 653 674 654 // draw a circle centered on psfX,Y with size of the psf limit … … 676 656 psVector *yLimit = psVectorAlloc (120, PS_TYPE_F32); 677 657 678 int nRegions = psMetadataLookupS32 (&status, recipe, "PSF.CLUMP.NREGIONS");658 int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS"); 679 659 float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA"); 680 660 … … 682 662 graphdata.style = 0; 683 663 684 graphdata.xmin = Xmin;685 graphdata.ymin = Ymin;686 graphdata.xmax = Xmax;687 graphdata.ymax = Ymax;688 KapaSetLimits (kapa3, &graphdata);664 graphdata.xmin = Xmin; 665 graphdata.ymin = Ymin; 666 graphdata.xmax = Xmax; 667 graphdata.ymax = Ymax; 668 KapaSetLimits (myKapa, &graphdata); 689 669 690 670 for (int n = 0; n < nRegions; n++) { … … 692 672 char regionName[64]; 693 673 snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n); 694 psMetadata *regionMD = psMetadataLookupPtr (&status, recipe, regionName);674 psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName); 695 675 696 676 float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); … … 705 685 yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY; 706 686 } 707 KapaPrepPlot ( kapa3, xLimit->n, &graphdata);708 KapaPlotVector ( kapa3, xLimit->n, xLimit->data.F32, "x");709 KapaPlotVector ( kapa3, yLimit->n, yLimit->data.F32, "y");687 KapaPrepPlot (myKapa, xLimit->n, &graphdata); 688 KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x"); 689 KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y"); 710 690 } 711 691 psFree (xLimit); 712 692 psFree (yLimit); 713 693 } 714 715 # if (0)716 // *** make a histogram of the source counts in the x and y directions717 psHistogram *nX = psHistogramAlloc (graphdata.xmin, graphdata.xmax, 50.0);718 psHistogram *nY = psHistogramAlloc (graphdata.ymin, graphdata.ymax, 50.0);719 psVectorHistogram (nX, xFaint, NULL, NULL, 0);720 psVectorHistogram (nY, yFaint, NULL, NULL, 0);721 psVector *dX = psVectorAlloc (nX->nums->n, PS_TYPE_F32);722 psVector *vX = psVectorAlloc (nX->nums->n, PS_TYPE_F32);723 psVector *dY = psVectorAlloc (nY->nums->n, PS_TYPE_F32);724 psVector *vY = psVectorAlloc (nY->nums->n, PS_TYPE_F32);725 for (int i = 0; i < nX->nums->n; i++) {726 dX->data.F32[i] = nX->nums->data.S32[i];727 vX->data.F32[i] = 0.5*(nX->bounds->data.F32[i] + nX->bounds->data.F32[i+1]);728 }729 for (int i = 0; i < nY->nums->n; i++) {730 dY->data.F32[i] = nY->nums->data.S32[i];731 vY->data.F32[i] = 0.5*(nY->bounds->data.F32[i] + nY->bounds->data.F32[i+1]);732 }733 734 graphdata.color = KapaColorByName ("black");735 graphdata.ptype = 0;736 graphdata.size = 0.0;737 graphdata.style = 0;738 KapaPrepPlot (kapa3, dX->n, &graphdata);739 KapaPlotVector (kapa3, dX->n, dX->data.F32, "x");740 KapaPlotVector (kapa3, vX->n, vX->data.F32, "y");741 742 psFree (nX);743 psFree (dX);744 psFree (vX);745 746 psFree (nY);747 psFree (dY);748 psFree (vY);749 # endif750 694 751 695 psFree (xBright); … … 756 700 psFree (mFaint); 757 701 758 // pause and wait for user input: 759 // continue, save (provide name), ?? 760 char key[10]; 761 fprintf (stdout, "[c]ontinue? "); 762 if (!fgets(key, 8, stdin)) { 763 psWarning("Unable to read option"); 764 } 702 pmVisualAskUser(NULL); 765 703 return true; 766 704 } 767 705 768 706 // assumes 'kapa' value is checked and set 769 bool psphotVisualShowRoughClass_Single ( psArray *sources, pmSourceType type, pmSourceMode mode, char *color) {707 bool psphotVisualShowRoughClass_Single (int myKapa, psArray *sources, pmSourceType type, pmSourceMode mode, char *color) { 770 708 771 709 int Noverlay; … … 802 740 overlay[Noverlay].dx = 2.0*axes.major; 803 741 overlay[Noverlay].dy = 2.0*axes.minor; 804 overlay[Noverlay].angle = -axes.theta * PS_DEG_RAD;742 overlay[Noverlay].angle = axes.theta * PS_DEG_RAD; 805 743 overlay[Noverlay].text = NULL; 806 744 Noverlay ++; 807 745 } 808 746 809 KiiLoadOverlay ( kapa, overlay, Noverlay, color);747 KiiLoadOverlay (myKapa, overlay, Noverlay, color); 810 748 FREE (overlay); 811 749 … … 817 755 if (!pmVisualIsVisual()) return true; 818 756 819 if (kapa == -1) { 820 fprintf (stderr, "kapa not opened, skipping\n"); 821 return false; 822 } 823 824 KiiEraseOverlay (kapa, "yellow"); // moments 825 826 psphotVisualShowRoughClass_Single (sources, PM_SOURCE_TYPE_STAR, 0, "red"); 827 psphotVisualShowRoughClass_Single (sources, PM_SOURCE_TYPE_EXTENDED, 0, "blue"); 828 psphotVisualShowRoughClass_Single (sources, PM_SOURCE_TYPE_DEFECT, 0, "blue"); 829 psphotVisualShowRoughClass_Single (sources, PM_SOURCE_TYPE_SATURATED, 0, "red"); 830 psphotVisualShowRoughClass_Single (sources, PM_SOURCE_TYPE_STAR, PM_SOURCE_MODE_PSFSTAR, "yellow"); 831 psphotVisualShowRoughClass_Single (sources, PM_SOURCE_TYPE_STAR, PM_SOURCE_MODE_SATSTAR, "green"); 832 833 // pause and wait for user input: 834 // continue, save (provide name), ?? 835 char key[10]; 757 int myKapa = psphotKapaChannel (1); 758 if (myKapa == -1) return false; 759 760 KiiEraseOverlay (myKapa, "yellow"); // moments 761 762 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_STAR, 0, "red"); 763 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_EXTENDED, 0, "blue"); 764 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_DEFECT, 0, "blue"); 765 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_SATURATED, 0, "red"); 766 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_STAR, PM_SOURCE_MODE_PSFSTAR, "yellow"); 767 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_STAR, PM_SOURCE_MODE_SATSTAR, "green"); 768 836 769 fprintf (stdout, "red: STAR or SAT AREA; blue: EXTENDED or DEFECT; green: SATSTAR; yellow: PSFSTAR\n"); 837 fprintf (stdout, "[c]ontinue? "); 838 if (!fgets(key, 8, stdin)) { 839 psWarning("Unable to read option"); 840 } 770 pmVisualAskUser(NULL); 841 771 return true; 842 772 } … … 846 776 if (!pmVisualIsVisual()) return true; 847 777 848 if (kapa2 == -1) { 849 kapa2 = KapaOpenNamedSocket ("kapa", "psphot:psfstars"); 850 if (kapa2 == -1) { 851 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 852 pmVisualSetVisual(false); 853 return false; 854 } 855 } 778 int myKapa = psphotKapaChannel (3); 779 if (myKapa == -1) return false; 856 780 857 781 int DX = 64; … … 898 822 899 823 psImage *psfLogFlux = (psImage *) psUnaryOp (NULL, psfMosaic, "log"); 900 psphotVisualRangeImage ( kapa2, psfLogFlux, "psf_mosaic", 0, -2.0, 3.0);901 psphotVisualRangeImage ( kapa2, funMosaic, "psf_analytical", 1, -10.0, 100.0);902 psphotVisualRangeImage ( kapa2, resMosaic, "psf_residual", 2, -10.0, 100.0);824 psphotVisualRangeImage (myKapa, psfLogFlux, "psf_mosaic", 0, -2.0, 3.0); 825 psphotVisualRangeImage (myKapa, funMosaic, "psf_analytical", 1, -10.0, 100.0); 826 psphotVisualRangeImage (myKapa, resMosaic, "psf_residual", 2, -10.0, 100.0); 903 827 904 828 psFree (psfMosaic); … … 908 832 psFree (modelRef); 909 833 910 // pause and wait for user input: 911 // continue, save (provide name), ?? 912 char key[10]; 913 fprintf (stdout, "[c]ontinue? "); 914 if (!fgets(key, 8, stdin)) { 915 psWarning("Unable to read option"); 916 } 834 pmVisualAskUser(NULL); 917 835 return true; 918 836 } … … 924 842 if (!pmVisualIsVisual()) return true; 925 843 926 if (kapa2 == -1) { 927 kapa2 = KapaOpenNamedSocket ("kapa", "psphot:psfstars"); 928 if (kapa2 == -1) { 929 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 930 pmVisualSetVisual(false); 931 return false; 932 } 933 } 844 int myKapa = psphotKapaChannel (3); 845 if (myKapa == -1) return false; 934 846 935 847 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) … … 1017 929 if (Xo == 0) { 1018 930 // place source alone on this row 1019 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 931 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 932 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1020 933 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true); 1021 934 1022 p sphotSubWithTest (source, false, maskVal); // remove source (force)935 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1023 936 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true); 1024 psphotSetState (source, false, maskVal); // reset source Add/Sub state to recorded 937 938 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1025 939 1026 940 Yo += DY; … … 1032 946 Xo = 0; 1033 947 1034 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 948 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 949 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1035 950 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true); 1036 951 1037 p sphotSubWithTest (source, false, maskVal); // remove source (force)952 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1038 953 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true); 1039 psphotSetState (source, false, maskVal); // replace source (has been subtracted) 954 955 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1040 956 1041 957 Xo = DX; … … 1044 960 } else { 1045 961 // extend this row 1046 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 962 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 963 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1047 964 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true); 1048 965 1049 p sphotSubWithTest (source, false, maskVal); // remove source (force)966 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1050 967 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true); 1051 psphotSetState (source, false, maskVal); // replace source (has been subtracted)968 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1052 969 1053 970 Xo += DX; … … 1056 973 } 1057 974 1058 psphotVisualRangeImage (kapa2, outpos, "psfpos", 0, -0.05, 0.95); 1059 psphotVisualRangeImage (kapa2, outsub, "psfsub", 1, -0.05, 0.95); 1060 1061 // pause and wait for user input: 1062 // continue, save (provide name), ?? 1063 char key[10]; 1064 fprintf (stdout, "[c]ontinue? "); 1065 if (!fgets(key, 8, stdin)) { 1066 psWarning("Unable to read option"); 1067 } 1068 975 psphotVisualRangeImage (myKapa, outpos, "psfpos", 0, -0.05, 0.95); 976 psphotVisualRangeImage (myKapa, outsub, "psfsub", 1, -0.05, 0.95); 977 978 pmVisualAskUser(NULL); 1069 979 psFree (outpos); 1070 980 psFree (outsub); … … 1084 994 if (!pmVisualIsVisual()) return true; 1085 995 1086 if (kapa2 == -1) { 1087 kapa2 = KapaOpenNamedSocket ("kapa", "psphot:images"); 1088 if (kapa2 == -1) { 1089 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 1090 pmVisualSetVisual(false); 1091 return false; 1092 } 1093 } 996 int myKapa = psphotKapaChannel (3); 997 if (myKapa == -1) return false; 1094 998 1095 999 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) … … 1119 1023 pmSource *source = sources->data[i]; 1120 1024 1121 bool keep = false;1122 keep |= (source->mode & PM_SOURCE_MODE_SATSTAR);1123 if ( !keep) continue;1025 // only show "real" saturated stars (not defects) 1026 if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;; 1027 if (source->mode & PM_SOURCE_MODE_DEFECT) continue;; 1124 1028 1125 1029 // how does this subimage get placed into the output image? … … 1164 1068 pmSource *source = sources->data[i]; 1165 1069 1166 bool keep = false; 1167 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 1168 nSAT ++; 1169 keep = true; 1170 } 1171 if (!keep) continue; 1070 // only show "real" saturated stars (not defects) 1071 if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;; 1072 if (source->mode & PM_SOURCE_MODE_DEFECT) continue;; 1073 nSAT ++; 1172 1074 1173 1075 if (Xo + DX > NX) { … … 1175 1077 if (Xo == 0) { 1176 1078 // place source alone on this row 1177 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 1079 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 1080 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1178 1081 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false); 1179 psphotSetState (source, true, maskVal); // reset source Add/Sub state to recorded1082 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1180 1083 1181 1084 Yo += DY; … … 1186 1089 Yo += dY; 1187 1090 Xo = 0; 1188 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 1091 1092 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 1093 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1189 1094 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false); 1190 psphotSetState (source, true, maskVal); // replace source (has been subtracted)1095 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1191 1096 1192 1097 Xo = DX; … … 1195 1100 } else { 1196 1101 // extend this row 1197 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 1102 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 1103 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1198 1104 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false); 1199 psphotSetState (source, true, maskVal); // replace source (has been subtracted)1105 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1200 1106 1201 1107 Xo += DX; … … 1204 1110 } 1205 1111 1206 psphotVisualScaleImage (kapa2, outsat, "satstar", 2); 1207 1208 // pause and wait for user input: 1209 // continue, save (provide name), ?? 1210 char key[10]; 1211 fprintf (stdout, "[c]ontinue? "); 1212 if (!fgets(key, 8, stdin)) { 1213 psWarning("Unable to read option"); 1214 } 1215 1112 psphotVisualScaleImage (myKapa, outsat, NULL, "satstar", 2); 1113 1114 pmVisualAskUser(NULL); 1216 1115 psFree (outsat); 1217 1116 return true; 1218 1117 } 1219 1118 1119 static 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"); 1129 } 1130 1220 1131 bool psphotVisualPlotRadialProfile (int myKapa, pmSource *source, psImageMaskType maskVal) { 1221 1132 1222 1133 Graphdata graphdata; 1223 1134 1224 bool s tate = !(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);1225 psphotAddWithTest (source, true, maskVal); // replace source if subtracted1135 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 1136 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1226 1137 1227 1138 int nPts = source->pixels->numRows * source->pixels->numCols; … … 1240 1151 for (int ix = 0; ix < source->pixels->numCols; ix++) { 1241 1152 if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) { 1242 //rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;1243 rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ;1153 rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ; 1154 // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ; 1244 1155 Rb->data.F32[nb] = log10(rb->data.F32[nb]); 1245 1156 fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]); 1246 1157 nb++; 1247 1158 } else { 1248 //rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ;1249 rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ;1159 rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ; 1160 // rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ; 1250 1161 Rg->data.F32[ng] = log10(rg->data.F32[ng]); 1251 1162 fg->data.F32[ng] = log10(source->pixels->data.F32[iy][ix]); … … 1255 1166 } 1256 1167 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 1257 1228 // reset source Add/Sub state to recorded 1258 psphotSetState (source, state, maskVal);1229 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1259 1230 1260 1231 KapaInitGraph (&graphdata); … … 1291 1262 KapaPlotVector (myKapa, nb, fb->data.F32, "y"); 1292 1263 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 1293 1293 // ** loglog ** 1294 1294 KapaSelectSection (myKapa, "loglog"); … … 1299 1299 graphdata.ymin = -0.05; 1300 1300 graphdata.ymax = +5.05; 1301 graphdata.color = KapaColorByName ("black"); 1301 1302 KapaSetLimits (myKapa, &graphdata); 1302 1303 … … 1321 1322 KapaPlotVector (myKapa, nb, Rb->data.F32, "x"); 1322 1323 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); 1323 1344 1324 1345 psFree (rg); … … 1337 1358 if (!pmVisualIsVisual()) return true; 1338 1359 1339 if (kapa3 == -1) { 1340 kapa3 = KapaOpenNamedSocket ("kapa", "psphot:plots"); 1341 if (kapa3 == -1) { 1342 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 1343 pmVisualSetVisual(false); 1344 return false; 1345 } 1346 } 1360 int myKapa = psphotKapaChannel (2); 1361 if (myKapa == -1) return false; 1347 1362 1348 1363 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) … … 1351 1366 assert (maskVal); 1352 1367 1353 KapaClearPlots (kapa3); 1368 section.bg = KapaColorByName ("none"); // XXX probably should be 'none' 1369 1370 KapaClearPlots (myKapa); 1354 1371 // first section : mag vs CR nSigma 1355 1372 section.dx = 1.0; … … 1359 1376 section.name = NULL; 1360 1377 psStringAppend (§ion.name, "linlog"); 1361 KapaSetSection ( kapa3, §ion);1378 KapaSetSection (myKapa, §ion); 1362 1379 psFree (section.name); 1363 1380 … … 1369 1386 section.name = NULL; 1370 1387 psStringAppend (§ion.name, "loglog"); 1371 KapaSetSection ( kapa3, §ion);1388 KapaSetSection (myKapa, §ion); 1372 1389 psFree (section.name); 1373 1390 … … 1378 1395 if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue; 1379 1396 1380 psphotVisualPlotRadialProfile ( kapa3, source, maskVal);1397 psphotVisualPlotRadialProfile (myKapa, source, maskVal); 1381 1398 1382 1399 // pause and wait for user input: … … 1388 1405 } 1389 1406 if (key[0] == 'e') { 1390 KapaClearPlots ( kapa3);1407 KapaClearPlots (myKapa); 1391 1408 } 1392 1409 if (key[0] == 's') { … … 1407 1424 psEllipseAxes axes; 1408 1425 1426 // XXX skip this for now: it is not very clear 1427 return true; 1428 1409 1429 if (!pmVisualIsVisual()) return true; 1410 1430 1411 if (kapa == -1) { 1412 fprintf (stderr, "kapa not opened, skipping\n"); 1413 return false; 1414 } 1431 int myKapa = psphotKapaChannel (1); 1432 if (myKapa == -1) return false; 1415 1433 1416 1434 // note: this uses the Ohana allocation tools: … … 1485 1503 } 1486 1504 1487 KiiLoadOverlay ( kapa, overlayE, NoverlayE, "red");1488 KiiLoadOverlay ( kapa, overlayO, NoverlayO, "yellow");1505 KiiLoadOverlay (myKapa, overlayE, NoverlayE, "red"); 1506 KiiLoadOverlay (myKapa, overlayO, NoverlayO, "yellow"); 1489 1507 FREE (overlayE); 1490 1508 FREE (overlayO); 1491 1509 1492 // pause and wait for user input:1493 // continue, save (provide name), ??1494 char key[10];1495 1510 fprintf (stdout, "even bits (0x0001, 0x0004, ... : red\n"); 1496 1511 fprintf (stdout, "odd bits (0x0002, 0x0008, ... : yellow\n"); 1497 fprintf (stdout, "[c]ontinue? "); 1498 if (!fgets(key, 8, stdin)) { 1499 psWarning("Unable to read option"); 1500 } 1501 1502 return true; 1503 } 1504 1505 bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources) { 1506 1507 int Noverlay, NOVERLAY; 1512 pmVisualAskUser(NULL); 1513 1514 return true; 1515 } 1516 1517 bool psphotVisualShowSourceSize_Single (int myKapa, psArray *sources, pmSourceMode mode, bool keep, float scale, char *color) { 1518 1519 int Noverlay; 1508 1520 KiiOverlay *overlay; 1509 1521 1510 if (!pmVisualIsVisual()) return true; 1511 1512 if (kapa == -1) { 1513 fprintf (stderr, "kapa not opened, skipping\n"); 1514 return false; 1515 } 1522 psEllipseMoments emoments; 1523 psEllipseAxes axes; 1516 1524 1517 1525 // note: this uses the Ohana allocation tools: 1526 ALLOCATE (overlay, KiiOverlay, sources->n); 1527 1518 1528 Noverlay = 0; 1519 NOVERLAY = 100;1520 ALLOCATE (overlay, KiiOverlay, sources->n);1521 1522 // mark CRs with red boxes1523 1529 for (int i = 0; i < sources->n; i++) { 1524 1530 … … 1526 1532 if (source == NULL) continue; 1527 1533 1528 if (!(source->mode & PM_SOURCE_MODE_CR_LIMIT)) continue; 1529 1530 overlay[Noverlay].type = KII_OVERLAY_BOX; 1531 overlay[Noverlay].x = source->peak->xf; 1532 overlay[Noverlay].y = source->peak->yf; 1533 1534 overlay[Noverlay].dx = 4; 1535 overlay[Noverlay].dy = 4; 1536 overlay[Noverlay].angle = 0; 1534 if (mode) { 1535 if (keep) { 1536 if (!(source->mode & mode)) continue; 1537 } else { 1538 if (source->mode & mode) continue; 1539 } 1540 } 1541 1542 pmMoments *moments = source->moments; 1543 if (moments == NULL) continue; 1544 1545 overlay[Noverlay].type = KII_OVERLAY_CIRCLE; 1546 overlay[Noverlay].x = moments->Mx; 1547 overlay[Noverlay].y = moments->My; 1548 1549 emoments.x2 = moments->Mxx; 1550 emoments.y2 = moments->Myy; 1551 emoments.xy = moments->Mxy; 1552 1553 axes = psEllipseMomentsToAxes (emoments, 20.0); 1554 1555 overlay[Noverlay].dx = scale*2.0*axes.major; 1556 overlay[Noverlay].dy = scale*2.0*axes.minor; 1557 overlay[Noverlay].angle = axes.theta * PS_DEG_RAD; 1537 1558 overlay[Noverlay].text = NULL; 1538 1559 Noverlay ++; 1539 CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100); 1540 } 1541 KiiLoadOverlay (kapa, overlay, Noverlay, "red"); 1542 1543 1544 Noverlay = 0; 1545 for (int i = 0; i < sources->n; i++) { 1546 1547 pmSource *source = sources->data[i]; 1548 if (source == NULL) continue; 1549 1550 // mark EXTs with yellow circles 1551 if (!(source->mode & PM_SOURCE_MODE_EXT_LIMIT)) continue; 1552 1553 overlay[Noverlay].type = KII_OVERLAY_CIRCLE; 1554 overlay[Noverlay].x = source->peak->xf; 1555 overlay[Noverlay].y = source->peak->yf; 1556 1557 overlay[Noverlay].dx = 10; 1558 overlay[Noverlay].dy = 10; 1559 overlay[Noverlay].angle = 0; 1560 overlay[Noverlay].text = NULL; 1561 Noverlay ++; 1562 CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100); 1563 } 1564 1565 KiiLoadOverlay (kapa, overlay, Noverlay, "blue"); 1560 } 1561 1562 KiiLoadOverlay (myKapa, overlay, Noverlay, color); 1566 1563 FREE (overlay); 1567 1564 1568 psphotVisualShowMask (kapa, readout->mask, "mask", 2); 1569 1570 // pause and wait for user input: 1571 // continue, save (provide name), ?? 1572 char key[10]; 1573 fprintf (stdout, "CR: 4pix red BOX; EXT: 10pix blue circle\n"); 1574 fprintf (stdout, "[c]ontinue? "); 1575 if (!fgets(key, 8, stdin)) { 1576 psWarning("Unable to read option"); 1577 } 1578 1579 return true; 1580 } 1581 1582 bool psphotVisualPlotSourceSize (psArray *sources) { 1583 1565 return true; 1566 } 1567 1568 bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources) { 1569 1570 if (!pmVisualIsVisual()) return true; 1571 1572 int myKapa = psphotKapaChannel (1); 1573 if (myKapa == -1) return false; 1574 1575 KiiEraseOverlay (myKapa, "red"); 1576 KiiEraseOverlay (myKapa, "blue"); 1577 KiiEraseOverlay (myKapa, "green"); 1578 KiiEraseOverlay (myKapa, "yellow"); 1579 1580 psphotVisualShowSourceSize_Single (myKapa, sources, PM_SOURCE_MODE_EXT_LIMIT | PM_SOURCE_MODE_DEFECT | PM_SOURCE_MODE_CR_LIMIT | PM_SOURCE_MODE_SATSTAR, 0, 1.0, "green"); 1581 psphotVisualShowSourceSize_Single (myKapa, sources, PM_SOURCE_MODE_EXT_LIMIT, 1, 1.0, "blue"); 1582 psphotVisualShowSourceSize_Single (myKapa, sources, PM_SOURCE_MODE_CR_LIMIT, 1, 1.0, "red"); 1583 psphotVisualShowSourceSize_Single (myKapa, sources, PM_SOURCE_MODE_DEFECT, 1, 2.0, "red"); 1584 psphotVisualShowSourceSize_Single (myKapa, sources, PM_SOURCE_MODE_SATSTAR, 1, 1.0, "yellow"); 1585 1586 fprintf (stdout, "red: CR; blue: EXTENDED; green: PSF-like; yellow: SATSTAR\n"); 1587 pmVisualAskUser(NULL); 1588 return true; 1589 } 1590 1591 bool psphotVisualPlotSourceSize (psMetadata *recipe, psMetadata *analysis, psArray *sources) { 1592 1593 bool status; 1584 1594 Graphdata graphdata; 1585 1595 KapaSection section; … … 1587 1597 if (!pmVisualIsVisual()) return true; 1588 1598 1589 if (kapa3 == -1) { 1590 kapa3 = KapaOpenNamedSocket ("kapa", "psphot:plots"); 1591 if (kapa3 == -1) { 1592 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 1593 pmVisualSetVisual(false); 1594 return false; 1595 } 1596 } 1597 1598 KapaClearPlots (kapa3); 1599 int myKapa = psphotKapaChannel (2); 1600 if (myKapa == -1) return false; 1601 1602 KapaClearPlots (myKapa); 1599 1603 KapaInitGraph (&graphdata); 1600 1601 // first section : mag vs CR nSigma 1602 section.dx = 1.0; 1603 section.dy = 0.5; 1604 section.x = 0.0; 1605 section.y = 0.0; 1606 section.name = NULL; 1607 psStringAppend (§ion.name, "a1"); 1608 KapaSetSection (kapa3, §ion); 1604 KapaSetFont (myKapa, "courier", 14); 1605 1606 section.bg = KapaColorByName ("none"); // XXX probably should be 'none' 1607 1608 // select the max psfX,Y values for the plot limits 1609 float Xmin = 1000.0, Xmax = 0.0; 1610 float Ymin = 1000.0, Ymax = 0.0; 1611 { 1612 int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS"); 1613 for (int n = 0; n < nRegions; n++) { 1614 1615 char regionName[64]; 1616 snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n); 1617 psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName); 1618 1619 float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); 1620 float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y"); 1621 float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX"); 1622 float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY"); 1623 1624 float X0 = psfX - 10.0*psfdX; 1625 float X1 = psfX + 10.0*psfdX; 1626 float Y0 = psfY - 10.0*psfdY; 1627 float Y1 = psfY + 10.0*psfdY; 1628 1629 if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); } 1630 if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); } 1631 if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); } 1632 if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); } 1633 } 1634 } 1635 Xmin = PS_MAX(Xmin, -0.1); 1636 Ymin = PS_MAX(Ymin, -0.1); 1637 1638 // storage vectors for data to be plotted 1639 psVector *xSAT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1640 psVector *ySAT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1641 psVector *mSAT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1642 psVector *sSAT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1643 1644 psVector *xPSF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1645 psVector *yPSF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1646 psVector *mPSF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1647 psVector *sPSF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1648 1649 psVector *xEXT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1650 psVector *yEXT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1651 psVector *mEXT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1652 psVector *sEXT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1653 1654 psVector *xDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1655 psVector *yDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1656 psVector *mDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1657 psVector *sDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1658 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 1664 psVector *xCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1665 psVector *yCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1666 psVector *mCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1667 psVector *sCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1668 1669 // construct the vectors 1670 int nSAT = 0; 1671 int nEXT = 0; 1672 int nPSF = 0; 1673 int nDEF = 0; 1674 int nLOW = 0; 1675 int nCR = 0; 1676 for (int i = 0; i < sources->n; i++) { 1677 pmSource *source = sources->data[i]; 1678 if (source->moments == NULL) continue; 1679 1680 // only plot the measured sources... 1681 if (!(source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED)) continue; 1682 1683 if (source->mode & PM_SOURCE_MODE_CR_LIMIT) { 1684 xCR->data.F32[nCR] = source->moments->Mxx; 1685 yCR->data.F32[nCR] = source->moments->Myy; 1686 mCR->data.F32[nCR] = -2.5*log10(source->moments->Sum); 1687 sCR->data.F32[nCR] = source->extNsigma; 1688 nCR++; 1689 } 1690 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 1691 xSAT->data.F32[nSAT] = source->moments->Mxx; 1692 ySAT->data.F32[nSAT] = source->moments->Myy; 1693 mSAT->data.F32[nSAT] = -2.5*log10(source->moments->Sum); 1694 sSAT->data.F32[nSAT] = source->extNsigma; 1695 nSAT++; 1696 } 1697 if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) { 1698 xEXT->data.F32[nEXT] = source->moments->Mxx; 1699 yEXT->data.F32[nEXT] = source->moments->Myy; 1700 mEXT->data.F32[nEXT] = -2.5*log10(source->moments->Sum); 1701 sEXT->data.F32[nEXT] = source->extNsigma; 1702 nEXT++; 1703 continue; 1704 } 1705 if (source->mode & PM_SOURCE_MODE_DEFECT) { 1706 xDEF->data.F32[nDEF] = source->moments->Mxx; 1707 yDEF->data.F32[nDEF] = source->moments->Myy; 1708 mDEF->data.F32[nDEF] = -2.5*log10(source->moments->Sum); 1709 sDEF->data.F32[nDEF] = source->extNsigma; 1710 nDEF++; 1711 continue; 1712 } 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++; 1719 continue; 1720 } 1721 xPSF->data.F32[nPSF] = source->moments->Mxx; 1722 yPSF->data.F32[nPSF] = source->moments->Myy; 1723 mPSF->data.F32[nPSF] = -2.5*log10(source->moments->Sum); 1724 sPSF->data.F32[nPSF] = source->extNsigma; 1725 nPSF++; 1726 } 1727 1728 xSAT->n = nSAT; 1729 ySAT->n = nSAT; 1730 mSAT->n = nSAT; 1731 sSAT->n = nSAT; 1732 1733 xPSF->n = nPSF; 1734 yPSF->n = nPSF; 1735 mPSF->n = nPSF; 1736 sPSF->n = nPSF; 1737 1738 xEXT->n = nEXT; 1739 yEXT->n = nEXT; 1740 mEXT->n = nEXT; 1741 sEXT->n = nEXT; 1742 1743 xCR->n = nCR; 1744 yCR->n = nCR; 1745 mCR->n = nCR; 1746 sCR->n = nCR; 1747 1748 xDEF->n = nDEF; 1749 yDEF->n = nDEF; 1750 mDEF->n = nDEF; 1751 sDEF->n = nDEF; 1752 1753 xLOW->n = nLOW; 1754 yLOW->n = nLOW; 1755 mLOW->n = nLOW; 1756 sLOW->n = nLOW; 1757 1758 // four sections: MxxMyy, MagMxx, MagMyy, MagSigma 1759 1760 // first section: MxxMyy 1761 section.dx = 0.75; 1762 section.dy = 0.60; 1763 section.x = 0.00; 1764 section.y = 0.00; 1765 section.name = psStringCopy ("MxxMyy"); 1766 KapaSetSection (myKapa, §ion); 1609 1767 psFree (section.name); 1768 1769 graphdata.color = KapaColorByName ("black"); 1770 graphdata.xmin = Xmin; 1771 graphdata.ymin = Ymin; 1772 graphdata.xmax = Xmax; 1773 graphdata.ymax = Ymax; 1774 KapaSetLimits (myKapa, &graphdata); 1775 1776 graphdata.padXm = NAN; 1777 graphdata.padYm = NAN; 1778 graphdata.padXp = 0.5; 1779 graphdata.padYp = 0.5; 1780 KapaBox (myKapa, &graphdata); 1781 KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM); 1782 KapaSendLabel (myKapa, "M_yy| (pixels)", KAPA_LABEL_YM); 1783 1784 graphdata.color = KapaColorByName ("black"); 1785 graphdata.ptype = 0; 1786 graphdata.size = 0.5; 1787 graphdata.style = 2; 1788 KapaPrepPlot (myKapa, nPSF, &graphdata); 1789 KapaPlotVector (myKapa, nPSF, xPSF->data.F32, "x"); 1790 KapaPlotVector (myKapa, nPSF, yPSF->data.F32, "y"); 1791 1792 graphdata.color = KapaColorByName ("blue"); 1793 graphdata.ptype = 0; 1794 graphdata.size = 0.5; 1795 graphdata.style = 2; 1796 KapaPrepPlot (myKapa, nEXT, &graphdata); 1797 KapaPlotVector (myKapa, nEXT, xEXT->data.F32, "x"); 1798 KapaPlotVector (myKapa, nEXT, yEXT->data.F32, "y"); 1799 1800 graphdata.color = KapaColorByName ("red"); 1801 graphdata.ptype = 0; 1802 graphdata.size = 0.5; 1803 graphdata.style = 2; 1804 KapaPrepPlot (myKapa, nDEF, &graphdata); 1805 KapaPlotVector (myKapa, nDEF, xDEF->data.F32, "x"); 1806 KapaPlotVector (myKapa, nDEF, yDEF->data.F32, "y"); 1807 1808 graphdata.color = KapaColorByName ("red"); 1809 graphdata.ptype = 7; 1810 graphdata.size = 1.0; 1811 graphdata.style = 2; 1812 KapaPrepPlot (myKapa, nCR, &graphdata); 1813 KapaPlotVector (myKapa, nCR, xCR->data.F32, "x"); 1814 KapaPlotVector (myKapa, nCR, yCR->data.F32, "y"); 1815 1816 graphdata.color = KapaColorByName ("blue"); 1817 graphdata.ptype = 7; 1818 graphdata.size = 1.0; 1819 graphdata.style = 2; 1820 KapaPrepPlot (myKapa, nSAT, &graphdata); 1821 KapaPlotVector (myKapa, nSAT, xSAT->data.F32, "x"); 1822 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"); 1831 1832 // second section: MagMyy 1833 section.dx = 0.75; 1834 section.dy = 0.20; 1835 section.x = 0.00; 1836 section.y = 0.80; 1837 section.name = psStringCopy ("MagMyy"); 1838 KapaSetSection (myKapa, §ion); 1839 psFree (section.name); 1840 1841 graphdata.color = KapaColorByName ("black"); 1842 graphdata.xmin = -17.1; 1843 graphdata.xmax = -6.9; 1844 graphdata.ymin = Ymin; 1845 graphdata.ymax = Ymax; 1846 KapaSetLimits (myKapa, &graphdata); 1847 1848 graphdata.padXm = 0.5; 1849 graphdata.padYm = NAN; 1850 graphdata.padXp = NAN; 1851 graphdata.padYp = 0.5; 1852 strcpy (graphdata.labels, "0210"); 1853 KapaBox (myKapa, &graphdata); 1854 KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_XP); 1855 KapaSendLabel (myKapa, "M_yy| (pixels)", KAPA_LABEL_YM); 1856 1857 graphdata.color = KapaColorByName ("black"); 1858 graphdata.ptype = 0; 1859 graphdata.size = 0.5; 1860 graphdata.style = 2; 1861 KapaPrepPlot (myKapa, nPSF, &graphdata); 1862 KapaPlotVector (myKapa, nPSF, mPSF->data.F32, "x"); 1863 KapaPlotVector (myKapa, nPSF, yPSF->data.F32, "y"); 1864 1865 graphdata.color = KapaColorByName ("blue"); 1866 graphdata.ptype = 0; 1867 graphdata.size = 0.5; 1868 graphdata.style = 2; 1869 KapaPrepPlot (myKapa, nEXT, &graphdata); 1870 KapaPlotVector (myKapa, nEXT, mEXT->data.F32, "x"); 1871 KapaPlotVector (myKapa, nEXT, yEXT->data.F32, "y"); 1872 1873 graphdata.color = KapaColorByName ("red"); 1874 graphdata.ptype = 0; 1875 graphdata.size = 0.5; 1876 graphdata.style = 2; 1877 KapaPrepPlot (myKapa, nDEF, &graphdata); 1878 KapaPlotVector (myKapa, nDEF, mDEF->data.F32, "x"); 1879 KapaPlotVector (myKapa, nDEF, yDEF->data.F32, "y"); 1880 1881 graphdata.color = KapaColorByName ("red"); 1882 graphdata.ptype = 7; 1883 graphdata.size = 1.0; 1884 graphdata.style = 2; 1885 KapaPrepPlot (myKapa, nCR, &graphdata); 1886 KapaPlotVector (myKapa, nCR, mCR->data.F32, "x"); 1887 KapaPlotVector (myKapa, nCR, yCR->data.F32, "y"); 1888 1889 graphdata.color = KapaColorByName ("blue"); 1890 graphdata.ptype = 7; 1891 graphdata.size = 1.0; 1892 graphdata.style = 2; 1893 KapaPrepPlot (myKapa, nSAT, &graphdata); 1894 KapaPlotVector (myKapa, nSAT, mSAT->data.F32, "x"); 1895 KapaPlotVector (myKapa, nSAT, ySAT->data.F32, "y"); 1896 1897 // third section: MagMxx 1898 section.dx = 0.25; 1899 section.dy = 0.60; 1900 section.x = 0.75; 1901 section.y = 0.00; 1902 section.name = psStringCopy ("MagMxx"); 1903 KapaSetSection (myKapa, §ion); 1904 psFree (section.name); 1905 1906 graphdata.color = KapaColorByName ("black"); 1907 graphdata.xmin = Xmin; 1908 graphdata.xmax = Xmax; 1909 graphdata.ymin = -6.9; 1910 graphdata.ymax = -17.1; 1911 KapaSetLimits (myKapa, &graphdata); 1912 1913 graphdata.padXm = NAN; 1914 graphdata.padYm = 0.5; 1915 graphdata.padXp = 0.5; 1916 graphdata.padYp = NAN; 1917 strcpy (graphdata.labels, "2001"); 1918 KapaBox (myKapa, &graphdata); 1919 KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM); 1920 KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_YP); 1921 1922 graphdata.color = KapaColorByName ("black"); 1923 graphdata.ptype = 0; 1924 graphdata.size = 0.5; 1925 graphdata.style = 2; 1926 KapaPrepPlot (myKapa, nPSF, &graphdata); 1927 KapaPlotVector (myKapa, nPSF, xPSF->data.F32, "x"); 1928 KapaPlotVector (myKapa, nPSF, mPSF->data.F32, "y"); 1929 1930 graphdata.color = KapaColorByName ("blue"); 1931 graphdata.ptype = 0; 1932 graphdata.size = 0.5; 1933 graphdata.style = 2; 1934 KapaPrepPlot (myKapa, nEXT, &graphdata); 1935 KapaPlotVector (myKapa, nEXT, xEXT->data.F32, "x"); 1936 KapaPlotVector (myKapa, nEXT, mEXT->data.F32, "y"); 1937 1938 graphdata.color = KapaColorByName ("red"); 1939 graphdata.ptype = 0; 1940 graphdata.size = 0.5; 1941 graphdata.style = 2; 1942 KapaPrepPlot (myKapa, nDEF, &graphdata); 1943 KapaPlotVector (myKapa, nDEF, xDEF->data.F32, "x"); 1944 KapaPlotVector (myKapa, nDEF, mDEF->data.F32, "y"); 1945 1946 graphdata.color = KapaColorByName ("red"); 1947 graphdata.ptype = 7; 1948 graphdata.size = 1.0; 1949 graphdata.style = 2; 1950 KapaPrepPlot (myKapa, nCR, &graphdata); 1951 KapaPlotVector (myKapa, nCR, xCR->data.F32, "x"); 1952 KapaPlotVector (myKapa, nCR, mCR->data.F32, "y"); 1953 1954 graphdata.color = KapaColorByName ("blue"); 1955 graphdata.ptype = 7; 1956 graphdata.size = 1.0; 1957 graphdata.style = 2; 1958 KapaPrepPlot (myKapa, nSAT, &graphdata); 1959 KapaPlotVector (myKapa, nSAT, xSAT->data.F32, "x"); 1960 KapaPlotVector (myKapa, nSAT, mSAT->data.F32, "y"); 1961 1962 // fourth section: MagSigma 1963 section.dx = 0.75; 1964 section.dy = 0.20; 1965 section.x = 0.00; 1966 section.y = 0.60; 1967 section.name = psStringCopy ("MagSigma"); 1968 KapaSetSection (myKapa, §ion); 1969 psFree (section.name); 1970 1971 graphdata.color = KapaColorByName ("black"); 1972 graphdata.xmax = -6.9; 1973 graphdata.xmin = -17.1; 1974 graphdata.ymin = -20.1; 1975 graphdata.ymax = +20.1; 1976 KapaSetLimits (myKapa, &graphdata); 1977 1978 graphdata.padXm = 0.5; 1979 graphdata.padYm = NAN; 1980 graphdata.padXp = 0.5; 1981 graphdata.padYp = 0.5; 1982 strcpy (graphdata.labels, "0100"); 1983 KapaBox (myKapa, &graphdata); 1984 // KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_XM); 1985 KapaSendLabel (myKapa, "EXT&ss&c", KAPA_LABEL_YM); 1986 1987 graphdata.color = KapaColorByName ("black"); 1988 graphdata.ptype = 0; 1989 graphdata.size = 0.5; 1990 graphdata.style = 2; 1991 KapaPrepPlot (myKapa, nPSF, &graphdata); 1992 KapaPlotVector (myKapa, nPSF, mPSF->data.F32, "x"); 1993 KapaPlotVector (myKapa, nPSF, sPSF->data.F32, "y"); 1994 1995 graphdata.color = KapaColorByName ("blue"); 1996 graphdata.ptype = 0; 1997 graphdata.size = 0.5; 1998 graphdata.style = 2; 1999 KapaPrepPlot (myKapa, nEXT, &graphdata); 2000 KapaPlotVector (myKapa, nEXT, mEXT->data.F32, "x"); 2001 KapaPlotVector (myKapa, nEXT, sEXT->data.F32, "y"); 2002 2003 graphdata.color = KapaColorByName ("red"); 2004 graphdata.ptype = 0; 2005 graphdata.size = 0.5; 2006 graphdata.style = 2; 2007 KapaPrepPlot (myKapa, nDEF, &graphdata); 2008 KapaPlotVector (myKapa, nDEF, mDEF->data.F32, "x"); 2009 KapaPlotVector (myKapa, nDEF, sDEF->data.F32, "y"); 2010 2011 graphdata.color = KapaColorByName ("red"); 2012 graphdata.ptype = 7; 2013 graphdata.size = 1.0; 2014 graphdata.style = 2; 2015 KapaPrepPlot (myKapa, nCR, &graphdata); 2016 KapaPlotVector (myKapa, nCR, mCR->data.F32, "x"); 2017 KapaPlotVector (myKapa, nCR, sCR->data.F32, "y"); 2018 2019 graphdata.color = KapaColorByName ("blue"); 2020 graphdata.ptype = 7; 2021 graphdata.size = 1.0; 2022 graphdata.style = 2; 2023 KapaPrepPlot (myKapa, nSAT, &graphdata); 2024 KapaPlotVector (myKapa, nSAT, mSAT->data.F32, "x"); 2025 KapaPlotVector (myKapa, nSAT, sSAT->data.F32, "y"); 2026 2027 // draw N circles to outline the clumps 2028 { 2029 KapaSelectSection (myKapa, "MxxMyy"); 2030 2031 // draw a circle centered on psfX,Y with size of the psf limit 2032 psVector *xLimit = psVectorAlloc (120, PS_TYPE_F32); 2033 psVector *yLimit = psVectorAlloc (120, PS_TYPE_F32); 2034 2035 int nRegions = psMetadataLookupS32 (&status, analysis, "PSF.CLUMP.NREGIONS"); 2036 float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA"); 2037 2038 graphdata.color = KapaColorByName ("blue"); 2039 graphdata.style = 0; 2040 2041 graphdata.xmin = Xmin; 2042 graphdata.ymin = Ymin; 2043 graphdata.xmax = Xmax; 2044 graphdata.ymax = Ymax; 2045 KapaSetLimits (myKapa, &graphdata); 2046 2047 for (int n = 0; n < nRegions; n++) { 2048 2049 char regionName[64]; 2050 snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n); 2051 psMetadata *regionMD = psMetadataLookupPtr (&status, analysis, regionName); 2052 2053 float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); 2054 float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y"); 2055 float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX"); 2056 float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY"); 2057 float Rx = psfdX * PSF_CLUMP_NSIGMA; 2058 float Ry = psfdY * PSF_CLUMP_NSIGMA; 2059 2060 for (int i = 0; i < xLimit->n; i++) { 2061 xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX; 2062 yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY; 2063 } 2064 KapaPrepPlot (myKapa, xLimit->n, &graphdata); 2065 KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x"); 2066 KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y"); 2067 } 2068 psFree (xLimit); 2069 psFree (yLimit); 2070 } 2071 2072 psFree (xSAT); 2073 psFree (ySAT); 2074 psFree (mSAT); 2075 psFree (sSAT); 2076 2077 psFree (xEXT); 2078 psFree (yEXT); 2079 psFree (mEXT); 2080 psFree (sEXT); 2081 2082 psFree (xPSF); 2083 psFree (yPSF); 2084 psFree (mPSF); 2085 psFree (sPSF); 2086 2087 psFree (xDEF); 2088 psFree (yDEF); 2089 psFree (mDEF); 2090 psFree (sDEF); 2091 2092 psFree (xLOW); 2093 psFree (yLOW); 2094 psFree (mLOW); 2095 psFree (sLOW); 2096 2097 psFree (xCR); 2098 psFree (yCR); 2099 psFree (mCR); 2100 psFree (sCR); 2101 2102 pmVisualAskUser(NULL); 2103 return true; 2104 } 2105 2106 bool psphotVisualShowResidualImage (pmReadout *readout) { 2107 2108 if (!pmVisualIsVisual()) return true; 2109 2110 int myKapa = psphotKapaChannel (1); 2111 if (myKapa == -1) return false; 2112 2113 psphotVisualScaleImage (myKapa, readout->image, readout->mask, "resid", 1); 2114 2115 pmVisualAskUser(NULL); 2116 return true; 2117 } 2118 2119 bool psphotVisualPlotApResid (psArray *sources, float mean, float error) { 2120 2121 Graphdata graphdata; 2122 float lineX[2], lineY[2]; 2123 2124 if (!pmVisualIsVisual()) return true; 2125 2126 int myKapa = psphotKapaChannel (2); 2127 if (myKapa == -1) return false; 2128 2129 KapaClearPlots (myKapa); 2130 KapaInitGraph (&graphdata); 1610 2131 1611 2132 psVector *x = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1612 2133 psVector *y = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1613 1614 graphdata.xmin = +32.0; 1615 graphdata.xmax = -32.0; 1616 graphdata.ymin = +32.0; 1617 graphdata.ymax = -32.0; 1618 1619 // construct the plot vectors 1620 int n = 0; 1621 for (int i = 0; i < sources->n; i++) { 1622 pmSource *source = sources->data[i]; 1623 if (!source) continue; 1624 if (source->type != PM_SOURCE_TYPE_STAR) continue; 1625 if (!isfinite (source->crNsigma)) continue; 1626 1627 x->data.F32[n] = -2.5*log10(source->peak->flux); 1628 y->data.F32[n] = source->crNsigma; 1629 graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]); 1630 graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]); 1631 graphdata.ymin = -0.5; 1632 graphdata.ymax = 10.0; 1633 1634 n++; 1635 } 1636 x->n = y->n = n; 1637 1638 float range; 1639 range = graphdata.xmax - graphdata.xmin; 1640 graphdata.xmax += 0.05*range; 1641 graphdata.xmin -= 0.05*range; 1642 1643 // XXX set the plot range to match the image 1644 KapaSetLimits (kapa3, &graphdata); 1645 1646 KapaSetFont (kapa3, "helvetica", 14); 1647 KapaBox (kapa3, &graphdata); 1648 KapaSendLabel (kapa3, "Peak as Mag", KAPA_LABEL_XM); 1649 KapaSendLabel (kapa3, "CR N Sigma", KAPA_LABEL_YM); 1650 1651 graphdata.color = KapaColorByName ("black"); 1652 graphdata.ptype = 2; 1653 graphdata.size = 0.5; 1654 graphdata.style = 2; 1655 KapaPrepPlot (kapa3, n, &graphdata); 1656 KapaPlotVector (kapa3, n, x->data.F32, "x"); 1657 KapaPlotVector (kapa3, n, y->data.F32, "y"); 1658 1659 // second section : mag vs EXT nSigma 1660 section.dx = 1.0; 1661 section.dy = 0.5; 1662 section.x = 0.0; 1663 section.y = 0.5; 1664 section.name = NULL; 1665 psStringAppend (§ion.name, "a2"); 1666 KapaSetSection (kapa3, §ion); 1667 psFree (section.name); 1668 1669 graphdata.xmin = +32.0; 1670 graphdata.xmax = -32.0; 1671 graphdata.ymin = +32.0; 1672 graphdata.ymax = -32.0; 1673 1674 // construct the plot vectors 1675 n = 0; 1676 for (int i = 0; i < sources->n; i++) { 1677 pmSource *source = sources->data[i]; 1678 if (!source) continue; 1679 if (source->type != PM_SOURCE_TYPE_STAR) continue; 1680 if (!isfinite (source->extNsigma)) continue; 1681 1682 x->data.F32[n] = -2.5*log10(source->peak->flux); 1683 y->data.F32[n] = source->extNsigma; 1684 graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]); 1685 graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]); 1686 graphdata.ymin = -0.5; 1687 graphdata.ymax = 10.0; 1688 1689 n++; 1690 } 1691 x->n = y->n = n; 1692 1693 range = graphdata.xmax - graphdata.xmin; 1694 graphdata.xmax += 0.05*range; 1695 graphdata.xmin -= 0.05*range; 1696 1697 // XXX set the plot range to match the image 1698 KapaSetLimits (kapa3, &graphdata); 1699 1700 KapaSetFont (kapa3, "helvetica", 14); 1701 KapaBox (kapa3, &graphdata); 1702 KapaSendLabel (kapa3, "EXT N Sigma", KAPA_LABEL_YM); 1703 1704 graphdata.color = KapaColorByName ("black"); 1705 graphdata.ptype = 2; 1706 graphdata.size = 0.5; 1707 graphdata.style = 2; 1708 KapaPrepPlot (kapa3, n, &graphdata); 1709 KapaPlotVector (kapa3, n, x->data.F32, "x"); 1710 KapaPlotVector (kapa3, n, y->data.F32, "y"); 1711 1712 psFree (x); 1713 psFree (y); 1714 1715 // pause and wait for user input: 1716 // continue, save (provide name), ?? 1717 char key[10]; 1718 fprintf (stdout, "[c]ontinue? "); 1719 if (!fgets(key, 8, stdin)) { 1720 psWarning("Unable to read option"); 1721 } 1722 return true; 1723 } 1724 1725 bool psphotVisualShowResidualImage (pmReadout *readout) { 1726 1727 if (!pmVisualIsVisual()) return true; 1728 1729 if (kapa == -1) { 1730 kapa = KapaOpenNamedSocket ("kapa", "psphot:images"); 1731 if (kapa == -1) { 1732 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 1733 pmVisualSetVisual(false); 1734 return false; 1735 } 1736 } 1737 1738 psphotVisualScaleImage (kapa, readout->image, "resid", 1); 1739 1740 // pause and wait for user input: 1741 // continue, save (provide name), ?? 1742 char key[10]; 1743 fprintf (stdout, "[c]ontinue? "); 1744 if (!fgets(key, 8, stdin)) { 1745 psWarning("Unable to read option"); 1746 } 1747 return true; 1748 } 1749 1750 bool psphotVisualPlotApResid (psArray *sources) { 1751 1752 Graphdata graphdata; 1753 1754 if (!pmVisualIsVisual()) return true; 1755 1756 if (kapa3 == -1) { 1757 kapa3 = KapaOpenNamedSocket ("kapa", "psphot:plots"); 1758 if (kapa3 == -1) { 1759 fprintf (stderr, "failure to open kapa; visual mode disabled\n"); 1760 pmVisualSetVisual(false); 1761 return false; 1762 } 1763 } 1764 1765 KapaClearPlots (kapa3); 1766 KapaInitGraph (&graphdata); 1767 1768 psVector *x = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1769 psVector *y = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 2134 psVector *dy = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1770 2135 1771 2136 graphdata.xmin = +32.0; … … 1785 2150 x->data.F32[n] = source->psfMag; 1786 2151 y->data.F32[n] = source->apMag - source->psfMag; 2152 dy->data.F32[n] = source->errMag; 1787 2153 graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]); 1788 2154 graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]); … … 1792 2158 n++; 1793 2159 } 1794 x->n = y->n = n;2160 x->n = y->n = dy->n = n; 1795 2161 1796 2162 float range; … … 1802 2168 graphdata.ymin -= 0.05*range; 1803 2169 1804 // XXX set the plot range to match the image 1805 KapaSetLimits (kapa3, &graphdata); 1806 1807 KapaSetFont (kapa3, "helvetica", 14); 1808 KapaBox (kapa3, &graphdata); 1809 KapaSendLabel (kapa3, "PSF Mag", KAPA_LABEL_XM); 1810 KapaSendLabel (kapa3, "Ap Mag - PSF Mag", KAPA_LABEL_YM); 2170 // XXX test 2171 graphdata.xmin = -17.0; 2172 graphdata.xmax = -9.0; 2173 graphdata.ymin = -0.31; 2174 graphdata.ymax = +0.31; 2175 2176 KapaSetLimits (myKapa, &graphdata); 2177 2178 KapaSetFont (myKapa, "helvetica", 14); 2179 KapaBox (myKapa, &graphdata); 2180 KapaSendLabel (myKapa, "PSF Mag", KAPA_LABEL_XM); 2181 KapaSendLabel (myKapa, "Ap Mag - PSF Mag", KAPA_LABEL_YM); 1811 2182 1812 2183 graphdata.color = KapaColorByName ("black"); … … 1814 2185 graphdata.size = 0.5; 1815 2186 graphdata.style = 2; 1816 KapaPrepPlot (kapa3, n, &graphdata); 1817 KapaPlotVector (kapa3, n, x->data.F32, "x"); 1818 KapaPlotVector (kapa3, n, y->data.F32, "y"); 2187 graphdata.etype |= 0x01; 2188 KapaPrepPlot (myKapa, n, &graphdata); 2189 KapaPlotVector (myKapa, n, x->data.F32, "x"); 2190 KapaPlotVector (myKapa, n, y->data.F32, "y"); 2191 KapaPlotVector (myKapa, n, dy->data.F32, "dym"); 2192 KapaPlotVector (myKapa, n, dy->data.F32, "dyp"); 2193 2194 graphdata.color = KapaColorByName ("blue"); 2195 graphdata.ptype = 0; 2196 graphdata.size = 0.5; 2197 graphdata.style = 0; 2198 graphdata.etype = 0; 2199 lineX[0] = graphdata.xmin; 2200 lineX[1] = graphdata.xmax; 2201 lineY[0] = lineY[1] = mean; 2202 KapaPrepPlot (myKapa, 2, &graphdata); 2203 KapaPlotVector (myKapa, 2, lineX, "x"); 2204 KapaPlotVector (myKapa, 2, lineY, "y"); 2205 2206 graphdata.color = KapaColorByName ("red"); 2207 graphdata.ptype = 0; 2208 graphdata.size = 0.5; 2209 graphdata.style = 0; 2210 graphdata.etype = 0; 2211 lineX[0] = graphdata.xmin; 2212 lineX[1] = graphdata.xmax; 2213 lineY[0] = lineY[1] = mean + error; 2214 KapaPrepPlot (myKapa, 2, &graphdata); 2215 KapaPlotVector (myKapa, 2, lineX, "x"); 2216 KapaPlotVector (myKapa, 2, lineY, "y"); 2217 2218 graphdata.color = KapaColorByName ("red"); 2219 graphdata.ptype = 0; 2220 graphdata.size = 0.5; 2221 graphdata.style = 0; 2222 graphdata.etype = 0; 2223 lineX[0] = graphdata.xmin; 2224 lineX[1] = graphdata.xmax; 2225 lineY[0] = lineY[1] = mean - error; 2226 KapaPrepPlot (myKapa, 2, &graphdata); 2227 KapaPlotVector (myKapa, 2, lineX, "x"); 2228 KapaPlotVector (myKapa, 2, lineY, "y"); 1819 2229 1820 2230 psFree (x); 1821 2231 psFree (y); 1822 1823 // pause and wait for user input: 1824 // continue, save (provide name), ?? 1825 char key[10]; 1826 fprintf (stdout, "[c]ontinue? "); 1827 if (!fgets(key, 8, stdin)) { 1828 psWarning("Unable to read option"); 1829 } 2232 psFree (dy); 2233 2234 pmVisualAskUser(NULL); 2235 return true; 2236 } 2237 2238 bool 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 2321 bool psphotVisualShowPetrosians (psArray *sources) { 2322 2323 int Noverlay, NOVERLAY; 2324 KiiOverlay *overlay; 2325 2326 if (!pmVisualIsVisual()) return true; 2327 2328 int kapa = psphotKapaChannel (1); 2329 if (kapa == -1) return false; 2330 2331 Noverlay = 0; 2332 NOVERLAY = 100; 2333 ALLOCATE (overlay, KiiOverlay, NOVERLAY); 2334 2335 for (int i = 0; i < sources->n; i++) { 2336 pmSource *source = sources->data[i]; 2337 2338 if (!source) continue; 2339 if (!source->extpars) continue; 2340 if (!source->extpars->petProfile) continue; 2341 2342 float petrosianRadius = source->extpars->petrosianRadius; 2343 psEllipseAxes *axes = &source->extpars->axes; 2344 2345 overlay[Noverlay].type = KII_OVERLAY_CIRCLE; 2346 overlay[Noverlay].x = source->peak->xf; 2347 overlay[Noverlay].y = source->peak->yf; 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; 2351 overlay[Noverlay].text = NULL; 2352 Noverlay ++; 2353 CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100); 2354 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); 2364 } 2365 2366 KiiLoadOverlay (kapa, overlay, Noverlay, "red"); 2367 FREE (overlay); 2368 2369 pmVisualAskUser(NULL); 1830 2370 return true; 1831 2371 } … … 1850 2390 1851 2391 # endif 2392 2393 # if (0) 2394 // *** make a histogram of the source counts in the x and y directions 2395 psHistogram *nX = psHistogramAlloc (graphdata.xmin, graphdata.xmax, 50.0); 2396 psHistogram *nY = psHistogramAlloc (graphdata.ymin, graphdata.ymax, 50.0); 2397 psVectorHistogram (nX, xFaint, NULL, NULL, 0); 2398 psVectorHistogram (nY, yFaint, NULL, NULL, 0); 2399 psVector *dX = psVectorAlloc (nX->nums->n, PS_TYPE_F32); 2400 psVector *vX = psVectorAlloc (nX->nums->n, PS_TYPE_F32); 2401 psVector *dY = psVectorAlloc (nY->nums->n, PS_TYPE_F32); 2402 psVector *vY = psVectorAlloc (nY->nums->n, PS_TYPE_F32); 2403 for (int i = 0; i < nX->nums->n; i++) { 2404 dX->data.F32[i] = nX->nums->data.S32[i]; 2405 vX->data.F32[i] = 0.5*(nX->bounds->data.F32[i] + nX->bounds->data.F32[i+1]); 2406 } 2407 for (int i = 0; i < nY->nums->n; i++) { 2408 dY->data.F32[i] = nY->nums->data.S32[i]; 2409 vY->data.F32[i] = 0.5*(nY->bounds->data.F32[i] + nY->bounds->data.F32[i+1]); 2410 } 2411 2412 graphdata.color = KapaColorByName ("black"); 2413 graphdata.ptype = 0; 2414 graphdata.size = 0.0; 2415 graphdata.style = 0; 2416 KapaPrepPlot (myKapa, dX->n, &graphdata); 2417 KapaPlotVector (myKapa, dX->n, dX->data.F32, "x"); 2418 KapaPlotVector (myKapa, vX->n, vX->data.F32, "y"); 2419 2420 psFree (nX); 2421 psFree (dX); 2422 psFree (vX); 2423 2424 psFree (nY); 2425 psFree (dY); 2426 psFree (vY); 2427 2428 # endif 2429
Note:
See TracChangeset
for help on using the changeset viewer.
