Changeset 25755
- Timestamp:
- Oct 2, 2009, 3:12:47 PM (17 years ago)
- Location:
- trunk/psphot
- Files:
-
- 43 edited
- 10 copied
-
doc/notes.20090523.txt (modified) (2 diffs)
-
doc/notes.txt (modified) (1 diff)
-
doc/outline.txt (modified) (1 diff)
-
src (modified) (1 prop)
-
src/Makefile.am (modified) (5 diffs)
-
src/psphot.h (modified) (8 diffs)
-
src/psphotAddNoise.c (modified) (2 diffs)
-
src/psphotApResid.c (modified) (15 diffs)
-
src/psphotBlendFit.c (modified) (3 diffs)
-
src/psphotChoosePSF.c (modified) (8 diffs)
-
src/psphotEfficiency.c (modified) (1 prop)
-
src/psphotEllipticalContour.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotEllipticalContour.c )
-
src/psphotEllipticalProfile.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotEllipticalProfile.c )
-
src/psphotExtendedSourceAnalysis.c (modified) (8 diffs)
-
src/psphotExtendedSourceFits.c (modified) (2 diffs)
-
src/psphotFake.c (modified) (1 prop)
-
src/psphotFindDetections.c (modified) (1 diff)
-
src/psphotFindFootprints.c (modified) (2 diffs)
-
src/psphotFindPeaks.c (modified) (1 diff)
-
src/psphotFitSourcesLinear.c (modified) (5 diffs)
-
src/psphotFitSourcesLinearStack.c (modified) (1 diff)
-
src/psphotGuessModels.c (modified) (1 diff)
-
src/psphotImageLoop.c (modified) (1 diff)
-
src/psphotImageQuality.c (modified) (1 diff)
-
src/psphotMagnitudes.c (modified) (4 diffs)
-
src/psphotMakeFluxScale.c (modified) (1 diff)
-
src/psphotMakeResiduals.c (modified) (8 diffs)
-
src/psphotMaskReadout.c (modified) (1 diff)
-
src/psphotOutput.c (modified) (3 diffs)
-
src/psphotPSFConvModel.c (modified) (2 diffs)
-
src/psphotPetrosian.c (modified) (1 diff)
-
src/psphotPetrosianAnalysis.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotPetrosianAnalysis.c )
-
src/psphotPetrosianProfile.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotPetrosianProfile.c )
-
src/psphotPetrosianRadialBins.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotPetrosianRadialBins.c )
-
src/psphotPetrosianStats.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotPetrosianStats.c )
-
src/psphotPetrosianStudy.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotPetrosianStudy.c )
-
src/psphotPetrosianVisual.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotPetrosianVisual.c )
-
src/psphotRadialProfile.c (modified) (2 diffs)
-
src/psphotRadialProfileByAngles.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotRadialProfileByAngles.c )
-
src/psphotRadiiFromProfiles.c (copied) (copied from branches/eam_branches/20090715/psphot/src/psphotRadiiFromProfiles.c )
-
src/psphotRadiusChecks.c (modified) (8 diffs)
-
src/psphotReadout.c (modified) (9 diffs)
-
src/psphotReadoutFindPSF.c (modified) (1 diff)
-
src/psphotReadoutKnownSources.c (modified) (1 diff)
-
src/psphotReadoutMinimal.c (modified) (1 diff)
-
src/psphotReplaceUnfit.c (modified) (5 diffs)
-
src/psphotRoughClass.c (modified) (3 diffs)
-
src/psphotSetThreads.c (modified) (2 diffs)
-
src/psphotSourceFits.c (modified) (19 diffs)
-
src/psphotSourcePlots.c (modified) (3 diffs)
-
src/psphotSourceSize.c (modified) (6 diffs)
-
src/psphotSourceStats.c (modified) (7 diffs)
-
src/psphotVisual.c (modified) (68 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/doc/notes.20090523.txt
r24993 r25755 1 2 20090809 : more on extended sources: 3 4 my algorithm for getting the petrosian radii and fluxes is: 5 6 * measure radial profile by interpolation to specific locations along the radial line 7 (at low radii, this gives much more accurate results; at high radii, we may need to 8 average a group of pixels -- say, for 15 deg separations, choose a box that is 9 < 5 degree in width -- this is > 1 pixel at a distance of 12 pixels. 10 11 psphotRadialProfilesByAngle 12 13 * find intersection of profile with isophot 14 15 psphotRadiusFromProfile -> r50(theta) 16 17 * generate r50x, r50y and fit to ellipse 18 19 psphotEllipticalContour 20 21 * generate elliptical profile 22 23 psphotEllipticalProfile 24 25 * convert to \alpha r_i < r < \beta r_i bins 26 27 psphotPetrosianRadialBins 1 28 2 29 20090725 : extended source radial profiles … … 54 81 *** get rest of math from my notebook... 55 82 56 57 58 83 20090525 : some clarity of issues: 59 84 -
trunk/psphot/doc/notes.txt
r21164 r25755 1 2 2009.09.26 3 4 Remaining PSPHOT Issues: 5 6 o soften errors a bit for bright stars? (essentially allow a 7 systematic error on the flat of some percentage). this may help 8 the very saturated stars (peaks > 10k) which seem to be 9 excessively driven by the cores. 10 ** did not seem to be a big success --> makes things worse for f = 11 0.01, about the same for f = 0.005 12 13 o clean up and remove test bits of code. 14 15 o clean up psphot.config files : drop unused, fix some conflicting 16 names, reduce camera-specific options, make S/N limits 17 consistent... 18 19 * PSF Eval & ChiSq test?? 20 21 * EXT fail fit? lack of iterations? 22 23 * extended source output 24 25 * still some concerns with the source size analysis: the parameters 26 space seems fine (Mxx, Myy, nSigma), but we need to define more 27 sophisticated boundaries (perhaps include dMag or Mag). 28 29 * some optimization issues: 30 * too many re-calculations of all magnitude / aperture data 31 * is FluxScale really faster? do we need a finer mapping? (5x5 32 clearly yields too much scatter) 33 * is psphotFitSourcesLinear.c (build matrix) super-slow when optimized? 34 35 * very saturated stars are somewhat segmented. 36 37 * footprint coverage in dense simtest image 005.001? 38 39 * footprint S/N limit vs peaks S/N limit? 40 41 * warning about burntool table? 42 43 * is the residual map failing to be masked at the radius? 44 45 * PSF 2D convergence : how to choose between marginally different 46 options? (note that the GPC1 images may go to 2x2 instead of 3x3) 47 48 * -visual needs more fine-grained control 49 50 * visualization graphs should reset the sections in general. 51 52 * some excess verbosity (my log level is 9, lower?) 53 54 ----- 55 56 Apparently I'm getting bad psf vs ap mags because of the difference 57 between linear and non-linear fits. I think this is due to the 58 weighting schemes: 59 60 psphotChoosePSF & psphotBlendFit depend on POISSON.ERRORS.PHOT.LMM, 61 which is set to TRUE => use Poisson errors 62 63 psphotFitSourcesLinear depends on CONSTANT_PHOTOMETRIC_WEIGHTS, 64 which is set to TRUE => do not use Poisson errors. 65 66 nothing seems to use the value POISSON.ERRORS.PHOT.LIN 67 68 ** Poisson errors seeem to be working much better than Constant 69 errors (as judged by consistency between PSF and APERTURE 70 magnitdues). Not sure I understand this. It could be that the 71 implementation of Constant errors in the linear fitting analysis 72 is busted. 73 74 ** Also, I was getting some additional scatter from the FluxScale 75 (lookup-table for Io -> mags). 76 77 * surprisingly, it is not clear that the FluxScale method is 78 faster than the more accurate integration technique... 79 80 2009.09.25 81 82 Notes on pmSourceMagnitudes: 83 84 * in psphotChoosePSF, in pmPSFtry: raw PSF & raw AP 85 * in psphotChoosePSF, psphotMakeGrowthCurve: uses direct all to pmSourcePhotometryAper 86 * in psphotSourceSize, in psphotSourceSizePSF, raw PSF & raw AP (but uses moments->Sum) for PSF stars 87 NOTE: on the initial call, the PSF stars may have had multiple models tried and the psfMag 88 may not be the value for the chosen model. 89 * in psphotSourceSize, in psphotSourceClassRegion, raw PSF & raw AP for all sources for which size is not yet measured. 90 * in psphotApResid: raw PSF & raw AP for STARS only 91 * in psphotMagnitudes; corrected PSF & AP mags 1 92 2 93 2009.01.24 -
trunk/psphot/doc/outline.txt
r10053 r25755 2 2 Here is a summary outline of the steps taken by psphotReadout: 3 3 4 * setup (choose recipe, choose readout, define break-point) 5 * create mask and weight images if needed, set mask for analysis region 6 * psphotImageMedian : construct a background model image and subtract it 7 * psphotFindPeaks : smooth and find the peak pixels from the smoothed image 8 - no pmSource defined yet, only pmPeak 9 * psphotSourceStats : create sources for each peak and measure their moments 10 - pmSource defined here, with pixels covering SKY_OUTER_RADIUS 11 - no pmModel is defined yet. 12 * psphotBasicDeblend : identify blended sources by proximity and valley depth 13 * psphotRoughClass : source classification guess based on moments 14 - set the source.type,mode. 15 - re-calculate moments for saturated stars 16 * psphotChoosePSF : define the psf model 17 - this generates model fits to the identified psf stars 18 (one for each tested model) 19 - these models are not kept (seems like a waste, but later fits must be consistent) 20 * psphotGuessModels : set the initial PSF model for each object (even EXTENDED) 21 - creates modelPSF entries 4 * setup (choose recipe, readout, etc) 5 6 * create mask and weight images if needed 7 8 * construct a background model image and subtract it 9 10 * generate the significance image (smoothed by small Gaussian) 11 12 * find peaks and associated footprints 13 14 * create sources for each peak and measure moments 15 - scan over several window sigma values and choose an optimal window size 16 - at this stage, the moments are aimed at identifying psf-like objects 17 18 * identify blended sources by proximity and valley depth 19 20 * crude source classification guess based on moments & saturated pixels 21 - major goal is to identify the psf-stars 22 - allows for 2D variations in the psf 23 24 * use the selected PSF candidate stars to generate a PSF model 25 - fits PSF model parameters as a function of position 26 - uses psfMag - apMag to choose order of 2D (minimize systematic error in this value) 27 - generates a PSF residual image & optional 2D variations 28 29 * fit all detected sources to the psf model (linear fit for normalization only) 30 31 * high-quality source classification 32 - uses Mxx, Myy, psfMag - moment->Sum (equiv to apMags) 33 * should the extended / psf cut be a function of galactic latitude? 34 * should the cosmic ray / psf cut be a function of galactic latitude? 35 36 * non-linear fit for all brighter sources to single psf, double psf, or extended source model 37 - sources identified as extended above are fitted with extended source model 38 * are group / clumps of sources being fitted in the best way? 39 * is the psf-model ap mag being measured in an appropriate-size aperture? 40 * is the criterion for choosing between 2 psfs and extended source OK? 41 * is the test for double psf OK? (uses moments to guess starting positions) 42 43 * subtract, re-detect, measure faint sources (PSF-only) 44 45 * optional extended source aperture-like measurements (petrosian, etc) 46 47 * optional extended source non-linear fits (Sersic, etc) 48 49 * measure psfMag-apMag correcion (2D) 50 * convert analysis to use systematic error measurement 51 52 * generate magnitudes 53 54 * measure detection efficiency 55 56 * output -
trunk/psphot/src
- Property svn:ignore
-
old new 18 18 psphotVersionDefinitions.h 19 19 psphotMomentsStudy 20 psphotPetrosianStudy
-
- Property svn:ignore
-
trunk/psphot/src/Makefile.am
r25383 r25755 25 25 libpsphot_la_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 26 26 27 bin_PROGRAMS = psphot psphotTest psphotMomentsStudy 27 bin_PROGRAMS = psphot psphotTest psphotMomentsStudy 28 # bin_PROGRAMS = psphotPetrosianStudy 29 # bin_PROGRAMS = psphot 28 30 29 31 psphot_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) … … 38 40 psphotMomentsStudy_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 39 41 psphotMomentsStudy_LDADD = libpsphot.la 42 43 # psphotPetrosianStudy_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS) 44 # psphotPetrosianStudy_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS) 45 # psphotPetrosianStudy_LDADD = libpsphot.la 40 46 41 47 psphot_SOURCES = \ … … 61 67 psphotMomentsStudy_SOURCES = \ 62 68 psphotMomentsStudy.c 69 70 # psphotPetrosianStudy_SOURCES = \ 71 # psphotPetrosianStudy.c 63 72 64 73 libpsphot_la_SOURCES = \ … … 104 113 psphotExtendedSourceAnalysis.c \ 105 114 psphotExtendedSourceFits.c \ 106 psphotRadialProfile.c \107 psphotPetrosian.c \108 psphotIsophotal.c \109 psphotAnnuli.c \110 psphotKron.c \111 115 psphotKernelFromPSF.c \ 112 116 psphotPSFConvModel.c \ … … 129 133 psphotThreadTools.c \ 130 134 psphotAddNoise.c \ 135 psphotRadialProfile.c \ 136 psphotRadialProfileByAngles.c \ 137 psphotRadiiFromProfiles.c \ 138 psphotEllipticalContour.c \ 139 psphotEllipticalProfile.c \ 140 psphotPetrosian.c \ 141 psphotPetrosianRadialBins.c \ 142 psphotPetrosianStats.c \ 131 143 psphotEfficiency.c 132 144 133 # dropped? psphotGrowthCurve.c 145 # re-instate these 146 # psphotIsophotal.c \ 147 # psphotAnnuli.c \ 148 # psphotKron.c \ 149 # psphotPetrosianVisual.c \ 150 # 151 152 # test versions 153 # psphotPetrosianProfile.c \ 154 # psphotPetrosianAnalysis.c \ 155 # 134 156 135 157 include_HEADERS = \ -
trunk/psphot/src/psphot.h
r25383 r25755 58 58 bool psphotBlendFit_Threaded (psThreadJob *job); 59 59 60 psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections );60 psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections, bool setWindow); 61 61 bool psphotSourceStats_Threaded (psThreadJob *job); 62 62 … … 71 71 72 72 bool psphotApResid (pmConfig *config, pmReadout *readout, psArray *sources, pmPSF *psf); 73 bool psphotApResidMags_Threaded (psThreadJob *job);74 73 75 74 bool psphotSkyReplace (pmConfig *config, const pmFPAview *view); … … 87 86 psImage *psphotSignificanceImage (pmReadout *readout, psMetadata *recipe, const int pass, psImageMaskType maskVal); 88 87 psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax); 89 bool psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const int pass, psImageMaskType maskVal);88 bool psphotFindFootprints (pmDetections *detections, psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int pass, psImageMaskType maskVal); 90 89 psErrorCode psphotCullPeaks(const psImage *img, const psImage *weight, const psMetadata *recipe, psArray *footprints); 91 90 … … 94 93 95 94 // used by ApResid 96 bool psphotMagErrorScale (float *errorScale, float *errorFloor, psVector *dMag, psVector *dap, psVector *mask, int nGroup);97 bool psphotApResid Trend (pmReadout *readout, pmPSF *psf, int Npsf, int scale, float *errorScale, float *errorFloor, psVector *mask, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag);95 pmTrend2D *psphotApResidTrend (float *apResidSysErr, pmReadout *readout, int Nx, int Ny, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag); 96 bool psphotApResidMags_Threaded (psThreadJob *job); 98 97 99 98 // basic support functions … … 109 108 bool psphotInitRadiusEXT (psMetadata *recipe, pmModelType type); 110 109 bool psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal); 110 float psphotSetRadiusEXT (pmReadout *readout, pmSource *source, psImageMaskType markVal); 111 111 112 112 // output functions … … 159 159 bool psphotSetState (pmSource *source, bool curState, psImageMaskType maskVal); 160 160 bool psphotDeblendSatstars (pmReadout *readout, psArray *sources, psMetadata *recipe); 161 bool psphotSourceSize (pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, long first);161 bool psphotSourceSize (pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, long first); 162 162 163 163 bool psphotMakeResiduals (psArray *sources, psMetadata *recipe, pmPSF *psf, psImageMaskType maskVal); … … 167 167 psKernel *psphotKernelFromPSF (pmSource *source, int nPix); 168 168 169 bool psphotRadialProfile (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 170 bool psphotPetrosian (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 171 bool psphotIsophotal (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 172 bool psphotAnnuli (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 173 bool psphotKron (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 169 // functions related to extended source analysis 170 bool psphotRadialProfile (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal); 171 bool psphotRadialProfilesByAngles (pmSource *source, int Nsec, float Rmax); 172 float psphotRadiusFromProfile (pmSource *source, psVector *radius, psVector *flux, float fluxMin, float fluxMax); 173 bool psphotRadiiFromProfiles (pmSource *source, float fluxMin, float fluxMax); 174 bool psphotEllipticalProfile (pmSource *source); 175 bool psphotEllipticalContour (pmSource *source); 174 176 175 177 // psphotVisual functions … … 190 192 bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources); 191 193 bool psphotVisualShowResidualImage (pmReadout *readout); 192 bool psphotVisualPlotApResid (psArray *sources); 193 bool psphotVisualPlotSourceSize (psArray *sources); 194 bool psphotVisualPlotApResid (psArray *sources, float mean, float error); 195 bool psphotVisualPlotSourceSize (psMetadata *recipe, psArray *sources); 196 bool psphotVisualShowPetrosians (psArray *sources); 197 198 // bool psphotPetrosianAnalysis (pmReadout *readout, psArray *sources, psMetadata *recipe); 199 // bool psphotPetrosianProfile (pmReadout *readout, pmSource *source, float skynoise); 200 201 bool psphotPetrosian (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal); 202 bool psphotPetrosianRadialBins (pmSource *source, float radiusMax, float skynoise); 203 bool psphotPetrosianStats (pmSource *source); 204 205 // XXX old versions, currently disabled 206 // bool psphotIsophotal (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 207 // bool psphotAnnuli (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 208 // bool psphotKron (pmSource *source, psMetadata *recipe, psImageMaskType maskVal); 209 210 // XXX visualization functions related to radial profiles (disabled) 211 // bool psphotPetrosianVisualProfileByAngle (psVector *radius, psVector *flux); 212 // bool psphotPetrosianVisualProfileRadii (psVector *radius, psVector *flux, psVector *radiusBin, psVector *fluxBin, float peakFlux, float RadiusRef); 213 // bool psphotPetrosianVisualEllipticalContour (pmPetrosian *petrosian); 214 // bool psphotPetrosianVisualStats (psVector *radBin, psVector *fluxBin, 215 // psVector *refRadius, psVector *meanSB, 216 // psVector *petRatio, psVector *petRatioErr, psVector *fluxSum, 217 // float petRadius, float ratioForRadius, 218 // float petFlux, float radiusForFlux); 194 219 195 220 bool psphotImageQuality (psMetadata *recipe, psArray *sources); -
trunk/psphot/src/psphotAddNoise.c
r25383 r25755 50 50 51 51 // skip sources which were not subtracted 52 // NOTE: this bit is not modified when pmSourceOp applies to noise 52 53 if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) continue; 53 54 … … 79 80 axes.minor *= SIZE; 80 81 newshape = psEllipseAxesToShape (axes); 81 PAR[PM_PAR_I0] = FACTOR* PS_SQR(oldI0);82 PAR[PM_PAR_I0] = FACTOR*oldI0; 82 83 PAR[PM_PAR_SXX] = newshape.sx; 83 84 PAR[PM_PAR_SYY] = newshape.sy; -
trunk/psphot/src/psphotApResid.c
r24878 r25755 33 33 if (!measureAptrend) { 34 34 // 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 35 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN); 38 36 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN); 37 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0); 39 38 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);41 39 return true; 42 40 } … … 53 51 maskVal |= markVal; 54 52 55 // S/N limit to perform full non-linear fits 53 // clipping for extreme outliers 54 // XXX this is not currently defined in the recipe 56 55 float MAX_AP_OFFSET = psMetadataLookupF32 (&status, recipe, "MAX_AP_OFFSET"); 57 56 58 // this is the smallest radius allowed: need to at least extend growth curve down to this... 57 // options for how the photometry is calculated 58 // XXX are these sensible? 59 59 bool IGNORE_GROWTH = psMetadataLookupBool (&status, recipe, "IGNORE_GROWTH"); 60 60 bool INTERPOLATE_AP = psMetadataLookupBool (&status, recipe, "INTERPOLATE_AP"); … … 100 100 PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32); 101 101 PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK); 102 PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK); 102 103 103 104 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for Nskip … … 110 111 } 111 112 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 113 } 126 114 … … 138 126 } else { 139 127 psScalar *scalar = NULL; 140 scalar = job->args->data[ 4];128 scalar = job->args->data[5]; 141 129 Nskip += scalar->data.S32; 142 scalar = job->args->data[ 5];130 scalar = job->args->data[6]; 143 131 Nfail += scalar->data.S32; 144 132 } … … 150 138 151 139 // gather the stats to assess the aperture residuals 152 psVector *mask = psVectorAllocEmpty (300, PS_TYPE_VECTOR_MASK);153 140 psVector *mag = psVectorAllocEmpty (300, PS_TYPE_F32); 154 141 psVector *xPos = psVectorAllocEmpty (300, PS_TYPE_F32); … … 158 145 Npsf = 0; 159 146 147 # ifdef DEBUG 148 FILE *f = fopen ("apresid.dat", "w"); 149 psAssert (f, "failed open"); 150 # endif 151 160 152 for (int i = 0; i < sources->n; i++) { 161 153 source = sources->data[i]; … … 170 162 if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) SKIPSTAR ("EXTENDED"); 171 163 if (source->mode & PM_SOURCE_MODE_CR_LIMIT) SKIPSTAR ("COSMIC RAY"); 164 if (source->mode & PM_SOURCE_MODE_DEFECT) SKIPSTAR ("DEFECT"); 172 165 173 166 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 174 167 continue; 175 168 } 169 170 // XXX make this user-configurable? 171 if (source->errMag > 0.01) continue; 176 172 177 173 // aperture residual for this source … … 185 181 } 186 182 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); 183 # ifdef DEBUG 184 fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f\n", 185 source->peak->xf, source->peak->yf, 186 source->modelPSF->params->data.F32[PM_PAR_XPOS], source->modelPSF->params->data.F32[PM_PAR_YPOS], 187 source->psfMag, source->apMag, source->errMag, 188 source->modelPSF->params->data.F32[PM_PAR_I0], 189 source->modelPSF->params->data.F32[PM_PAR_SXX], source->modelPSF->params->data.F32[PM_PAR_SXY], source->modelPSF->params->data.F32[PM_PAR_SYY], 190 source->modelPSF->params->data.F32[PM_PAR_7]); 191 # endif 192 if (!isfinite(source->psfMag)) psAbort ("nan in psfMag"); 193 if (!isfinite(source->errMag)) psAbort ("nan in errMag"); 194 if (!isfinite(source->apMag)) psAbort ("nan in apMag"); 195 if (!isfinite(model->params->data.F32[PM_PAR_XPOS])) psAbort ("nan in xPos"); 196 if (!isfinite(model->params->data.F32[PM_PAR_YPOS])) psAbort ("nan in yPos"); 197 198 psVectorAppend (mag, source->psfMag); 199 psVectorAppend (dMag,source->errMag); 200 psVectorAppend (apResid, dap); 201 psVectorAppend (xPos, model->params->data.F32[PM_PAR_XPOS]); 202 psVectorAppend (yPos, model->params->data.F32[PM_PAR_YPOS]); 202 203 Npsf ++; 203 204 } … … 205 206 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "measure aperture residuals for %d objects (%d skipped, %d failed, %ld invalid)\n", 206 207 Npsf, Nskip, Nfail, sources->n - Npsf - Nskip - Nfail); 208 209 # ifdef DEBUG 210 fclose (f); 211 # endif 207 212 208 213 // XXX choose a better value here? … … 212 217 } 213 218 214 // XXX deprecating the old code which allowed the ApResid to be fitted as a function of flux and r^2/flux215 // 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 fit217 // systematic error information218 float errorScale = 0.0; 219 float errorFloor = 0.0;220 219 // XXX set the min number of needed source more carefully 220 if ((Npsf < 15) && (APTREND_ORDER_MAX >= 4)) APTREND_ORDER_MAX = 3; 221 if ((Npsf < 11) && (APTREND_ORDER_MAX >= 3)) APTREND_ORDER_MAX = 2; 222 if ((Npsf < 8) && (APTREND_ORDER_MAX >= 2)) APTREND_ORDER_MAX = 1; 223 224 psFree (psf->ApTrend); 225 psf->ApTrend = NULL; 221 226 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 227 228 // as we loop over orders, we need to refer to the initial selection, but we modify the 229 // option values to match the current guess: save the max values here: 230 int NX = readout->image->numCols; 231 int NY = readout->image->numRows; 226 232 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 233 234 int Nx, Ny; 235 if (NX > NY) { 236 Nx = i; 237 Ny = PS_MAX (1, (int)(i * (NY / (float)(NX)) + 0.5)); 238 } else { 239 Ny = i; 240 Nx = PS_MAX (1, (int)(i * (NX / (float)(NY)) + 0.5)); 241 } 242 243 float errorFloor; 244 pmTrend2D *apTrend = psphotApResidTrend (&errorFloor, readout, Nx, Ny, xPos, yPos, apResid, dMag); 245 if (!apTrend) { 246 continue; 247 } 248 249 // apply ApTrend results 250 // float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5; 251 // float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5; 252 // float ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center 253 // if (!isfinite(ApResid)) psAbort("nan apresid @ center"); 254 255 // store the minimum errorFloor and best ApTrend to keep 233 256 if (errorFloor < errorFloorMin) { 234 257 errorFloorMin = errorFloor; 235 entryMin = i; 258 psFree (psf->ApTrend); 259 psf->ApTrend = psMemIncrRefCounter(apTrend); 236 260 } 237 } 238 if (entryMin == -1) { 261 psFree (apTrend); 262 } 263 if (psf->ApTrend == NULL) { 239 264 psWarning("Failed to find a valid aperture residual value"); 240 265 goto escape; 241 266 } 242 267 243 // XXX catch error condition 244 psphotApResidTrend (readout, psf, Npsf, entryMin, &errorScale, &errorFloor, mask, xPos, yPos, apResid, dMag); 268 // apply ApTrend results 269 float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5; 270 float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5; 271 272 psf->ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center 273 psf->dApResid = errorFloorMin; 274 psf->nApResid = Npsf; 275 276 // save results for later output 277 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", psf->ApResid); 278 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", psf->dApResid); 279 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", psf->nApResid); 280 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", psf->growth->apLoss); 281 282 psLogMsg ("psphot.apresid", PS_LOG_DETAIL, "aperture residual: %f +/- %f\n", psf->ApResid, psf->dApResid); 283 psLogMsg ("psphot.apresid", PS_LOG_INFO, "measure full-frame aperture residuals for %d sources: %f sec\n", Npsf, psTimerMark ("psphot.apresid")); 284 285 psFree (xPos); 286 psFree (yPos); 287 psFree (apResid); 288 psFree (mag); 289 psFree (dMag); 290 291 psphotVisualPlotApResid (sources, psf->ApResid, psf->dApResid); 292 293 return true; 294 295 escape: 296 // save nan values since these were not calculated 297 psMetadataAdd (recipe, PS_LIST_TAIL, "APMIFIT", PS_DATA_F32 | PS_META_REPLACE, "aperture residual", NAN); 298 psMetadataAdd (recipe, PS_LIST_TAIL, "DAPMIFIT", PS_DATA_F32 | PS_META_REPLACE, "ap residual scatter", NAN); 299 psMetadataAdd (recipe, PS_LIST_TAIL, "NAPMIFIT", PS_DATA_S32 | PS_META_REPLACE, "number of apresid stars", 0); 300 psMetadataAdd (recipe, PS_LIST_TAIL, "APLOSS", PS_DATA_F32 | PS_META_REPLACE, "aperture loss (mag)", NAN); 301 302 psFree (xPos); 303 psFree (yPos); 304 psFree (apResid); 305 psFree (mag); 306 psFree (dMag); 307 return false; 308 } 309 310 pmTrend2D *psphotApResidTrend (float *apResidSysErr, pmReadout *readout, int Nx, int Ny, psVector *xPos, psVector *yPos, psVector *apResid, psVector *dMag) { 311 312 // the mask marks the values not used to calculate the ApTrend 313 psVector *mask = psVectorAlloc(xPos->n, PS_TYPE_VECTOR_MASK); 314 psVectorInit (mask, 0); 315 316 // XXX allow user to set this optionally? 317 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); 318 319 // measure Trend2D for the current spatial scale 320 pmTrend2D *apTrend = pmTrend2DAlloc (PM_TREND_MAP, readout->image, Nx, Ny, stats); 321 322 // XXX somewhat arbitrary: soften the errors so the few bright stars do not totally dominate: 323 // XXX use this or not? probably not, since this is the point of the systematic error analysis 324 psVector *dMagSoft = psVectorAlloc (dMag->n, PS_TYPE_F32); 325 for (int i = 0; i < dMag->n; i++) { 326 dMagSoft->data.F32[i] = hypot(dMag->data.F32[i], 0.005); 327 } 328 329 // XXX test for errors here 330 if (!pmTrend2DFit (apTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft)) { 331 psWarning("Failed to fit trend for %d x %d map", Nx, Ny); 332 psFree (apTrend); 333 return NULL; 334 } 335 if (apTrend->mode == PM_TREND_MAP) { 336 // p_psImagePrint (2, apTrend->map->map, "ApTrend Before"); // XXX TEST: 337 psImageMapRepair (apTrend->map->map); 338 // p_psImagePrint (2, apTrend->map->map, "ApTrend After"); // XXX TEST: 339 } 245 340 246 341 // construct the fitted values and the residuals 247 psVector *apResidFit = pmTrend2DEvalVector ( psf->ApTrend, mask, 0xff, xPos, yPos);342 psVector *apResidFit = pmTrend2DEvalVector (apTrend, mask, 0xff, xPos, yPos); 248 343 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"); 344 345 // measure systematic error 346 *apResidSysErr = psVectorSystematicError (apResidRes, dMag, 0.10); 347 if (!isfinite(*apResidSysErr)) { 348 psWarning("Failed to find systematic error for %d x %d map", Nx, Ny); 349 psFree (apTrend); 350 return NULL; 351 } 352 353 psLogMsg ("psphot.apresid", PS_LOG_INFO, "result of %d x %d grid\n", Nx, Ny); 354 psLogMsg ("psphot.apresid", PS_LOG_INFO, "systematic scatter floor: %f\n", *apResidSysErr); 355 356 if (psTraceGetLevel("psphot") >= 4) { 357 char filename[64]; 358 snprintf (filename, 64, "apresid.%dx%d.dat", Nx, Ny); 359 FILE *dumpFile = fopen (filename, "w"); 253 360 for (int i = 0; i < xPos->n; i++) { 254 fprintf (dumpFile, "%f %f %f %f %f%f %f %x\n",361 fprintf (dumpFile, "%f %f %f %f %f %f %x\n", 255 362 xPos->data.F32[i], yPos->data.F32[i], 256 mag->data.F32[i], dMag->data.F32[i], dMagSys->data.F32[i],363 dMag->data.F32[i], hypot(dMag->data.F32[i], *apResidSysErr), 257 364 apResid->data.F32[i], apResidRes->data.F32[i], 258 365 mask->data.PS_TYPE_VECTOR_MASK_DATA[i]); … … 261 368 } 262 369 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 370 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 371 psFree (stats); 464 372 psFree (dMagSoft); … … 466 374 psFree (apResidRes); 467 375 468 return true;376 return apTrend; 469 377 } 470 378 … … 480 388 pmSourcePhotometryMode photMode = PS_SCALAR_VALUE(job->args->data[2],S32); 481 389 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3],PS_TYPE_IMAGE_MASK_DATA); 390 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[4],PS_TYPE_IMAGE_MASK_DATA); 482 391 483 392 for (int i = 0; i < sources->n; i++) { … … 490 399 if (source->mode & PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR"); 491 400 492 if (!pmSourceMagnitudes (source, psf, photMode, maskVal)) { 493 Nskip ++; 494 psTrace ("psphot", 3, "skip : bad source mag"); 495 continue; 401 // replace object in image 402 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 403 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 496 404 } 497 405 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; 406 // clear the mask bit and set the circular mask pixels 407 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 408 psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal); 409 410 bool status = pmSourceMagnitudes (source, psf, photMode, maskVal); 411 412 // clear the mask bit 413 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 414 415 // re-subtract the object, leave local sky 416 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 417 418 if (!status) { 419 Nskip ++; 420 psTrace ("psphot", 3, "skip : bad source mag"); 421 continue; 422 } 423 424 if (!isfinite(source->apMag) || !isfinite(source->psfMag)) { 425 Nfail ++; 426 psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag); 427 continue; 428 } 429 source->mode |= PM_SOURCE_MODE_AP_MAGS; 504 430 } 505 431 506 432 // change the value of a scalar on the array (wrap this and put it in psArray.h) 507 scalar = job->args->data[ 4];433 scalar = job->args->data[5]; 508 434 scalar->data.S32 = Nskip; 509 435 510 scalar = job->args->data[ 5];436 scalar = job->args->data[6]; 511 437 scalar->data.S32 = Nfail; 512 438 513 439 return true; 514 440 } 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 -
trunk/psphot/src/psphotBlendFit.c
r24029 r25755 254 254 pmSourceCacheModel (source, maskVal); 255 255 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 256 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;257 256 } 258 257 … … 365 364 pmSourceCacheModel (source, maskVal); 366 365 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 367 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;368 366 } 369 367 … … 374 372 *nfail = Nfail; 375 373 374 // moments are modified by the fit; re-display 375 psphotVisualPlotMoments (recipe, sources); 376 psphotVisualShowResidualImage (readout); 377 376 378 return true; 377 379 } -
trunk/psphot/src/psphotChoosePSF.c
r23989 r25755 1 1 # include "psphotInternal.h" 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);16 }17 2 18 3 // try PSF models and select best option … … 73 58 // get the fixed PSF fit radius 74 59 // XXX check that PSF_FIT_RADIUS < SKY_OUTER_RADIUS 75 options->radius = psMetadataLookupF32 (&status, recipe, "PSF_FIT_RADIUS"); 76 assert (status); 60 // options->radius = psMetadataLookupF32 (&status, recipe, "PSF_FIT_RADIUS"); 61 // assert (status); 62 63 // We have calculated a Gaussian window function, use that for both the PSF fit radius and 64 // the aperture radius (scaling SIGMA) 65 float gaussSigma = psMetadataLookupF32(&status, recipe, "MOMENTS_GAUSS_SIGMA"); 66 float fitScale = psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS_SCALE"); 67 float apScale = psMetadataLookupF32(&status, recipe, "PSF_APERTURE_SCALE"); 68 options->fitRadius = (int)(fitScale*gaussSigma); 69 options->apRadius = (int)(apScale*gaussSigma); 70 71 // XXX use the same radii for standard analysis as for the PSF creation 72 psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_FIT_RADIUS", PS_META_REPLACE, "fit radius", options->fitRadius); 73 psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_APERTURE", PS_META_REPLACE, "psf aperture", options->apRadius); 77 74 78 75 // XXX ROBUST seems to be too agressive given the small numbers. … … 99 96 100 97 psArray *stars = psArrayAllocEmpty (sources->n); 101 102 // psphotCountPSFStars (sources);103 98 104 99 // select the candidate PSF stars (pointers to original sources) … … 115 110 } 116 111 117 // psphotCountPSFStars (sources);118 119 112 // check that the identified psf stars sufficiently cover the region; if not, extend the 120 113 // limits somewhat 121 114 psphotCheckStarDistribution (stars, sources, options); 122 123 // psphotCountPSFStars (sources);124 115 125 116 psLogMsg ("psphot.pspsf", PS_LOG_DETAIL, "selected candidate %ld PSF objects\n", stars->n); … … 289 280 // XXX test dump of psf star data and psf-subtracted image 290 281 if (psTraceGetLevel("psphot.psfstars") > 5) { 291 psphotDumpPSFStars (readout, try, options-> radius, maskVal, markVal);282 psphotDumpPSFStars (readout, try, options->fitRadius, maskVal, markVal); 292 283 } 293 284 294 285 // 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 286 pmPSF *psf = psMemIncrRefCounter(try->psf); 298 287 psFree (models); … … 305 294 } 306 295 307 // psphotCountPSFStars (sources);308 309 296 char *modelName = pmModelClassGetName (psf->type); 310 297 psLogMsg ("psphot.pspsf", PS_LOG_INFO, "select psf model: %f sec\n", psTimerMark ("psphot.choose.psf")); … … 341 328 // create modelPSF from this model 342 329 pmModel *modelPSF = pmModelFromPSFforXY (psf, xc, yc, 1.0); 343 if (!modelPSF) continue; 330 if (!modelPSF) { 331 fprintf (stderr, "?"); 332 continue; 333 } 344 334 345 335 // get the model full-width at half-max … … 354 344 355 345 float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major); 356 if (!isfinite(FWHM_MAJOR) || !isfinite(FWHM_MINOR)) continue; 346 if (!isfinite(FWHM_MAJOR) || !isfinite(FWHM_MINOR)) { 347 fprintf (stderr, "!"); 348 continue; 349 } 357 350 psVectorAppend (fwhmMajor, FWHM_MAJOR); 358 351 psVectorAppend (fwhmMinor, FWHM_MINOR); -
trunk/psphot/src/psphotEfficiency.c
- Property svn:mergeinfo changed
/branches/eam_branches/20090715/psphot/src/psphotEfficiency.c (added) merged: 25409,25433,25746,25750
- Property svn:mergeinfo changed
-
trunk/psphot/src/psphotExtendedSourceAnalysis.c
r21519 r25755 21 21 } 22 22 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"); 23 // XXX require petrosian analysis for non-linear fits? 24 25 // XXX temporary user-supplied systematic sky noise measurement (derive from background model) 26 float skynoise = psMetadataLookupF32 (&status, recipe, "SKY.NOISE"); 27 28 # if (0) 29 // if backModel or backStdev are missing, the values of sky and/or skyErr will be set to NAN 30 // XXX use this to set skynoise 31 pmReadout *backModel = psphotSelectBackground (config, view); 32 pmReadout *backStdev = psphotSelectBackgroundStdev (config, view); 33 # endif 27 34 28 35 // S/N limit to perform full non-linear fits … … 38 45 sources = psArraySort (sources, pmSourceSortBySN); 39 46 40 // XXX some init functions for the extended source recipe options? 47 // option to limit analysis to a specific region 48 char *region = psMetadataLookupStr (&status, recipe, "ANALYSIS_REGION"); 49 psRegion AnalysisRegion = psRegionForImage (readout->image, psRegionFromString (region)); 50 if (psRegionIsNaN (AnalysisRegion)) psAbort("analysis region mis-defined"); 41 51 42 52 // choose the sources of interest … … 49 59 if (source->type == PM_SOURCE_TYPE_DEFECT) continue; 50 60 if (source->type == PM_SOURCE_TYPE_SATURATED) continue; 61 if (source->mode & PM_SOURCE_MODE_DEFECT) continue; 62 if (source->mode & PM_SOURCE_MODE_SATSTAR) continue; 63 if (!(source->mode & PM_SOURCE_MODE_EXT_LIMIT)) continue; 51 64 52 65 // limit selection to some SN limit … … 68 81 // if we request any of these measurements, we require the radial profile 69 82 if (doPetrosian || doIsophotal || doAnnuli || doKron) { 70 if (!psphotRadialProfile (source, recipe, maskVal)) {83 if (!psphotRadialProfile (source, recipe, skynoise, maskVal)) { 71 84 // all measurements below require the radial profile; skip them all 72 85 // re-subtract the object, leave local sky 73 86 psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My); 74 87 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 75 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;76 88 continue; 77 89 } … … 79 91 } 80 92 93 // Petrosian Mags 94 if (doPetrosian) { 95 if (!psphotPetrosian (source, recipe, skynoise, maskVal)) { 96 psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My); 97 } else { 98 psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My); 99 Npetro ++; 100 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS; 101 } 102 } 103 104 # if (0) 81 105 // Isophotal Mags 82 106 if (doIsophotal) { … … 89 113 } 90 114 } 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 115 // Kron Mags 104 116 if (doKron) { … … 111 123 } 112 124 } 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 } 125 # endif 124 126 125 127 // re-subtract the object, leave local sky 126 128 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 127 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED; 129 130 if (source->extpars) { 131 pmSourceRadialProfileFreeVectors(source->extpars->profile); 132 } 128 133 } 129 134 … … 133 138 psLogMsg ("psphot", PS_LOG_INFO, " %d annuli\n", Nannuli); 134 139 psLogMsg ("psphot", PS_LOG_INFO, " %d kron\n", Nkron); 140 141 psphotVisualShowResidualImage (readout); 142 143 if (doPetrosian) { 144 psphotVisualShowPetrosians (sources); 145 } 146 135 147 return true; 136 148 } -
trunk/psphot/src/psphotExtendedSourceFits.c
r21519 r25755 226 226 227 227 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 228 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;229 228 230 229 psFree (modelFluxes); … … 253 252 // subtract the best fit from the object, leave local sky 254 253 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 255 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;256 254 257 255 // the initial model flux is no longer needed -
trunk/psphot/src/psphotFake.c
- Property svn:mergeinfo changed
/branches/eam_branches/20090715/psphot/src/psphotFake.c (added) merged: 25409,25627,25746,25749-25750
- Property svn:mergeinfo changed
-
trunk/psphot/src/psphotFindDetections.c
r21183 r25755 52 52 // optionally merge peaks into footprints 53 53 if (useFootprints) { 54 psphotFindFootprints (detections, significance, readout, recipe, pass, maskVal);54 psphotFindFootprints (detections, significance, readout, recipe, threshold, pass, maskVal); 55 55 } 56 56 -
trunk/psphot/src/psphotFindFootprints.c
r24274 r25755 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; -
trunk/psphot/src/psphotFindPeaks.c
r21519 r25755 31 31 peak->SN = sqrt(peak->value); 32 32 peak->flux = readout->image->data.F32[peak->y-row0][peak->x-col0]; 33 // if (peak->flux / peak->value > 5.0/12.0) { 34 // psWarning ("odd peak levels (1)"); 35 // } 36 // if (peak->value / peak->flux > 5*12.0) { 37 // psWarning ("odd peak levels (2)"); 38 // } 33 39 if (readout->variance && isfinite (peak->dx)) { 34 40 peak->dx *= sqrt(readout->variance->data.F32[peak->y-row0][peak->x-col0]); -
trunk/psphot/src/psphotFitSourcesLinear.c
r25383 r25755 76 76 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) continue; 77 77 } else { 78 if (source->mode & PM_SOURCE_MODE_BLEND) continue;78 // if (source->mode & PM_SOURCE_MODE_BLEND) continue; 79 79 } 80 80 … … 186 186 if (SKY_FIT_LINEAR) { 187 187 psSparseBorderSolve (&norm, &skyfit, constraint, border, 5); 188 fprintf (stderr, "skyfit: %f\n", skyfit->data.F32[0]);188 psLogMsg ("psphot", PS_LOG_MINUTIA, "skyfit: %f\n", skyfit->data.F32[0]); 189 189 } else { 190 190 norm = psSparseSolve (NULL, constraint, sparse, 5); … … 215 215 // subtract object 216 216 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 217 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;218 217 } 219 218 psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "sub models: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem); … … 239 238 240 239 psphotVisualShowResidualImage (readout); 241 psphotVisualShowFlags (sources);240 // psphotVisualShowFlags (sources); 242 241 243 242 return true; … … 264 263 float x = model->params->data.F32[PM_PAR_XPOS]; 265 264 float y = model->params->data.F32[PM_PAR_YPOS]; 266 psImageMaskCircle (source->maskView, x, y, model-> radiusFit, "AND", PS_NOT_IMAGE_MASK(markVal));265 psImageMaskCircle (source->maskView, x, y, model->fitRadius, "AND", PS_NOT_IMAGE_MASK(markVal)); 267 266 } 268 267 -
trunk/psphot/src/psphotFitSourcesLinearStack.c
r24584 r25755 168 168 // subtract object 169 169 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 170 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;171 170 } 172 171 psLogMsg ("psphot.ensemble", PS_LOG_MINUTIA, "sub models: %f sec (%d elements)\n", psTimerMark ("psphot.linear"), sparse->Nelem); -
trunk/psphot/src/psphotGuessModels.c
r24876 r25755 177 177 178 178 // set the source PSF model 179 psAssert (source->modelPSF == NULL, "failed to free one of the models?"); 179 180 source->modelPSF = modelPSF; 180 181 source->modelPSF->residuals = psf->residuals; 181 182 182 183 pmSourceCacheModel (source, maskVal); // ALLOC x14 (!) 183 184 184 } 185 185 -
trunk/psphot/src/psphotImageLoop.c
r23957 r25755 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 -
trunk/psphot/src/psphotImageQuality.c
r23989 r25755 279 279 #endif 280 280 281 psLogMsg ("psphot", PS_LOG_INFO, "Image Quality Stats from %ld psf stars : FWHM (major, minor) : %f, %f\n",281 psLogMsg ("psphot", PS_LOG_INFO, "Image Quality Stats from %ld psf stars : FWHM (major, minor) [pixels]: %f, %f\n", 282 282 M2->n, fwhm_major, fwhm_minor); 283 283 284 psLogMsg ("psphot", PS_LOG_INFO, "M_2 : %f +/- %f, M_3 : %f +/- %f, M_4 : %f +/- %f \n",284 psLogMsg ("psphot", PS_LOG_INFO, "M_2 : %f +/- %f, M_3 : %f +/- %f, M_4 : %f +/- %f [pixels^n]\n", 285 285 vM2, dM2, vM3, dM3, vM4, dM4); 286 286 -
trunk/psphot/src/psphotMagnitudes.c
r25383 r25755 71 71 PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32); 72 72 PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK); 73 PS_ARRAY_ADD_SCALAR(job->args, markVal, PS_TYPE_IMAGE_MASK); 73 74 PS_ARRAY_ADD_SCALAR(job->args, 0, PS_TYPE_S32); // this is used as a return value for nAp 74 75 … … 102 103 fprintf (stderr, "error with job\n"); 103 104 } else { 104 psScalar *scalar = job->args->data[ 7];105 psScalar *scalar = job->args->data[8]; 105 106 Nap += scalar->data.S32; 106 107 } … … 127 128 pmSourcePhotometryMode photMode = PS_SCALAR_VALUE(job->args->data[5],S32); 128 129 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[6],PS_TYPE_IMAGE_MASK_DATA); 130 psImageMaskType markVal = PS_SCALAR_VALUE(job->args->data[7],PS_TYPE_IMAGE_MASK_DATA); 129 131 130 132 for (int i = 0; i < sources->n; i++) { 131 133 pmSource *source = (pmSource *) sources->data[i]; 132 status = pmSourceMagnitudes (source, psf, photMode, maskVal); 134 135 // replace object in image 136 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 137 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 138 } 139 140 // clear the mask bit and set the circular mask pixels 141 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 142 psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal); 143 144 status = pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal 133 145 if (status && isfinite(source->apMag)) Nap ++; 146 147 // clear the mask bit 148 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 149 150 // re-subtract the object, leave local sky 151 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 134 152 135 153 if (backModel) { … … 155 173 156 174 // change the value of a scalar on the array (wrap this and put it in psArray.h) 157 psScalar *scalar = job->args->data[ 7];175 psScalar *scalar = job->args->data[8]; 158 176 scalar->data.S32 = Nap; 159 177 -
trunk/psphot/src/psphotMakeFluxScale.c
r20453 r25755 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 -
trunk/psphot/src/psphotMakeResiduals.c
r23989 r25755 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 307 } 294 //resid->variance->data.F32[oy][ox] = XXX;295 308 } 296 309 } -
trunk/psphot/src/psphotMaskReadout.c
r24484 r25755 33 33 } 34 34 35 bool softenVariance = psMetadataLookupBool (&status, recipe, "SOFTEN.VARIANCE"); 36 float softenFraction = psMetadataLookupF32 (&status, recipe, "SOFTEN.VARIANCE.FRACTION"); 37 35 38 // make this an option via the recipe 36 if ( 0) {39 if (softenVariance) { 37 40 psImage *im = readout->image; 38 41 psImage *wt = readout->variance; 39 psImage *mk = readout->mask;40 42 for (int j = 0; j < im->numRows; j++) { 41 43 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; 44 if (!isfinite(im->data.F32[j][i])) continue; 45 if (!isfinite(wt->data.F32[j][i])) continue; 46 float sysError = softenFraction * im->data.F32[j][i]; 47 wt->data.F32[j][i] += PS_SQR(sysError); 44 48 } 45 49 } -
trunk/psphot/src/psphotOutput.c
r21366 r25755 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 … … 160 192 psMetadataItemSupplement (header, recipe, "DAPMIFIT"); 161 193 psMetadataItemSupplement (header, recipe, "NAPMIFIT"); 162 psMetadataItemSupplement (header, recipe, "SKYBIAS");163 psMetadataItemSupplement (header, recipe, "SKYSAT");164 194 165 195 // PSF model parameters (shape values for image center) … … 256 286 psImageKeepCircle (source->maskObj, x, y, radius, "OR", markVal); 257 287 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));288 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 259 289 } 260 290 -
trunk/psphot/src/psphotPSFConvModel.c
r21183 r25755 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)) 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 -
trunk/psphot/src/psphotPetrosian.c
r21183 r25755 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->profile, "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->petrosian_80->radius, 27 source->extpars->petrosian_80->flux, 28 source->extpars->profile->axes.minor/source->extpars->profile->axes.major, 29 source->extpars->profile->axes.theta*PS_DEG_RAD); 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 } -
trunk/psphot/src/psphotRadialProfile.c
r21366 r25755 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 } 18 19 bool psphotRadialProfile (pmSource *source, psMetadata *recipe, psImageMaskType maskVal) { 3 bool psphotRadialProfile (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal) { 20 4 21 5 // allocate pmSourceExtendedParameters, if not already defined … … 28 12 } 29 13 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); 14 // XXX these need to go into recipe values 15 int Nsec = 24; 16 float Rmax = 200; 17 float fluxMin = 0.0; 18 float fluxMax = source->peak->flux; 34 19 35 psVector *radius = source->extpars->profile->radius; 36 psVector *flux = source->extpars->profile->flux; 37 psVector *variance = source->extpars->profile->variance; 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; 26 } 38 27 39 // XXX use the extended source model here for Xo, Yo? 40 // XXX define a radius scaled to the elliptical contour? 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 50% 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 } 41 35 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)) { 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 70 49 return true; 71 50 } -
trunk/psphot/src/psphotRadiusChecks.c
r21183 r25755 7 7 // and a per-object radius is calculated) 8 8 9 static float PSF_APERTURE = 0; // radius to use in PSF aperture mags 10 11 9 12 bool psphotInitRadiusPSF(const psMetadata *recipe, const pmModelType type) { 10 13 … … 13 16 PSF_FIT_NSIGMA = psMetadataLookupF32(&status, recipe, "PSF_FIT_NSIGMA"); 14 17 PSF_FIT_PADDING = psMetadataLookupF32(&status, recipe, "PSF_FIT_PADDING"); 15 PSF_FIT_RADIUS = psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS"); 18 PSF_FIT_RADIUS = psMetadataLookupF32(&status, recipe, "PSF_FIT_RADIUS"); 19 PSF_APERTURE = psMetadataLookupF32(&status, recipe, "PSF_APERTURE"); 16 20 17 21 return true; … … 34 38 radiusFit = model->modelRadius(model->params, 1.0); 35 39 } 40 model->fitRadius = (RADIUS_TYPE)(radiusFit + PSF_FIT_PADDING); 41 } else { 42 model->fitRadius = radiusFit; 36 43 } 37 model->radiusFit = (RADIUS_TYPE)(radiusFit + PSF_FIT_PADDING); 38 39 if (isnan(model->radiusFit)) psAbort("error in radius"); 44 if (isnan(model->fitRadius)) psAbort("error in radius"); 40 45 41 46 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 42 model-> radiusFit*= 2;47 model->fitRadius *= 2; 43 48 } 44 49 45 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit); 50 // radius used to measure aperture photometry 51 source->apRadius = PSF_APERTURE; 52 53 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius); 46 54 47 55 // set the mask to flag the excluded pixels 48 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model-> radiusFit, "OR", markVal);56 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius, "OR", markVal); 49 57 return status; 50 58 } … … 58 66 59 67 // 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 68 float radiusFit = PSF_FIT_RADIUS; 69 if (radiusFit <= 0) { // use fixed radius 70 if (moments == NULL) { 71 radiusFit = model->modelRadius(model->params, PSF_FIT_NSIGMA*moments->dSky); 72 } else { 73 radiusFit = model->modelRadius(model->params, 1.0); 74 } 75 model->fitRadius = (RADIUS_TYPE)(radiusFit + PSF_FIT_PADDING); 76 } else { 77 model->fitRadius = radiusFit; 78 } 79 if (isnan(model->fitRadius)) psAbort("error in radius"); 80 81 // above sets a radius for a single star, bump by blend separation 82 model->fitRadius += dR; 83 63 84 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 64 model-> radiusFit*= 2;85 model->fitRadius *= 2; 65 86 } 66 87 67 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->radiusFit); 88 // radius used to measure aperture photometry 89 source->apRadius = PSF_APERTURE; 90 91 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius); 68 92 69 93 // set the mask to flag the excluded pixels 70 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model-> radiusFit, "OR", markVal);94 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius, "OR", markVal); 71 95 return status; 72 96 } … … 74 98 static float EXT_FIT_NSIGMA; 75 99 static float EXT_FIT_PADDING; 100 static float EXT_FIT_MAX_RADIUS; 76 101 77 102 bool psphotInitRadiusEXT (psMetadata *recipe, pmModelType type) { … … 79 104 bool status; 80 105 81 EXT_FIT_NSIGMA = psMetadataLookupF32 (&status, recipe, "EXT_FIT_NSIGMA"); 82 EXT_FIT_PADDING = psMetadataLookupF32 (&status, recipe, "EXT_FIT_PADDING"); 106 EXT_FIT_NSIGMA = psMetadataLookupF32 (&status, recipe, "EXT_FIT_NSIGMA"); 107 EXT_FIT_PADDING = psMetadataLookupF32 (&status, recipe, "EXT_FIT_PADDING"); 108 EXT_FIT_MAX_RADIUS = psMetadataLookupF32 (&status, recipe, "EXT_FIT_MAX_RADIUS"); 83 109 84 110 return true; … … 86 112 87 113 // call this function whenever you (re)-define the EXT model 114 float psphotSetRadiusEXT (pmReadout *readout, pmSource *source, psImageMaskType markVal) { 115 116 psAssert (source, "source not defined??"); 117 psAssert (source->peak, "peak not defined??"); 118 119 pmPeak *peak = source->peak; 120 121 // set the radius based on the footprint: 122 if (!peak->footprint) goto escape; 123 pmFootprint *footprint = peak->footprint; 124 if (!footprint->spans) goto escape; 125 if (footprint->spans->n < 1) goto escape; 126 127 // find the max radius 128 float radius = 0.0; 129 for (int j = 0; j < footprint->spans->n; j++) { 130 pmSpan *span = footprint->spans->data[j]; 131 132 float dY = span->y - peak->yf; 133 float dX0 = span->x0 - peak->xf; 134 float dX1 = span->x1 - peak->xf; 135 136 radius = PS_MAX (radius, hypot(dY, dX0)); 137 radius = PS_MAX (radius, hypot(dY, dX1)); 138 } 139 140 radius += EXT_FIT_PADDING; 141 if (isnan(radius)) psAbort("error in radius"); 142 143 radius = PS_MIN (radius, EXT_FIT_MAX_RADIUS); 144 145 // redefine the pixels if needed 146 pmSourceRedefinePixels (source, readout, peak->xf, peak->yf, radius); 147 148 // set the mask to flag the excluded pixels 149 psImageKeepCircle (source->maskObj, peak->xf, peak->yf, radius, "OR", markVal); 150 return radius; 151 152 escape: 153 return NAN; 154 // bool result = psphotCheckRadiusEXT (readout, source, model, markVal); 155 // return result; 156 } 157 158 // alternative EXT radius based on model guess (for use without footprints) 88 159 bool psphotCheckRadiusEXT (pmReadout *readout, pmSource *source, pmModel *model, psImageMaskType markVal) { 160 161 psAbort ("do not use this function"); 89 162 90 163 psF32 *PAR = model->params->data.F32; … … 96 169 float rawRadius = model->modelRadius (model->params, EXT_FIT_NSIGMA*moments->dSky); 97 170 98 model-> radiusFit= rawRadius + EXT_FIT_PADDING;99 if (isnan(model-> radiusFit)) psAbort("error in radius");171 model->fitRadius = rawRadius + EXT_FIT_PADDING; 172 if (isnan(model->fitRadius)) psAbort("error in radius"); 100 173 101 174 // redefine the pixels if needed 102 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model-> radiusFit);175 bool status = pmSourceRedefinePixels (source, readout, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius); 103 176 104 177 // set the mask to flag the excluded pixels 105 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model-> radiusFit, "OR", markVal);178 psImageKeepCircle (source->maskObj, PAR[PM_PAR_XPOS], PAR[PM_PAR_YPOS], model->fitRadius, "OR", markVal); 106 179 return status; 107 180 } -
trunk/psphot/src/psphotReadout.c
r25738 r25755 81 81 82 82 // construct sources and measure basic stats 83 psArray *sources = psphotSourceStats (config, readout, detections );83 psArray *sources = psphotSourceStats (config, readout, detections, true); 84 84 if (!sources) return false; 85 85 if (!strcasecmp (breakPt, "PEAKS")) { … … 126 126 return psphotReadoutCleanup (config, readout, recipe, detections, psf, sources); 127 127 } 128 129 128 psphotVisualShowPSFModel (readout, psf); 130 129 … … 132 131 psphotLoadExtSources (config, view, sources); 133 132 134 // construct an initial model for each object 133 // construct an initial model for each object, set the radius to fitRadius, set circular fit mask 135 134 psphotGuessModels (config, readout, sources, psf); 136 135 137 // XXX test output of models 138 // psphotTestSourceOutput (readout, sources, recipe, psf); 139 140 // linear PSF fit to source peaks 136 // linear PSF fit to source peaks, subtract the models from the image (in PSF mask) 141 137 psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE); 142 138 … … 144 140 // psphotGuessModels or fitted until psphotFitSourcesLinear. 145 141 psphotVisualShowPSFStars (recipe, psf, sources); 146 psphotVisualShowSatStars (recipe, psf, sources);147 142 148 143 // identify CRs and extended sources 149 psphotSourceSize (config, readout, sources, recipe, 0);144 psphotSourceSize (config, readout, sources, recipe, psf, 0); 150 145 if (!strcasecmp (breakPt, "ENSEMBLE")) { 151 146 goto finish; 152 147 } 148 psphotVisualShowSatStars (recipe, psf, sources); 153 149 154 150 // non-linear PSF and EXT fit to brighter sources 151 // replace model flux, adjust mask as needed, fit, subtract the models (full stamp) 155 152 psphotBlendFit (config, readout, sources, psf); 156 153 … … 158 155 psphotReplaceAllSources (sources, recipe); 159 156 160 // linear fit to include all sources 157 // linear fit to include all sources (subtract again) 161 158 psphotFitSourcesLinear (readout, sources, recipe, psf, TRUE); 162 159 … … 165 162 goto pass1finish; 166 163 } 167 168 // XXX for the moment, drop the re-calc of the background (prove this works) 169 // replace background in residual image 170 // psphotSkyReplace (config, view); 171 // re-measure background model (median, smoothed image) 172 // psphotImageMedian (config, view); 164 // NOTE: possibly re-measure background model here with objects subtracted 173 165 174 166 // add noise for subtracted objects … … 182 174 183 175 // define new sources based on only the new peaks 184 psArray *newSources = psphotSourceStats (config, readout, detections );176 psArray *newSources = psphotSourceStats (config, readout, detections, false); 185 177 186 178 // set source type … … 190 182 } 191 183 192 // create full input models 184 // create full input models, set the radius to fitRadius, set circular fit mask 193 185 psphotGuessModels (config, readout, newSources, psf); 194 186 … … 206 198 207 199 // measure source size for the remaining sources 208 psphotSourceSize (config, readout, sources, recipe, 0);200 psphotSourceSize (config, readout, sources, recipe, psf, 0); 209 201 210 202 psphotExtendedSourceAnalysis (readout, sources, recipe); -
trunk/psphot/src/psphotReadoutFindPSF.c
r23442 r25755 41 41 42 42 // construct sources and measure basic stats (moments, local sky) 43 psArray *sources = psphotSourceStats(config, readout, detections );43 psArray *sources = psphotSourceStats(config, readout, detections, true); 44 44 if (!sources) return false; 45 45 -
trunk/psphot/src/psphotReadoutKnownSources.c
r23442 r25755 41 41 42 42 // construct sources and measure basic stats 43 psArray *sources = psphotSourceStats (config, readout, detections );43 psArray *sources = psphotSourceStats (config, readout, detections, true); 44 44 if (!sources) return false; 45 45 -
trunk/psphot/src/psphotReadoutMinimal.c
r25738 r25755 56 56 57 57 // construct sources and measure basic stats 58 psArray *sources = psphotSourceStats (config, readout, detections );58 psArray *sources = psphotSourceStats (config, readout, detections, true); 59 59 if (!sources) return false; 60 60 -
trunk/psphot/src/psphotReplaceUnfit.c
r25383 r25755 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); … … 41 40 42 41 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 43 source->tmpFlags &= ~PM_SOURCE_TMPF_SUBTRACTED;44 42 } 45 43 psLogMsg ("psphot.replace", PS_LOG_INFO, "replaced models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.replace")); … … 64 62 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) continue; 65 63 66 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 67 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED; 64 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 68 65 } 69 66 psLogMsg ("psphot.replace", PS_LOG_INFO, "replaced models for %ld objects: %f sec\n", sources->n, psTimerMark ("psphot.replace")); … … 71 68 } 72 69 70 # if (0) 73 71 // add source, if the source has been subtracted; do not modify state 74 72 bool psphotAddWithTest (pmSource *source, bool useState, psImageMaskType maskVal) { … … 108 106 return true; 109 107 } 108 # endif -
trunk/psphot/src/psphotRoughClass.c
r23989 r25755 26 26 for (int iy = 0; iy < NY; iy ++) { 27 27 28 psRegion region = psRegionSet(ix*dX, (ix + 1)*dX, iy*dY, (iy + 1)*dY);29 if (!psphotRoughClassRegion (nRegion, ®ion, sources, recipe, havePSF)) {28 psRegion *region = psRegionAlloc (ix*dX, (ix + 1)*dX, iy*dY, (iy + 1)*dY); 29 if (!psphotRoughClassRegion (nRegion, region, sources, recipe, havePSF)) { 30 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); 31 region->x0, region->y0, region->x1, region->y1); 32 psFree (region); 32 33 continue; 33 34 } 34 35 psFree (region); 35 36 nRegion ++; 36 37 } … … 45 46 psphotVisualPlotMoments (recipe, sources); 46 47 psphotVisualShowRoughClass (sources); 47 psphotVisualShowFlags (sources);48 // XXX better visualization: psphotVisualShowFlags (sources); 48 49 49 50 return true; … … 63 64 psMetadata *regionMD = psMetadataLookupPtr (&status, recipe, regionName); 64 65 if (!regionMD) { 66 // allocate the region metadata folder and add this region to it. 65 67 regionMD = psMetadataAlloc(); 66 68 psMetadataAddMetadata (recipe, PS_LIST_TAIL, regionName, PS_META_REPLACE, "psf clump region", regionMD); 67 69 psFree (regionMD); 68 70 } 71 psMetadataAddPtr (regionMD, PS_LIST_TAIL, "REGION", PS_DATA_REGION | PS_META_REPLACE, "psf clump region", region); 69 72 70 73 if (!havePSF) { 71 74 // determine the PSF parameters from the source moment values 75 // XXX why not save the psfClump as a PTR? 72 76 psfClump = pmSourcePSFClump (region, sources, recipe); 73 77 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X", PS_META_REPLACE, "psf clump center", psfClump.X); -
trunk/psphot/src/psphotSetThreads.c
r23218 r25755 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); -
trunk/psphot/src/psphotSourceFits.c
r24592 r25755 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 … … 221 224 if (source->type == PM_SOURCE_TYPE_DEFECT) return false; 222 225 if (source->type == PM_SOURCE_TYPE_SATURATED) return false; 223 if (source->peak->SN < EXT_MIN_SN) return false; 224 226 227 // set the radius based on the footprint (also sets the mask pixels) 228 float radius = psphotSetRadiusEXT (readout, source, markVal); 229 230 // XXX note that this changes the source moments that are published... 225 231 // recalculate the source moments using the larger extended-source moments radius 226 232 // 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; 233 // this uses the footprint to judge both radius and aperture? 234 if (!pmSourceMoments (source, radius, 0.0, 0.0)) return false; 228 235 229 236 psTrace ("psphot", 5, "trying blob...\n"); … … 237 244 // XXX need to handle failures better here 238 245 pmModel *EXT = psphotFitEXT (readout, source, modelTypeEXT, maskVal, markVal); 246 if (!isfinite(EXT->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 247 239 248 okEXT = psphotEvalEXT (tmpSrc, EXT); 240 249 chiEXT = EXT ? EXT->chisq / EXT->nDOF : NAN; … … 246 255 // XXX should I keep / save the flags set in the eval functions? 247 256 257 // clear the circular mask 258 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal)); 259 248 260 // correct first model chisqs for flux trend 249 261 chiDBL = NAN; 250 262 ONE = DBL->data[0]; 251 263 if (ONE) { 264 if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 252 265 chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]); 253 266 ONE->chisqNorm = ONE->chisq / chiTrend; … … 258 271 ONE = DBL->data[1]; 259 272 if (ONE) { 273 if (!isfinite(ONE->params->data.F32[PM_PAR_I0])) psAbort("nan in fit"); 260 274 chiTrend = psPolynomial1DEval (psf->ChiTrend, ONE->params->data.F32[1]); 261 275 ONE->chisqNorm = ONE->chisq / chiTrend; … … 277 291 278 292 // both models failed; reject them both 293 // XXX -- change type flags to psf in this case and keep original moments? 279 294 psFree (EXT); 280 295 psFree (DBL); … … 287 302 // save new model 288 303 source->modelEXT = EXT; 304 source->modelEXT->fitRadius = radius; 289 305 source->type = PM_SOURCE_TYPE_EXTENDED; 290 306 source->mode |= PM_SOURCE_MODE_EXTMODEL; … … 293 309 pmSourceCacheModel (source, maskVal); 294 310 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 295 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED; 311 312 # if (PS_TRACE_ON) 296 313 psTrace ("psphot", 5, "blob as EXT: %f %f\n", EXT->params->data.F32[PM_PAR_XPOS], EXT->params->data.F32[PM_PAR_YPOS]); 314 if (psTraceGetLevel("psphot") >= 6) { 315 psLogMsg ("psphot", 1, "source 2:\n"); 316 for (int i = 0; i < source->modelEXT->params->n; i++) { 317 psLogMsg ("psphot", 1, "PAR %d : %f +/- %f\n", i, source->modelEXT->params->data.F32[i], source->modelEXT->dparams->data.F32[i]); 318 } 319 } 320 # endif 321 297 322 return true; 298 323 … … 304 329 psFree (source->modelPSF); 305 330 source->modelPSF = psMemIncrRefCounter (DBL->data[0]); 306 source->tmpFlags |= PM_SOURCE_TMPF_SUBTRACTED;307 331 source->mode |= PM_SOURCE_MODE_PAIR; 332 source->modelPSF->fitRadius = radius; 308 333 309 334 // copy most data from the primary source (modelEXT, blends stay NULL) 310 // XXX use pmSourceCopy?311 335 pmSource *newSrc = pmSourceCopy (source); 312 336 newSrc->modelPSF = psMemIncrRefCounter (DBL->data[1]); 337 newSrc->modelPSF->fitRadius = radius; 313 338 314 339 // build cached models and subtract … … 317 342 pmSourceCacheModel (newSrc, maskVal); 318 343 pmSourceSub (newSrc, PM_MODEL_OP_FULL, maskVal); 344 345 # if (PS_TRACE_ON) 319 346 psTrace ("psphot", 5, "blob as DBL: %f %f\n", ONE->params->data.F32[PM_PAR_XPOS], ONE->params->data.F32[PM_PAR_YPOS]); 347 if (psTraceGetLevel("psphot") >= 6) { 348 psLogMsg ("psphot", 1, "source 1:\n"); 349 for (int i = 0; i < newSrc->modelPSF->params->n; i++) { 350 psLogMsg ("psphot", 1, "PAR %d : %f +/- %f\n", i, newSrc->modelPSF->params->data.F32[i], newSrc->modelPSF->dparams->data.F32[i]); 351 } 352 psLogMsg ("psphot", 1, "source 2:\n"); 353 for (int i = 0; i < source->modelPSF->params->n; i++) { 354 psLogMsg ("psphot", 1, "PAR %d : %f +/- %f\n", i, source->modelPSF->params->data.F32[i], source->modelPSF->dparams->data.F32[i]); 355 } 356 psphotVisualShowResidualImage (readout); 357 } 358 # endif 320 359 321 360 psArrayAdd (newSources, 100, newSrc); … … 356 395 // save the PSF model from the Ensemble fit 357 396 PSF = source->modelPSF; 358 psphotCheckRadiusPSFBlend (readout, source, PSF, markVal, 8.0);359 397 if (isnan(PSF->params->data.F32[1])) psAbort("nan in dbl fit"); 360 398 … … 389 427 PS_ASSERT (EXT, NULL); 390 428 391 // if (isnan(EXT->params->data.F32[1])) psAbort("nan in ext fit");392 393 psphotCheckRadiusEXT (readout, source, EXT, markVal);394 395 429 if ((source->moments->Mxx < 1e-3) || (source->moments->Myy < 1e-3)) { 396 430 psTrace ("psphot", 5, "problem source: moments: %f %f\n", source->moments->Mxx, source->moments->Myy); … … 401 435 return (EXT); 402 436 } 403 -
trunk/psphot/src/psphotSourcePlots.c
r21183 r25755 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; -
trunk/psphot/src/psphotSourceSize.c
r21519 r25755 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 } psphotSourceSizeOptions; 16 17 bool psphotSourceSizePSF (psphotSourceSizeOptions *options, psArray *sources, pmPSF *psf); 18 bool psphotSourceClass (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options); 19 bool psphotSourceClassRegion (psRegion *region, pmPSFClump *psfClump, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options); 20 bool psphotSourceSizeCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options); 21 bool psphotMaskCosmicRay (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask); 22 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask); 9 23 10 24 // we need to call this function after sources have been fitted to the PSF model and … … 14 28 // deviation from the psf model at the r = FWHM/2 position 15 29 16 bool psphotSourceSize(pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, long first) 30 // XXX use an internal flag to mark sources which have already been measured 31 bool psphotSourceSize(pmConfig *config, pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, long first) 17 32 { 18 33 bool status; 34 psphotSourceSizeOptions options; 19 35 20 36 psTimerStart ("psphot.size"); 21 37 22 38 // 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); 39 options.maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Mask value for bad pixels 40 assert (options.maskVal); 41 42 options.markVal = psMetadataLookupImageMask(&status, recipe, "MARK.PSPHOT"); // Mask value for bad pixels 43 assert (options.markVal); 25 44 26 45 // 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");46 options.crMask = pmConfigMaskGet("CR", config); // Mask value for cosmic rays 47 48 options.nSigmaCR = psMetadataLookupF32 (&status, recipe, "PSPHOT.CR.NSIGMA.LIMIT"); 30 49 assert (status); 31 50 32 float EXT_NSIGMA_LIMIT = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.LIMIT"); 51 // XXX recipe name is not great 52 options.nSigmaApResid = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.LIMIT"); 33 53 assert (status); 34 54 35 int grow = psMetadataLookupS32(&status, recipe, "PSPHOT.CR.GROW"); // Growth size for CRs 36 if (!status || grow < 0) { 55 // XXX recipe name is not great 56 options.nSigmaMoments = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.MOMENTS"); 57 assert (status); 58 59 options.grow = psMetadataLookupS32(&status, recipe, "PSPHOT.CR.GROW"); // Growth size for CRs 60 if (!status || options.grow < 0) { 37 61 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "PSPHOT.CR.GROW is not positive."); 38 62 return false; 39 63 } 40 64 41 floatsoft = psMetadataLookupF32(&status, recipe, "PSPHOT.CR.NSIGMA.SOFTEN"); // Softening parameter42 if (!status || !isfinite( soft) ||soft < 0.0) {65 options.soft = psMetadataLookupF32(&status, recipe, "PSPHOT.CR.NSIGMA.SOFTEN"); // Softening parameter 66 if (!status || !isfinite(options.soft) || options.soft < 0.0) { 43 67 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++) { 49 pmSource *source = sources->data[i]; 50 51 // skip source if it was already measured 52 if (isfinite(source->crNsigma)) { 53 psTrace("psphot", 7, "Not calculating extNsigma,crNsigma since already measured\n"); 54 continue; 68 options.soft = 0.0; 69 } 70 71 // We are using the value psfMag - 2.5*log10(moment.Sum) as a measure of the extendedness 72 // of and object. We need to model this distribution for the PSF stars before we can test 73 // the significance for a specific object 74 // XXX move this to the code that generates the PSF? 75 // XXX store the results on pmPSF? 76 psphotSourceSizePSF (&options, sources, psf); 77 78 // classify the sources based on ApResid and Moments (extended sources) 79 psphotSourceClass(readout, sources, recipe, psf, &options); 80 81 psphotSourceSizeCR (readout, sources, &options); 82 83 psLogMsg ("psphot.size", PS_LOG_INFO, "measure source sizes for %ld sources: %f sec\n", sources->n - first, psTimerMark ("psphot.size")); 84 85 psphotVisualPlotSourceSize (recipe, sources); 86 psphotVisualShowSourceSize (readout, sources); 87 psphotVisualPlotApResid (sources, options.ApResid, options.ApSysErr); 88 89 return true; 90 } 91 92 bool psphotMaskCosmicRay (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) { 93 94 // replace the source flux 95 pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 96 97 // flag this as a CR 98 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 99 pmPeak *peak = source->peak; 100 psAssert (peak, "NULL peak"); 101 102 // grab the matching footprint 103 pmFootprint *footprint = peak->footprint; 104 if (!footprint) { 105 // if we have not footprint, use the old code to mask by isophot 106 psphotMaskCosmicRayIsophot (source, maskVal, crMask); 107 return true; 108 } 109 110 if (!footprint->spans) { 111 // if we have no footprint, use the old code to mask by isophot 112 psphotMaskCosmicRayIsophot (source, maskVal, crMask); 113 return true; 114 } 115 116 // mask all of the pixels covered by the spans of the footprint 117 for (int j = 1; j < footprint->spans->n; j++) { 118 pmSpan *span1 = footprint->spans->data[j]; 119 120 int iy = span1->y; 121 int xs = span1->x0; 122 int xe = span1->x1; 123 124 for (int ix = xs; ix < xe; ix++) { 125 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask; 126 } 127 } 128 return true; 129 } 130 131 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) { 132 133 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 134 pmPeak *peak = source->peak; 135 psAssert (peak, "NULL peak"); 136 137 psImage *mask = source->maskView; 138 psImage *pixels = source->pixels; 139 psImage *variance = source->variance; 140 141 // XXX This should be a recipe variable 142 # define SN_LIMIT 5.0 143 144 int xo = peak->x - pixels->col0; 145 int yo = peak->y - pixels->row0; 146 147 // mark the pixels in this row to the left, then the right 148 for (int ix = xo; ix >= 0; ix--) { 149 float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]); 150 if (SN > SN_LIMIT) { 151 mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask; 152 } 153 } 154 for (int ix = xo + 1; ix < pixels->numCols; ix++) { 155 float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]); 156 if (SN > SN_LIMIT) { 157 mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask; 158 } 159 } 160 161 // for each of the neighboring rows, mark the high pixels if they have a marked neighbor 162 // first go up: 163 for (int iy = PS_MIN(yo, mask->numRows-2); iy >= 0; iy--) { 164 // mark the pixels in this row to the left, then the right 165 for (int ix = 0; ix < pixels->numCols; ix++) { 166 float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]); 167 if (SN < SN_LIMIT) continue; 168 169 bool valid = false; 170 valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix] & crMask); 171 valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix-1] & crMask) : 0; 172 valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix+1] & crMask) : 0; 173 174 if (!valid) continue; 175 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask; 176 } 177 } 178 // next go down: 179 for (int iy = PS_MIN(yo+1, mask->numRows-1); iy < pixels->numRows; iy++) { 180 // mark the pixels in this row to the left, then the right 181 for (int ix = 0; ix < pixels->numCols; ix++) { 182 float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]); 183 if (SN < SN_LIMIT) continue; 184 185 bool valid = false; 186 valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix] & crMask); 187 valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix-1] & crMask) : 0; 188 valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix+1] & crMask) : 0; 189 190 if (!valid) continue; 191 mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask; 192 } 193 } 194 return true; 195 } 196 197 // model the apmifit distribution for the psf stars: 198 bool psphotSourceSizePSF (psphotSourceSizeOptions *options, psArray *sources, pmPSF *psf) { 199 200 // select stats from the psf stars 201 psVector *Ap = psVectorAllocEmpty (100, PS_TYPE_F32); 202 psVector *ApErr = psVectorAllocEmpty (100, PS_TYPE_F32); 203 204 psImageMaskType maskVal = options->maskVal | options->markVal; 205 206 // XXX why PHOT_WEIGHT?? 207 pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_WEIGHT; 208 209 for (int i = 0; i < sources->n; i++) { 210 pmSource *source = sources->data[i]; 211 if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue; 212 213 // replace object in image 214 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 215 pmSourceAdd (source, PM_MODEL_OP_FULL, options->maskVal); 55 216 } 56 217 57 // source must have been subtracted 58 if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) { 218 // clear the mask bit and set the circular mask pixels 219 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal)); 220 psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", options->markVal); 221 222 // XXX can we test if psfMag is set and calculate only if needed? 223 pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal 224 225 // clear the mask bit 226 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal)); 227 228 // re-subtract the object, leave local sky 229 pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal); 230 231 float apMag = -2.5*log10(source->moments->Sum); 232 float dMag = source->psfMag - apMag; 233 234 psVectorAppend (Ap, 100, dMag); 235 psVectorAppend (ApErr, 100, source->errMag); 236 } 237 238 // model the distribution as a mean or median value and a systematic error from that value: 239 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 240 psVectorStats (stats, Ap, NULL, NULL, 0); 241 242 psVector *dAp = psVectorAlloc (Ap->n, PS_TYPE_F32); 243 for (int i = 0; i < Ap->n; i++) { 244 dAp->data.F32[i] = Ap->data.F32[i] - stats->robustMedian; 245 } 246 247 options->ApResid = stats->robustMedian; 248 options->ApSysErr = psVectorSystematicError(dAp, ApErr, 0.05); 249 psLogMsg ("psphot", PS_LOG_DETAIL, "psf - Sum: %f +/- %f\n", options->ApResid, options->ApSysErr); 250 251 psFree (Ap); 252 psFree (ApErr); 253 psFree (stats); 254 psFree (dAp); 255 256 return true; 257 } 258 259 // classify sources based on the combination of psf-mag, Mxx, Myy 260 bool psphotSourceClass (pmReadout *readout, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options) { 261 262 bool status; 263 pmPSFClump psfClump; 264 char regionName[64]; 265 266 psLogMsg("psModules.objects", PS_LOG_INFO, "Source Size classifications: %4s %4s %4s %4s %4s %4s", "Npsf", "Next", "Nsat", "Ncr", "Nmiss", "Nskip"); 267 268 int nRegions = psMetadataLookupS32 (&status, recipe, "PSF.CLUMP.NREGIONS"); 269 for (int i = 0; i < nRegions; i ++) { 270 snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", i); 271 psMetadata *regionMD = psMetadataLookupPtr (&status, recipe, regionName); 272 psAssert (regionMD, "regions must be defined by earlier call to psphotRoughClassRegion"); 273 274 psRegion *region = psMetadataLookupPtr (&status, regionMD, "REGION"); 275 psAssert (region, "regions must be defined by earlier call to psphotRoughClassRegion"); 276 277 // pull FWHM_X,Y from the recipe, use to define psfClump.X,Y 278 psfClump.X = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); psAssert (status, "missing PSF.CLUMP.X"); 279 psfClump.Y = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y"); psAssert (status, "missing PSF.CLUMP.Y"); 280 psfClump.dX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX"); psAssert (status, "missing PSF.CLUMP.DX"); 281 psfClump.dY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY"); psAssert (status, "missing PSF.CLUMP.DY"); 282 283 if ((psfClump.X < 0) || (psfClump.Y < 0) || !psfClump.X || !psfClump.Y || isnan(psfClump.X) || isnan(psfClump.Y)) { 284 psLogMsg ("psphot", 4, "Failed to find a valid PSF clump for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1); 285 continue; 286 } 287 288 if (!psphotSourceClassRegion (region, &psfClump, sources, recipe, psf, options)) { 289 psLogMsg ("psphot", 4, "Failed to determine source classification for region %f,%f - %f,%f\n", region->x0, region->y0, region->x1, region->y1); 290 continue; 291 } 292 } 293 294 return true; 295 } 296 297 bool psphotSourceClassRegion (psRegion *region, pmPSFClump *psfClump, psArray *sources, psMetadata *recipe, pmPSF *psf, psphotSourceSizeOptions *options) { 298 299 PS_ASSERT_PTR_NON_NULL(sources, false); 300 PS_ASSERT_PTR_NON_NULL(recipe, false); 301 302 int Nsat = 0; 303 int Next = 0; 304 int Npsf = 0; 305 int Ncr = 0; 306 int Nmiss = 0; 307 int Nskip = 0; 308 309 pmSourceMode noMoments = PM_SOURCE_MODE_MOMENTS_FAILURE | PM_SOURCE_MODE_SKYVAR_FAILURE | PM_SOURCE_MODE_SKY_FAILURE | PM_SOURCE_MODE_BELOW_MOMENTS_SN; 310 pmSourcePhotometryMode photMode = PM_SOURCE_PHOT_WEIGHT; 311 312 psImageMaskType maskVal = options->maskVal | options->markVal; 313 314 for (psS32 i = 0 ; i < sources->n ; i++) { 315 316 pmSource *source = (pmSource *) sources->data[i]; 317 318 // psfClumps are found for image subregions: 319 // skip sources not in this region 320 if (source->peak->x < region->x0) continue; 321 if (source->peak->x >= region->x1) continue; 322 if (source->peak->y < region->y0) continue; 323 if (source->peak->y >= region->y1) continue; 324 325 // skip source if it was already measured 326 if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) { 327 psTrace("psphot", 7, "Not calculating source size since it has already been measured\n"); 328 continue; 329 } 330 331 // source must have been subtracted 332 if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) { 59 333 source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED; 60 psTrace("psphot", 7, "Not calculating extNsigma,crNsigma since source is not subtracted\n"); 61 continue; 334 psTrace("psphot", 7, "Not calculating source size since source is not subtracted\n"); 335 continue; 336 } 337 338 // we are basically classifying by moments; use the default if not found 339 psAssert (source->moments, "why is this source missing moments?"); 340 if (source->mode & noMoments) { 341 Nskip ++; 342 continue; 343 } 344 345 psF32 Mxx = source->moments->Mxx; 346 psF32 Myy = source->moments->Myy; 347 348 // replace object in image 349 if (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED) { 350 pmSourceAdd (source, PM_MODEL_OP_FULL, options->maskVal); 62 351 } 63 352 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) { 74 source->mode |= PM_SOURCE_MODE_EXT_LIMIT; 75 } 76 77 // Integer position of peak 78 int xPeak = source->peak->xf - source->pixels->col0 + 0.5; 79 int yPeak = source->peak->yf - source->pixels->row0 + 0.5; 80 81 // XXX for now, skip sources which are too close to a boundary 82 // XXX raise a flag? 83 if (xPeak < 1 || xPeak > source->pixels->numCols - 2 || 84 yPeak < 1 || yPeak > source->pixels->numRows - 2) { 85 source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED; 86 psTrace("psphot", 7, "Not calculating crNsigma due to edge\n"); 87 continue; 88 } 89 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 } 170 } 171 172 // now that we have masked pixels associated with CRs, we can grow the mask 173 if (grow > 0) { 174 bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading for psImageConvolveMask 175 psImage *newMask = psImageConvolveMask(NULL, readout->mask, crMask, crMask, -grow, grow, -grow, grow); 176 psImageConvolveSetThreads(oldThreads); 177 if (!newMask) { 178 psError(PS_ERR_UNKNOWN, false, "Unable to grow CR mask"); 179 return false; 180 } 181 psFree(readout->mask); 182 readout->mask = newMask; 183 } 184 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); 353 // clear the mask bit and set the circular mask pixels 354 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal)); 355 psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", options->markVal); 356 357 // XXX can we test if psfMag is set and calculate only if needed? 358 pmSourceMagnitudes (source, psf, photMode, maskVal); // maskVal includes markVal 359 360 // clear the mask bit 361 psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(options->markVal)); 362 363 // re-subtract the object, leave local sky 364 pmSourceSub (source, PM_MODEL_OP_FULL, options->maskVal); 365 366 float apMag = -2.5*log10(source->moments->Sum); 367 float dMag = source->psfMag - apMag; 368 float nSigma = (dMag - options->ApResid) / hypot(source->errMag, options->ApSysErr); 369 370 source->extNsigma = nSigma; 371 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED; 372 373 // Anything within this region is a probably PSF-like object. Saturated stars may land 374 // in this region, but are detected elsewhere on the basis of their peak value. 375 bool isPSF = (fabs(nSigma) < options->nSigmaApResid) && (fabs(Mxx - psfClump->X) < options->nSigmaMoments*psfClump->dX) && (fabs(Myy - psfClump->Y) < options->nSigmaMoments*psfClump->dY); 376 if (isPSF) { 377 Npsf ++; 378 continue; 379 } 380 381 // Defects may not always match CRs from peak curvature analysis 382 // Defects may also be marked as SATSTAR -- XXX deactivate this flag? 383 // XXX this rule is not great 384 if ((Mxx < psfClump->X) || (Myy < psfClump->Y)) { 385 source->mode |= PM_SOURCE_MODE_DEFECT; 386 Ncr ++; 387 continue; 388 } 389 390 // saturated star (determined in PSF fit). These may also be saturated galaxies, or 391 // just large saturated regions. 392 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 393 Nsat ++; 394 continue; 395 } 396 397 // XXX allow the Mxx, Myy to be less than psfClump->X,Y (by some nSigma)? 398 bool isEXT = (nSigma > options->nSigmaApResid) || ((Mxx > psfClump->X) && (Myy > psfClump->Y)); 399 if (isEXT) { 400 source->mode |= PM_SOURCE_MODE_EXT_LIMIT; 401 Next ++; 402 continue; 403 } 404 405 psWarning ("sourse size was missed for %f,%f : %f %f -- %f\n", source->peak->xf, source->peak->yf, Mxx, Myy, nSigma); 406 Nmiss ++; 407 } 408 409 psLogMsg("psModules.objects", PS_LOG_INFO, "Source Size classifications: %4d %4d %4d %4d %4d %4d", Npsf, Next, Nsat, Ncr, Nmiss, Nskip); 190 410 191 411 return true; … … 194 414 // given the PSF ellipse parameters, navigate around the 1sigma contour, return the total 195 415 // 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) 416 // deviations? NOTE: This function was an early attempt to classify extended objects, and is 417 // no longer used by psphot. 418 float psphotModelContour(const psImage *image, const psImage *variance, const psImage *mask, 419 psImageMaskType maskVal, const pmModel *model, float Ro) 199 420 { 200 421 psF32 *PAR = model->params->data.F32; // Model parameters … … 211 432 float Q = Ro * PS_SQR(sxx) / (1.0 - PS_SQR(sxx * syy * sxy) / 4.0); 212 433 if (Q < 0.0) { 213 // ellipse is imaginary214 return NAN;434 // ellipse is imaginary 435 return NAN; 215 436 } 216 437 … … 220 441 221 442 for (int x = -radius; x <= radius; x++) { 222 // Polynomial coefficients223 // XXX Should we be using the centre of the pixel as x or x+0.5?224 float A = PS_SQR (1.0 / syy);225 float B = x * sxy;226 float C = PS_SQR (x / sxx) - Ro;227 float T = PS_SQR(B) - 4*A*C;228 if (T < 0.0) {229 continue;230 }231 232 // y position in source frame233 float yP = (-B + sqrt (T)) / (2.0 * A);234 float yM = (-B - sqrt (T)) / (2.0 * A);235 236 // Get the closest pixel positions (image frame)237 int xPix = x + PAR[PM_PAR_XPOS] - image->col0 + 0.5;238 int yPixM = yM + PAR[PM_PAR_YPOS] - image->row0 + 0.5;239 int yPixP = yP + PAR[PM_PAR_YPOS] - image->row0 + 0.5;240 241 if (xPix < 0 || xPix >= image->numCols) {242 continue;243 }244 245 if (yPixM >= 0 && yPixM < image->numRows &&246 !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixM][xPix] & maskVal))) {247 float dSigma = image->data.F32[yPixM][xPix] / sqrtf(variance->data.F32[yPixM][xPix]);248 nSigma += dSigma;249 nPts++;250 }251 252 if (yPixM == yPixP) {253 continue;254 }255 256 if (yPixP >= 0 && yPixP < image->numRows &&257 !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixP][xPix] & maskVal))) {258 float dSigma = image->data.F32[yPixP][xPix] / sqrtf(variance->data.F32[yPixP][xPix]);259 nSigma += dSigma;260 nPts++;261 }443 // Polynomial coefficients 444 // XXX Should we be using the centre of the pixel as x or x+0.5? 445 float A = PS_SQR (1.0 / syy); 446 float B = x * sxy; 447 float C = PS_SQR (x / sxx) - Ro; 448 float T = PS_SQR(B) - 4*A*C; 449 if (T < 0.0) { 450 continue; 451 } 452 453 // y position in source frame 454 float yP = (-B + sqrt (T)) / (2.0 * A); 455 float yM = (-B - sqrt (T)) / (2.0 * A); 456 457 // Get the closest pixel positions (image frame) 458 int xPix = x + PAR[PM_PAR_XPOS] - image->col0 + 0.5; 459 int yPixM = yM + PAR[PM_PAR_YPOS] - image->row0 + 0.5; 460 int yPixP = yP + PAR[PM_PAR_YPOS] - image->row0 + 0.5; 461 462 if (xPix < 0 || xPix >= image->numCols) { 463 continue; 464 } 465 466 if (yPixM >= 0 && yPixM < image->numRows && 467 !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixM][xPix] & maskVal))) { 468 float dSigma = image->data.F32[yPixM][xPix] / sqrtf(variance->data.F32[yPixM][xPix]); 469 nSigma += dSigma; 470 nPts++; 471 } 472 473 if (yPixM == yPixP) { 474 continue; 475 } 476 477 if (yPixP >= 0 && yPixP < image->numRows && 478 !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixP][xPix] & maskVal))) { 479 float dSigma = image->data.F32[yPixP][xPix] / sqrtf(variance->data.F32[yPixP][xPix]); 480 nSigma += dSigma; 481 nPts++; 482 } 262 483 } 263 484 nSigma /= nPts; … … 265 486 } 266 487 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 } 488 bool psphotSourceSizeCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) { 489 490 // classify the sources based on the CR test (place this in a function?) 491 // XXX use an internal flag to mark sources which have already been measured 492 for (int i = 0; i < sources->n; i++) { 493 pmSource *source = sources->data[i]; 494 495 // skip source if it was already measured 496 if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) { 497 psTrace("psphot", 7, "Not calculating source size since it has already been measured\n"); 498 continue; 499 } 500 501 // source must have been subtracted 502 if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) { 503 source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED; 504 psTrace("psphot", 7, "Not calculating source size since source is not subtracted\n"); 505 continue; 506 } 507 508 psF32 **resid = source->pixels->data.F32; 509 psF32 **variance = source->variance->data.F32; 510 psImageMaskType **mask = source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA; 511 512 // Integer position of peak 513 int xPeak = source->peak->xf - source->pixels->col0 + 0.5; 514 int yPeak = source->peak->yf - source->pixels->row0 + 0.5; 515 516 // Skip sources which are too close to a boundary. These are mostly caught as DEFECT 517 if (xPeak < 1 || xPeak > source->pixels->numCols - 2 || 518 yPeak < 1 || yPeak > source->pixels->numRows - 2) { 519 psTrace("psphot", 7, "Not calculating crNsigma due to edge\n"); 520 continue; 521 } 522 523 // Skip sources with masked pixels. These are mostly caught as DEFECT 524 bool keep = true; 525 for (int iy = -1; (iy <= +1) && keep; iy++) { 526 for (int ix = -1; (ix <= +1) && keep; ix++) { 527 if (mask[yPeak+iy][xPeak+ix] & options->maskVal) { 528 keep = false; 529 } 530 } 531 } 532 if (!keep) { 533 psTrace("psphot", 7, "Not calculating crNsigma due to masked pixels\n"); 534 continue; 535 } 536 537 // Compare the central pixel with those on either side, for the four possible lines through it. 538 539 // Soften variances (add systematic error) 540 float softening = options->soft * PS_SQR(source->peak->flux); // Softening for variances 541 542 // Across the middle: y = 0 543 float cX = 2*resid[yPeak][xPeak] - resid[yPeak+0][xPeak-1] - resid[yPeak+0][xPeak+1]; 544 float dcX = 4*variance[yPeak][xPeak] + variance[yPeak+0][xPeak-1] + variance[yPeak+0][xPeak+1]; 545 float nX = cX / sqrtf(dcX + softening); 546 547 // Up the centre: x = 0 548 float cY = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak+0] - resid[yPeak+1][xPeak+0]; 549 float dcY = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak+0] + variance[yPeak+1][xPeak+0]; 550 float nY = cY / sqrtf(dcY + softening); 551 552 // Diagonal: x = y 553 float cL = 2*resid[yPeak][xPeak] - resid[yPeak-1][xPeak-1] - resid[yPeak+1][xPeak+1]; 554 float dcL = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak-1] + variance[yPeak+1][xPeak+1]; 555 float nL = cL / sqrtf(dcL + softening); 556 557 // Diagonal: x = - y 558 float cR = 2*resid[yPeak][xPeak] - resid[yPeak+1][xPeak-1] - resid[yPeak-1][xPeak+1]; 559 float dcR = 4*variance[yPeak][xPeak] + variance[yPeak+1][xPeak-1] + variance[yPeak-1][xPeak+1]; 560 float nR = cR / sqrtf(dcR + softening); 561 562 // P(chisq > chisq_obs; Ndof) = gamma_Q (Ndof/2, chisq/2) 563 // Ndof = 4 ? (four measurements, no free parameters) 564 // XXX this value is going to be biased low because of systematic errors. 565 // we need to calibrate it somehow 566 // source->psfProb = gsl_sf_gamma_inc_Q (2, 0.5*chisq); 567 568 // not strictly accurate: overcounts the chisq contribution from the center pixel (by 569 // factor of 4); also biases a bit low if any pixels are masked 570 // XXX I am not sure I want to keep this value... 571 source->psfChisq = PS_SQR(nX) + PS_SQR(nY) + PS_SQR(nL) + PS_SQR(nR); 572 573 float fCR = 0.0; 574 int nCR = 0; 575 if (nX > 0.0) { 576 fCR += nX; 577 nCR ++; 578 } 579 if (nY > 0.0) { 580 fCR += nY; 581 nCR ++; 582 } 583 if (nL > 0.0) { 584 fCR += nL; 585 nCR ++; 586 } 587 if (nR > 0.0) { 588 fCR += nR; 589 nCR ++; 590 } 591 source->crNsigma = (nCR > 0) ? fCR / nCR : 0.0; 592 source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED; 593 594 if (!isfinite(source->crNsigma)) { 595 continue; 596 } 597 598 // this source is thought to be a cosmic ray. flag the detection and mask the pixels 599 if (source->crNsigma > options->nSigmaCR) { 600 source->mode |= PM_SOURCE_MODE_CR_LIMIT; 601 // XXX still testing... : psphotMaskCosmicRay (readout->mask, source, maskVal, crMask); 602 // XXX acting strange... psphotMaskCosmicRay_Old (source, maskVal, crMask); 603 } 604 } 605 606 // now that we have masked pixels associated with CRs, we can grow the mask 607 if (options->grow > 0) { 608 bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading for psImageConvolveMask 609 psImage *newMask = psImageConvolveMask(NULL, readout->mask, options->crMask, options->crMask, -options->grow, options->grow, -options->grow, options->grow); 610 psImageConvolveSetThreads(oldThreads); 611 if (!newMask) { 612 psError(PS_ERR_UNKNOWN, false, "Unable to grow CR mask"); 613 return false; 614 } 615 psFree(readout->mask); 616 readout->mask = newMask; 303 617 } 304 618 return true; 305 619 } 306 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 } -
trunk/psphot/src/psphotSourceStats.c
r24589 r25755 1 1 # include "psphotInternal.h" 2 2 3 psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections) { 3 bool psphotSetMomentsWindow (psMetadata *recipe, psArray *sources); 4 5 psArray *psphotSourceStats (pmConfig *config, pmReadout *readout, pmDetections *detections, bool setWindow) { 4 6 5 7 bool status = false; … … 21 23 float OUTER = psMetadataLookupF32 (&status, recipe, "SKY_OUTER_RADIUS"); 22 24 if (!status) return NULL; 25 26 OUTER = PS_MAX(OUTER, 20.0); // XXX Guarantee that we can encompass the max moments radius 27 23 28 char *breakPt = psMetadataLookupStr (&status, recipe, "BREAK_POINT"); 24 29 if (!status) return NULL; … … 60 65 psphotVisualShowMoments (sources); 61 66 return sources; 67 } 68 69 if (setWindow) { 70 if (!psphotSetMomentsWindow(recipe, sources)) { 71 psError(PS_ERR_UNEXPECTED_NULL, false, "Failed to determine Moments Window!"); 72 return NULL; 73 } 62 74 } 63 75 … … 144 156 float RADIUS = psMetadataLookupF32 (&status, recipe, "PSF_MOMENTS_RADIUS"); 145 157 if (!status) return false; 146 float MIN_PIXEL_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_MIN_PIXEL_SN");147 if (!status) return false;148 158 float SIGMA = psMetadataLookupF32 (&status, recipe, "MOMENTS_GAUSS_SIGMA"); 149 159 if (!status) return false; … … 194 204 } 195 205 196 // measure basic source moments 197 status = pmSourceMoments (source, RADIUS, SIGMA, MIN_PIXEL_SN);206 // measure basic source moments (no S/N clipping on input pixels) 207 status = pmSourceMoments (source, RADIUS, SIGMA, 0.0); 198 208 if (status) { 199 209 Nmoments ++; … … 205 215 BIG_RADIUS = PS_MIN (INNER, 3*RADIUS); 206 216 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);217 status = pmSourceMoments (source, BIG_RADIUS, 3.0*SIGMA, 0.0); 208 218 if (status) { 209 219 source->mode |= PM_SOURCE_MODE_BIG_RADIUS; … … 231 241 } 232 242 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 243 // this function attempts to iteratively determine the best value for sigma of the moments weighting Gaussian 244 bool psphotSetMomentsWindow (psMetadata *recipe, psArray *sources) { 245 246 bool status; 247 248 float MIN_SN = psMetadataLookupF32 (&status, recipe, "MOMENTS_SN_MIN"); 249 if (!status) return false; 250 251 // XXX move this to a config file? 252 float sigma[4] = {1.0, 2.0, 3.0, 4.5}; 253 float Sout[4]; 254 255 // this sorts by peak->SN 256 sources = psArraySort (sources, pmSourceSortBySN); 257 258 // loop over radii: 259 for (int i = 0; i < 4; i++) { 260 261 // XXX move max source number to config 262 for (int j = 0; (j < sources->n) && (j < 400); j++) { 263 264 pmSource *source = sources->data[j]; 265 psAssert (source->moments, "force moments to exist"); 266 source->moments->nPixels = 0; 267 268 // skip faint sources for moments measurement 269 if (source->peak->SN < MIN_SN) { 270 continue; 271 } 272 273 // measure basic source moments (no S/N clipping on input pixels) 274 status = pmSourceMoments (source, 4*sigma[i], sigma[i], 0.0); 275 } 276 277 // choose a grid scale that is a fixed fraction of the psf sigma^2 278 psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_CLUMP_GRID_SCALE", PS_META_REPLACE, "clump grid", 0.1*PS_SQR(sigma[i])); 279 psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SX_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(sigma[i])); 280 psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SY_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(sigma[i])); 281 282 // determine the PSF parameters from the source moment values 283 pmPSFClump psfClump = pmSourcePSFClump (NULL, sources, recipe); 284 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]); 285 286 psMetadataAddS32 (recipe, PS_LIST_TAIL, "PSF.CLUMP.NREGIONS", PS_META_REPLACE, "psf clump regions", 1); 287 psMetadata *regionMD = psMetadataLookupPtr (&status, recipe, "PSF.CLUMP.REGION.000"); 288 if (!regionMD) { 289 regionMD = psMetadataAlloc(); 290 psMetadataAddMetadata (recipe, PS_LIST_TAIL, "PSF.CLUMP.REGION.000", PS_META_REPLACE, "psf clump region", regionMD); 291 psFree (regionMD); 292 } 293 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.X", PS_META_REPLACE, "psf clump center", psfClump.X); 294 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.Y", PS_META_REPLACE, "psf clump center", psfClump.Y); 295 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DX", PS_META_REPLACE, "psf clump center", psfClump.dX); 296 psMetadataAddF32 (regionMD, PS_LIST_TAIL, "PSF.CLUMP.DY", PS_META_REPLACE, "psf clump center", psfClump.dY); 297 298 // psphotVisualPlotMoments (recipe, sources); 299 300 Sout[i] = sqrt(0.5*(psfClump.X + psfClump.Y)) / sigma[i]; 301 } 302 303 // we are looking for sigma for which Sout = 0.65 (or some other value) 304 305 float Sigma = NAN; 306 float minS = Sout[0]; 307 float maxS = Sout[0]; 308 for (int i = 0; i < 4; i++) { 309 minS = PS_MIN(Sout[i], minS); 310 maxS = PS_MAX(Sout[i], maxS); 311 } 312 if (minS > 0.65) Sigma = sigma[3]; 313 if (maxS < 0.65) Sigma = sigma[0]; 314 315 for (int i = 0; i < 3; i++) { 316 if ((Sout[i] > 0.65) && (Sout[i+1] > 0.65)) continue; 317 if ((Sout[i] < 0.65) && (Sout[i+1] < 0.65)) continue; 318 Sigma = sigma[i] + (0.65 - Sout[i])*(sigma[i+1] - sigma[i])/(Sout[i+1] - Sout[i]); 319 } 320 psAssert (isfinite(Sigma), "did we miss a case?"); 321 322 // choose a grid scale that is a fixed fraction of the psf sigma^2 323 psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_CLUMP_GRID_SCALE", PS_META_REPLACE, "clump grid", 0.1*PS_SQR(Sigma)); 324 psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SX_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma)); 325 psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_SY_MAX", PS_META_REPLACE, "moments limit", 2.0*PS_SQR(Sigma)); 326 psMetadataAddF32(recipe, PS_LIST_TAIL, "MOMENTS_GAUSS_SIGMA", PS_META_REPLACE, "moments limit", Sigma); 327 psMetadataAddF32(recipe, PS_LIST_TAIL, "PSF_MOMENTS_RADIUS", PS_META_REPLACE, "moments limit", 4.0*Sigma); 328 329 psLogMsg ("psphot", 3, "using window function with sigma = %f\n", Sigma); 312 330 return true; 313 331 } 314 # endif -
trunk/psphot/src/psphotVisual.c
r24636 r25755 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 } 24 61 25 62 bool psphotVisualShowMask (int kapaFD, psImage *inImage, const char *name, int channel) { … … 131 168 if (!pmVisualIsVisual()) return true; 132 169 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 } 170 int kapa = psphotKapaChannel (1); 171 if (kapa == -1) return false; 141 172 142 173 // psphotVisualShowMask (kapa, readout->mask, "mask", 2); … … 144 175 psphotVisualScaleImage (kapa, readout->image, "image", 0); 145 176 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 } 177 pmVisualAskUser(NULL); 153 178 return true; 154 179 } … … 160 185 if (!pmVisualIsVisual()) return true; 161 186 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 } 187 int kapa = psphotKapaChannel (1); 188 if (kapa == -1) return false; 170 189 171 190 bool status = false; … … 181 200 psphotVisualScaleImage (kapa, readout->image, "backsub", 0); 182 201 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 } 202 pmVisualAskUser(NULL); 190 203 return true; 191 204 } … … 195 208 if (!pmVisualIsVisual()) return true; 196 209 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; 210 int kapa = psphotKapaChannel (1); 211 if (kapa == -1) return false; 212 207 213 psphotVisualRangeImage (kapa, image, "signif", 2, -1.0, 25.0*25.0); 208 214 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 } 215 pmVisualAskUser(NULL); 216 216 return true; 217 217 } … … 224 224 if (!pmVisualIsVisual()) return true; 225 225 226 if (kapa == -1) { 227 fprintf (stderr, "kapa not opened, skipping\n"); 228 return false; 229 } 226 int kapa = psphotKapaChannel (1); 227 if (kapa == -1) return false; 230 228 231 229 psArray *peaks = detections->peaks; … … 233 231 // note: this uses the Ohana allocation tools: 234 232 // ALLOCATE (overlay, KiiOverlay, 3*peaks->n + 1); 235 ALLOCATE (overlay, KiiOverlay, peaks->n );233 ALLOCATE (overlay, KiiOverlay, peaks->n + 2); 236 234 237 235 Noverlay = 0; … … 271 269 } 272 270 273 # if ( 0)271 # if (1) 274 272 overlay[Noverlay].type = KII_OVERLAY_BOX; 275 273 overlay[Noverlay].x = 10.0; 276 274 overlay[Noverlay].y = 10.0; 277 overlay[Noverlay].dx = 0.5;278 overlay[Noverlay].dy = 0.5;275 overlay[Noverlay].dx = 1.0; 276 overlay[Noverlay].dy = 1.0; 279 277 overlay[Noverlay].angle = 0.0; 280 278 overlay[Noverlay].text = NULL; … … 285 283 FREE (overlay); 286 284 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 } 285 pmVisualAskUser(NULL); 294 286 return true; 295 287 } … … 302 294 if (!pmVisualIsVisual()) return true; 303 295 304 if (kapa == -1) { 305 fprintf (stderr, "kapa not opened, skipping\n"); 306 return false; 307 } 296 int kapa = psphotKapaChannel (1); 297 if (kapa == -1) return false; 308 298 309 299 psArray *footprints = detections->footprints; … … 325 315 326 316 // draw the top 317 // XXX need to allow top (and bottom) to have more than one span 327 318 span = footprint->spans->data[0]; 328 319 overlay[Noverlay].type = KII_OVERLAY_LINE; … … 399 390 FREE (overlay); 400 391 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 } 392 pmVisualAskUser(NULL); 408 393 return true; 409 394 } … … 419 404 if (!pmVisualIsVisual()) return true; 420 405 421 if (kapa == -1) { 422 fprintf (stderr, "kapa not opened, skipping\n"); 423 return false; 424 } 406 int kapa = psphotKapaChannel (1); 407 if (kapa == -1) return false; 408 409 // XXX mark the different source classes with different color/shape dots 410 // XXX are moments S/N and peak S/N consistent? 425 411 426 412 // note: this uses the Ohana allocation tools: … … 448 434 overlay[Noverlay].dx = 2.0*axes.major; 449 435 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 436 437 overlay[Noverlay].angle = axes.theta * PS_DEG_RAD; 438 451 439 overlay[Noverlay].text = NULL; 452 440 Noverlay ++; … … 456 444 FREE (overlay); 457 445 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 446 pmVisualAskUser(NULL); 466 447 return true; 467 448 } … … 475 456 if (!pmVisualIsVisual()) return true; 476 457 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); 458 int myKapa = psphotKapaChannel (2); 459 if (myKapa == -1) return false; 460 461 KapaClearPlots (myKapa); 487 462 KapaInitGraph (&graphdata); 488 KapaSetFont ( kapa3, "courier", 14);463 KapaSetFont (myKapa, "courier", 14); 489 464 490 465 float SN_LIM = psMetadataLookupF32(&status, recipe, "PSF_SN_LIM"); 491 466 492 467 // 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;468 float Xmin = 1000.0, Xmax = 0.0; 469 float Ymin = 1000.0, Ymax = 0.0; 495 470 { 496 471 int nRegions = psMetadataLookupS32 (&status, recipe, "PSF.CLUMP.NREGIONS"); … … 511 486 float Y1 = psfY + 4.0*psfdY; 512 487 513 if (isfinite(X0)) { Xmin = PS_M AX(Xmin, X0); }488 if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); } 514 489 if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); } 515 if (isfinite(Y0)) { Ymin = PS_M AX(Ymin, Y0); }490 if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); } 516 491 if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); } 517 492 } 518 493 } 494 Xmin = PS_MAX(Xmin, -0.1); 495 Ymin = PS_MAX(Ymin, -0.1); 519 496 520 497 // storage vectors for data to be plotted … … 564 541 section.y = 0.00; 565 542 section.name = psStringCopy ("MxxMyy"); 566 KapaSetSection ( kapa3, §ion);543 KapaSetSection (myKapa, §ion); 567 544 psFree (section.name); 568 545 … … 572 549 graphdata.xmax = Xmax; 573 550 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);551 KapaSetLimits (myKapa, &graphdata); 552 553 KapaBox (myKapa, &graphdata); 554 KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM); 555 KapaSendLabel (myKapa, "M_yy| (pixels)", KAPA_LABEL_YM); 579 556 580 557 graphdata.color = KapaColorByName ("black"); … … 582 559 graphdata.size = 0.3; 583 560 graphdata.style = 2; 584 KapaPrepPlot ( kapa3, nF, &graphdata);585 KapaPlotVector ( kapa3, nF, xFaint->data.F32, "x");586 KapaPlotVector ( kapa3, nF, yFaint->data.F32, "y");561 KapaPrepPlot (myKapa, nF, &graphdata); 562 KapaPlotVector (myKapa, nF, xFaint->data.F32, "x"); 563 KapaPlotVector (myKapa, nF, yFaint->data.F32, "y"); 587 564 588 565 graphdata.color = KapaColorByName ("red"); … … 590 567 graphdata.size = 0.5; 591 568 graphdata.style = 2; 592 KapaPrepPlot ( kapa3, nB, &graphdata);593 KapaPlotVector ( kapa3, nB, xBright->data.F32, "x");594 KapaPlotVector ( kapa3, nB, yBright->data.F32, "y");569 KapaPrepPlot (myKapa, nB, &graphdata); 570 KapaPlotVector (myKapa, nB, xBright->data.F32, "x"); 571 KapaPlotVector (myKapa, nB, yBright->data.F32, "y"); 595 572 596 573 // second section: MagMyy … … 600 577 section.y = 0.80; 601 578 section.name = psStringCopy ("MagMyy"); 602 KapaSetSection ( kapa3, §ion);579 KapaSetSection (myKapa, §ion); 603 580 psFree (section.name); 604 581 … … 608 585 graphdata.ymin = Ymin; 609 586 graphdata.ymax = Ymax; 610 KapaSetLimits ( kapa3, &graphdata);587 KapaSetLimits (myKapa, &graphdata); 611 588 612 589 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);590 KapaBox (myKapa, &graphdata); 591 KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_XP); 592 KapaSendLabel (myKapa, "M_yy| (pixels)", KAPA_LABEL_YM); 616 593 617 594 graphdata.color = KapaColorByName ("black"); … … 619 596 graphdata.size = 0.3; 620 597 graphdata.style = 2; 621 KapaPrepPlot ( kapa3, nF, &graphdata);622 KapaPlotVector ( kapa3, nF, mFaint->data.F32, "x");623 KapaPlotVector ( kapa3, nF, yFaint->data.F32, "y");598 KapaPrepPlot (myKapa, nF, &graphdata); 599 KapaPlotVector (myKapa, nF, mFaint->data.F32, "x"); 600 KapaPlotVector (myKapa, nF, yFaint->data.F32, "y"); 624 601 625 602 graphdata.color = KapaColorByName ("red"); … … 627 604 graphdata.size = 0.5; 628 605 graphdata.style = 2; 629 KapaPrepPlot ( kapa3, nB, &graphdata);630 KapaPlotVector ( kapa3, nB, mBright->data.F32, "x");631 KapaPlotVector ( kapa3, nB, yBright->data.F32, "y");606 KapaPrepPlot (myKapa, nB, &graphdata); 607 KapaPlotVector (myKapa, nB, mBright->data.F32, "x"); 608 KapaPlotVector (myKapa, nB, yBright->data.F32, "y"); 632 609 633 610 // third section: MagMxx … … 637 614 section.y = 0.00; 638 615 section.name = psStringCopy ("MagMxx"); 639 KapaSetSection ( kapa3, §ion);616 KapaSetSection (myKapa, §ion); 640 617 psFree (section.name); 641 618 … … 645 622 graphdata.ymin = -7.9; 646 623 graphdata.ymax = -17.1; 647 KapaSetLimits ( kapa3, &graphdata);624 KapaSetLimits (myKapa, &graphdata); 648 625 649 626 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);627 KapaBox (myKapa, &graphdata); 628 KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM); 629 KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_YP); 653 630 654 631 graphdata.color = KapaColorByName ("black"); … … 656 633 graphdata.size = 0.3; 657 634 graphdata.style = 2; 658 KapaPrepPlot ( kapa3, nF, &graphdata);659 KapaPlotVector ( kapa3, nF, xFaint->data.F32, "x");660 KapaPlotVector ( kapa3, nF, mFaint->data.F32, "y");635 KapaPrepPlot (myKapa, nF, &graphdata); 636 KapaPlotVector (myKapa, nF, xFaint->data.F32, "x"); 637 KapaPlotVector (myKapa, nF, mFaint->data.F32, "y"); 661 638 662 639 graphdata.color = KapaColorByName ("red"); … … 664 641 graphdata.size = 0.5; 665 642 graphdata.style = 2; 666 KapaPrepPlot ( kapa3, nB, &graphdata);667 KapaPlotVector ( kapa3, nB, xBright->data.F32, "x");668 KapaPlotVector ( kapa3, nB, mBright->data.F32, "y");643 KapaPrepPlot (myKapa, nB, &graphdata); 644 KapaPlotVector (myKapa, nB, xBright->data.F32, "x"); 645 KapaPlotVector (myKapa, nB, mBright->data.F32, "y"); 669 646 670 647 // draw N circles to outline the clumps 671 648 { 672 KapaSelectSection ( kapa3, "MxxMyy");649 KapaSelectSection (myKapa, "MxxMyy"); 673 650 674 651 // draw a circle centered on psfX,Y with size of the psf limit … … 686 663 graphdata.xmax = Xmax; 687 664 graphdata.ymax = Ymax; 688 KapaSetLimits ( kapa3, &graphdata);665 KapaSetLimits (myKapa, &graphdata); 689 666 690 667 for (int n = 0; n < nRegions; n++) { … … 705 682 yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY; 706 683 } 707 KapaPrepPlot ( kapa3, xLimit->n, &graphdata);708 KapaPlotVector ( kapa3, xLimit->n, xLimit->data.F32, "x");709 KapaPlotVector ( kapa3, yLimit->n, yLimit->data.F32, "y");684 KapaPrepPlot (myKapa, xLimit->n, &graphdata); 685 KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x"); 686 KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y"); 710 687 } 711 688 psFree (xLimit); 712 689 psFree (yLimit); 713 690 } 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 691 751 692 psFree (xBright); … … 756 697 psFree (mFaint); 757 698 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 } 699 pmVisualAskUser(NULL); 765 700 return true; 766 701 } 767 702 768 703 // assumes 'kapa' value is checked and set 769 bool psphotVisualShowRoughClass_Single ( psArray *sources, pmSourceType type, pmSourceMode mode, char *color) {704 bool psphotVisualShowRoughClass_Single (int myKapa, psArray *sources, pmSourceType type, pmSourceMode mode, char *color) { 770 705 771 706 int Noverlay; … … 802 737 overlay[Noverlay].dx = 2.0*axes.major; 803 738 overlay[Noverlay].dy = 2.0*axes.minor; 804 overlay[Noverlay].angle = -axes.theta * PS_DEG_RAD;739 overlay[Noverlay].angle = axes.theta * PS_DEG_RAD; 805 740 overlay[Noverlay].text = NULL; 806 741 Noverlay ++; 807 742 } 808 743 809 KiiLoadOverlay ( kapa, overlay, Noverlay, color);744 KiiLoadOverlay (myKapa, overlay, Noverlay, color); 810 745 FREE (overlay); 811 746 … … 817 752 if (!pmVisualIsVisual()) return true; 818 753 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]; 754 int myKapa = psphotKapaChannel (1); 755 if (myKapa == -1) return false; 756 757 KiiEraseOverlay (myKapa, "yellow"); // moments 758 759 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_STAR, 0, "red"); 760 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_EXTENDED, 0, "blue"); 761 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_DEFECT, 0, "blue"); 762 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_SATURATED, 0, "red"); 763 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_STAR, PM_SOURCE_MODE_PSFSTAR, "yellow"); 764 psphotVisualShowRoughClass_Single (myKapa, sources, PM_SOURCE_TYPE_STAR, PM_SOURCE_MODE_SATSTAR, "green"); 765 836 766 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 } 767 pmVisualAskUser(NULL); 841 768 return true; 842 769 } … … 846 773 if (!pmVisualIsVisual()) return true; 847 774 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 } 775 int myKapa = psphotKapaChannel (3); 776 if (myKapa == -1) return false; 856 777 857 778 int DX = 64; … … 898 819 899 820 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);821 psphotVisualRangeImage (myKapa, psfLogFlux, "psf_mosaic", 0, -2.0, 3.0); 822 psphotVisualRangeImage (myKapa, funMosaic, "psf_analytical", 1, -10.0, 100.0); 823 psphotVisualRangeImage (myKapa, resMosaic, "psf_residual", 2, -10.0, 100.0); 903 824 904 825 psFree (psfMosaic); … … 908 829 psFree (modelRef); 909 830 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 } 831 pmVisualAskUser(NULL); 917 832 return true; 918 833 } … … 924 839 if (!pmVisualIsVisual()) return true; 925 840 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 } 841 int myKapa = psphotKapaChannel (3); 842 if (myKapa == -1) return false; 934 843 935 844 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) … … 1017 926 if (Xo == 0) { 1018 927 // place source alone on this row 1019 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 928 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 929 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1020 930 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true); 1021 931 1022 psphotSubWithTest (source, false, maskVal); // remove source (force) 932 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1023 933 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true); 1024 psphotSetState (source, false, maskVal); // reset source Add/Sub state to recorded 934 935 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1025 936 1026 937 Yo += DY; … … 1032 943 Xo = 0; 1033 944 1034 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 945 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 946 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1035 947 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true); 1036 948 1037 psphotSubWithTest (source, false, maskVal); // remove source (force) 949 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1038 950 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true); 1039 psphotSetState (source, false, maskVal); // replace source (has been subtracted) 951 952 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1040 953 1041 954 Xo = DX; … … 1044 957 } else { 1045 958 // extend this row 1046 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 959 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 960 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1047 961 psphotMosaicSubimage (outpos, source, Xo, Yo, DX, DY, true); 1048 962 1049 psphotSubWithTest (source, false, maskVal); // remove source (force) 963 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1050 964 psphotMosaicSubimage (outsub, source, Xo, Yo, DX, DY, true); 1051 psphotSetState (source, false, maskVal); // replace source (has been subtracted) 965 if (!subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1052 966 1053 967 Xo += DX; … … 1056 970 } 1057 971 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 972 psphotVisualRangeImage (myKapa, outpos, "psfpos", 0, -0.05, 0.95); 973 psphotVisualRangeImage (myKapa, outsub, "psfsub", 1, -0.05, 0.95); 974 975 pmVisualAskUser(NULL); 1069 976 psFree (outpos); 1070 977 psFree (outsub); … … 1084 991 if (!pmVisualIsVisual()) return true; 1085 992 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 } 993 int myKapa = psphotKapaChannel (3); 994 if (myKapa == -1) return false; 1094 995 1095 996 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) … … 1119 1020 pmSource *source = sources->data[i]; 1120 1021 1121 bool keep = false; 1122 keep |= (source->mode & PM_SOURCE_MODE_SATSTAR);1123 if ( !keep) continue;1022 // only show "real" saturated stars (not defects) 1023 if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;; 1024 if (source->mode & PM_SOURCE_MODE_DEFECT) continue;; 1124 1025 1125 1026 // how does this subimage get placed into the output image? … … 1164 1065 pmSource *source = sources->data[i]; 1165 1066 1166 bool keep = false; 1167 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 1168 nSAT ++; 1169 keep = true; 1170 } 1171 if (!keep) continue; 1067 // only show "real" saturated stars (not defects) 1068 if (!(source->mode & PM_SOURCE_MODE_SATSTAR)) continue;; 1069 if (source->mode & PM_SOURCE_MODE_DEFECT) continue;; 1070 nSAT ++; 1172 1071 1173 1072 if (Xo + DX > NX) { … … 1175 1074 if (Xo == 0) { 1176 1075 // place source alone on this row 1177 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 1076 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 1077 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1178 1078 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false); 1179 psphotSetState (source, true, maskVal); // reset source Add/Sub state to recorded 1079 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1180 1080 1181 1081 Yo += DY; … … 1186 1086 Yo += dY; 1187 1087 Xo = 0; 1188 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 1088 1089 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 1090 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1189 1091 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false); 1190 psphotSetState (source, true, maskVal); // replace source (has been subtracted) 1092 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1191 1093 1192 1094 Xo = DX; … … 1195 1097 } else { 1196 1098 // extend this row 1197 psphotAddWithTest (source, true, maskVal); // replace source if subtracted 1099 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 1100 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1198 1101 psphotMosaicSubimage (outsat, source, Xo, Yo, DX, DY, false); 1199 psphotSetState (source, true, maskVal); // replace source (has been subtracted) 1102 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1200 1103 1201 1104 Xo += DX; … … 1204 1107 } 1205 1108 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 1109 psphotVisualScaleImage (myKapa, outsat, "satstar", 2); 1110 1111 pmVisualAskUser(NULL); 1216 1112 psFree (outsat); 1217 1113 return true; … … 1222 1118 Graphdata graphdata; 1223 1119 1224 bool s tate = !(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED);1225 psphotAddWithTest (source, true, maskVal); // replace source if subtracted1120 bool subtracted = (source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED); 1121 if (subtracted) pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal); 1226 1122 1227 1123 int nPts = source->pixels->numRows * source->pixels->numCols; … … 1240 1136 for (int ix = 0; ix < source->pixels->numCols; ix++) { 1241 1137 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) ;1138 rb->data.F32[nb] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ; 1139 // rb->data.F32[nb] = hypot (ix - Xo, iy - Yo) ; 1244 1140 Rb->data.F32[nb] = log10(rb->data.F32[nb]); 1245 1141 fb->data.F32[nb] = log10(source->pixels->data.F32[iy][ix]); 1246 1142 nb++; 1247 1143 } 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) ;1144 rg->data.F32[ng] = hypot (ix + 0.5 - Xo, iy + 0.5 - Yo) ; 1145 // rg->data.F32[ng] = hypot (ix - Xo, iy - Yo) ; 1250 1146 Rg->data.F32[ng] = log10(rg->data.F32[ng]); 1251 1147 fg->data.F32[ng] = log10(source->pixels->data.F32[iy][ix]); … … 1256 1152 1257 1153 // reset source Add/Sub state to recorded 1258 psphotSetState (source, state, maskVal);1154 if (subtracted) pmSourceSub (source, PM_MODEL_OP_FULL, maskVal); 1259 1155 1260 1156 KapaInitGraph (&graphdata); … … 1337 1233 if (!pmVisualIsVisual()) return true; 1338 1234 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 } 1235 int myKapa = psphotKapaChannel (2); 1236 if (myKapa == -1) return false; 1347 1237 1348 1238 // user-defined masks to test for good/bad pixels (build from recipe list if not yet set) … … 1351 1241 assert (maskVal); 1352 1242 1353 KapaClearPlots ( kapa3);1243 KapaClearPlots (myKapa); 1354 1244 // first section : mag vs CR nSigma 1355 1245 section.dx = 1.0; … … 1359 1249 section.name = NULL; 1360 1250 psStringAppend (§ion.name, "linlog"); 1361 KapaSetSection ( kapa3, §ion);1251 KapaSetSection (myKapa, §ion); 1362 1252 psFree (section.name); 1363 1253 … … 1369 1259 section.name = NULL; 1370 1260 psStringAppend (§ion.name, "loglog"); 1371 KapaSetSection ( kapa3, §ion);1261 KapaSetSection (myKapa, §ion); 1372 1262 psFree (section.name); 1373 1263 … … 1378 1268 if (!(source->mode & PM_SOURCE_MODE_PSFSTAR)) continue; 1379 1269 1380 psphotVisualPlotRadialProfile ( kapa3, source, maskVal);1270 psphotVisualPlotRadialProfile (myKapa, source, maskVal); 1381 1271 1382 1272 // pause and wait for user input: … … 1388 1278 } 1389 1279 if (key[0] == 'e') { 1390 KapaClearPlots ( kapa3);1280 KapaClearPlots (myKapa); 1391 1281 } 1392 1282 if (key[0] == 's') { … … 1407 1297 psEllipseAxes axes; 1408 1298 1299 // XXX skip this for now: it is not very clear 1300 return true; 1301 1409 1302 if (!pmVisualIsVisual()) return true; 1410 1303 1411 if (kapa == -1) { 1412 fprintf (stderr, "kapa not opened, skipping\n"); 1413 return false; 1414 } 1304 int myKapa = psphotKapaChannel (1); 1305 if (myKapa == -1) return false; 1415 1306 1416 1307 // note: this uses the Ohana allocation tools: … … 1485 1376 } 1486 1377 1487 KiiLoadOverlay ( kapa, overlayE, NoverlayE, "red");1488 KiiLoadOverlay ( kapa, overlayO, NoverlayO, "yellow");1378 KiiLoadOverlay (myKapa, overlayE, NoverlayE, "red"); 1379 KiiLoadOverlay (myKapa, overlayO, NoverlayO, "yellow"); 1489 1380 FREE (overlayE); 1490 1381 FREE (overlayO); 1491 1382 1492 // pause and wait for user input:1493 // continue, save (provide name), ??1494 char key[10];1495 1383 fprintf (stdout, "even bits (0x0001, 0x0004, ... : red\n"); 1496 1384 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; 1385 pmVisualAskUser(NULL); 1386 1387 return true; 1388 } 1389 1390 bool psphotVisualShowSourceSize_Single (int myKapa, psArray *sources, pmSourceMode mode, bool keep, float scale, char *color) { 1391 1392 int Noverlay; 1508 1393 KiiOverlay *overlay; 1509 1394 1510 if (!pmVisualIsVisual()) return true; 1511 1512 if (kapa == -1) { 1513 fprintf (stderr, "kapa not opened, skipping\n"); 1514 return false; 1515 } 1395 psEllipseMoments emoments; 1396 psEllipseAxes axes; 1516 1397 1517 1398 // note: this uses the Ohana allocation tools: 1399 ALLOCATE (overlay, KiiOverlay, sources->n); 1400 1518 1401 Noverlay = 0; 1519 NOVERLAY = 100;1520 ALLOCATE (overlay, KiiOverlay, sources->n);1521 1522 // mark CRs with red boxes1523 1402 for (int i = 0; i < sources->n; i++) { 1524 1403 … … 1526 1405 if (source == NULL) continue; 1527 1406 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; 1407 // if (source->type != type) continue; 1408 if (mode) { 1409 if (keep) { 1410 if (!(source->mode & mode)) continue; 1411 } else { 1412 if (source->mode & mode) continue; 1413 } 1414 } 1415 1416 pmMoments *moments = source->moments; 1417 if (moments == NULL) continue; 1418 1419 overlay[Noverlay].type = KII_OVERLAY_CIRCLE; 1420 overlay[Noverlay].x = moments->Mx; 1421 overlay[Noverlay].y = moments->My; 1422 1423 emoments.x2 = moments->Mxx; 1424 emoments.y2 = moments->Myy; 1425 emoments.xy = moments->Mxy; 1426 1427 axes = psEllipseMomentsToAxes (emoments, 20.0); 1428 1429 overlay[Noverlay].dx = scale*2.0*axes.major; 1430 overlay[Noverlay].dy = scale*2.0*axes.minor; 1431 overlay[Noverlay].angle = axes.theta * PS_DEG_RAD; 1537 1432 overlay[Noverlay].text = NULL; 1538 1433 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"); 1434 } 1435 1436 KiiLoadOverlay (myKapa, overlay, Noverlay, color); 1566 1437 FREE (overlay); 1567 1438 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 1439 return true; 1440 } 1441 1442 bool psphotVisualShowSourceSize (pmReadout *readout, psArray *sources) { 1443 1444 if (!pmVisualIsVisual()) return true; 1445 1446 int myKapa = psphotKapaChannel (1); 1447 if (myKapa == -1) return false; 1448 1449 KiiEraseOverlay (myKapa, "red"); 1450 KiiEraseOverlay (myKapa, "blue"); 1451 KiiEraseOverlay (myKapa, "green"); 1452 KiiEraseOverlay (myKapa, "yellow"); 1453 1454 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"); 1455 psphotVisualShowSourceSize_Single (myKapa, sources, PM_SOURCE_MODE_EXT_LIMIT, 1, 1.0, "blue"); 1456 psphotVisualShowSourceSize_Single (myKapa, sources, PM_SOURCE_MODE_CR_LIMIT, 1, 1.0, "red"); 1457 psphotVisualShowSourceSize_Single (myKapa, sources, PM_SOURCE_MODE_DEFECT, 1, 2.0, "red"); 1458 psphotVisualShowSourceSize_Single (myKapa, sources, PM_SOURCE_MODE_SATSTAR, 1, 1.0, "yellow"); 1459 1460 fprintf (stdout, "red: CR; blue: EXTENDED; green: PSF-like; yellow: SATSTAR\n"); 1461 pmVisualAskUser(NULL); 1462 return true; 1463 } 1464 1465 bool psphotVisualPlotSourceSize (psMetadata *recipe, psArray *sources) { 1466 1467 bool status; 1584 1468 Graphdata graphdata; 1585 1469 KapaSection section; … … 1587 1471 if (!pmVisualIsVisual()) return true; 1588 1472 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; 1473 int myKapa = psphotKapaChannel (2); 1474 if (myKapa == -1) return false; 1475 1476 KapaClearPlots (myKapa); 1477 KapaInitGraph (&graphdata); 1478 KapaSetFont (myKapa, "courier", 14); 1479 1480 // select the max psfX,Y values for the plot limits 1481 float Xmin = 1000.0, Xmax = 0.0; 1482 float Ymin = 1000.0, Ymax = 0.0; 1483 { 1484 int nRegions = psMetadataLookupS32 (&status, recipe, "PSF.CLUMP.NREGIONS"); 1485 for (int n = 0; n < nRegions; n++) { 1486 1487 char regionName[64]; 1488 snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n); 1489 psMetadata *regionMD = psMetadataLookupPtr (&status, recipe, regionName); 1490 1491 float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); 1492 float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y"); 1493 float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX"); 1494 float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY"); 1495 1496 float X0 = psfX - 10.0*psfdX; 1497 float X1 = psfX + 10.0*psfdX; 1498 float Y0 = psfY - 10.0*psfdY; 1499 float Y1 = psfY + 10.0*psfdY; 1500 1501 if (isfinite(X0)) { Xmin = PS_MIN(Xmin, X0); } 1502 if (isfinite(X1)) { Xmax = PS_MAX(Xmax, X1); } 1503 if (isfinite(Y0)) { Ymin = PS_MIN(Ymin, Y0); } 1504 if (isfinite(Y1)) { Ymax = PS_MAX(Ymax, Y1); } 1595 1505 } 1596 1506 } 1597 1598 KapaClearPlots (kapa3); 1507 Xmin = PS_MAX(Xmin, -0.1); 1508 Ymin = PS_MAX(Ymin, -0.1); 1509 1510 // storage vectors for data to be plotted 1511 psVector *xSAT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1512 psVector *ySAT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1513 psVector *mSAT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1514 psVector *sSAT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1515 1516 psVector *xPSF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1517 psVector *yPSF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1518 psVector *mPSF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1519 psVector *sPSF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1520 1521 psVector *xEXT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1522 psVector *yEXT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1523 psVector *mEXT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1524 psVector *sEXT = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1525 1526 psVector *xDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1527 psVector *yDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1528 psVector *mDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1529 psVector *sDEF = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1530 1531 psVector *xCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1532 psVector *yCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1533 psVector *mCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1534 psVector *sCR = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1535 1536 // construct the vectors 1537 int nSAT = 0; 1538 int nEXT = 0; 1539 int nPSF = 0; 1540 int nDEF = 0; 1541 int nCR = 0; 1542 for (int i = 0; i < sources->n; i++) { 1543 pmSource *source = sources->data[i]; 1544 if (source->moments == NULL) continue; 1545 1546 if (source->mode & PM_SOURCE_MODE_CR_LIMIT) { 1547 xCR->data.F32[nCR] = source->moments->Mxx; 1548 yCR->data.F32[nCR] = source->moments->Myy; 1549 mCR->data.F32[nCR] = -2.5*log10(source->moments->Sum); 1550 sCR->data.F32[nCR] = source->extNsigma; 1551 nCR++; 1552 } 1553 if (source->mode & PM_SOURCE_MODE_SATSTAR) { 1554 xSAT->data.F32[nSAT] = source->moments->Mxx; 1555 ySAT->data.F32[nSAT] = source->moments->Myy; 1556 mSAT->data.F32[nSAT] = -2.5*log10(source->moments->Sum); 1557 sSAT->data.F32[nSAT] = source->extNsigma; 1558 nSAT++; 1559 } 1560 if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) { 1561 xEXT->data.F32[nEXT] = source->moments->Mxx; 1562 yEXT->data.F32[nEXT] = source->moments->Myy; 1563 mEXT->data.F32[nEXT] = -2.5*log10(source->moments->Sum); 1564 sEXT->data.F32[nEXT] = source->extNsigma; 1565 nEXT++; 1566 continue; 1567 } 1568 if (source->mode & PM_SOURCE_MODE_DEFECT) { 1569 xDEF->data.F32[nDEF] = source->moments->Mxx; 1570 yDEF->data.F32[nDEF] = source->moments->Myy; 1571 mDEF->data.F32[nDEF] = -2.5*log10(source->moments->Sum); 1572 sDEF->data.F32[nDEF] = source->extNsigma; 1573 nDEF++; 1574 continue; 1575 } 1576 if ((source->mode & PM_SOURCE_MODE_CR_LIMIT) || (source->mode & PM_SOURCE_MODE_SATSTAR)) { 1577 continue; 1578 } 1579 xPSF->data.F32[nPSF] = source->moments->Mxx; 1580 yPSF->data.F32[nPSF] = source->moments->Myy; 1581 mPSF->data.F32[nPSF] = -2.5*log10(source->moments->Sum); 1582 sPSF->data.F32[nPSF] = source->extNsigma; 1583 nPSF++; 1584 } 1585 xSAT->n = nSAT; 1586 ySAT->n = nSAT; 1587 mSAT->n = nSAT; 1588 sSAT->n = nSAT; 1589 1590 xPSF->n = nPSF; 1591 yPSF->n = nPSF; 1592 mPSF->n = nPSF; 1593 sPSF->n = nPSF; 1594 1595 xEXT->n = nEXT; 1596 yEXT->n = nEXT; 1597 mEXT->n = nEXT; 1598 sEXT->n = nEXT; 1599 1600 xCR->n = nCR; 1601 yCR->n = nCR; 1602 mCR->n = nCR; 1603 sCR->n = nCR; 1604 1605 xDEF->n = nDEF; 1606 yDEF->n = nDEF; 1607 mDEF->n = nDEF; 1608 sDEF->n = nDEF; 1609 1610 // four sections: MxxMyy, MagMxx, MagMyy, MagSigma 1611 1612 // first section: MxxMyy 1613 section.dx = 0.75; 1614 section.dy = 0.60; 1615 section.x = 0.00; 1616 section.y = 0.00; 1617 section.name = psStringCopy ("MxxMyy"); 1618 KapaSetSection (myKapa, §ion); 1619 psFree (section.name); 1620 1621 graphdata.color = KapaColorByName ("black"); 1622 graphdata.xmin = Xmin; 1623 graphdata.ymin = Ymin; 1624 graphdata.xmax = Xmax; 1625 graphdata.ymax = Ymax; 1626 KapaSetLimits (myKapa, &graphdata); 1627 1628 KapaBox (myKapa, &graphdata); 1629 KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM); 1630 KapaSendLabel (myKapa, "M_yy| (pixels)", KAPA_LABEL_YM); 1631 1632 graphdata.color = KapaColorByName ("black"); 1633 graphdata.ptype = 0; 1634 graphdata.size = 0.5; 1635 graphdata.style = 2; 1636 KapaPrepPlot (myKapa, nPSF, &graphdata); 1637 KapaPlotVector (myKapa, nPSF, xPSF->data.F32, "x"); 1638 KapaPlotVector (myKapa, nPSF, yPSF->data.F32, "y"); 1639 1640 graphdata.color = KapaColorByName ("blue"); 1641 graphdata.ptype = 0; 1642 graphdata.size = 0.5; 1643 graphdata.style = 2; 1644 KapaPrepPlot (myKapa, nEXT, &graphdata); 1645 KapaPlotVector (myKapa, nEXT, xEXT->data.F32, "x"); 1646 KapaPlotVector (myKapa, nEXT, yEXT->data.F32, "y"); 1647 1648 graphdata.color = KapaColorByName ("red"); 1649 graphdata.ptype = 0; 1650 graphdata.size = 0.5; 1651 graphdata.style = 2; 1652 KapaPrepPlot (myKapa, nDEF, &graphdata); 1653 KapaPlotVector (myKapa, nDEF, xDEF->data.F32, "x"); 1654 KapaPlotVector (myKapa, nDEF, yDEF->data.F32, "y"); 1655 1656 graphdata.color = KapaColorByName ("red"); 1657 graphdata.ptype = 7; 1658 graphdata.size = 1.0; 1659 graphdata.style = 2; 1660 KapaPrepPlot (myKapa, nCR, &graphdata); 1661 KapaPlotVector (myKapa, nCR, xCR->data.F32, "x"); 1662 KapaPlotVector (myKapa, nCR, yCR->data.F32, "y"); 1663 1664 graphdata.color = KapaColorByName ("blue"); 1665 graphdata.ptype = 7; 1666 graphdata.size = 1.0; 1667 graphdata.style = 2; 1668 KapaPrepPlot (myKapa, nSAT, &graphdata); 1669 KapaPlotVector (myKapa, nSAT, xSAT->data.F32, "x"); 1670 KapaPlotVector (myKapa, nSAT, ySAT->data.F32, "y"); 1671 1672 // second section: MagMyy 1673 section.dx = 0.75; 1674 section.dy = 0.20; 1675 section.x = 0.00; 1676 section.y = 0.80; 1677 section.name = psStringCopy ("MagMyy"); 1678 KapaSetSection (myKapa, §ion); 1679 psFree (section.name); 1680 1681 graphdata.color = KapaColorByName ("black"); 1682 graphdata.xmin = -17.1; 1683 graphdata.xmax = -7.9; 1684 graphdata.ymin = Ymin; 1685 graphdata.ymax = Ymax; 1686 KapaSetLimits (myKapa, &graphdata); 1687 1688 strcpy (graphdata.labels, "0210"); 1689 KapaBox (myKapa, &graphdata); 1690 KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_XP); 1691 KapaSendLabel (myKapa, "M_yy| (pixels)", KAPA_LABEL_YM); 1692 1693 graphdata.color = KapaColorByName ("black"); 1694 graphdata.ptype = 0; 1695 graphdata.size = 0.5; 1696 graphdata.style = 2; 1697 KapaPrepPlot (myKapa, nPSF, &graphdata); 1698 KapaPlotVector (myKapa, nPSF, mPSF->data.F32, "x"); 1699 KapaPlotVector (myKapa, nPSF, yPSF->data.F32, "y"); 1700 1701 graphdata.color = KapaColorByName ("blue"); 1702 graphdata.ptype = 0; 1703 graphdata.size = 0.5; 1704 graphdata.style = 2; 1705 KapaPrepPlot (myKapa, nEXT, &graphdata); 1706 KapaPlotVector (myKapa, nEXT, mEXT->data.F32, "x"); 1707 KapaPlotVector (myKapa, nEXT, yEXT->data.F32, "y"); 1708 1709 graphdata.color = KapaColorByName ("red"); 1710 graphdata.ptype = 0; 1711 graphdata.size = 0.5; 1712 graphdata.style = 2; 1713 KapaPrepPlot (myKapa, nDEF, &graphdata); 1714 KapaPlotVector (myKapa, nDEF, mDEF->data.F32, "x"); 1715 KapaPlotVector (myKapa, nDEF, yDEF->data.F32, "y"); 1716 1717 graphdata.color = KapaColorByName ("red"); 1718 graphdata.ptype = 7; 1719 graphdata.size = 1.0; 1720 graphdata.style = 2; 1721 KapaPrepPlot (myKapa, nCR, &graphdata); 1722 KapaPlotVector (myKapa, nCR, mCR->data.F32, "x"); 1723 KapaPlotVector (myKapa, nCR, yCR->data.F32, "y"); 1724 1725 graphdata.color = KapaColorByName ("blue"); 1726 graphdata.ptype = 7; 1727 graphdata.size = 1.0; 1728 graphdata.style = 2; 1729 KapaPrepPlot (myKapa, nSAT, &graphdata); 1730 KapaPlotVector (myKapa, nSAT, mSAT->data.F32, "x"); 1731 KapaPlotVector (myKapa, nSAT, ySAT->data.F32, "y"); 1732 1733 // third section: MagMxx 1734 section.dx = 0.25; 1735 section.dy = 0.60; 1736 section.x = 0.80; 1737 section.y = 0.00; 1738 section.name = psStringCopy ("MagMxx"); 1739 KapaSetSection (myKapa, §ion); 1740 psFree (section.name); 1741 1742 graphdata.color = KapaColorByName ("black"); 1743 graphdata.xmin = Xmin; 1744 graphdata.xmax = Xmax; 1745 graphdata.ymin = -7.9; 1746 graphdata.ymax = -17.1; 1747 KapaSetLimits (myKapa, &graphdata); 1748 1749 strcpy (graphdata.labels, "2001"); 1750 KapaBox (myKapa, &graphdata); 1751 KapaSendLabel (myKapa, "M_xx| (pixels)", KAPA_LABEL_XM); 1752 KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_YP); 1753 1754 graphdata.color = KapaColorByName ("black"); 1755 graphdata.ptype = 0; 1756 graphdata.size = 0.5; 1757 graphdata.style = 2; 1758 KapaPrepPlot (myKapa, nPSF, &graphdata); 1759 KapaPlotVector (myKapa, nPSF, xPSF->data.F32, "x"); 1760 KapaPlotVector (myKapa, nPSF, mPSF->data.F32, "y"); 1761 1762 graphdata.color = KapaColorByName ("blue"); 1763 graphdata.ptype = 0; 1764 graphdata.size = 0.5; 1765 graphdata.style = 2; 1766 KapaPrepPlot (myKapa, nEXT, &graphdata); 1767 KapaPlotVector (myKapa, nEXT, xEXT->data.F32, "x"); 1768 KapaPlotVector (myKapa, nEXT, mEXT->data.F32, "y"); 1769 1770 graphdata.color = KapaColorByName ("red"); 1771 graphdata.ptype = 0; 1772 graphdata.size = 0.5; 1773 graphdata.style = 2; 1774 KapaPrepPlot (myKapa, nDEF, &graphdata); 1775 KapaPlotVector (myKapa, nDEF, xDEF->data.F32, "x"); 1776 KapaPlotVector (myKapa, nDEF, mDEF->data.F32, "y"); 1777 1778 graphdata.color = KapaColorByName ("red"); 1779 graphdata.ptype = 7; 1780 graphdata.size = 1.0; 1781 graphdata.style = 2; 1782 KapaPrepPlot (myKapa, nCR, &graphdata); 1783 KapaPlotVector (myKapa, nCR, xCR->data.F32, "x"); 1784 KapaPlotVector (myKapa, nCR, mCR->data.F32, "y"); 1785 1786 graphdata.color = KapaColorByName ("blue"); 1787 graphdata.ptype = 7; 1788 graphdata.size = 1.0; 1789 graphdata.style = 2; 1790 KapaPrepPlot (myKapa, nSAT, &graphdata); 1791 KapaPlotVector (myKapa, nSAT, xSAT->data.F32, "x"); 1792 KapaPlotVector (myKapa, nSAT, mSAT->data.F32, "y"); 1793 1794 // fourth section: MagSigma 1795 section.dx = 0.75; 1796 section.dy = 0.15; 1797 section.x = 0.00; 1798 section.y = 0.65; 1799 section.name = psStringCopy ("MagSigma"); 1800 KapaSetSection (myKapa, §ion); 1801 psFree (section.name); 1802 1803 graphdata.color = KapaColorByName ("black"); 1804 graphdata.xmax = -7.9; 1805 graphdata.xmin = -17.1; 1806 graphdata.ymin = -20.1; 1807 graphdata.ymax = +20.1; 1808 KapaSetLimits (myKapa, &graphdata); 1809 1810 strcpy (graphdata.labels, "0100"); 1811 KapaBox (myKapa, &graphdata); 1812 // KapaSendLabel (myKapa, "inst mag", KAPA_LABEL_XM); 1813 KapaSendLabel (myKapa, "EXT&ss&c", KAPA_LABEL_YM); 1814 1815 graphdata.color = KapaColorByName ("black"); 1816 graphdata.ptype = 0; 1817 graphdata.size = 0.5; 1818 graphdata.style = 2; 1819 KapaPrepPlot (myKapa, nPSF, &graphdata); 1820 KapaPlotVector (myKapa, nPSF, mPSF->data.F32, "x"); 1821 KapaPlotVector (myKapa, nPSF, sPSF->data.F32, "y"); 1822 1823 graphdata.color = KapaColorByName ("blue"); 1824 graphdata.ptype = 0; 1825 graphdata.size = 0.5; 1826 graphdata.style = 2; 1827 KapaPrepPlot (myKapa, nEXT, &graphdata); 1828 KapaPlotVector (myKapa, nEXT, mEXT->data.F32, "x"); 1829 KapaPlotVector (myKapa, nEXT, sEXT->data.F32, "y"); 1830 1831 graphdata.color = KapaColorByName ("red"); 1832 graphdata.ptype = 0; 1833 graphdata.size = 0.5; 1834 graphdata.style = 2; 1835 KapaPrepPlot (myKapa, nDEF, &graphdata); 1836 KapaPlotVector (myKapa, nDEF, mDEF->data.F32, "x"); 1837 KapaPlotVector (myKapa, nDEF, sDEF->data.F32, "y"); 1838 1839 graphdata.color = KapaColorByName ("red"); 1840 graphdata.ptype = 7; 1841 graphdata.size = 1.0; 1842 graphdata.style = 2; 1843 KapaPrepPlot (myKapa, nCR, &graphdata); 1844 KapaPlotVector (myKapa, nCR, mCR->data.F32, "x"); 1845 KapaPlotVector (myKapa, nCR, sCR->data.F32, "y"); 1846 1847 graphdata.color = KapaColorByName ("blue"); 1848 graphdata.ptype = 7; 1849 graphdata.size = 1.0; 1850 graphdata.style = 2; 1851 KapaPrepPlot (myKapa, nSAT, &graphdata); 1852 KapaPlotVector (myKapa, nSAT, mSAT->data.F32, "x"); 1853 KapaPlotVector (myKapa, nSAT, sSAT->data.F32, "y"); 1854 1855 // draw N circles to outline the clumps 1856 { 1857 KapaSelectSection (myKapa, "MxxMyy"); 1858 1859 // draw a circle centered on psfX,Y with size of the psf limit 1860 psVector *xLimit = psVectorAlloc (120, PS_TYPE_F32); 1861 psVector *yLimit = psVectorAlloc (120, PS_TYPE_F32); 1862 1863 int nRegions = psMetadataLookupS32 (&status, recipe, "PSF.CLUMP.NREGIONS"); 1864 float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA"); 1865 1866 graphdata.color = KapaColorByName ("blue"); 1867 graphdata.style = 0; 1868 1869 graphdata.xmin = Xmin; 1870 graphdata.ymin = Ymin; 1871 graphdata.xmax = Xmax; 1872 graphdata.ymax = Ymax; 1873 KapaSetLimits (myKapa, &graphdata); 1874 1875 for (int n = 0; n < nRegions; n++) { 1876 1877 char regionName[64]; 1878 snprintf (regionName, 64, "PSF.CLUMP.REGION.%03d", n); 1879 psMetadata *regionMD = psMetadataLookupPtr (&status, recipe, regionName); 1880 1881 float psfX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.X"); 1882 float psfY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.Y"); 1883 float psfdX = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DX"); 1884 float psfdY = psMetadataLookupF32 (&status, regionMD, "PSF.CLUMP.DY"); 1885 float Rx = psfdX * PSF_CLUMP_NSIGMA; 1886 float Ry = psfdY * PSF_CLUMP_NSIGMA; 1887 1888 for (int i = 0; i < xLimit->n; i++) { 1889 xLimit->data.F32[i] = Rx*cos(i*2.0*M_PI/120.0) + psfX; 1890 yLimit->data.F32[i] = Ry*sin(i*2.0*M_PI/120.0) + psfY; 1891 } 1892 KapaPrepPlot (myKapa, xLimit->n, &graphdata); 1893 KapaPlotVector (myKapa, xLimit->n, xLimit->data.F32, "x"); 1894 KapaPlotVector (myKapa, yLimit->n, yLimit->data.F32, "y"); 1895 } 1896 psFree (xLimit); 1897 psFree (yLimit); 1898 } 1899 1900 psFree (xSAT); 1901 psFree (ySAT); 1902 psFree (mSAT); 1903 1904 psFree (xEXT); 1905 psFree (yEXT); 1906 psFree (mEXT); 1907 1908 psFree (xPSF); 1909 psFree (yPSF); 1910 psFree (mPSF); 1911 1912 psFree (xDEF); 1913 psFree (yDEF); 1914 psFree (mDEF); 1915 1916 psFree (xCR); 1917 psFree (yCR); 1918 psFree (mCR); 1919 1920 pmVisualAskUser(NULL); 1921 return true; 1922 } 1923 1924 bool psphotVisualShowResidualImage (pmReadout *readout) { 1925 1926 if (!pmVisualIsVisual()) return true; 1927 1928 int myKapa = psphotKapaChannel (1); 1929 if (myKapa == -1) return false; 1930 1931 psphotVisualScaleImage (myKapa, readout->image, "resid", 1); 1932 1933 pmVisualAskUser(NULL); 1934 return true; 1935 } 1936 1937 bool psphotVisualPlotApResid (psArray *sources, float mean, float error) { 1938 1939 Graphdata graphdata; 1940 float lineX[2], lineY[2]; 1941 1942 if (!pmVisualIsVisual()) return true; 1943 1944 int myKapa = psphotKapaChannel (2); 1945 if (myKapa == -1) return false; 1946 1947 KapaClearPlots (myKapa); 1599 1948 KapaInitGraph (&graphdata); 1600 1601 // first section : mag vs CR nSigma1602 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);1609 psFree (section.name);1610 1949 1611 1950 psVector *x = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1612 1951 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); 1952 psVector *dy = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 1770 1953 1771 1954 graphdata.xmin = +32.0; … … 1785 1968 x->data.F32[n] = source->psfMag; 1786 1969 y->data.F32[n] = source->apMag - source->psfMag; 1970 dy->data.F32[n] = source->errMag; 1787 1971 graphdata.xmin = PS_MIN(graphdata.xmin, x->data.F32[n]); 1788 1972 graphdata.xmax = PS_MAX(graphdata.xmax, x->data.F32[n]); … … 1792 1976 n++; 1793 1977 } 1794 x->n = y->n = n;1978 x->n = y->n = dy->n = n; 1795 1979 1796 1980 float range; … … 1802 1986 graphdata.ymin -= 0.05*range; 1803 1987 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); 1988 // XXX test 1989 graphdata.xmin = -17.0; 1990 graphdata.xmax = -9.0; 1991 graphdata.ymin = -0.31; 1992 graphdata.ymax = +0.31; 1993 1994 KapaSetLimits (myKapa, &graphdata); 1995 1996 KapaSetFont (myKapa, "helvetica", 14); 1997 KapaBox (myKapa, &graphdata); 1998 KapaSendLabel (myKapa, "PSF Mag", KAPA_LABEL_XM); 1999 KapaSendLabel (myKapa, "Ap Mag - PSF Mag", KAPA_LABEL_YM); 1811 2000 1812 2001 graphdata.color = KapaColorByName ("black"); … … 1814 2003 graphdata.size = 0.5; 1815 2004 graphdata.style = 2; 1816 KapaPrepPlot (kapa3, n, &graphdata); 1817 KapaPlotVector (kapa3, n, x->data.F32, "x"); 1818 KapaPlotVector (kapa3, n, y->data.F32, "y"); 2005 graphdata.etype |= 0x01; 2006 KapaPrepPlot (myKapa, n, &graphdata); 2007 KapaPlotVector (myKapa, n, x->data.F32, "x"); 2008 KapaPlotVector (myKapa, n, y->data.F32, "y"); 2009 KapaPlotVector (myKapa, n, dy->data.F32, "dym"); 2010 KapaPlotVector (myKapa, n, dy->data.F32, "dyp"); 2011 2012 graphdata.color = KapaColorByName ("blue"); 2013 graphdata.ptype = 0; 2014 graphdata.size = 0.5; 2015 graphdata.style = 0; 2016 graphdata.etype = 0; 2017 lineX[0] = graphdata.xmin; 2018 lineX[1] = graphdata.xmax; 2019 lineY[0] = lineY[1] = mean; 2020 KapaPrepPlot (myKapa, 2, &graphdata); 2021 KapaPlotVector (myKapa, 2, lineX, "x"); 2022 KapaPlotVector (myKapa, 2, lineY, "y"); 2023 2024 graphdata.color = KapaColorByName ("red"); 2025 graphdata.ptype = 0; 2026 graphdata.size = 0.5; 2027 graphdata.style = 0; 2028 graphdata.etype = 0; 2029 lineX[0] = graphdata.xmin; 2030 lineX[1] = graphdata.xmax; 2031 lineY[0] = lineY[1] = mean + error; 2032 KapaPrepPlot (myKapa, 2, &graphdata); 2033 KapaPlotVector (myKapa, 2, lineX, "x"); 2034 KapaPlotVector (myKapa, 2, lineY, "y"); 2035 2036 graphdata.color = KapaColorByName ("red"); 2037 graphdata.ptype = 0; 2038 graphdata.size = 0.5; 2039 graphdata.style = 0; 2040 graphdata.etype = 0; 2041 lineX[0] = graphdata.xmin; 2042 lineX[1] = graphdata.xmax; 2043 lineY[0] = lineY[1] = mean - error; 2044 KapaPrepPlot (myKapa, 2, &graphdata); 2045 KapaPlotVector (myKapa, 2, lineX, "x"); 2046 KapaPlotVector (myKapa, 2, lineY, "y"); 1819 2047 1820 2048 psFree (x); 1821 2049 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 } 2050 psFree (dy); 2051 2052 pmVisualAskUser(NULL); 2053 return true; 2054 } 2055 2056 bool psphotVisualShowPetrosians (psArray *sources) { 2057 2058 int Noverlay, NOVERLAY; 2059 KiiOverlay *overlay; 2060 2061 if (!pmVisualIsVisual()) return true; 2062 2063 int kapa = psphotKapaChannel (1); 2064 if (kapa == -1) return false; 2065 2066 Noverlay = 0; 2067 NOVERLAY = 100; 2068 ALLOCATE (overlay, KiiOverlay, NOVERLAY); 2069 2070 for (int i = 0; i < sources->n; i++) { 2071 pmSource *source = sources->data[i]; 2072 2073 if (!source) continue; 2074 if (!source->extpars) continue; 2075 if (!source->extpars->profile) continue; 2076 if (!source->extpars->petrosian_80) continue; 2077 2078 pmSourceRadialProfile *profile = source->extpars->profile; 2079 pmSourceExtendedFlux *petrosian = source->extpars->petrosian_80; 2080 2081 overlay[Noverlay].type = KII_OVERLAY_CIRCLE; 2082 overlay[Noverlay].x = source->peak->xf; 2083 overlay[Noverlay].y = source->peak->yf; 2084 overlay[Noverlay].dx = 2.0*petrosian->radius; 2085 overlay[Noverlay].dy = 2.0*petrosian->radius*profile->axes.minor/profile->axes.major; 2086 overlay[Noverlay].angle = profile->axes.theta * PS_DEG_RAD; 2087 overlay[Noverlay].text = NULL; 2088 Noverlay ++; 2089 CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100); 2090 2091 overlay[Noverlay].type = KII_OVERLAY_CIRCLE; 2092 overlay[Noverlay].x = source->peak->xf; 2093 overlay[Noverlay].y = source->peak->yf; 2094 overlay[Noverlay].dx = 4.0*petrosian->radius; 2095 overlay[Noverlay].dy = 4.0*petrosian->radius*profile->axes.minor/profile->axes.major; 2096 overlay[Noverlay].angle = profile->axes.theta * PS_DEG_RAD; 2097 overlay[Noverlay].text = NULL; 2098 Noverlay ++; 2099 CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 100); 2100 } 2101 2102 KiiLoadOverlay (kapa, overlay, Noverlay, "red"); 2103 FREE (overlay); 2104 2105 pmVisualAskUser(NULL); 1830 2106 return true; 1831 2107 } … … 1850 2126 1851 2127 # endif 2128 2129 # if (0) 2130 // *** make a histogram of the source counts in the x and y directions 2131 psHistogram *nX = psHistogramAlloc (graphdata.xmin, graphdata.xmax, 50.0); 2132 psHistogram *nY = psHistogramAlloc (graphdata.ymin, graphdata.ymax, 50.0); 2133 psVectorHistogram (nX, xFaint, NULL, NULL, 0); 2134 psVectorHistogram (nY, yFaint, NULL, NULL, 0); 2135 psVector *dX = psVectorAlloc (nX->nums->n, PS_TYPE_F32); 2136 psVector *vX = psVectorAlloc (nX->nums->n, PS_TYPE_F32); 2137 psVector *dY = psVectorAlloc (nY->nums->n, PS_TYPE_F32); 2138 psVector *vY = psVectorAlloc (nY->nums->n, PS_TYPE_F32); 2139 for (int i = 0; i < nX->nums->n; i++) { 2140 dX->data.F32[i] = nX->nums->data.S32[i]; 2141 vX->data.F32[i] = 0.5*(nX->bounds->data.F32[i] + nX->bounds->data.F32[i+1]); 2142 } 2143 for (int i = 0; i < nY->nums->n; i++) { 2144 dY->data.F32[i] = nY->nums->data.S32[i]; 2145 vY->data.F32[i] = 0.5*(nY->bounds->data.F32[i] + nY->bounds->data.F32[i+1]); 2146 } 2147 2148 graphdata.color = KapaColorByName ("black"); 2149 graphdata.ptype = 0; 2150 graphdata.size = 0.0; 2151 graphdata.style = 0; 2152 KapaPrepPlot (myKapa, dX->n, &graphdata); 2153 KapaPlotVector (myKapa, dX->n, dX->data.F32, "x"); 2154 KapaPlotVector (myKapa, vX->n, vX->data.F32, "y"); 2155 2156 psFree (nX); 2157 psFree (dX); 2158 psFree (vX); 2159 2160 psFree (nY); 2161 psFree (dY); 2162 psFree (vY); 2163 2164 # endif 2165
Note:
See TracChangeset
for help on using the changeset viewer.
