Changeset 25228
- Timestamp:
- Sep 1, 2009, 4:30:19 PM (17 years ago)
- File:
-
- 1 edited
-
branches/pap/psphot/src/psphotFake.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/pap/psphot/src/psphotFake.c
r25062 r25228 13 13 // We limit ourselves to calculating the peak flux in the smoothed image, which should be close (modulo 14 14 // non-Gaussian PSF) to the limiting flux in the un-smoothed original image. 15 static float fakeLimit(const pmReadout *ro, // Readout of interest 16 const psMetadata *recipe // psphot recipe 17 ); 15 static bool fakeLimit(float *magLim, // Limiting magntiude, to return 16 float *minFlux, // Minimum flux, to return 17 const pmReadout *ro, // Readout of interest 18 float thresh, // Threshold for source identification 19 float xFWHM, float yFWHM, // Size of PSF 20 float smoothNsigma, // Smoothing limit 21 psImageMaskType maskVal // Value to mask 22 ); 18 23 { 19 PM_ASSERT_READOUT_NON_NULL(ro, NAN); 20 PM_ASSERT_READOUT_VARIANCE(ro, NAN); 21 PS_ASSERT_METADATA_NON_NULL(recipe, NAN); 22 23 float xFWHM = psMetadataLookupF32(NULL, recipe, "FWHM_X"); 24 float yFWHM = psMetadataLookupF32(NULL, recipe, "FWHM_Y"); 25 if (!isfinite(xFWHM) || !isfinite(yFWHM)) { 26 psError(PSPHOT_ERR_CONFIG, false, "Unable to find FWHM_X and FWHM_Y"); 27 return NAN; 28 } 24 PM_ASSERT_READOUT_NON_NULL(ro, false); 25 PM_ASSERT_READOUT_VARIANCE(ro, false); 26 PS_ASSERT_METADATA_NON_NULL(recipe, false); 29 27 30 28 float smoothSigma = 0.5*(FWHM_X + FWHM_Y) / (2.0*sqrtf(2.0*log(2.0))); 31 float smoothNsigma = psMetadataLookupF32(NULL, recipe, "PEAKS_SMOOTH_NSIGMA");32 if (!isfinite(smoothSigma) || !isfinite(smoothNsigma)) {33 psError(PSPHOT_ERR_CONFIG, false, "Unable to set smoothing parameters");34 return NAN;35 }36 37 29 psKernel *kernel = psImageSmoothKernel(smoothSigma, smoothNsigma); // Kernel used for smoothing 38 30 psKernel *newCovar = psImageCovarianceCalculate(kernel, readout->covariance); // Covariance matrix … … 40 32 float factor = psImageCovarianceFactor(newCovar); // Variance factor 41 33 psFree(newCovar); 42 43 psImageMaskType maskVal = psMetadataLookupImageMask(NULL, recipe, "MASK.PSPHOT"); // Value to mask44 34 45 35 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for variance … … 50 40 psFree(stats); 51 41 psFree(rng); 52 return NAN;42 return false; 53 43 } 54 44 psFree(rng); … … 56 46 psFree(stats); 57 47 58 float thresh = psMetadataLookupF32(NULL, recipe, "PEAKS_NSIGMA_LIMIT_2"); 59 if (!isfinite(thresh)) { 60 psError(PSPHOT_ERR_CONFIG, false, "Unable to find threshold"); 61 return NAN; 62 } 63 64 return -2.5 * log10(thresh * sqrtf(meanVar * factor)); 48 if (magLim) { 49 *magLim = -2.5 * log10(thresh * sqrtf(meanVar * factor)); 50 } 51 if (minFlux) { 52 int fudge = psMetadataLookupF32(NULL, recipe, "FAKE.MINFLUX"); // Fudge factor for minimum flux 53 *minFlux = sqrtf(meanVar) * fudge; 54 } 55 56 return true; 65 57 } 66 58 59 /// Generate a fake image and add it in to the existing readout 67 60 static bool fakeGenerate(psImage **xSrc, psImage **ySrc, // Positions of sources 68 61 const pmReadout *ro, // Readout of interest 69 const psMetadata *recipe, // psphot recipe 70 float refMag // Reference magnitude 62 const psVector *magOffsets, // Magnitude offsets for fake sources 63 int numSources, // Number of fake sources for each bin 64 float refMag, // Reference magnitude 65 float minFlux // Minimum flux level for fake image 71 66 ) 72 67 { 73 PM_ASSERT_READOUT_NON_NULL(ro, NULL); 74 PM_ASSERT_READOUT_IMAGE(ro, NULL); 75 PS_ASSERT_METADATA_NON_NULL(recipe, NULL); 76 77 psMetadata *fake = psMetadataLookupMetadata(NULL, recipe, "FAKE"); // Fake information 78 if (!fake) { 79 psError(PSPHOT_ERR_CONFIG, false, "Unable to find FAKE information in recipe"); 80 return NULL; 81 } 82 83 psVector *magOffsets = psMetadataLookupVector(NULL, recipe, "FAKE.MAG"); // Magnitude offsets 84 if (!magOffset || magOffset->type.type != PS_TYPE_F32) { 85 psError(PSPHOT_ERR_CONFIG, false, "Unable to find FAKE.MAG F32 vector in recipe"); 86 return NULL; 87 } 68 PM_ASSERT_READOUT_NON_NULL(ro, false); 69 PM_ASSERT_READOUT_IMAGE(ro, false); 70 PS_ASSERT_METADATA_NON_NULL(recipe, false); 71 PS_ASSERT_VECTOR_NON_NULL(magOffsets, false); 72 PS_ASSERT_VECTOR_TYPE(magOffsets, PS_TYPE_F32, false); 73 88 74 int numBins = magOffset->n; // Number of bins 89 int numSources = psMetadataLookupS32(NULL, recipe, "FAKE.NUM"); // Number of sources for each bin90 91 75 int numCols = ro->image->numCols, numRows = ro->image->numRows; // Size of image 92 93 94 76 95 77 *xSrc = psImageRecycle(*xSrc, numSources, numBins, PS_TYPE_F32); … … 123 105 124 106 pmReadout *fakeRO = pmReadoutAlloc(); // Fake readout 125 pmReadoutFakeFromVectors(fakeRO, xAll, yAll, mag, 126 107 if (!pmReadoutFakeFromVectors(fakeRO, xAll, yAll, mag, NULL, NULL, psf, minFlux, NAN, false, false)) { 108 psError(PS_ERR_UNKNOWN, false, "Unable to generate fake image"); 109 psFree(fakeRO); 110 psFree(xAll); 111 psFree(yAll); 112 psFree(magAll); 113 return false; 114 } 115 psFree(xAll); 116 psFree(yAll); 117 psFree(magAll); 118 119 psBinaryOp(ro->image, ro->image, "+", fakeRO->image); 120 psFree(fakeRO); 121 122 return true; 123 } 127 124 128 125 … … 138 135 PS_ASSERT_ARRAY_NON_NULL(realSources, false); 139 136 140 psTimerStart("psphotFake"); 141 142 // Generate array of fake sources and define the pixels with pmSourceDefinePixels 143 psArray *fakeOrig = fakeGenerate(config, readout, recipe); 144 145 psArray *fakeMeasured = psArrayAlloc(fakeOrig->n); // Measured values for the sources in fakeOrig 146 for (int i = 0; i < fakeOrig->n; i++) { 147 fakeMeasured->data[i] = pmSourceCopy(fakeOrig->data[i]); 148 } 149 150 int numCols = readout->image->numCols, numRows = readout->image->numRows; // Size of image 151 152 pmReadout *fakeRO = pmReadoutAlloc(NULL); // Readout with fake sources 153 154 if (!pmReadoutFakeFromSources(fakeRO, numCols, numRows, fakeOrig, NULL, NULL, 155 psf, MIN_FLUX, 0, false, false)) { 156 psError(psErrorCodeLast(), false, "Unable to generate fake readout"); 157 psFree(fakeRO); 158 psFree(fakeMeasured); 159 psFree(fakeOrig); 160 return false; 161 } 162 163 164 bool pmReadoutFakeFromSources(pmReadout *readout, ///< Output readout, or NULL 165 int numCols, int numRows, ///< Dimension of image 166 const psArray *sources, ///< Array of pmSource 167 const psVector *xOffset, ///< x offsets for sources (source -> img), or NULL 168 const psVector *yOffset, ///< y offsets for sources (source -> img), or NULL 169 const pmPSF *psf, ///< PSF for sources 170 float minFlux, ///< Minimum flux to bother about; for setting source radius 171 int radius, ///< Fixed radius for sources 172 bool circularise, ///< Circularise PSF model? 173 bool normalise ///< Normalise the peak value? 174 ); 175 176 177 178 179 // remove all sources 137 psTimerStart("psphot.fake"); 138 139 // Collect recipe information 140 float xFWHM = psMetadataLookupF32(NULL, recipe, "FWHM_X"); // PSF size in x 141 float yFWHM = psMetadataLookupF32(NULL, recipe, "FWHM_Y"); // PSF size in y 142 if (!isfinite(xFWHM) || !isfinite(yFWHM)) { 143 psError(PSPHOT_ERR_CONFIG, false, "Unable to find FWHM_X and FWHM_Y in recipe"); 144 return false; 145 } 146 float smoothNsigma = psMetadataLookupF32(NULL, recipe, "PEAKS_SMOOTH_NSIGMA"); // Smoothing limit 147 if (!isfinite(smoothNsigma)) { 148 psError(PSPHOT_ERR_CONFIG, false, "Unable to find PEAKS_SMOOTH_NSIGMA in recipe"); 149 return false; 150 } 151 float thresh = psMetadataLookupF32(NULL, recipe, "PEAKS_NSIGMA_LIMIT_2"); 152 if (!isfinite(thresh)) { 153 psError(PSPHOT_ERR_CONFIG, false, "Unable to find PEAKS_NSIGMA_LIMIT_2 in recipe"); 154 return false; 155 } 156 psVector *magOffsets = psMetadataLookupVector(NULL, recipe, "FAKE.MAG"); // Magnitude offsets 157 if (!magOffset || magOffset->type.type != PS_TYPE_F32) { 158 psError(PSPHOT_ERR_CONFIG, false, "Unable to find FAKE.MAG F32 vector in recipe"); 159 return NULL; 160 } 161 int numSources = psMetadataLookupS32(NULL, recipe, "FAKE.NUM"); // Number of sources for each bin 162 if (numSources == 0) { 163 psError(PSPHOT_ERR_CONFIG, false, "Unable to find FAKE.NUM in recipe"); 164 return NULL; 165 } 166 psImageMaskType maskVal = psMetadataLookupImageMask(&status, recipe, "MASK.PSPHOT"); // Value to mask 167 168 169 // remove all sources, adding noise for subtracted sources 180 170 psphotRemoveAllSources(realSources, recipe); 181 182 // add noise for real (subtracted) objects 183 psphotAddNoise (readout, realSources, recipe); 184 185 // XXX fake sources should measure peak->x,y, force sources should not 186 psImageMaskType maskVal = 0xff; 187 psImage *significance = psphotSignificanceImage(readout, recipe, 1, maskVal); 188 ppSimDetections (significance, recipe, fakeSources); 189 psFree (significance); 190 191 // remove noise for subtracted objects (ie, return to normal noise level) 192 psphotSubNoise (readout, realSources, recipe); 193 194 // replace all sources 195 psphotReplaceAllSources (realSources, recipe); 196 197 // construct an initial model for each object 198 psphotGuessModels (config, readout, realSources, psf); 199 psphotGuessModels (config, readout, fakeSources, psf); 200 201 // linear fit to real + fake sources 202 psArray *sources = ppSimMergeSources (realSources, fakeSources); 203 psphotFitSourcesLinear (readout, sources, recipe, psf, FALSE); // XXX option to NOT subtract 204 psphotReplaceAllSources (sources, recipe); 205 psFree (sources); // only frees the merged references 206 207 // calculate source magnitudes (for which set??) 208 psphotMagnitudes(config, readout, view, fakeSources, psf); 209 210 // drop the references to the image pixels held by each source 211 psphotSourceFreePixels (realSources); 212 psphotSourceFreePixels (fakeSources); 213 214 // create the exported-metadata and free local data 215 // XXX this places the sources on readout->analysis as PSPHOT.SOURCES. modify? 216 // (or don't supply the sources, and do this with a different function) 217 psphotReadoutCleanup(config, readout, recipe, NULL, psf, NULL); 218 219 pmCell *fakeCell = pmFPAfileThisCell (config->files, view, "PPSIM.FAKE.SOURCES"); psAssert (fakeCell, "no cell?"); 220 pmChip *fakeChip = pmFPAfileThisChip (config->files, view, "PPSIM.FAKE.SOURCES"); psAssert (fakeChip, "no chip?"); 221 pmReadout *fakeReadout = pmFPAfileThisReadout (config->files, view, "PPSIM.FAKE.SOURCES"); 222 if (!fakeReadout) { 223 fakeReadout = pmReadoutAlloc (fakeCell); 224 psFree (fakeReadout); // there is a copy on 'cell' as well 225 } 226 psAssert (fakeReadout, "no fakeReadout?"); 227 pmChipSetDataStatus (fakeChip, true); 228 psMetadataAddArray (fakeReadout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_META_REPLACE, "fake photometry ", fakeSources); 171 psphotAddNoise(readout, realSources, recipe); 172 173 float magLim; // Guess at limiting magnitude 174 float minFlux; // Minimum flux for fake image 175 if (!fakeLimit(&magLim, &minFlux, readout, thresh, xFWHM, yFWHM, smoothNsigma, maskVal)) { 176 psError(PS_ERR_UNKNOWN, false, "Unable to determine limits for image"); 177 return false; 178 } 179 180 psImage *xFake = NULL, *yFake = NULL; // Coordinates of sources, each bin in a row 181 if (!fakeGenerate(&xFake, &yFake, readout, magOffsets, numSources, magLim, minFlux)) { 182 psError(PS_ERR_UNKNOWN, false, "Unable to generate fake sources"); 183 psFree(xFake); 184 psFree(yFake); 185 return false; 186 } 187 188 psImage *significance = psphotSignificanceImage(readout, recipe, 2, maskVal); 189 if (!significance) { 190 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to generate significance image"); 191 psFree(xFake); 192 psFree(yFake); 193 return false; 194 } 195 196 int numBins = magOffsets->n; // Number of bins 197 psVector *frac = psVectorAlloc(numBins, PS_TYPE_S32); // Fraction of sources in each bin 198 for (int i = 0; i < numBins; i++) { 199 int numFound = 0; // Number found 200 for (int j = 0; j < numSources; j++) { 201 float x = xFake->data.F32[i][j], y = yFake->data.F32[i][j]; // Coordinates of interest 202 int xPix = x, yPix = y; // Pixel coordinates 203 if (significance->data.F32[yPix][xPix] > thresh) { 204 numFound++; 205 } 206 } 207 frac->data.S32[i] = (float)numFound / (float)numSources; 208 } 209 210 psFree(xFake); 211 psFree(yFake); 212 psFree(significance); 213 214 // Putting results on recipe because that appears to be the psphot standard, but it's not a good idea 215 psMetadataAddVector(recipe, PS_LIST_TAIL, "FAKE.EFF", PS_META_REPLACE, 216 "Efficiency fractions", frac); 217 psMetadataAddVector(recipe, PS_LIST_TAIL, "FAKE.MAG", PS_META_REPLACE, 218 "Efficiency magnitudes", magOffsets); 219 psMetadataAddF32(recipe, PS_LIST_TAIL, "FAKE.REF", PS_META_REPLACE, 220 "Efficiency reference magnitude", magLim); 221 222 psFree(frac); 229 223 230 224 return true;
Note:
See TracChangeset
for help on using the changeset viewer.
