Changeset 25906
- Timestamp:
- Oct 21, 2009, 12:42:17 PM (17 years ago)
- Location:
- trunk/psastro/src
- Files:
-
- 2 edited
-
psastro.h (modified) (1 diff)
-
psastroZeroPoint.c (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psastro/src/psastro.h
r24653 r25906 146 146 147 147 bool psastroZeroPoint (pmConfig *config); 148 bool psastroZeroPointReadout(pmReadout *readout, float zeropt, float exptime); 148 psVector *psastroZeroPointReadoutAccum(psVector *dMag, pmReadout *readout, float exptime); 149 bool psastroZeroPointAnalysis (psMetadata *header, psVector *dMag, float zeropt, float edgeFraction, bool useMean); 149 150 bool psastroZeroPointFromRecipe (float *zeropt, float *exptime, float *ghostMaxMag, pmFPA *fpa, psMetadata *recipe); 151 152 psStats *psastroStatsPercentile (psVector *myVector, float flimit); 150 153 151 154 // masking functions -
trunk/psastro/src/psastroZeroPoint.c
r24649 r25906 15 15 bool psastroZeroPoint (pmConfig *config) { 16 16 17 bool status; 17 18 float zeropt, exptime; 18 19 pmChip *chip = NULL; … … 27 28 } 28 29 30 // recipe options 31 bool byExposure = psMetadataLookupBool (&status, recipe, "ZERO.POINT.BY.EXPOSURE"); 32 bool useMean = psMetadataLookupBool (&status, recipe, "ZERO.POINT.USE.MEAN"); 33 float edgeFraction = psMetadataLookupF32 (&status, recipe, "ZERO.POINT.EDGE.FRACTION"); 34 29 35 // select the input data sources 30 36 pmFPAfile *input = psMetadataLookupPtr (NULL, config->files, "PSASTRO.INPUT"); … … 55 61 } 56 62 63 // if we measure the zero point by exposure, accumulate the dMag values here: 64 psVector *dMag = NULL; 65 57 66 // this loop selects the matched stars for all chips 67 // XXX optionally measure zero point for entire exposure in a single statistic 58 68 while ((chip = pmFPAviewNextChip (view, fpa, 1)) != NULL) { 59 69 psTrace ("psastro", 4, "Chip %d: %x %x\n", view->chip, chip->file_exists, chip->process); … … 71 81 72 82 // calculate dMag for the matched stars 73 psastroZeroPointReadout (readout, zeropt, exptime); 74 83 dMag = psastroZeroPointReadoutAccum (dMag, readout, exptime); 84 85 if (!byExposure) { 86 // calculate dMag for the matched stars just for this readout (well, chip) 87 psMetadata *header = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER"); 88 psastroZeroPointAnalysis (header, dMag, zeropt, edgeFraction, useMean); 89 psFree (dMag); 90 dMag = NULL; 91 } 75 92 } 76 93 } 94 } 95 96 if (byExposure) { 97 psMetadata *header = psMetadataLookupMetadata (&status, fpa->analysis, "PSASTRO.HEADER"); 98 psastroZeroPointAnalysis (header, dMag, zeropt, edgeFraction, useMean); 99 psFree (dMag); 100 dMag = NULL; 77 101 } 78 102 … … 82 106 83 107 /** 84 * we measure <dMag> and \sigma_dMag and write them to the header108 * accumulate the dMag values from this readout 85 109 */ 86 bool psastroZeroPointReadout(pmReadout *readout, float zeropt, float exptime) {110 psVector *psastroZeroPointReadoutAccum(psVector *dMag, pmReadout *readout, float exptime) { 87 111 88 112 bool status; … … 90 114 // select the raw objects for this readout 91 115 psArray *rawstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.RAWSTARS"); 92 if (rawstars == NULL) return false;116 if (rawstars == NULL) return dMag; 93 117 94 118 // select the raw objects for this readout 95 119 psArray *refstars = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.REFSTARS"); 96 if (refstars == NULL) return false;120 if (refstars == NULL) return dMag; 97 121 98 122 psArray *matches = psMetadataLookupPtr (&status, readout->analysis, "PSASTRO.MATCH"); 99 if (matches == NULL) return false; 100 101 psVector *dMag = psVectorAllocEmpty (100, PS_TYPE_F32); 102 103 int Npts = 0; 123 if (matches == NULL) return dMag; 124 125 if (!dMag) { 126 dMag = psVectorAllocEmpty (100, PS_TYPE_F32); 127 } 128 104 129 for (int i = 0; i < matches->n; i++) { 105 130 … … 110 135 pmAstromObj *ref = refstars->data[match->ref]; 111 136 112 dMag->data.F32[Npts] = ref->Mag - raw->Mag - 2.5*log10(exptime); 113 psVectorExtend (dMag, 100, 1); 114 Npts++; 115 } 116 117 psTrace ("psModules.astrom", 4, "Npts: %d\n", Npts); 118 119 if (Npts < 3) { 137 float value = ref->Mag - raw->Mag - 2.5*log10(exptime); 138 psVectorAppend (dMag, value); 139 } 140 return dMag; 141 } 142 143 bool psastroZeroPointAnalysis (psMetadata *header, psVector *dMag, float zeropt, float edgeFraction, bool useMean) { 144 145 // XXX make this depend on the mode? 146 if (dMag->n < 3) { 120 147 fprintf (stderr, "zero point NaN +/- NaN\n"); 121 psFree (dMag);122 148 return false; 123 149 } 124 150 125 // stats structure and mask for use in measuring the clipping statistic 126 // this analysis has too few data points to use the robust median method 127 psStats *stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV); 128 if (!psVectorStats (stats, dMag, NULL, NULL, 0)) { 129 psError(PS_ERR_UNKNOWN, false, "failure to measure stats"); 130 return false; 131 } 132 fprintf (stderr, "zero point %f +/- %f using %d stars; transparency %f\n", stats->clippedMean, stats->clippedStdev, Npts, zeropt - stats->clippedMean); 133 134 psMetadata *header = psMetadataLookupMetadata (&status, readout->analysis, "PSASTRO.HEADER"); 151 // the zero point analysis depends on the type of desired statistic. For comparisons 152 // against a high-quality reference catalog with a good match to the actual filter used, it 153 // is best to use a standard clipped mean or global mean statistic. If the reference 154 // catalog has some unmodeled extra parameter, as is the case for the synthetic grizy 155 // database vs PS1, then it is best to use some consistent feature in the color 156 // distribution. 157 158 psStats *stats = NULL; 159 if (useMean) { 160 // stats structure and mask for use in measuring the clipping statistic 161 // this analysis has too few data points to use the robust median method 162 stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV); 163 if (!psVectorStats (stats, dMag, NULL, NULL, 0)) { 164 psError(PS_ERR_UNKNOWN, false, "failure to measure zero point by mean"); 165 return false; 166 } 167 } else { 168 stats = psastroStatsPercentile (dMag, edgeFraction); 169 if (!stats) { 170 psError(PS_ERR_UNKNOWN, false, "failure to measure zero point by edge"); 171 return false; 172 } 173 } 174 fprintf (stderr, "zero point %f +/- %f using %ld stars; transparency %f\n", stats->clippedMean, stats->clippedStdev, dMag->n, zeropt - stats->clippedMean); 135 175 136 176 psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_OBS", PS_META_REPLACE, "measured zero point", stats->clippedMean); … … 139 179 psMetadataAddF32 (header, PS_LIST_TAIL, "ZPT_OFF", PS_META_REPLACE, "measured zero point", zeropt - stats->clippedMean); 140 180 141 psFree (dMag);142 181 psFree (stats); 143 182 return true; 144 183 } 184 185 #define MAG_RESOLUTION 0.001 186 187 // set the bin closest to the corresponding value. if USE_END is +/- 1, 188 // out-of-range saturates on lower/upper bin REGARDLESS of actual value 189 #define PS_BIN_FOR_VALUE(RESULT, VECTOR, VALUE, USE_END) { \ 190 psVectorBinaryDisectResult result; \ 191 psScalar tmpScalar; \ 192 tmpScalar.type.type = PS_TYPE_F32; \ 193 tmpScalar.data.F32 = (VALUE); \ 194 RESULT = psVectorBinaryDisect (&result, VECTOR, &tmpScalar); \ 195 switch (result) { \ 196 case PS_BINARY_DISECT_PASS: \ 197 break; \ 198 case PS_BINARY_DISECT_OUTSIDE_RANGE: \ 199 psTrace("psastro", 6, "selected bin outside range"); \ 200 if (USE_END == -1) { RESULT = 0; } \ 201 if (USE_END == +1) { RESULT = VECTOR->n - 1; } \ 202 break; \ 203 case PS_BINARY_DISECT_INVALID_INPUT: \ 204 case PS_BINARY_DISECT_INVALID_TYPE: \ 205 psAbort ("programming error"); \ 206 break; \ 207 } } 208 209 # define PS_BIN_INTERPOLATE(RESULT, VECTOR, BOUNDS, BIN, VALUE) { \ 210 float dX, dY, Xo, Yo, Xt; \ 211 if (BIN == BOUNDS->n - 1) { \ 212 dX = 0.5*(BOUNDS->data.F32[BIN+1] - BOUNDS->data.F32[BIN-1]); \ 213 dY = VECTOR->data.F32[BIN] - VECTOR->data.F32[BIN-1]; \ 214 Xo = 0.5*(BOUNDS->data.F32[BIN+1] + BOUNDS->data.F32[BIN]); \ 215 Yo = VECTOR->data.F32[BIN]; \ 216 } else { \ 217 dX = 0.5*(BOUNDS->data.F32[BIN+2] - BOUNDS->data.F32[BIN]); \ 218 dY = VECTOR->data.F32[BIN+1] - VECTOR->data.F32[BIN]; \ 219 Xo = 0.5*(BOUNDS->data.F32[BIN+1] + BOUNDS->data.F32[BIN]); \ 220 Yo = VECTOR->data.F32[BIN]; \ 221 } \ 222 if (dY != 0) { \ 223 Xt = (VALUE - Yo)*dX/dY + Xo; \ 224 } else { \ 225 Xt = Xo; \ 226 } \ 227 Xt = PS_MIN (BOUNDS->data.F32[BIN+1], PS_MAX(BOUNDS->data.F32[BIN], Xt)); \ 228 psTrace("psastro", 6, "(Xo, Yo, dX, dY, Xt, Yt) is (%.2f %.2f %.2f %.2f %.2f %.2f)\n", \ 229 Xo, Yo, dX, dY, Xt, VALUE); \ 230 RESULT = Xt; } 231 232 // measure the edge of the sample at flimit 233 // return results in stats->sampleMean, sampleStdev 234 // XXX this is a misuse of psStats -- make our own structure? 235 psStats *psastroStatsPercentile (psVector *myVector, float flimit) { 236 237 // search for the 'blue' edge of the dMag distribution: 238 // the distribution is not a normal population, but instead has a broad range with fairly hard edges. 239 // construct a histogram and look for the 240 241 // stats is first used to find the data range 242 psStats *stats = psStatsAlloc(PS_STAT_MIN | PS_STAT_MAX); // Statistics for min and max 243 psHistogram *histogram = NULL; // Histogram of the data 244 psHistogram *cumulative = NULL; // Cumulative histogram of the data 245 float min = NAN, max = NAN; // Mimimum and maximum values 246 247 // Get the minimum and maximum values 248 if (!psVectorStats(stats, myVector, NULL, NULL, 0)) goto escape; 249 min = stats->min; 250 max = stats->max; 251 if (isnan(min) || isnan(max)) goto escape; 252 psTrace("psastro", 6, "Data min/max is (%.2f, %.2f)\n", min, max); 253 254 // If all data points have the same value, then we set the appropriate members of stats and return. 255 if (fabs(max - min) <= FLT_EPSILON) { 256 stats->clippedMean = min; 257 stats->clippedStdev = NAN; 258 stats->results |= PS_STAT_CLIPPED_MEAN; 259 stats->results |= PS_STAT_CLIPPED_STDEV; 260 return stats; 261 } 262 263 // Define the histogram bin size. 264 float binSize = MAG_RESOLUTION; 265 long numBins = (max - min) / binSize; // Number of bins 266 psTrace("psastro", 6, "Numbins is %ld\n", numBins); 267 psTrace("psastro", 6, "Creating a robust histogram from data range (%.2f - %.2f)\n", min, max); 268 269 // Generate the histogram 270 histogram = psHistogramAlloc(min, max, numBins); 271 if (!psVectorHistogram(histogram, myVector, NULL, NULL, 0)) { 272 // if psVectorHistogram returns false, we have a programming error 273 psError(PS_ERR_UNKNOWN, false, "Unable to generate histogram for psastroZeroPointAnalysis\n"); 274 psFree(histogram); 275 psFree(stats); 276 return NULL; 277 } 278 if (psTraceGetLevel("psastro") >= 8) { 279 PS_VECTOR_PRINT_F32(histogram->bounds); 280 PS_VECTOR_PRINT_F32(histogram->nums); 281 } 282 283 // Convert the specific histogram to a cumulative histogram 284 // The cumulative histogram data points correspond to the UPPER bound value (N < Bin[i+1]) 285 cumulative = psHistogramAlloc(min, max, numBins); 286 cumulative->nums->data.F32[0] = histogram->nums->data.F32[0]; 287 for (long i = 1; i < histogram->nums->n; i++) { 288 cumulative->nums->data.F32[i] = cumulative->nums->data.F32[i-1] + histogram->nums->data.F32[i]; 289 cumulative->bounds->data.F32[i-1] = histogram->bounds->data.F32[i]; 290 } 291 if (psTraceGetLevel("psastro") >= 8) { 292 PS_VECTOR_PRINT_F32(cumulative->bounds); 293 PS_VECTOR_PRINT_F32(cumulative->nums); 294 } 295 296 // Find the bin which contains the first data point above the limit 297 long totalDataPoints = cumulative->nums->data.F32[numBins - 1]; 298 psTrace("psastro", 6, "Total data points is %ld\n", totalDataPoints); 299 300 // find bin which is the lower bound of the limit value (value[bin] < f < value[bin+1] 301 long bin; 302 PS_BIN_FOR_VALUE(bin, cumulative->nums, flimit * totalDataPoints, 0); 303 psTrace("psastro", 6, "The bin is %ld (%.2f to %.2f)\n", bin, cumulative->bounds->data.F32[bin], cumulative->bounds->data.F32[bin+1]); 304 305 // Linear interpolation to the limit value in bin units 306 float value; 307 PS_BIN_INTERPOLATE (value, cumulative->nums, cumulative->bounds, bin, totalDataPoints * flimit); 308 psTrace("psastro", 6, "limit value is %f\n", value); 309 310 stats->clippedMean = value; 311 stats->clippedStdev = 0.0; // XXX derive correct error value 312 stats->results |= PS_STAT_CLIPPED_MEAN; 313 stats->results |= PS_STAT_CLIPPED_STDEV; 314 stats->options = PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV; 315 316 // Clean up 317 psFree(histogram); 318 psFree(cumulative); 319 return stats; 320 321 escape: 322 stats->clippedMean = NAN; 323 stats->clippedStdev = NAN; 324 stats->results |= PS_STAT_CLIPPED_MEAN; 325 stats->results |= PS_STAT_CLIPPED_STDEV; 326 stats->options = PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV; 327 328 psFree(histogram); 329 psFree(cumulative); 330 331 return stats; 332 } 333 145 334 146 335 # define ESCAPE(MSG) { \
Note:
See TracChangeset
for help on using the changeset viewer.
