Changeset 25405
- Timestamp:
- Sep 15, 2009, 4:00:18 PM (17 years ago)
- Location:
- branches/eam_branches/20090715/psLib
- Files:
-
- 13 edited
-
src/db/psDB.c (modified) (6 diffs)
-
src/fits/psFits.c (modified) (6 diffs)
-
src/fits/psFits.h (modified) (1 diff)
-
src/fits/psFitsHeader.c (modified) (13 diffs)
-
src/imageops/psImageConvolve.c (modified) (4 diffs)
-
src/imageops/psImageConvolve.h (modified) (1 diff)
-
src/sys/psType.h (modified) (4 diffs)
-
src/types/psMetadata.c (modified) (4 diffs)
-
src/types/psMetadata.h (modified) (1 diff)
-
src/types/psTree.c (modified) (21 diffs)
-
src/types/psTree.h (modified) (5 diffs)
-
test/optime (modified) (1 prop)
-
test/types/tap_psTree.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/20090715/psLib/src/db/psDB.c
r23915 r25405 2261 2261 PS_DB_OP_LE, 2262 2262 PS_DB_OP_GE, 2263 PS_DB_OP_NE, 2263 2264 } psDBOpValue; 2264 2265 … … 2308 2309 opStr = "<"; 2309 2310 op = PS_DB_OP_LT; 2310 } 2311 } 2311 } else if (strstr(item->comment, "!=")) { 2312 opStr = "!="; 2313 op = PS_DB_OP_NE; 2314 } 2315 } 2316 2312 2317 2313 2318 // XXX why are >, < searches not supported here???? … … 2341 2346 case PS_DB_OP_EQ: 2342 2347 psStringAppend(&query, "(ABS(%s - %.8f) < %.8f)", itemName, (float)(item->data.F32), PS_DB_FLT_PAD); 2348 break; 2349 case PS_DB_OP_NE: 2350 psStringAppend(&query, "(ABS(%s - %.8f) >= %.8f)", itemName, (float)(item->data.F32), PS_DB_FLT_PAD); 2343 2351 break; 2344 2352 case PS_DB_OP_LE: … … 2360 2368 psStringAppend(&query, "(ABS(%s - %.17f) < %.17f)", itemName, (float)(item->data.F64), PS_DB_DBL_PAD); 2361 2369 break; 2370 case PS_DB_OP_NE: 2371 psStringAppend(&query, "(ABS(%s - %.17f) >= %.17f)", itemName, (float)(item->data.F64), PS_DB_DBL_PAD); 2372 break; 2362 2373 case PS_DB_OP_LE: 2363 2374 case PS_DB_OP_LT: … … 2376 2387 case PS_DB_OP_EQ: 2377 2388 psStringAppend(&query, "%s = %d", itemName, (int)(item->data.B)); 2389 break; 2390 case PS_DB_OP_NE: 2391 psStringAppend(&query, "%s != %d", itemName, (int)(item->data.B)); 2378 2392 break; 2379 2393 default: … … 2397 2411 psStringAppend(&query, "%s LIKE '%s'", itemName, item->data.str); 2398 2412 } else { 2399 psStringAppend(&query, "%s = '%s'", itemName, item->data.str);2413 psStringAppend(&query, "%s %s '%s'", itemName, opStr, item->data.str); 2400 2414 } 2401 2415 } -
branches/eam_branches/20090715/psLib/src/fits/psFits.c
r25022 r25405 150 150 char errorBuf[MAX_STRING_LENGTH], *errorMsg; 151 151 #if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE) 152 errorMsg = strerror_r(thisErrno, errorBuf, MAX_STRING_LENGTH);153 #else154 152 strerror_r(thisErrno, errorBuf, MAX_STRING_LENGTH); 155 153 errorMsg = errorBuf; 154 #else 155 errorMsg = strerror_r(thisErrno, errorBuf, MAX_STRING_LENGTH); 156 156 #endif 157 157 psError(PS_ERR_IO, true, "Directory (%s) for requested file is not accessible: %s", … … 209 209 char errorBuf[64], *errorMsg; 210 210 # if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE) 211 errorMsg = strerror_r (errno, errorBuf, 64);212 # else213 211 strerror_r (errno, errorBuf, 64); 214 212 errorMsg = errorBuf; 213 # else 214 errorMsg = strerror_r (errno, errorBuf, 64); 215 215 # endif 216 216 psError(PS_ERR_IO, true, "Failed to delete a previously-existing file (%s), error %d: %s", … … 344 344 // Therefore, we implement our own version of moving to an extension specified by name. The pure cfitsio 345 345 // version is used if "conventions.compression" handling is turned off in the psFits structure. 346 bool psFitsMoveExtName(const psFits* fits, 347 const char* extname) 346 static bool fitsMoveExtName(const psFits* fits, // FITS file 347 const char* extname, // Extension name 348 bool errors // Generate errors? 349 ) 348 350 { 349 351 PS_ASSERT_FITS_NON_NULL(fits, false); … … 356 358 // User wants to use cfitsio. Good luck to them! 357 359 if (fits_movnam_hdu(fits->fd, ANY_HDU, (char*)extname, 0, &status) != 0) { 358 psFitsError(status, true, _("Could not find HDU '%s'"), extname); 360 if (errors) { 361 psFitsError(status, true, _("Could not find HDU '%s'"), extname); 362 } 359 363 return false; 360 364 } … … 378 382 if (fits_movabs_hdu(fits->fd, i, &hdutype, &status)) { 379 383 // We've run off the end 380 psFitsError(status, true, _("Could not find HDU with %s = '%s'"), extword, extname); 384 if (errors) { 385 psFitsError(status, true, _("Could not find HDU with %s = '%s'"), extword, extname); 386 } 381 387 return false; 382 388 } … … 406 412 } 407 413 psAbort("Should never reach here."); 414 } 415 416 417 bool psFitsMoveExtName(const psFits* fits, const char* extname) 418 { 419 return fitsMoveExtName(fits, extname, true); 420 } 421 422 bool psFitsMoveExtNameClean(const psFits* fits, const char* extname) 423 { 424 return fitsMoveExtName(fits, extname, false); 408 425 } 409 426 -
branches/eam_branches/20090715/psLib/src/fits/psFits.h
r19035 r25405 245 245 ); 246 246 247 /** Moves the FITS HDU to the specified extension name without generating errors. 248 * 249 * @return bool TRUE if the extension name was found and move was 250 * successful, otherwise FALSE 251 */ 252 bool psFitsMoveExtNameClean( 253 const psFits* fits, ///< the psFits object to move 254 const char* extname ///< the extension name 255 ); 256 247 257 /** Moves the FITS HDU to the specified extension number 248 258 * -
branches/eam_branches/20090715/psLib/src/fits/psFitsHeader.c
r25022 r25405 50 50 51 51 // List of the start of FITS header keys not to write (handled by cfitsio); NULL-terminated 52 static const char *noWriteFitsKeyStarts[] = { "NAXIS", "TTYPE", "TFORM", NULL };52 static const char *noWriteFitsKeyStarts[] = { "NAXIS", "TTYPE", "TFORM", "TZERO", "TSCAL", NULL }; 53 53 54 54 // List of compressed FITS header keys not to write (handled by cfitsio); NULL-terminated … … 305 305 keyType = 'C'; 306 306 } 307 psTrace("psLib.fits", 3, "Reading keyword %s, type %c\n", keyName, keyType); 307 308 if (status != 0) { 308 309 break; … … 327 328 -INFINITY); 328 329 } else { 329 success = psMetadataAddS32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment, 330 atoi(keyValue)); 330 long long value = atoll(keyValue); // Value 331 if (value > PS_MIN_S32 && value < PS_MAX_S32) { 332 success = psMetadataAddS32(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment, 333 value); 334 } else { 335 success = psMetadataAddS64(header, PS_LIST_TAIL, keyNameTrans, dupFlag, keyComment, 336 value); 337 } 331 338 } 332 339 break; … … 509 516 psMetadataItem *simpleItem = psMetadataLookup(output, "SIMPLE"); // SIMPLE in the header 510 517 if (simpleItem) { 511 if (simpleItem->type != PS_DATA_BOOL) { 512 psError(PS_ERR_BAD_PARAMETER_TYPE, true, "SIMPLE in a FITS header must be of boolean type: " 513 "not %x --- assuming FALSE.\n", simpleItem->type); 518 if (simpleItem->type != PS_DATA_BOOL || !simpleItem->data.B) { 514 519 int value = false; // Temporary holder for boolean 520 psWarning("Writing SIMPLE=F to FITS header by request"); 515 521 fits_update_key(fits->fd, TLOGICAL, "SIMPLE", &value, 516 522 "File does not conform to FITS standard", &status); 517 523 simple = false; 518 } else if (!simpleItem->data.B) {519 simple = false;520 int value = false; // Temporary holder for boolean521 fits_update_key(fits->fd, TLOGICAL, "SIMPLE", &value,522 "File does not conform to FITS standard", &status);523 524 } 524 525 // Uncompressed SIMPLE = T is taken care of by cfitsio. … … 546 547 char comment[FLEN_CARD]; // Comment for ZIMAGE; unused 547 548 int value; // Value for ZIMAGE; unused 549 psTrace("psLib.fits", 3, "Writing header ZSIMPLE to preserve PHU"); 548 550 fits_read_key(fits->fd, TLOGICAL, "ZIMAGE", &value, comment, &status); 549 551 fits_insert_key_log(fits->fd, "ZSIMPLE", simple, "Uncompressed file's conforms to FITS", &status); … … 575 577 if (keywordInList(name, noWriteCompressedKeys) || 576 578 (keyStarts && keywordStartsWith(name, noWriteCompressedKeyStarts))) { 579 psTrace("psLib.fits", 3, "Not writing FITS keyword %s", name); 577 580 continue; 578 581 } 579 582 } else if (keywordInList(name, noWriteCompressedKeys) || 580 583 (keyStarts && keywordStartsWith(name, noWriteCompressedKeyStarts))) { 584 psTrace("psLib.fits", 3, "Not writing FITS keyword %s", name); 581 585 continue; 582 586 } … … 584 588 if (keywordInList(name, noWriteFitsKeys) || 585 589 (keyStarts && keywordStartsWith(name, noWriteFitsKeyStarts))) { 590 psTrace("psLib.fits", 3, "Not writing FITS keyword %s", name); 586 591 continue; 587 592 } … … 592 597 psWarning("COMMENT header is not of type STRING (%x) --- ignored.", item->type); 593 598 } else { 599 psTrace("psLib.fits", 5, "Writing header COMMENT: %s", item->data.str); 594 600 fits_write_comment(fits->fd, item->data.str, &status); 595 601 } … … 598 604 psWarning("COMMENT header is not of type STRING (%x) --- ignored.", item->type); 599 605 } else { 606 psTrace("psLib.fits", 5, "Writing header HISTORY: %s", item->data.str); 600 607 fits_write_history(fits->fd, item->data.str, &status); 601 608 } … … 605 612 case PS_DATA_BOOL: { 606 613 int value = item->data.B; 614 psTrace("psLib.fits", 5, "Writing BOOL header %s: %d", name, value); 607 615 fits_update_key(fits->fd, TLOGICAL, name, &value, item->comment, &status); 608 616 break; 609 617 } 610 618 case PS_DATA_S8: 619 psTrace("psLib.fits", 5, "Writing S8 header %s: %d", name, (int)item->data.S8); 611 620 fits_update_key(fits->fd, TBYTE, name, &item->data.S8, item->comment, &status); 612 621 break; 613 622 case PS_DATA_S16: 623 psTrace("psLib.fits", 5, "Writing S16 header %s: %d", name, (int)item->data.S16); 614 624 fits_update_key(fits->fd, TSHORT, name, &item->data.S16, item->comment, &status); 615 625 break; 616 626 case PS_DATA_S32: 627 psTrace("psLib.fits", 5, "Writing S32 header %s: %d", name, (int)item->data.S32); 617 628 fits_update_key(fits->fd, TINT, name, &item->data.S32, item->comment, &status); 618 629 break; 619 630 case PS_DATA_S64: 631 psTrace("psLib.fits", 5, "Writing S64 header %s: %" PRId64, name, item->data.S64); 620 632 fits_update_key(fits->fd, TLONGLONG, name, &item->data.S64, item->comment, &status); 621 633 break; 622 634 case PS_DATA_U8: { 623 635 unsigned short int temp = item->data.U8; 636 psTrace("psLib.fits", 5, "Writing U8 header %s: %d", name, (int)item->data.U8); 624 637 fits_update_key(fits->fd, TUSHORT, name, &temp, item->comment, &status); 625 638 break; 626 639 } 627 640 case PS_DATA_U16: 641 psTrace("psLib.fits", 5, "Writing U16 header %s: %d", name, (int)item->data.U16); 628 642 fits_update_key(fits->fd, TUSHORT, name, &item->data.U16, item->comment, &status); 629 643 break; 630 644 case PS_DATA_U32: 645 psTrace("psLib.fits", 5, "Writing U32 header %s: %d", name, (unsigned int)item->data.U32); 631 646 fits_update_key(fits->fd, TUINT, name, &item->data.U32, item->comment, &status); 632 647 break; … … 639 654 } 640 655 psS64 temp = item->data.U64; // Signed version 656 psTrace("psLib.fits", 5, "Writing U64 header %s: %" PRIu64, name, item->data.U64); 641 657 fits_update_key(fits->fd, TLONGLONG, name, &temp, item->comment, &status); 642 658 break; 643 659 case PS_DATA_F32: { 644 660 int infCheck = 0; // Result of isinf() 661 psTrace("psLib.fits", 5, "Writing F32 header %s: %f", name, item->data.F32); 645 662 if (isnan(item->data.F32)) { 646 663 fits_update_key(fits->fd, TSTRING, name, "NaN", item->comment, &status); … … 659 676 case PS_DATA_F64: { 660 677 int infCheck = 0; // Result of isinf() 678 psTrace("psLib.fits", 5, "Writing F32 header %s: %lf", name, item->data.F64); 661 679 if (isnan(item->data.F64)) { 662 680 fits_update_key(fits->fd, TSTRING, name, "NaN", item->comment, &status); … … 674 692 } 675 693 case PS_DATA_STRING: 694 psTrace("psLib.fits", 5, "Writing STR header %s: %s", name, item->data.str); 676 695 fits_update_key(fits->fd, TSTRING, name, item->data.V, item->comment, &status); 677 696 break; -
branches/eam_branches/20090715/psLib/src/imageops/psImageConvolve.c
r24272 r25405 678 678 } 679 679 680 static bool imageSmoothMaskPixels(psVector *out, const psImage *image, const psImage *mask, 681 psImageMaskType maskVal, const psVector *x, const psVector *y, 682 const psVector *gaussNorm, float minGauss, int size, int start, int stop) 683 { 684 const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel 685 int numCols = image->numCols, numRows = image->numRows; // Size of image 686 int xLast = numCols - 1, yLast = numRows - 1; // Last index 687 for (int i = start; i < stop; i++) { 688 int xPix = x->data.S32[i], yPix = y->data.S32[i]; // Pixel coordinates for smoothing 689 690 int yMin = PS_MAX(yPix - size, 0); 691 int yMax = PS_MIN(yPix + size, yLast); 692 int xMin = PS_MAX(xPix - size, 0); 693 int xMax = PS_MIN(xPix + size, xLast); 694 695 const float *yGauss = &gauss[yMin - yPix]; 696 697 double ySumIG = 0.0, ySumG = 0.0; 698 for (int v = yMin; v <= yMax; v++, yGauss++) { 699 const float *xGauss = &gauss[xMin - xPix]; 700 double xSumIG = 0.0, xSumG = 0.0; 701 const psImageMaskType *maskData = &mask->data.PS_TYPE_IMAGE_MASK_DATA[v][xMin]; 702 const psF32 *imageData = &image->data.F32[v][xMin]; 703 for (int u = xMin; u <= xMax; u++, xGauss++, imageData++, maskData++) { 704 if (*maskData & maskVal) { 705 continue; 706 } 707 xSumIG += *imageData * *xGauss; 708 xSumG += *xGauss; 709 } 710 if (xSumG > minGauss) { 711 ySumIG += xSumIG * *yGauss; 712 ySumG += xSumG * *yGauss; 713 } 714 } 715 716 out->data.F32[i] = ySumG > minGauss ? ySumIG / ySumG : NAN; 717 } 718 719 return true; 720 } 721 722 static bool psImageSmoothMaskPixelsThread(psThreadJob *job) 723 { 724 PS_ASSERT_THREAD_JOB_NON_NULL(job, false); 725 psAssert(job->args, "programming error: no job arguments"); 726 psAssert(job->args->n == 11, "programming error: wrong number of job arguments"); 727 728 psVector *out = job->args->data[0]; // Output vector 729 const psImage *image = job->args->data[1]; // Input image 730 const psImage *mask = job->args->data[2]; // Input mask 731 psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3], PS_TYPE_IMAGE_MASK_DATA); 732 const psVector *x = job->args->data[4]; 733 const psVector *y = job->args->data[5]; 734 const psVector *gaussNorm = job->args->data[6]; 735 float minGauss = PS_SCALAR_VALUE(job->args->data[7], F32); 736 int size = PS_SCALAR_VALUE(job->args->data[8], S32); 737 int start = PS_SCALAR_VALUE(job->args->data[9], S32); 738 int stop = PS_SCALAR_VALUE(job->args->data[10], S32); 739 return imageSmoothMaskPixels(out, image, mask, maskVal, x, y, gaussNorm, 740 minGauss, size, start, stop); 741 } 742 743 744 psVector *psImageSmoothMaskPixels(const psImage *image, const psImage *mask, psImageMaskType maskVal, 745 const psVector *x, const psVector *y, 746 float sigma, float numSigma, float minGauss) 747 { 748 PS_ASSERT_IMAGE_NON_NULL(image, NULL); 749 PS_ASSERT_IMAGE_NON_NULL(mask, NULL); 750 PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_IMAGE_MASK, NULL); 751 PS_ASSERT_IMAGES_SIZE_EQUAL(image, mask, NULL); 752 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 753 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_S32, NULL); 754 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 755 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_S32, NULL); 756 PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, NULL); 757 758 int size = sigma * numSigma + 0.5; // Half-size of kernel 759 760 int num = x->n; // Number of pixels to smooth 761 psVector *out = psVectorAlloc(num, PS_TYPE_F32); // Output results 762 763 // Generate normalized gaussian 764 IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32); 765 766 // Columns 767 if (threaded) { 768 int numThreads = psThreadPoolSize(); // Number of threads 769 int delta = (numThreads) ? num / numThreads + 1 : num; // Block of cols to do at once 770 for (int start = 0; start < num; start += delta) { 771 int stop = PS_MIN(start + delta, num); // End of block 772 773 psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS"); 774 psArrayAdd(job->args, 1, out); 775 psArrayAdd(job->args, 1, (psImage*)image); 776 psArrayAdd(job->args, 1, (psImage*)mask); 777 PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK); 778 psArrayAdd(job->args, 1, (psVector*)x); 779 psArrayAdd(job->args, 1, (psVector*)y); 780 psArrayAdd(job->args, 1, gaussNorm); 781 PS_ARRAY_ADD_SCALAR(job->args, minGauss, PS_TYPE_F32); 782 PS_ARRAY_ADD_SCALAR(job->args, size, PS_TYPE_S32); 783 PS_ARRAY_ADD_SCALAR(job->args, start, PS_TYPE_S32); 784 PS_ARRAY_ADD_SCALAR(job->args, stop, PS_TYPE_S32); 785 if (!psThreadJobAddPending(job)) { 786 psFree(job); 787 psFree(gaussNorm); 788 psFree(out); 789 return NULL; 790 } 791 psFree(job); 792 } 793 } else if (!imageSmoothMaskPixels(out, image, mask, maskVal, x, y, 794 gaussNorm, minGauss, size, 0, num)) { 795 psError(PS_ERR_UNKNOWN, false, "Unable to smooth pixels."); 796 psFree(gaussNorm); 797 psFree(out); 798 return NULL; 799 } 800 801 if (threaded && !psThreadPoolWait(true)) { 802 psError(PS_ERR_UNKNOWN, false, "Error waiting for threads."); 803 psFree(gaussNorm); 804 psFree(out); 805 return NULL; 806 } 807 808 psFree(gaussNorm); 809 return out; 810 } 811 812 680 813 // Smooth an image with masked pixels 681 814 // The calculation and calcMask images are *deliberately* backwards (row,col instead of col,row or … … 1325 1458 if (threaded) { 1326 1459 int numThreads = psThreadPoolSize(); // Number of threads 1327 int deltaRows = (numThreads) ? numRows / numThreads : numRows; // Block of rows to do at once1460 int deltaRows = (numThreads) ? numRows / numThreads + 1 : numRows; // Block of rows to do at once 1328 1461 for (int start = 0; start < numRows; start += deltaRows) { 1329 int stop = PS_MIN (start + deltaRows, numRows); // end of row block1462 int stop = PS_MIN(start + deltaRows, numRows); // end of row block 1330 1463 1331 1464 psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_CONVOLVE_MASK"); … … 1363 1496 if (threaded) { 1364 1497 int numThreads = psThreadPoolSize(); // Number of threads 1365 int deltaCols = (numThreads) ? numCols / numThreads : numCols; // Block of cols to do at once1498 int deltaCols = (numThreads) ? numCols / numThreads + 1 : numCols; // Block of cols to do at once 1366 1499 for (int start = 0; start < numCols; start += deltaCols) { 1367 int stop = PS_MIN (start + deltaCols, numCols); // end of col block1500 int stop = PS_MIN(start + deltaCols, numCols); // end of col block 1368 1501 1369 1502 psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_CONVOLVE_MASK"); … … 1486 1619 psFree(task); 1487 1620 } 1621 { 1622 psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS", 9); 1623 task->function = &psImageSmoothMaskPixelsThread; 1624 psThreadTaskAdd(task); 1625 psFree(task); 1626 } 1488 1627 } else if (!set && threaded) { 1489 1628 psThreadTaskRemove("PSLIB_IMAGE_CONVOLVE_MASK"); -
branches/eam_branches/20090715/psLib/src/imageops/psImageConvolve.h
r24272 r25405 222 222 ); 223 223 224 /// Smooth particular pixels on an image, allowing for masked pixels 225 /// 226 /// Applies a circularly symmetric Gaussian smoothing first in x and then in y 227 /// directions with just a vector. This process is 2N faster than 2D convolutions (in general). 228 psVector *psImageSmoothMaskPixels( 229 const psImage *image, ///< Input image (F32) 230 const psImage *mask, ///< Mask image 231 psImageMaskType maskVal, ///< Value to mask 232 const psVector *x, ///< x coordinates 233 const psVector *y, ///< y coordinates 234 float sigma, ///< Width of the smoothing kernel (pixels) 235 float numSigma, ///< Size of the smoothing box (sigma) 236 float minGauss ///< Minimum fraction of Gaussian to accept 237 ); 224 238 225 239 psImage *psImageSmoothMask_Threaded(psImage *output, -
branches/eam_branches/20090715/psLib/src/sys/psType.h
r21183 r25405 141 141 } psDataType; 142 142 143 // macros to abstract the generic mask type : these values must be consistent 143 // macros to abstract the generic mask type : these values must be consistent 144 144 #define PS_TYPE_MASK PS_TYPE_U8 /**< the psElemType to use for mask image */ 145 145 #define PS_TYPE_MASK_DATA U8 /**< the data member to use for mask image */ … … 152 152 // alternate versions if needed 153 153 // #define PS_NOT_MASK(A)(UINT16_MAX-(A)) 154 // #define PS_NOT_MASK(A)(UINT32_MAX-(A)) 154 // #define PS_NOT_MASK(A)(UINT32_MAX-(A)) 155 155 // #define PS_NOT_MASK(A)(UINT64_MAX-(A)) 156 156 157 // macros to abstract the vector mask type : these values must be consistent 157 // macros to abstract the vector mask type : these values must be consistent 158 158 #define PS_TYPE_VECTOR_MASK PS_TYPE_U8 /**< the psElemType to use for mask image */ 159 159 #define PS_TYPE_VECTOR_MASK_DATA U8 /**< the data member to use for mask image */ … … 161 161 #define PS_MIN_VECTOR_MASK_TYPE 0 /**< minimum valid Vector Mask value */ 162 162 #define PS_MAX_VECTOR_MASK_TYPE UINT8_MAX /**< maximum valid Vector Mask value */ 163 typedef psU8 psVectorMaskType; ///< the C datatype for a mask image163 typedef psU8 psVectorMaskType; ///< the C datatype for a mask image 164 164 #define PS_NOT_VECTOR_MASK(A)(UINT8_MAX-(A)) 165 165 166 // macros to abstract the image mask type : these values must be consistent 167 #define PS_TYPE_IMAGE_MASK PS_TYPE_U16 /**< the psElemType to use for mask image */168 #define PS_TYPE_IMAGE_MASK_DATA U16 /**< the data member to use for mask image */169 #define PS_TYPE_IMAGE_MASK_NAME "psU16" /**< the data type for mask as a string */166 // macros to abstract the image mask type : these values must be consistent 167 #define PS_TYPE_IMAGE_MASK PS_TYPE_U16 /**< the psElemType to use for mask image */ 168 #define PS_TYPE_IMAGE_MASK_DATA U16 /**< the data member to use for mask image */ 169 #define PS_TYPE_IMAGE_MASK_NAME "psU16" /**< the data type for mask as a string */ 170 170 #define PS_MIN_IMAGE_MASK_TYPE 0 /**< minimum valid Image Mask value */ 171 171 #define PS_MAX_IMAGE_MASK_TYPE UINT16_MAX /**< maximum valid Image Mask value */ … … 246 246 }; 247 247 248 /// Macro to get the bad pixel reason code (stored as part of mask value)249 #define PS_BADPIXEL_BITMASK 0x0f250 #define PS_GET_BADPIXEL(maskValue) (maskValue & PS_BADPIXEL_BITMASK)251 252 #define PS_IS_BADPIXEL(maskValue) (PS_GET_BADPIXEL(maskValue) != 0)253 254 /// Macro to apply a bad pixel reason code to mask image255 #define PS_SET_BADPIXEL(maskValue, reasonCode) \256 { \257 maskValue = (psMaskType)((reasonCode & PS_BADPIXEL_BITMASK) | (maskValue & ~PS_BADPIXEL_BITMASK)); \258 }259 260 248 /// Macro to determine if the psElemType is an integer. 261 249 #define PS_IS_PSELEMTYPE_INT(x) ((x & 0x100) == 0x100) -
branches/eam_branches/20090715/psLib/src/types/psMetadata.c
r21183 r25405 996 996 if (metadataItem->type == PS_DATA_METADATA_MULTI) { 997 997 // if multiple keys found, use the first. 998 // metadataItem = (psMetadataItem*)((metadataItem->data.list)->head);999 998 metadataItem = (psMetadataItem*)(metadataItem->data.list->head->data); 1000 999 if (status) { … … 1082 1081 } \ 1083 1082 \ 1084 /* psFree(metadataItem); currently, the lookup doesn't increment the ref count */ \1085 1083 return value; \ 1086 1084 } … … 1101 1099 psMetadataLookupNumTYPE(VectorMaskType,VectorMask) 1102 1100 psMetadataLookupNumTYPE(ImageMaskType,ImageMask) 1101 1102 #define psMetadataLookupPtrTYPE(TYPENAME,NAME,TYPE,VAL) \ 1103 TYPENAME psMetadataLookup##NAME(bool *status, const psMetadata *md, const char *key) \ 1104 { \ 1105 PS_ASSERT_METADATA_NON_NULL(md, NULL); \ 1106 PS_ASSERT_STRING_NON_EMPTY(key, NULL); \ 1107 psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); /* The item of interest */ \ 1108 if (!item) { \ 1109 if (status) { \ 1110 *status = false; \ 1111 } else { \ 1112 psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n", key); \ 1113 } \ 1114 return NULL; \ 1115 } \ 1116 \ 1117 if (item->type == PS_DATA_METADATA_MULTI) { \ 1118 /* if multiple keys found, use the first. */ \ 1119 item = item->data.list->head->data; \ 1120 } \ 1121 if (item->type != TYPE) { \ 1122 if (status) { \ 1123 *status = false; \ 1124 } else { \ 1125 psLogMsg(__func__, PS_LOG_DETAIL, "%s isn't of type PS_DATA_META, as expected.\n", key); \ 1126 } \ 1127 return NULL; \ 1128 } \ 1129 \ 1130 if (status) { \ 1131 *status = true; \ 1132 } \ 1133 return item->data.VAL; \ 1134 } 1135 1136 psMetadataLookupPtrTYPE(psMetadata*, Metadata, PS_DATA_METADATA, md) 1137 psMetadataLookupPtrTYPE(psString, Str, PS_DATA_STRING, str) 1138 psMetadataLookupPtrTYPE(psTime*, Time, PS_DATA_TIME, V) 1139 psMetadataLookupPtrTYPE(psVector*, Vector, PS_DATA_VECTOR, V) 1140 1103 1141 1104 1142 psMetadataItem* psMetadataGet(const psMetadata *md, … … 1257 1295 } 1258 1296 1259 psMetadata *psMetadataLookupMetadata(bool *status, 1260 const psMetadata *md, 1261 const char *key) 1262 { 1263 PS_ASSERT_METADATA_NON_NULL(md,NULL); 1264 psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); // The metadata with instruments 1265 psMetadata *value = NULL; // The value to return 1266 if (!item) { 1267 // The given key isn't in the metadata 1268 if (status) { 1269 *status = false; 1270 } else { 1271 psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n", key); 1272 } 1273 } else if (item->type != PS_DATA_METADATA) { 1274 // The value at the key isn't metadata 1275 if (status) { 1276 *status = false; 1277 } else { 1278 psLogMsg(__func__, PS_LOG_DETAIL, "%s isn't of type PS_DATA_META, as expected.\n", key); 1279 } 1280 // value = NULL; 1281 } else { 1282 // We have the requested metadata 1283 if (status) { 1284 *status = true; 1285 } 1286 value = item->data.md; // The requested metadata 1287 } 1288 return value; 1289 } 1290 1291 psTime *psMetadataLookupTime(bool *status, 1292 const psMetadata *md, 1293 const char *key) 1294 { 1295 PS_ASSERT_METADATA_NON_NULL(md,NULL); 1296 1297 psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); 1298 if (!item) { 1299 // The given key isn't in the metadata 1300 if (status) { 1301 *status = false; 1302 } else { 1303 psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n", key); 1304 } 1305 return NULL; 1306 } 1307 1308 if (item->type != PS_DATA_TIME) { 1309 // The value at the key isn't metadata 1310 if (status) { 1311 *status = false; 1312 } else { 1313 psLogMsg(__func__, PS_LOG_DETAIL, "%s isn't of type PS_DATA_TIME, as expected.\n", key); 1314 } 1315 return NULL; 1316 } 1317 1318 // We have the requested metadata 1319 if (status) { 1320 *status = true; 1321 } 1322 1323 return item->data.V; 1324 } 1325 1326 1327 psString psMetadataLookupStr(bool *status, 1328 const psMetadata *md, 1329 const char *key) 1330 { 1331 PS_ASSERT_METADATA_NON_NULL(md,NULL); 1332 1333 psMetadataItem *item = psMetadataLookup((psMetadata*)md, key); // The metadata with instruments 1334 // char *value = NULL; // The value to return 1335 psString value = NULL; 1336 if (!item) { 1337 // The given key isn't in the metadata 1338 if (status) { 1339 *status = false; 1340 } else { 1341 psError(PS_ERR_IO, true, "Couldn't find %s in the metadata.\n", key); 1342 } 1343 } else if (item->type != PS_DATA_STRING) { 1344 // The value at the key isn't of the desired type 1345 if (status) { 1346 *status = false; 1347 } else { 1348 psLogMsg(__func__, PS_LOG_DETAIL, "%s isn't of type PS_DATA_STRING, as expected.\n", key); 1349 } 1350 // value = NULL; 1351 } else { 1352 // We have the requested metadata 1353 if (status) { 1354 *status = true; 1355 } 1356 value = item->data.V; 1357 } 1358 return value; 1359 } 1297 1298 1299 1360 1300 1361 1301 psList *psMetadataKeys(psMetadata *md) -
branches/eam_branches/20090715/psLib/src/types/psMetadata.h
r23148 r25405 717 717 PS_METADATA_LOOKUP_TYPE_DECL(Ptr, psPtr); 718 718 PS_METADATA_LOOKUP_TYPE_DECL(Str, psString); 719 PS_METADATA_LOOKUP_TYPE_DECL(Vector, psVector*); 719 720 PS_METADATA_LOOKUP_TYPE_DECL(Metadata, psMetadata*); 720 721 PS_METADATA_LOOKUP_TYPE_DECL(Time, psTime*); -
branches/eam_branches/20090715/psLib/src/types/psTree.c
r18344 r25405 14 14 #include "psTree.h" 15 15 16 //#define INPUT_CHECK // Check inputs for functions that may be in a tight loop? 17 16 18 17 19 // XXX Upgrades: … … 84 86 } 85 87 86 psTree *psTreeAlloc(int dim, int maxLeafContents, long numNodes)88 psTree *psTreeAlloc(int dim, int maxLeafContents, psTreeType type, long numNodes) 87 89 { 88 90 psAssert(dim > 0, "Dimensionality (%d) must be positive", dim); … … 95 97 tree->dim = dim; 96 98 tree->maxLeafContents = maxLeafContents; 99 tree->type = type; 97 100 98 101 tree->numNodes = numNodes; … … 115 118 116 119 117 psTree *psTreePlant(int dim, int maxLeafContents, ...)120 psTree *psTreePlant(int dim, int maxLeafContents, psTreeType type, ...) 118 121 { 119 122 PS_ASSERT_INT_POSITIVE(dim, NULL); … … 122 125 // Parse coordinate list 123 126 va_list args; // Variable argument list 124 va_start(args, maxLeafContents);127 va_start(args, type); 125 128 psArray *coords = psArrayAlloc(dim); // Array of coordinates 126 129 long numData = 0; // Number of data points … … 145 148 long pow2; // Smallest power of two >= numData 146 149 for (pow2 = 1; pow2 < numData; pow2 <<= 1); 147 numNodes = PS_M IN(pow2 - 1, 2 * numData - pow2 / 2 -1);148 } 149 150 psTree *tree = psTreeAlloc(dim, maxLeafContents, numNodes);150 numNodes = PS_MAX(PS_MIN(pow2 - 1, 2 * numData - pow2 / 2 - 1), 1); 151 } 152 153 psTree *tree = psTreeAlloc(dim, maxLeafContents, type, numNodes); 151 154 tree->data = psTreeCoordArrayAlloc(numData, dim); 152 155 tree->numData = numData; … … 199 202 } 200 203 204 if (numData <= maxLeafContents) { 205 // Don't need to do any more work 206 return tree; 207 } 208 201 209 psArray *work = psArrayAlloc(numNodes); // Work queue 202 210 work->data[0] = root; … … 365 373 psTreeNode *psTreeLeaf(const psTree *tree, const psVector *coords) 366 374 { 367 #if 1// Might be in a tight loop375 #ifdef INPUT_CHECK // Might be in a tight loop 368 376 PS_ASSERT_TREE_NON_NULL(tree, NULL); 369 377 PS_ASSERT_VECTOR_NON_NULL(coords, NULL); … … 403 411 { 404 412 int dim = tree->dim; // Dimensionality 405 switch (dim) { 406 case 2: 407 return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) + 408 PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]); 409 case 3: 410 return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) + 411 PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]) + 412 PS_SQR(coords->data.F64[2] - tree->data->F64[index][2]); 413 default: { 414 double distance2 = 0.0; // Distance of interest 415 for (int i = 0; i < dim; i++) { 416 distance2 += PS_SQR(coords->data.F64[i] - tree->data->F64[index][i]); 413 switch (tree->type) { 414 case PS_TREE_EUCLIDEAN: 415 switch (dim) { 416 case 2: 417 return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) + 418 PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]); 419 case 3: 420 return PS_SQR(coords->data.F64[0] - tree->data->F64[index][0]) + 421 PS_SQR(coords->data.F64[1] - tree->data->F64[index][1]) + 422 PS_SQR(coords->data.F64[2] - tree->data->F64[index][2]); 423 default: { 424 double distance2 = 0.0; // Distance of interest 425 for (int i = 0; i < dim; i++) { 426 distance2 += PS_SQR(coords->data.F64[i] - tree->data->F64[index][i]); 427 } 428 return distance2; 417 429 } 418 return distance2; 419 } 420 } 430 } 431 break; 432 case PS_TREE_SPHERICAL: 433 switch (dim) { 434 case 2: { 435 // Haversine formula 436 double dphi = coords->data.F64[1] - tree->data->F64[index][1]; 437 double sindphi = sin(dphi / 2.0); 438 double dlambda = coords->data.F64[0] - tree->data->F64[index][0]; 439 double sindlambda = sin(dlambda / 2.0); 440 return PS_SQR(sindphi) + 441 cos(coords->data.F64[1]) * cos(tree->data->F64[index][1]) * PS_SQR(sindlambda); 442 } 443 default: 444 psAbort("Spherical distances not supported for more than 2 dimensions"); 445 } 446 default: 447 psAbort("Unrecognised type: %x", tree->type); 448 } 449 421 450 return NAN; 422 451 } … … 430 459 double minDiff = tree->min->F64[index][i] - coords->data.F64[i]; 431 460 if (minDiff > 0) { 432 distance += PS_SQR(minDiff); 461 switch (tree->type) { 462 case PS_TREE_EUCLIDEAN: 463 distance += PS_SQR(minDiff); 464 break; 465 case PS_TREE_SPHERICAL: { 466 double sinDiff = sin(minDiff / 2.0); 467 distance += PS_SQR(sinDiff); 468 break; 469 } 470 default: 471 psAbort("Unrecognised type: %x", tree->type); 472 } 433 473 continue; 434 474 } 435 475 double maxDiff = coords->data.F64[i] - tree->max->F64[index][i]; 436 476 if (maxDiff > 0) { 437 distance += PS_SQR(maxDiff); 477 switch (tree->type) { 478 case PS_TREE_EUCLIDEAN: 479 distance += PS_SQR(maxDiff); 480 break; 481 case PS_TREE_SPHERICAL: { 482 double sinDiff = sin(maxDiff / 2.0); 483 distance += PS_SQR(sinDiff); 484 break; 485 } 486 default: 487 psAbort("Unrecognised type: %x", tree->type); 488 } 438 489 continue; 439 490 } … … 479 530 } 480 531 481 // Return the index of the nearest neighbour to given coordinates, within some radius532 // Return the index of the nearest neighbour to given coordinates, within some distance measure 482 533 // This is the engine for psTreeNearest() and psTreeNearestWithin() 483 534 static inline long treeNearestWithin(const psTree *tree, // Tree 484 535 const psVector *coordinates, // Coordinates of interest 485 double bestDistance // Distance (radius-squared)to best point536 double bestDistance // Distance measure to best point 486 537 ) 487 538 { 488 #if 1// Might be in a tight loop539 #ifdef INPUT_CHECK // Might be in a tight loop 489 540 PS_ASSERT_TREE_NON_NULL(tree, -1); 490 541 PS_ASSERT_VECTOR_NON_NULL(coordinates, -1); … … 545 596 546 597 598 // Convert a radius to our internal "distance measure" 599 // Often, we're given a search radius, but for efficiency reasons, we don't use that internally. 600 static double treeRadiusToDistance(const psTree *tree, double radius) 601 { 602 switch (tree->type) { 603 case PS_TREE_EUCLIDEAN: 604 // Using the square of the distance as the distance measure 605 return PS_SQR(radius); 606 case PS_TREE_SPHERICAL: { 607 // Using a rearrangement of the Haversine formula 608 double sindist = sin(radius / 2.0); 609 return PS_SQR(sindist); 610 } 611 default: 612 psAbort("Unrecognised type: %x", tree->type); 613 } 614 } 615 616 547 617 long psTreeNearestWithin(const psTree *tree, const psVector *coords, double radius) 548 618 { 549 return treeNearestWithin(tree, coords, PS_SQR(radius));550 } 551 552 553 // Search a leaf node for points within radius squared554 static inline long treeLeafSearchWithin(double radius2, // Radius squaredto search619 return treeNearestWithin(tree, coords, treeRadiusToDistance(tree, radius)); 620 } 621 622 623 // Search a leaf node for points within distance 624 static inline long treeLeafSearchWithin(double distance, // Distance to search 555 625 const psTree *tree, // Tree of interest 556 626 const psTreeNode *leaf, // Leaf to search … … 561 631 for (int i = 0; i < leaf->num; i++) { 562 632 long index = leaf->contents[i]; // Index of point 563 double distance = treeContentDistance(tree, index, coords); // Distance to point 564 if (distance < radius2) { 633 if (treeContentDistance(tree, index, coords) < distance) { 565 634 num++; 566 635 } … … 572 641 long psTreeWithin(const psTree *tree, const psVector *coordinates, double radius) 573 642 { 574 #if 1// Might be in a tight loop643 #ifdef INPUT_CHECK // Might be in a tight loop 575 644 PS_ASSERT_TREE_NON_NULL(tree, -1); 576 645 PS_ASSERT_VECTOR_NON_NULL(coordinates, -1); … … 581 650 psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates 582 651 583 radius *= radius; // We work with the radius-squared652 double distance = treeRadiusToDistance(tree, radius); // Distance measure 584 653 long num = 0; // Number of points in circle 585 654 … … 588 657 // Find the closest point in the leaf that contains the point of interest 589 658 psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest 590 num += treeLeafSearchWithin( radius, tree, leaf, coords);659 num += treeLeafSearchWithin(distance, tree, leaf, coords); 591 660 592 661 psArray *work = psArrayAlloc(tree->numNodes); // Work queue … … 605 674 } 606 675 // Leaf node 607 num += treeLeafSearchWithin( radius, tree, node, coords);676 num += treeLeafSearchWithin(distance, tree, node, coords); 608 677 work->data[workIndex] = NULL; 609 678 workIndex--; … … 618 687 } 619 688 620 // Search a leaf node for any points within radius squared 621 static inline bool treeLeafSearchWithinAny(double radius2, // Radius squared to search 622 const psTree *tree, // Tree of interest 623 const psTreeNode *leaf, // Leaf to search 624 const psVector *coords // Coordinates of interest 689 // Search a leaf node for points within distance 690 static inline void treeLeafSearchAllWithin(psVector *result, // Result vector 691 double distance, // Distance to search 692 const psTree *tree, // Tree of interest 693 const psTreeNode *leaf, // Leaf to search 694 const psVector *coords // Coordinates of interest 625 695 ) 626 696 { 627 697 for (int i = 0; i < leaf->num; i++) { 628 698 long index = leaf->contents[i]; // Index of point 629 double distance = treeContentDistance(tree, index, coords); // Distance to point 630 if (distance < radius2) { 631 return true; 632 } 633 } 634 return false; 635 } 636 637 // Given an arbitrary point and a matching radius, return whether there are any points within that radius 638 bool psTreeWithinAny(const psTree *tree, const psVector *coordinates, double radius) 639 { 640 #if 1 // Might be in a tight loop 641 PS_ASSERT_TREE_NON_NULL(tree, false); 642 PS_ASSERT_VECTOR_NON_NULL(coordinates, false); 643 PS_ASSERT_VECTOR_SIZE(coordinates, (long)tree->dim, false); 699 if (treeContentDistance(tree, index, coords) < distance) { 700 psVectorAppend(result, index); 701 } 702 } 703 return; 704 } 705 706 // Given an arbitrary point and a matching radius, return the index of all points within that radius 707 psVector *psTreeAllWithin(const psTree *tree, const psVector *coordinates, double radius) 708 { 709 #ifdef INPUT_CHECK // Might be in a tight loop 710 PS_ASSERT_TREE_NON_NULL(tree, NULL); 711 PS_ASSERT_VECTOR_NON_NULL(coordinates, NULL); 712 PS_ASSERT_VECTOR_SIZE(coordinates, (long)tree->dim, NULL); 644 713 #endif 645 714 … … 647 716 psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates 648 717 649 radius *= radius; // We work with the radius-squared 650 651 // This is essentially the same as psTreeWithin, except we can bail as soon as we find something 718 double distance = treeRadiusToDistance(tree, radius); // Distance measure 719 720 psVector *result = psVectorAllocEmpty(4, PS_TYPE_S64); // Indices of points within match radius 721 722 // This is essentially the same as psTreeNearest, except we're not allowed to prune 652 723 653 724 // Find the closest point in the leaf that contains the point of interest 654 725 psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest 655 if (treeLeafSearchWithinAny(radius, tree, leaf, coords)) { 656 psFree(coords); 657 return true; 658 } 726 treeLeafSearchAllWithin(result, distance, tree, leaf, coords); 659 727 660 728 psArray *work = psArrayAlloc(tree->numNodes); // Work queue … … 673 741 } 674 742 // Leaf node 675 if (treeLeafSearchWithinAny(radius, tree, node, coords)) { 743 treeLeafSearchAllWithin(result, distance, tree, node, coords); 744 work->data[workIndex] = NULL; 745 workIndex--; 746 } 747 748 leaf = up; 749 } 750 psFree(work); 751 psFree(coords); 752 753 return result; 754 } 755 756 // Search a leaf node for any points within distance measure 757 static inline bool treeLeafSearchWithinAny(double distance, // Distance to search 758 const psTree *tree, // Tree of interest 759 const psTreeNode *leaf, // Leaf to search 760 const psVector *coords // Coordinates of interest 761 ) 762 { 763 for (int i = 0; i < leaf->num; i++) { 764 long index = leaf->contents[i]; // Index of point 765 if (treeContentDistance(tree, index, coords) < distance) { 766 return true; 767 } 768 } 769 return false; 770 } 771 772 // Given an arbitrary point and a matching radius, return whether there are any points within that radius 773 bool psTreeWithinAny(const psTree *tree, const psVector *coordinates, double radius) 774 { 775 #ifdef INPUT_CHECK // Might be in a tight loop 776 PS_ASSERT_TREE_NON_NULL(tree, false); 777 PS_ASSERT_VECTOR_NON_NULL(coordinates, false); 778 PS_ASSERT_VECTOR_SIZE(coordinates, (long)tree->dim, false); 779 #endif 780 781 psVector *coords = (coordinates->type.type == PS_TYPE_F64 ? psMemIncrRefCounter((psVector*)coordinates) : 782 psVectorCopy(NULL, coordinates, PS_TYPE_F64)); // F64 version of coordinates 783 784 double distance = treeRadiusToDistance(tree, radius); // Distance measure 785 786 // This is essentially the same as psTreeWithin, except we can bail as soon as we find something 787 788 // Find the closest point in the leaf that contains the point of interest 789 psTreeNode *leaf = psTreeLeaf(tree, coords); // Leaf containing the point of interest 790 if (treeLeafSearchWithinAny(distance, tree, leaf, coords)) { 791 psFree(coords); 792 return true; 793 } 794 795 psArray *work = psArrayAlloc(tree->numNodes); // Work queue 796 while (leaf->up) { 797 psTreeNode *up = leaf->up; // Parent node 798 799 long workIndex = 0; 800 work->data[workIndex] = (leaf == up->left ? up->right : up->left); // The other node 801 while (workIndex >= 0) { 802 psTreeNode *node = work->data[workIndex]; 803 if (node->left) { 804 // Branch node 805 work->data[workIndex] = node->right; 806 work->data[++workIndex] = node->left; 807 continue; 808 } 809 // Leaf node 810 if (treeLeafSearchWithinAny(distance, tree, node, coords)) { 676 811 // Clear out the work queue 677 812 memset(work->data, 0, (workIndex + 1) * sizeof(void)); … … 695 830 psVector *psTreeCoords(psVector *out, const psTree *tree, long index) 696 831 { 697 #if 1// Might be in a tight loop832 #ifdef INPUT_CHECK // Might be in a tight loop 698 833 PS_ASSERT_TREE_NON_NULL(tree, NULL); 699 834 PS_ASSERT_INT_NONNEGATIVE(index, NULL); -
branches/eam_branches/20090715/psLib/src/types/psTree.h
r19539 r25405 16 16 } psTreeCoordArray; 17 17 18 /// Type of tree 19 /// 20 /// Specifies how distances are measured 21 typedef enum { 22 PS_TREE_EUCLIDEAN, // d^2 = dx^2 + dy^2 + ... 23 PS_TREE_SPHERICAL, // sin(dist/2)^2 = sin(dphi/2)^2 + cos(phi1)cos(phi2)sin(dlambda/2)^2 24 } psTreeType; 25 18 26 /// A simple kd-tree implementation 19 27 /// … … 23 31 int dim; ///< Dimensionality 24 32 int maxLeafContents; ///< Maximum number of points on a leaf 33 psTreeType type; ///< Type of tree 25 34 long numNodes; ///< Number of nodes 26 35 long numData; ///< Number of data points … … 67 76 psTree *psTreeAlloc(int dim, ///< Dimensionality 68 77 int maxLeafContents,///< Maximum number of points on a leaf 78 psTreeType type, ///< Type of tree 69 79 long numNodes ///< Number of nodes in tree 70 80 ); … … 75 85 psTree *psTreePlant(int dim, ///< Dimensionality 76 86 int maxLeafContents,///< Maximum number of points on a leaf 87 psTreeType type, ///< Type of tree 77 88 ... ///< psVector for each coordinate 78 89 ); … … 108 119 ); 109 120 121 /// Return the index of all points within some radius of given coordinates 122 psVector *psTreeAllWithin(const psTree *tree, ///< Tree 123 const psVector *coordinates, ///< Coordinates of interest 124 double radius ///< Radius of interest 125 ); 126 110 127 /// Return the coordinates of a point in the tree, specified by its index 111 128 psVector *psTreeCoords(psVector *out, ///< Output vector, or NULL -
branches/eam_branches/20090715/psLib/test/optime
- Property svn:ignore
-
old new 2 2 Makefile.in 3 3 .deps 4 tap_psStatsTiming
-
- Property svn:ignore
-
branches/eam_branches/20090715/psLib/test/types/tap_psTree.c
r23259 r25405 3 3 #include "pstap.h" 4 4 5 #define NUM 10000 // Number of points 5 #define NUM 1000000 // Number of points 6 #define SPHERICAL_DISTANCE 3.0 // Distance of interest for spherical test 6 7 7 8 int main(int argc, char *argv[]) 8 9 { 9 10 psLibInit(NULL); 10 plan_tests( 6);11 plan_tests(13); 11 12 13 // Euclidean geometry: 6 tests 12 14 { 13 15 psMemId id = psMemGetId(); … … 23 25 psFree(rng); 24 26 25 psTree *tree = psTreePlant(2, 2, x, y);27 psTree *tree = psTreePlant(2, 2, PS_TREE_EUCLIDEAN, x, y); 26 28 27 29 ok(tree, "Tree planted"); … … 35 37 long closeIndex = psTreeNearest(tree, coords); 36 38 psFree(coords); 37 ok(closeIndex >= 0 && closeIndex < tree->numNodes, "found point: %ld", closeIndex);39 ok(closeIndex >= 0 && closeIndex < tree->numNodes, "found closest point: %ld", closeIndex); 38 40 39 41 long bestIndex = -1; … … 68 70 } 69 71 72 // Spherical geometry: 7 tests 73 { 74 psMemId id = psMemGetId(); 75 76 psVector *ra = psVectorAlloc(NUM, PS_TYPE_F64); 77 psVector *dec = psVectorAlloc(NUM, PS_TYPE_F64); 78 79 psRandom *rng = psRandomAllocSpecific(PS_RANDOM_TAUS, 0); 80 for (int i = 0; i < NUM; i++) { 81 // Using http://mathworld.wolfram.com/SpherePointPicking.html 82 ra->data.F64[i] = psRandomUniform(rng); 83 dec->data.F64[i] = acos(2.0 * psRandomUniform(rng) - 1.0) - M_PI_2; 84 } 85 86 psTree *tree = psTreePlant(2, 2, PS_TREE_SPHERICAL, ra, dec); 87 88 ok(tree, "Tree planted"); 89 skip_start(!tree, 4, "tree died"); 90 { 91 // psTreePrint(stderr, tree); 92 93 psVector *coords = psVectorAlloc(2, PS_TYPE_F64); 94 coords->data.F64[0] = psRandomUniform(rng); 95 coords->data.F64[1] = acos(2.0 * psRandomUniform(rng) - 1.0) - M_PI_2; 96 97 psVector *indices = psTreeAllWithin(tree, coords, DEG_TO_RAD(SPHERICAL_DISTANCE)); 98 ok(indices && indices->type.type == PS_TYPE_S64, "got list of indices (%ld points)", indices->n); 99 long closeIndex = psTreeNearest(tree, coords); 100 ok(closeIndex >= 0 && closeIndex < tree->numNodes, "found closest point: %ld", closeIndex); 101 102 ok(psVectorSortInPlace(indices), "sorted indices"); 103 104 bool allgood = true; // All points in the appropriate place? 105 double bestDistance = INFINITY; // Distance to best point 106 long bestIndex = -1; // Index of best point 107 for (long i = 0, j = 0; i < NUM; i++) { 108 #if 1 109 // Traditional formula 110 double dist = acos(sin(coords->data.F64[1]) * sin(dec->data.F64[i]) + 111 cos(coords->data.F64[1]) * cos(dec->data.F64[i]) * 112 cos(coords->data.F64[0] - ra->data.F64[i])); 113 #else 114 // Haversine formula: used in psTree 115 double dphi = coords->data.F64[1] - dec->data.F64[i]; 116 double sindphi = sin(dphi/2.0); 117 double dlambda = coords->data.F64[0] - ra->data.F64[i]; 118 double sindlambda = sin(dlambda/2.0); 119 double dist = 2.0 * asin(sqrt(PS_SQR(sindphi) + 120 cos(coords->data.F64[1]) * cos(dec->data.F64[i]) * 121 PS_SQR(sindlambda))); 122 #endif 123 if (dist < bestDistance) { 124 bestDistance = dist; 125 bestIndex = i; 126 } 127 if (i == indices->data.S64[j]) { 128 j++; 129 if (dist > DEG_TO_RAD(SPHERICAL_DISTANCE)) { 130 diag("%ld is in the list, but shouldn't be (%lf vs %lf)", 131 i, RAD_TO_DEG(dist), SPHERICAL_DISTANCE); 132 allgood = false; 133 } 134 } else if (dist <= DEG_TO_RAD(SPHERICAL_DISTANCE)) { 135 diag("%ld is not in the list, but should be (%lf vs %lf)", 136 i, RAD_TO_DEG(dist), SPHERICAL_DISTANCE); 137 allgood = false; 138 } 139 } 140 ok(allgood, "list is acurate"); 141 ok(bestIndex == closeIndex, "correct point: %ld vs %ld", closeIndex, bestIndex); 142 143 psFree(coords); 144 psFree(indices); 145 146 } 147 skip_end(); 148 149 psFree(rng); 150 psFree(tree); 151 psFree(ra); 152 psFree(dec); 153 154 ok(!psMemCheckLeaks(id, NULL, NULL, false), "no memory leaks"); 155 } 156 70 157 psLibFinalize(); 71 158 }
Note:
See TracChangeset
for help on using the changeset viewer.
