Changeset 20953
- Timestamp:
- Dec 10, 2008, 5:24:56 PM (17 years ago)
- Location:
- trunk/psModules/src/objects
- Files:
-
- 2 edited
-
pmSourceMatch.c (modified) (8 diffs)
-
pmSourceMatch.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/objects/pmSourceMatch.c
r20949 r20953 63 63 pmSource *source = sources->data[i]; // Source of interest 64 64 if (!source || (source->mode & SOURCE_MASK) || !isfinite(source->psfMag) || 65 source->psfMag > SOURCE_FAINTEST) {65 !isfinite(source->errMag) || source->psfMag > SOURCE_FAINTEST) { 66 66 continue; 67 67 } … … 122 122 match->image = psVectorAllocEmpty(num, PS_TYPE_U32); 123 123 match->index = psVectorAllocEmpty(num, PS_TYPE_U32); 124 match->mask = psVectorAllocEmpty(num, PS_TYPE_MASK); 124 125 125 126 return match; … … 142 143 match->image->data.S32[num] = image; 143 144 match->index->data.S32[num] = index; 145 match->index->data.PS_TYPE_MASK_DATA[num] = 0; 144 146 match->num++; 145 147 146 match->mag->n = match->magErr->n = match->image->n = match->index->n = match-> num;148 match->mag->n = match->magErr->n = match->image->n = match->index->n = match->mask->n = match->num; 147 149 } 148 150 … … 287 289 psVector *stars, // Star magnitudes 288 290 const psArray *matches, // Array of matches 289 const psVector *zp // Zero points for each image (including airmass term) 291 const psVector *zp, // Zero points for each image (including airmass term) 292 const psVector *photo // Photometric image? 290 293 ) 291 294 { 295 psAssert(zp && zp->type.type == PS_TYPE_F32, "Need zero points"); 296 psAssert(matches, "Need list of matches"); 297 292 298 int numImages = zp->n; // Number of images 293 299 int numStars = matches->n; // Number of stars … … 297 303 psAssert(stars && stars->type.type == PS_TYPE_F32, "Need star magnitudes"); 298 304 psAssert(stars->n == numStars, "Not enough stars: %ld\n", stars->n); 299 psAssert(matches, "Need list of matches");300 psAssert(zp && zp->type.type == PS_TYPE_F32, "Need zero points");301 305 psAssert(zp->n == numImages, "Not enough ZPs: %ld", zp->n); 302 303 psVector *transErr = psVectorAlloc(numImages, PS_TYPE_F32); // Errors in the transparency 304 psVector *starsErr = psVectorAlloc(numStars, PS_TYPE_F32); // Errors in the star magnitudes 306 psAssert(!photo || photo->type.type == PS_TYPE_U8, "Photometric determination is wrong type"); 307 psAssert(!photo || photo->n == numImages, "Not enough photometric determinations: %ld", photo->n); 305 308 306 309 // Solve the star magnitudes 307 310 psVectorInit(stars, 0.0); 308 psVectorInit(starsErr, 0.0); 311 int numGoodStars = 0; // Number of stars with good measurements 312 for (int i = 0; i < numStars; i++) { 313 pmSourceMatch *match = matches->data[i]; // Matched stars 314 int numMeasurements = 0; // Number of unmasked measurements for star 315 double star = 0.0, starErr = 0.0; // Accumulators for star 316 for (int j = 0; j < match->num; j++) { 317 if (match->mask->data.PS_TYPE_MASK_DATA[j]) { 318 continue; 319 } 320 numMeasurements++; 321 int index = match->image->data.U32[j]; // Image index 322 float mag = match->mag->data.F32[j]; // Measured magnitude 323 double magErr = match->magErr->data.F32[j]; // Error in measured magnitude 324 double invErr2 = 1.0 / PS_SQR(magErr); // Inverse square error 325 float cal = zp->data.F32[index]; // Calibration to apply to image 326 if (!photo || !photo->data.U8[index]) { 327 cal -= trans->data.F32[index]; 328 } 329 star += (mag + cal) * invErr2; 330 starErr += invErr2; 331 } 332 if (numMeasurements > 1) { 333 // It's only a good star (contributing to the chi^2) if there's more than 1 measurement 334 numGoodStars++; 335 } 336 stars->data.F32[i] = star / starErr; 337 } 338 339 // Solve for the transparencies 340 // We solve even for the "photometric" images since they may jump out of that status upon iteration 341 psVector *accum = psVectorAlloc(numImages, PS_TYPE_F64); // Transparency accumulator 342 psVector *accumErr = psVectorAlloc(numImages, PS_TYPE_F64); // Transparency accumulator 343 psVectorInit(accum, 0.0); 344 psVectorInit(accumErr, 0.0); 309 345 for (int i = 0; i < numStars; i++) { 310 346 pmSourceMatch *match = matches->data[i]; // Matched stars 311 347 for (int j = 0; j < match->num; j++) { 348 if (match->mask->data.PS_TYPE_MASK_DATA[j]) { 349 continue; 350 } 351 int index = match->image->data.U32[j]; // Image index 352 float mag = match->mag->data.F32[j]; // Measured magnitude 353 double magErr = match->magErr->data.F32[j]; // Error in measured magnitude 354 double invErr2 = 1.0 / PS_SQR(magErr); // Inverse square error 355 float cal = zp->data.F32[index]; // Calibration to apply to image 356 accum->data.F64[index] += (mag + cal - stars->data.F32[i]) * invErr2; 357 accumErr->data.F64[index] += invErr2; 358 } 359 } 360 for (int i = 0; i < numImages; i++) { 361 trans->data.F32[i] = accum->data.F64[i] / accumErr->data.F64[i]; 362 363 psTrace("psModules.objects", 3, "Transparency for image %d: %f\n", i, trans->data.F32[i]); 364 } 365 psFree(accum); 366 psFree(accumErr); 367 368 // Once more through to evaluate chi^2 369 float chi2 = 0.0; // chi^2 for iteration 370 int dof = 0; // Degrees of freedom 371 for (int i = 0; i < numStars; i++) { 372 pmSourceMatch *match = matches->data[i]; // Matched stars 373 for (int j = 0; j < match->num; j++) { 374 if (match->mask->data.PS_TYPE_MASK_DATA[j]) { 375 continue; 376 } 312 377 int index = match->image->data.U32[j]; // Image index 313 378 float mag = match->mag->data.F32[j]; // Measured magnitude 314 379 float magErr = match->magErr->data.F32[j]; // Error in measured magnitude 315 float invErr2 = 1.0 / PS_SQR(magErr); // Inverse square error 316 stars->data.F32[i] += (mag + zp->data.F32[index] - trans->data.F32[index]) * invErr2; 317 starsErr->data.F32[i] += invErr2; 318 } 319 } 320 for (int i = 0; i < numStars; i++) { 321 float inverse = 1.0 / starsErr->data.F32[i]; // Inverse error 322 stars->data.F32[i] *= inverse; 323 starsErr->data.F32[i] = sqrtf(inverse); 324 } 325 326 // Solve for the transparencies 327 psVectorInit(trans, 0.0); 328 psVectorInit(transErr, 0.0); 380 float cal = zp->data.F32[index]; // Calibration to apply to image 381 if (!photo || !photo->data.U8[index]) { 382 cal -= trans->data.F32[index]; 383 } 384 float dev = (mag + cal - stars->data.F32[index]) / magErr; // Deviation from fit 385 if (isfinite(dev)) { 386 chi2 += PS_SQR(dev); 387 dof++; 388 } 389 } 390 } 391 dof -= numGoodStars + numImages; 392 chi2 /= dof; 393 394 return chi2; 395 } 396 397 // Determine which images are photometric, based on estimated transparencies 398 // Returns number of photometric images, or -1 on error 399 static int sourceMatchRelphotPhotometric(psVector *photo, // Photometric determination 400 const psVector *trans, // Estimated transparencies 401 int transIter, // Iterations for transparency 402 float transClip, // Clipping level for transparency 403 float photoLevel // Level below which we declare photometric 404 ) 405 { 406 psAssert(photo && photo->type.type == PS_TYPE_U8, "Need photometric determination"); 407 psAssert(trans && trans->type.type == PS_TYPE_F32, "Need transparencies"); 408 409 int numImages = photo->n; // Number of images 410 411 psAssert(trans->n == numImages, "Not enough transparencies: %ld", trans->n); 412 psAssert(transIter >= 0, "Iterations for transparency must be non-negative: %d", transIter); 413 psAssert(transClip > 0, "Clipping level for transparency must be positive: %f", transClip); 414 psAssert(photoLevel > 0, "Photometric level must be positive: %f", photoLevel); 415 416 psStats *stats = psStatsAlloc(PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV); // Statistics 417 stats->clipIter = transIter; 418 stats->clipSigma = transClip; 419 420 if (!psVectorStats(stats, trans, NULL, NULL, 0)) { 421 psError(PS_ERR_UNKNOWN, false, "Unable to perform statistics on transparencies."); 422 psFree(stats); 423 return -1; 424 } 425 426 float thresh = stats->clippedMean + photoLevel * stats->clippedStdev; // Threshold for clouds 427 psFree(stats); 428 429 int numPhoto = 0; // Number of photometric images 430 for (int i = 0; i < numImages; i++) { 431 if (trans->data.F32[i] < thresh) { 432 photo->data.U8[i] = 0xFF; 433 numPhoto++; 434 } else { 435 photo->data.U8[i] = 0; 436 } 437 } 438 439 return numPhoto; 440 } 441 442 443 // Reject star measurements 444 // Returns the fraction of measurements that were rejected 445 static float sourceMatchRelphotReject(psVector *trans, // Transparencies 446 psVector *stars, // Star magnitudes 447 const psArray *matches, // Array of matches 448 const psVector *zp, // Zero points for each image 449 const psVector *photo, // Photometric image? 450 float starClip, // Clipping for stars 451 float sysErr // Systematic error 452 ) 453 { 454 psAssert(zp && zp->type.type == PS_TYPE_F32, "Need zero points"); 455 psAssert(matches, "Need list of matches"); 456 457 int numImages = zp->n; // Number of images 458 int numStars = matches->n; // Number of stars 459 460 psAssert(trans && trans->type.type == PS_TYPE_F32, "Need transparencies"); 461 psAssert(trans->n == numImages, "Not enough transparencies: %ld\n", trans->n); 462 psAssert(stars && stars->type.type == PS_TYPE_F32, "Need star magnitudes"); 463 psAssert(stars->n == numStars, "Not enough stars: %ld\n", stars->n); 464 psAssert(zp->n == numImages, "Not enough ZPs: %ld", zp->n); 465 psAssert(!photo || photo->type.type == PS_TYPE_U8, "Photometric determination is wrong type"); 466 psAssert(!photo || photo->n == numImages, "Not enough photometric determinations: %ld", photo->n); 467 468 starClip = PS_SQR(starClip); 469 sysErr = PS_SQR(sysErr); 470 471 int numRejected = 0; // Number rejected 472 int numMeasurements = 0; // Number of measurements 329 473 for (int i = 0; i < numStars; i++) { 330 474 pmSourceMatch *match = matches->data[i]; // Matched stars 331 475 for (int j = 0; j < match->num; j++) { 476 if (match->mask->data.PS_TYPE_MASK_DATA[j]) { 477 continue; 478 } 479 numMeasurements++; 332 480 int index = match->image->data.U32[j]; // Image index 333 481 float mag = match->mag->data.F32[j]; // Measured magnitude 334 482 float magErr = match->magErr->data.F32[j]; // Error in measured magnitude 335 float invErr2 = 1.0 / PS_SQR(magErr); // Inverse square error 336 trans->data.F32[index] += (mag - stars->data.F32[i]) * invErr2; 337 transErr->data.F32[index] += invErr2; 338 } 339 } 340 for (int i = 0; i < numImages; i++) { 341 float inverse = 1.0 / transErr->data.F32[i]; // Inverse error 342 trans->data.F32[i] *= inverse; 343 transErr->data.F32[i] = sqrtf(inverse); 344 345 psTrace("psModules.objects", 3, "Transparency for image %d: %f +/- %f\n", 346 i, trans->data.F32[i], transErr->data.F32[i]); 347 } 348 349 // Once more through to evaluate chi^2 350 float chi2 = 0.0; // chi^2 for iteration 351 for (int i = 0; i < numStars; i++) { 352 pmSourceMatch *match = matches->data[i]; // Matched stars 353 for (int j = 0; j < match->num; j++) { 354 int index = match->image->data.U32[j]; // Image index 355 float mag = match->mag->data.F32[j]; // Measured magnitude 356 float magErr = match->magErr->data.F32[j]; // Error in measured magnitude 357 chi2 += PS_SQR(mag - stars->data.F32[index] - trans->data.F32[index] + zp->data.F32[index]) / 358 PS_SQR(magErr); 359 } 360 } 361 chi2 /= numStars + numImages; 362 363 psFree(transErr); 364 psFree(starsErr); 365 366 return chi2; 483 float cal = zp->data.F32[index]; // Calibration to apply to image 484 if (!photo || !photo->data.U8[index]) { 485 cal -= trans->data.F32[index]; 486 } 487 float dev = mag + cal - stars->data.F32[i]; // Deviation 488 if (PS_SQR(dev) > starClip * (PS_SQR(magErr) + sysErr)) { 489 numRejected++; 490 match->mask->data.PS_TYPE_MASK_DATA[j] = 0xFF; 491 } 492 } 493 } 494 495 return (float)numRejected / (float)numMeasurements; 367 496 } 368 497 … … 372 501 int maxIter, // Maximum number of iterations 373 502 float tol, // Relative tolerance for convergence 374 float cloudClip, // Clipping for clouds 375 float starClip // Clipping for stars 503 float rejLimit, // Limit on rejection between iterations 504 int transIter, // Clipping iterations for transparency 505 float transClip, // Clipping level for transparency 506 float photoLevel, // Level at which we declare image is photometric 507 float starClip, // Clipping for stars 508 float sysErr // Systematic error in measurements 376 509 ) 377 510 { … … 379 512 PS_ASSERT_VECTOR_NON_NULL(zp, NULL); 380 513 PS_ASSERT_VECTOR_TYPE(zp, PS_TYPE_F32, NULL); 381 PS_ASSERT_FLOAT_LARGER_THAN( cloudClip, 0.0, NULL);514 PS_ASSERT_FLOAT_LARGER_THAN(transClip, 0.0, NULL); 382 515 383 516 int numImages = zp->n; // Number of images … … 385 518 psVector *trans = psVectorAlloc(numImages, PS_TYPE_F32); // Transparencies for each image, magnitudes 386 519 psVectorInit(trans, 0.0); 520 psVector *photo = psVectorAlloc(numImages, PS_TYPE_U8); // Photometric determination for each image 521 psVectorInit(photo, 0); 387 522 psVector *stars = psVectorAlloc(numStars, PS_TYPE_F32); // Magnitudes for each star 388 523 389 float chi2 = sourceMatchRelphotIterate(trans, stars, matches, zp ); // chi^2 for solution524 float chi2 = sourceMatchRelphotIterate(trans, stars, matches, zp, photo); // chi^2 for solution 390 525 psTrace("psModules.objects", 1, "Initial: chi^2 = %f\n", chi2); 391 526 float lastChi2 = INFINITY; // chi^2 on last iteration 392 for (int i = 0; i < maxIter && (lastChi2 - chi2) / chi2 > tol; i++) { 527 float fracRej = INFINITY; // Fraction of measurements rejected 528 for (int i = 0; i < maxIter && (fabsf(lastChi2 - chi2) > tol * chi2 || fracRej > rejLimit); i++) { 393 529 lastChi2 = chi2; 394 chi2 = sourceMatchRelphotIterate(trans, stars, matches, zp); // chi^2 for solution 395 psTrace("psModules.objects", 1, "iter = %d: chi^2 = %f\n", i, chi2); 530 531 // Identify photometric nights 532 int numPhoto = sourceMatchRelphotPhotometric(photo, trans, transIter, transClip, 533 photoLevel); // Number of photometric images 534 if (numPhoto < 0) { 535 psError(PS_ERR_UNKNOWN, false, "Unable to perform photometric determination"); 536 psFree(trans); 537 psFree(photo); 538 psFree(stars); 539 return NULL; 540 } 541 psTrace("psModules.objects", 3, "Determined %d/%d are photometric", numPhoto, numImages); 542 543 fracRej = sourceMatchRelphotReject(trans, stars, matches, zp, photo, starClip, sysErr); 544 psTrace("psModules.objects", 3, "%f%% of measurements rejected", fracRej * 100); 545 546 chi2 = sourceMatchRelphotIterate(trans, stars, matches, zp, photo); // chi^2 for solution 547 psTrace("psModules.objects", 1, "iter = %d: chi^2 = %f rejected = %f\n", i, chi2, fracRej); 548 } 549 550 psFree(photo); 551 psFree(stars); 552 553 if (fabsf(lastChi2 - chi2) > tol * chi2 || fracRej > rejLimit) { 554 psWarning("Unable to converge to relphot solution (%f,%f)", (lastChi2 - chi2) / chi2, fracRej); 396 555 } 397 556 -
trunk/psModules/src/objects/pmSourceMatch.h
r20949 r20953 12 12 psVector *mag; // Magnitudes 13 13 psVector *magErr; // Magnitude errors 14 psVector *mask; // Mask for measurements 14 15 } pmSourceMatch; 15 16 … … 56 57 int maxIter, // Maximum number of iterations 57 58 float tol, // Relative tolerance for convergence 58 float cloudClip, // Clipping for clouds 59 float starClip // Clipping for stars 59 float rejLimit, // Limit on rejection between iterations 60 int transIter, // Clipping iterations for transparency 61 float transClip, // Clipping level for transparency 62 float photoLevel, // Level at which we declare image is photometric 63 float starClip, // Clipping for stars 64 float sysErr // Systematic error in measurements 60 65 ); 61 66
Note:
See TracChangeset
for help on using the changeset viewer.
