Changeset 3498
- Timestamp:
- Mar 24, 2005, 12:36:52 PM (21 years ago)
- Location:
- trunk/psModules/src
- Files:
-
- 2 edited
-
pmObjects.c (modified) (36 diffs)
-
pmObjects.h (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/pmObjects.c
r3231 r3498 5 5 * @author GLG, MHPCC 6 6 * 7 * @version $Revision: 1. 5$ $Name: not supported by cvs2svn $8 * @date $Date: 2005-0 2-15 23:59:05$7 * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2005-03-24 22:36:52 $ 9 9 * 10 10 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 11 xd*11 * 12 12 */ 13 13 … … 17 17 #include "psConstants.h" 18 18 #include "pmObjects.h" 19 /****************************************************************************** 20 *****************************************************************************/ 21 22 psPeak *pmPeakAlloc(psS32 x, 23 psS32 y, 24 psF32 counts, 25 psPeakType class) 26 { 27 psPeak *tmp = (psPeak *) psAlloc(sizeof(psPeak)); 28 tmp->x = x; 29 tmp->y = y; 30 tmp->counts = counts; 31 tmp->class = class; 32 33 return(tmp); 34 } 35 36 psMoments *pmMomentsAlloc() 37 { 38 psMoments *tmp = (psMoments *) psAlloc(sizeof(psMoments)); 39 tmp->x = 0.0; 40 tmp->y = 0.0; 41 tmp->Sx = 0.0; 42 tmp->Sx = 0.0; 43 tmp->Sxy = 0.0; 44 tmp->Sum = 0.0; 45 tmp->Peak = 0.0; 46 tmp->Sky = 0.0; 47 tmp->nPixels = 0; 48 49 return(tmp); 50 } 51 52 static void p_psModelFree(psModel *tmp) 53 { 54 psFree(tmp->params); 55 psFree(tmp->dparams); 56 } 57 58 psModel *pmModelAlloc(psModelType type) 59 { 60 psModel *tmp = (psModel *) psAlloc(sizeof(psModel)); 61 62 tmp->type = type; 63 tmp->Nparams = 0; 64 tmp->params = NULL; 65 tmp->dparams = NULL; 66 tmp->chisq = 0.0; 67 68 p_psMemSetDeallocator(tmp, (psFreeFcn) p_psModelFree); 69 return(tmp); 70 } 71 72 // XXX: We don't free pixels and mask since that caused a memory error. 73 // We might need to increase the reference counter and decrease it here. 74 // 75 static void p_psSourceFree(psSource *tmp) 76 { 77 psFree(tmp->peak); 78 // psFree(tmp->pixels); 79 // psFree(tmp->mask); 80 psFree(tmp->moments); 81 psFree(tmp->models); 82 } 83 84 psSource *pmSourceAlloc() 85 { 86 psSource *tmp = (psSource *) psAlloc(sizeof(psSource)); 87 tmp->peak = NULL; 88 tmp->pixels = NULL; 89 tmp->mask = NULL; 90 tmp->moments = NULL; 91 tmp->models = NULL; 92 p_psMemSetDeallocator(tmp, (psFreeFcn) p_psSourceFree); 93 94 return(tmp); 95 } 19 96 20 97 /****************************************************************************** … … 23 100 the location (x value) of all peaks. 24 101 25 XXX: What types should be supported? Only F32 us implemented.102 XXX: What types should be supported? Only F32 is implemented. 26 103 27 104 XXX: We currently step through the input vector twice; once to determine the … … 33 110 { 34 111 PS_VECTOR_CHECK_NULL(vector, NULL); 112 PS_VECTOR_CHECK_EMPTY(vector, NULL); 35 113 PS_VECTOR_CHECK_TYPE(vector, PS_TYPE_F32, NULL); 36 114 int count = 0; 37 115 int n = vector->n; 38 116 117 // 118 // Special case: the input vector has a single element. 119 // 120 if (n == 1) { 121 psVector *tmpVector = NULL; 122 ; 123 if (vector->data.F32[0] > threshold) { 124 tmpVector = psVectorAlloc(1, PS_TYPE_U32); 125 tmpVector->data.U32[0] = 0; 126 } else { 127 tmpVector = psVectorAlloc(0, PS_TYPE_U32); 128 } 129 return(tmpVector); 130 } 131 132 // 133 // Determine if first pixel is a peak 134 // 39 135 if ((vector->data.F32[0] > vector->data.F32[1]) && 40 136 (vector->data.F32[0] > threshold)) { … … 42 138 } 43 139 140 // 141 // Determine if interior pixels are peaks 142 // 44 143 for (psU32 i = 1; i < n-1 ; i++) { 45 144 if ((vector->data.F32[i] > vector->data.F32[i-1]) && … … 49 148 } 50 149 } 150 151 // 152 // Determine if last pixel is a peak 153 // 51 154 if ((vector->data.F32[n-1] > vector->data.F32[n-2]) && 52 155 (vector->data.F32[n-1] > threshold)) { … … 54 157 } 55 158 159 // 160 // We know how many peaks exist, so we now allocate a psVector to store 161 // those peaks. 162 // 56 163 psVector *tmpVector = psVectorAlloc(count, PS_TYPE_U32); 57 164 count = 0; 165 166 // 167 // Determine if first pixel is a peak 168 // 58 169 if ((vector->data.F32[0] > vector->data.F32[1]) && 59 170 (vector->data.F32[0] > threshold)) { 60 171 tmpVector->data.U32[count++] = 0; 61 172 } 173 174 // 175 // Determine if interior pixels are peaks 176 // 62 177 for (psU32 i = 1; i < (n-1) ; i++) { 63 178 if ((vector->data.F32[i] > vector->data.F32[i-1]) && … … 67 182 } 68 183 } 184 185 // 186 // Determine if last pixel is a peak 187 // 69 188 if ((vector->data.F32[n-1] > vector->data.F32[n-2]) && 70 189 (vector->data.F32[n-1] > threshold)) { … … 91 210 } 92 211 212 // XXX: Switch row, col args? 213 psList *MyListAddPeak(psList *list, 214 psS32 row, 215 psS32 col, 216 psF32 counts, 217 psPeakType type) 218 { 219 psPeak *tmpPeak = pmPeakAlloc(col, row, counts, type); 220 221 if (list == NULL) { 222 list = psListAlloc(tmpPeak); 223 } else { 224 psListAdd(list, PS_LIST_HEAD, tmpPeak); 225 } 226 227 return(list); 228 } 229 93 230 /****************************************************************************** 94 231 pmFindImagePeeks(image, threshold): Find all local peaks in the given psImage 95 232 above the given threshold. Returns a psList containing location (x/y value) 96 233 of all peaks. 234 235 XXX: I'm not convinced the peak type definition in the SDRS is mutually 236 exclusive. Some peaks can have multiple types. Edges for sure. Also, a 237 digonal line with the same value at each point will have a peak for every 238 point on that line. 239 240 XXX: This does not work if image has either a single row, or a single column. 241 242 XXX: In the output psList elements, should we use the image row/column offsets? 243 Currently, we do not. 97 244 *****************************************************************************/ 98 245 psList *pmFindImagePeeks(const psImage *image, … … 101 248 PS_IMAGE_CHECK_NULL(image, NULL); 102 249 PS_IMAGE_CHECK_TYPE(image, PS_TYPE_F32, NULL); 250 if ((image->numRows == 1) || (image->numCols == 1)) { 251 psError(PS_ERR_UNKNOWN, true, "Currently, input image must have at least 2 rows and 2 columns."); 252 } 103 253 psVector *tmpRow = NULL; 104 254 psU32 col = 0; 105 255 psU32 row = 0; 106 256 psList *list = NULL; 257 258 // 259 // Find peaks in row 0 only. 260 // 107 261 row = 0; 108 262 tmpRow = p_psGetRowVectorFromImage((psImage *) image, row); … … 110 264 for (psU32 i = 0 ; i < row1->n ; i++ ) { 111 265 col = row1->data.U32[i]; 266 267 // 268 // Determine if pixel (0,0) is a peak. 269 // 112 270 if (col == 0) { 113 271 if ( (image->data.F32[row][col] > image->data.F32[row][col+1]) && … … 115 273 (image->data.F32[row][col] >= image->data.F32[row+1][col+1])) { 116 274 if (image->data.F32[row][col] > threshold) { 117 // Add peak at location (row, col)275 list = MyListAddPeak(list, row, col, image->data.F32[row][col], PM_PEAK_EDGE); 118 276 } 119 277 } … … 125 283 (image->data.F32[row][col] >= image->data.F32[row+1][col+1])) { 126 284 if (image->data.F32[row][col] > threshold) { 127 // Add peak at location (row, col)285 list = MyListAddPeak(list, row, col, image->data.F32[row][col], PM_PEAK_EDGE); 128 286 } 129 287 } … … 134 292 (image->data.F32[row][col] >= image->data.F32[row+1][col-1])) { 135 293 if (image->data.F32[row][col] > threshold) { 136 // Add peak at location (row, col)294 list = MyListAddPeak(list, row, col, image->data.F32[row][col], PM_PEAK_EDGE); 137 295 } 138 296 } 139 297 140 298 } else { 141 printf("XXX: ERROR!\n"); 142 } 143 } 144 299 psError(PS_ERR_UNKNOWN, true, "peak specified valid colum range."); 300 } 301 } 302 // 303 // Exit if this image has a single row. 304 // 305 if (image->numRows == 1) { 306 return(list); 307 } 308 309 // 310 // Find peaks in interior rows only. 311 // 145 312 for (row = 1 ; row < (image->numRows - 1) ; row++) { 146 313 tmpRow = p_psGetRowVectorFromImage((psImage *) image, 0); … … 160 327 (image->data.F32[row][col] >= image->data.F32[row+1][col+1])) { 161 328 if (image->data.F32[row][col] > threshold) { 162 // Add peak at location (row, col) 329 330 psPeakType myType = PM_PEAK_UNDEF; 331 if ((image->data.F32[row][col] > image->data.F32[row-1][col-1]) && 332 (image->data.F32[row][col] > image->data.F32[row-1][col]) && 333 (image->data.F32[row][col] > image->data.F32[row-1][col+1]) && 334 (image->data.F32[row][col] > image->data.F32[row][col-1]) && 335 (image->data.F32[row][col] > image->data.F32[row][col+1]) && 336 (image->data.F32[row][col] > image->data.F32[row+1][col-1]) && 337 (image->data.F32[row][col] > image->data.F32[row+1][col]) && 338 (image->data.F32[row][col] > image->data.F32[row+1][col+1])) { 339 myType = PM_PEAK_LONE; 340 } 341 if ((image->data.F32[row][col] == image->data.F32[row-1][col-1]) || 342 (image->data.F32[row][col] == image->data.F32[row-1][col]) || 343 (image->data.F32[row][col] == image->data.F32[row-1][col+1]) || 344 (image->data.F32[row][col] == image->data.F32[row][col-1]) || 345 (image->data.F32[row][col] == image->data.F32[row][col+1]) || 346 (image->data.F32[row][col] == image->data.F32[row+1][col-1]) || 347 (image->data.F32[row][col] == image->data.F32[row+1][col]) || 348 (image->data.F32[row][col] == image->data.F32[row+1][col+1])) { 349 myType = PM_PEAK_FLAT; 350 } 351 352 list = MyListAddPeak(list, row, col, image->data.F32[row][col], myType); 163 353 } 164 354 } … … 166 356 } 167 357 358 // 359 // Find peaks in the last row only. 360 // 168 361 row = image->numRows - 1; 169 362 tmpRow = p_psGetRowVectorFromImage((psImage *) image, row); … … 176 369 (image->data.F32[row][col] > image->data.F32[row][col+1])) { 177 370 if (image->data.F32[row][col] > threshold) { 178 // Add peak at location (row, col)371 list = MyListAddPeak(list, row, col, image->data.F32[row][col], PM_PEAK_EDGE); 179 372 } 180 373 } … … 186 379 (image->data.F32[row][col] >= image->data.F32[row][col+1])) { 187 380 if (image->data.F32[row][col] > threshold) { 188 // Add peak at location (row, col)381 list = MyListAddPeak(list, row, col, image->data.F32[row][col], PM_PEAK_EDGE); 189 382 } 190 383 } … … 195 388 (image->data.F32[row][col] > image->data.F32[row][col-1])) { 196 389 if (image->data.F32[row][col] > threshold) { 197 // Add peak at location (row, col)390 list = MyListAddPeak(list, row, col, image->data.F32[row][col], PM_PEAK_EDGE); 198 391 } 199 392 } 200 393 } else { 201 printf("XXX: ERROR!\n"); 202 } 203 } 204 205 return(NULL); 206 } 394 psError(PS_ERR_UNKNOWN, true, "peak specified valid colum range."); 395 } 396 } 397 398 return(list); 399 } 400 401 // XXX: Macro this. 402 bool IsItInThisRegion(const psRegion *valid, 403 psS32 x, 404 psS32 y) 405 { 406 407 if ((x >= valid->x0) && 408 (x <= valid->x1) && 409 (y >= valid->y0) && 410 (y <= valid->y1)) { 411 return(true); 412 } 413 414 return(false); 415 } 416 207 417 208 418 /****************************************************************************** … … 210 420 a peak value above the given maximum, or fall outside the valid region. 211 421 212 XXX: Do we free the psList elements of those culled peaks? 422 XXX: Should the sky value be used when comparing the maximum? 423 424 XXX: warning message if valid is NULL? 213 425 *****************************************************************************/ 214 426 psList *pmCullPeeks(psList *peaks, … … 216 428 const psRegion *valid) 217 429 { 218 return(NULL); 219 } 220 221 /****************************************************************************** 222 psSource *pmSourceLocalSky(image, peak, innerRadius, outerRadius): 430 PS_PTR_CHECK_NULL(peaks, NULL); 431 // PS_PTR_CHECK_NULL(valid, NULL); 432 433 psListElem *tmpListElem = (psListElem *) peaks->head; 434 psS32 indexNum = 0; 435 436 // printf("pmCullPeeks(): list size is %d\n", peaks->size); 437 while (tmpListElem != NULL) { 438 psPeak *tmpPeak = (psPeak *) tmpListElem->data; 439 if ((tmpPeak->counts > maxValue) || 440 ((valid != NULL) && 441 (true == IsItInThisRegion(valid, tmpPeak->x, tmpPeak->y)))) { 442 psListRemoveData(peaks, (psPtr) tmpPeak); 443 } 444 445 indexNum++; 446 tmpListElem = tmpListElem->next; 447 } 448 449 return(peaks); 450 } 451 452 /****************************************************************************** 453 psSource *pmSourceLocalSky(image, peak, innerRadius, outerRadius): this 454 routine creates a new psSource data structure and sets the following members: 455 ->psPeak 456 ->psMoments->sky 457 458 The sky value is set from the pixels in the square annulus surrounding the 459 peak pixel. 460 461 We simply create a subSet image and mask the inner pixels, then call 462 psImageStats on that subImage+mask. 463 464 XXX: The subImage has width of 1+2*outerRadius. Verify with IfA. 465 466 XXX: Use static data structures for: 467 subImage 468 subImageMask 469 myStats 470 471 XXX: ensure that the inner and out radius fit in the actual image. Should 472 we generate an error, or warning? Currently an error. 473 474 XXX: Sync with IfA on whether the peak x/y coords are data structure coords, 475 or they use the image row/column offsets. 476 477 XXX: Should we simply set psSource->peak = peak? If so, should we increase 478 the reference counter? Or, should we copy the data structure? 479 480 XXX: Currently the subimage always has an even number of rows/columns. Is 481 this correct? Since there is a center pixel, maybe it should have an 482 odd number of rows/columns. 483 484 XXX: Use psTrace() for the print statements. 485 486 XXX: Don't use separate structs for the subimage and mask. Use the source-> 487 members. 223 488 *****************************************************************************/ 224 489 psSource *pmSourceLocalSky(const psImage *image, 225 490 const psPeak *peak, 491 psStatsOptions statsOptions, 226 492 psF32 innerRadius, 227 493 psF32 outerRadius) 228 494 { 229 return(NULL); 230 } 231 232 /****************************************************************************** 495 PS_IMAGE_CHECK_NULL(image, NULL); 496 PS_IMAGE_CHECK_TYPE(image, PS_TYPE_F32, NULL); 497 PS_PTR_CHECK_NULL(peak, NULL); 498 PS_FLOAT_COMPARE(0.0, innerRadius, NULL); 499 PS_FLOAT_COMPARE(innerRadius, outerRadius, NULL); 500 psS32 innerRadiusS32 = (psS32) innerRadius; 501 psS32 outerRadiusS32 = (psS32) outerRadius; 502 503 // 504 // We define variables for code readability. 505 // 506 psS32 SubImageCenterRow = peak->y; 507 psS32 SubImageCenterCol = peak->x; 508 psS32 SubImageStartRow = SubImageCenterRow - outerRadiusS32; 509 psS32 SubImageEndRow = SubImageCenterRow + outerRadiusS32; 510 psS32 SubImageStartCol = SubImageCenterCol - outerRadiusS32; 511 psS32 SubImageEndCol = SubImageCenterCol + outerRadiusS32; 512 // AnulusWidth == number of pixels width in the annulus. We add one since 513 // the pixels at the inner AND outher radius are included. 514 psS32 AnulusWidth = 1 + (outerRadiusS32 - innerRadiusS32); 515 // Example: assume an outer/inner radius of 20/10. Then the subimage 516 // should have width/length of 40. An 18-by-18 interior region will 517 // be masked. 518 // printf("pmSourceLocalSky(): innerRadiusS32 is %d\n", innerRadiusS32); 519 // printf("pmSourceLocalSky(): outerRadiusS32 is %d\n", outerRadiusS32); 520 // printf("pmSourceLocalSky(): AnulusWidth is %d\n", AnulusWidth); 521 522 if (SubImageStartRow < 0) { 523 psError(PS_ERR_UNKNOWN, true, "Sub image startRow is outside image boundaries (%d).\n", 524 SubImageStartRow); 525 return(NULL); 526 } 527 if (SubImageEndRow >= image->numRows) { 528 psError(PS_ERR_UNKNOWN, true, "Sub image endRow is outside image boundaries (%d).\n", 529 SubImageEndRow); 530 return(NULL); 531 } 532 if (SubImageStartCol < 0) { 533 psError(PS_ERR_UNKNOWN, true, "Sub image startCol is outside image boundaries (%d).\n", 534 SubImageStartCol); 535 return(NULL); 536 } 537 if (SubImageEndCol >= image->numCols) { 538 psError(PS_ERR_UNKNOWN, true, "Sub image endCol is outside image boundaries (%d).\n", 539 SubImageEndCol); 540 return(NULL); 541 } 542 543 // 544 // Grab a subimage of the original image of size (2 * outerRadius). 545 // 546 psImage *subImage = psImageSubset((psImage *) image, 547 SubImageStartCol, 548 SubImageStartRow, 549 SubImageEndCol, 550 SubImageEndRow); 551 // printf("pmSourceLocalSky: subimage width/length is (%d, %d)\n", subImage->numCols, subImage->numRows); 552 psImage *subImageMask = psImageAlloc(subImage->numCols, 553 subImage->numRows, 554 PS_TYPE_U8); 555 556 // 557 // Loop through the subimage mask, initialize mask to 0. 558 // 559 for (psS32 row = 0 ; row < subImageMask->numRows; row++) { 560 for (psS32 col = 0 ; col < subImageMask->numCols; col++) { 561 subImageMask->data.U8[row][col] = 0; 562 } 563 } 564 565 // 566 // Loop through the subimage, mask off pixels in the inner square. 567 // 568 for (psS32 row = AnulusWidth; row <= (subImageMask->numRows - AnulusWidth) - 1; row++) { 569 for (psS32 col = AnulusWidth; col <= (subImageMask->numCols - AnulusWidth) - 1; col++) { 570 subImageMask->data.U8[row][col] = 1; 571 } 572 } 573 574 575 // for (psS32 row = 0 ; row < subImage->numRows; row++) { 576 // for (psS32 col = 0 ; col < subImage->numCols; col++) { 577 // printf("(%d) ", subImageMask->data.U8[row][col]); 578 // } 579 // printf("\n"); 580 // } 581 582 // 583 // Allocate the myStats structure, then call psImageStats(), which will 584 // calculate the specified statistic. 585 // 586 psStats *myStats = psStatsAlloc(statsOptions); 587 myStats = psImageStats(myStats, subImage, subImageMask, 1); 588 589 // 590 // Create the output mySource, and set appropriate members. 591 // 592 psSource *mySource = pmSourceAlloc(); 593 mySource->peak = (psPeak *) peak; 594 mySource->moments = pmMomentsAlloc(); 595 psF64 tmpF64; 596 p_psGetStatValue(myStats, &tmpF64); 597 mySource->moments->Sky = (psF32) tmpF64; 598 mySource->pixels = subImage; 599 mySource->mask = subImageMask; 600 601 // 602 // Free things. XXX: This should be static memory. 603 // 604 psFree(myStats); 605 606 return(mySource); 607 } 608 609 /****************************************************************************** 610 bool CheckRadius(*peak, radius, x, y): private function which simply 611 determines if the (x, y) point is within the radius of the specified peak. 612 613 XXX: macro this for performance. 614 615 XXX: should arguments be (y, x) order? 616 *****************************************************************************/ 617 bool CheckRadius(psPeak *peak, 618 psF32 radius, 619 psS32 x, 620 psS32 y) 621 { 622 if (PS_SQR(radius) >= (psF32) (PS_SQR(x - peak->x) + PS_SQR(y - peak->y))) { 623 return(true); 624 } 625 626 return(false); 627 } 628 629 bool CheckRadius2(psF32 xCenter, 630 psF32 yCenter, 631 psF32 radius, 632 psF32 x, 633 psF32 y) 634 { 635 if ((PS_SQR(x - xCenter) + PS_SQR(y - yCenter)) < PS_SQR(radius)) { 636 return(true); 637 } 638 639 return(false); 640 } 641 642 /****************************************************************************** 643 pmSourceMoments(source, radius) 644 645 Requires the following to have been created: 646 psSource 647 psSource->peak 648 psSource->pixels 649 650 XXX: mask values? 233 651 *****************************************************************************/ 234 652 psSource *pmSourceMoments(psSource *source, 235 const psImage *image,236 653 psF32 radius) 237 654 { 238 return(NULL); 239 } 240 241 /****************************************************************************** 242 pmSourceRoughClass(source, saturate, SNlim, valid): make a guessat the source 655 PS_PTR_CHECK_NULL(source, NULL); 656 PS_PTR_CHECK_NULL(source->peak, NULL); 657 PS_PTR_CHECK_NULL(source->pixels, NULL); 658 PS_FLOAT_COMPARE(0.0, radius, NULL); 659 660 // 661 // XXX: Verify the setting for sky if source->moments == NULL. 662 // 663 psF32 sky = 0.0; 664 if (source->moments == NULL) { 665 source->moments = pmMomentsAlloc(); 666 } else { 667 sky = source->moments->Sky; 668 } 669 670 // 671 // Sum = SUM (z - sky) 672 // X1 = SUM (x - xc)*(z - sky) 673 // X2 = SUM (x - xc)^2 * (z - sky) 674 // XY = SUM (x - xc)*(y - yc)*(z - sky) 675 // 676 psF32 Sum = 0.0; 677 psF32 peakPixel = -PS_MAX_F32; 678 psS32 numPixels = 0; 679 psF32 X1 = 0.0; 680 psF32 Y1 = 0.0; 681 psF32 X2 = 0.0; 682 psF32 Y2 = 0.0; 683 psF32 XY = 0.0; 684 // 685 // We loop through all pixels in this subimage (source->pixels), and for each 686 // pixel that is not masked, AND within the radius of the peak pixel, we 687 // proceed with the moments calculation. 688 // 689 for (psS32 row = 0; row < source->pixels->numRows ; row++) { 690 for (psS32 col = 0; col < source->pixels->numCols ; col++) { 691 if ((source->mask != NULL) && (source->mask->data.U8[row][col] != 0)) { 692 psS32 imgColCoord = col + source->pixels->col0; 693 psS32 imgRowCoord = row + source->pixels->row0; 694 if (CheckRadius(source->peak, 695 radius, 696 imgColCoord, 697 imgRowCoord)) { 698 psF32 xDiff = (psF32) (imgColCoord - source->peak->x); 699 psF32 yDiff = (psF32) (imgRowCoord - source->peak->y); 700 psF32 pDiff = source->pixels->data.F32[row][col] - sky; 701 702 Sum+= pDiff; 703 X1+= xDiff * pDiff; 704 Y1+= yDiff * pDiff; 705 X2+= PS_SQR(xDiff) * pDiff; 706 Y2+= PS_SQR(yDiff) * pDiff; 707 XY+= xDiff * yDiff * pDiff; 708 709 if (source->pixels->data.F32[row][col] > peakPixel) { 710 peakPixel = source->pixels->data.F32[row][col]; 711 } 712 numPixels++; 713 } 714 } 715 } 716 } 717 718 // 719 // first moment X = X1/Sum + xc 720 // second moment X = sqrt (X2/Sum - (X1/Sum)^2) 721 // Sxy = XY / Sum 722 // 723 source->moments->x = X1/Sum + ((psF32) source->peak->x); 724 source->moments->y = Y1/Sum + ((psF32) source->peak->y); 725 source->moments->Sx = sqrt(X2/Sum - PS_SQR(X1/Sum)); 726 source->moments->Sy = sqrt(Y2/Sum - PS_SQR(Y1/Sum)); 727 source->moments->Sxy = XY/Sum; 728 source->moments->Peak = peakPixel; 729 source->moments->nPixels = numPixels; 730 731 return(source); 732 } 733 734 /****************************************************************************** 735 pmSourceRoughClass(source, saturate, SNlim, valid): make a guess at the source 243 736 classification. 244 *****************************************************************************/737 245 738 psSource *pmSourceRoughClass(psSource *source, 246 739 psF32 saturate, 247 740 float SNlim, 248 741 const psRegion *valid) 249 { 250 return(NULL); 251 } 742 XXX: Waiting for sample code from IfA. 743 744 XXX: Most code this. 745 *****************************************************************************/ 746 #define SATURATE 0.0 747 #define FAINT_SN_LIM 0.0 748 #define PSF_SN_LIM 0.0 749 #define SATURATE 0.0 750 #define SATURATE 0.0 751 752 bool pmSourceRoughClass(psArray *source, 753 psMetadata *metadata) 754 { 755 PS_PTR_CHECK_NULL(source, false); 756 PS_PTR_CHECK_NULL(metadata, false); 757 psBool rc = true; 758 759 for (psS32 i = 0 ; i < source->n ; i++) { 760 psSource *tmpSrc = (psSource *) source->data[i]; 761 PS_PTR_CHECK_NULL(tmpSrc->moments, false); 762 763 if (tmpSrc->moments->Peak > SATURATE) { 764 tmpSrc->peak->class = PS_SOURCE_SATURATED; 765 } else { 766 // XXX: gleen these from the metadata: keywords GAIN and READ_NOISE. 767 psF32 gain = 0.0; 768 psF32 readNoise = 0.0; 769 psF32 S = tmpSrc->moments->Sum; 770 psF32 A = PS_PI * tmpSrc->moments->Sx * tmpSrc->moments->Sy; 771 psF32 B = tmpSrc->moments->Sky; 772 psF32 SN = (PS_SQRT_F32(gain) * S) / 773 PS_SQRT_F32(S + (A * B) + ((A * readNoise * readNoise) / PS_SQRT_F32(gain))); 774 if (SN < FAINT_SN_LIM) { 775 tmpSrc->peak->class = PS_SOURCE_FAINTSTAR; 776 } 777 if (SN < PSF_SN_LIM) { 778 tmpSrc->peak->class = PS_SOURCE_FAINTSTAR; 779 } 780 } 781 } 782 783 return(rc); 784 } 785 786 252 787 253 788 /****************************************************************************** 254 789 pmSourceSetPixelCircle(source, image, radius) 790 791 XXX: Why boolean output? 792 793 XXX: Why are we checking source->moments for NULL? Should the circle be 794 centered on the centroid or the peak? 795 796 XXX: The circle will have a diameter of (1+radius). This is different from 797 the pmSourceSetLocal() function. 255 798 *****************************************************************************/ 256 799 bool pmSourceSetPixelCircle(psSource *source, … … 258 801 psF32 radius) 259 802 { 803 PS_IMAGE_CHECK_NULL(image, false); 804 PS_IMAGE_CHECK_TYPE(image, PS_TYPE_F32, false); 805 PS_PTR_CHECK_NULL(source, false); 806 // PS_PTR_CHECK_NULL(source->moments, false); 807 PS_PTR_CHECK_NULL(source->peak, false); 808 PS_FLOAT_COMPARE(0.0, radius, false); 809 810 // 811 // We define variables for code readability. 812 // 813 psS32 radiusS32 = (psS32) radius; 814 psS32 SubImageCenterRow = source->peak->y; 815 psS32 SubImageCenterCol = source->peak->x; 816 psS32 SubImageStartRow = SubImageCenterRow - radiusS32; 817 psS32 SubImageEndRow = SubImageCenterRow + radiusS32; 818 psS32 SubImageStartCol = SubImageCenterCol - radiusS32; 819 psS32 SubImageEndCol = SubImageCenterCol + radiusS32; 820 821 if (SubImageStartRow < 0) { 822 psError(PS_ERR_UNKNOWN, true, "Sub image startRow is outside image boundaries (%d).\n", 823 SubImageStartRow); 824 return(false); 825 } 826 if (SubImageEndRow+1 >= image->numRows) { 827 psError(PS_ERR_UNKNOWN, true, "Sub image endRow is outside image boundaries (%d).\n", 828 SubImageEndRow); 829 return(false); 830 } 831 if (SubImageStartCol < 0) { 832 psError(PS_ERR_UNKNOWN, true, "Sub image startCol is outside image boundaries (%d).\n", 833 SubImageStartCol); 834 return(false); 835 } 836 if (SubImageEndCol+1 >= image->numCols) { 837 psError(PS_ERR_UNKNOWN, true, "Sub image endCol is outside image boundaries (%d).\n", 838 SubImageEndCol); 839 return(false); 840 } 841 842 // XXX: Must recycle image. 843 if (source->pixels != NULL) { 844 psLogMsg(__func__, PS_LOG_WARN, 845 "WARNING: pmSourceSetPixelCircle(): image->pixels not NULL. Freeing and reallocating.\n"); 846 psFree(source->pixels); 847 } 848 source->pixels = psImageSubset((psImage *) image, 849 SubImageStartCol, 850 SubImageStartRow, 851 SubImageEndCol+1, 852 SubImageEndRow+1); 853 854 // XXX: Must recycle image. 855 if (source->mask != NULL) { 856 psFree(source->mask); 857 } 858 source->mask = psImageAlloc(1 + 2 * radiusS32, 1 + 2 * radiusS32, PS_TYPE_F32); 859 860 // 861 // Loop through the subimage mask, initialize mask to 0 or 1. 862 // 863 for (psS32 row = 0 ; row < source->mask->numRows; row++) { 864 for (psS32 col = 0 ; col < source->mask->numCols; col++) { 865 866 if (CheckRadius2((psF32) radiusS32, 867 (psF32) radiusS32, 868 radius, 869 (psF32) col, 870 (psF32) row)) { 871 source->mask->data.U8[row][col] = 1; 872 } else { 873 source->mask->data.U8[row][col] = 1; 874 } 875 } 876 } 877 878 /* 879 for (psS32 row = SubImageCenterRow - radiusS32; row <= SubImageCenterRow + radiusS32; row++) { 880 for (psS32 col = SubImageCenterCol - radiusS32; col <= SubImageCenterCol + radiusS32; col++) { 881 if (CheckRadius(source->peak, radius, (psF32) col, (psF32) row)) { 882 source->mask->data.U8[row-SubImageCenterRow][col-SubImageCenterCol] = 1; 883 } 884 } 885 } 886 */ 887 260 888 return(true); 261 889 } … … 263 891 264 892 /****************************************************************************** 893 pmSourceModelGuess(source, image, model): This function allocates a new 894 psModel structure and store it in the psSource data structure specified in the 895 argument list. The model type is specified in the argument list. The params 896 array in that psModel structure are allocated, and then set to the appropriate 897 values. This function returns true if everything was successful. 898 899 XXX: Many of the initial parameters are set to 0.0 since I don't know what 900 the appropiate initial guesses are. 265 901 *****************************************************************************/ 266 902 bool pmSourceModelGuess(psSource *source, 267 const psImage *image) 268 { 269 return(true); 270 } 271 272 273 /****************************************************************************** 903 const psImage *image, 904 psModelType model) 905 { 906 PS_PTR_CHECK_NULL(source, false); 907 PS_PTR_CHECK_NULL(source->moments, false); 908 PS_PTR_CHECK_NULL(source->peak, false); 909 PS_IMAGE_CHECK_NULL(image, false); 910 PS_IMAGE_CHECK_TYPE(image, PS_TYPE_F32, false); 911 if (source->models != NULL) { 912 psLogMsg(__func__, PS_LOG_WARN, "WARNING: source->models was non-NULL; calling psFree(source->models).\n"); 913 psFree(source->models); 914 } 915 source->models = pmModelAlloc(PS_MODEL_UNDEFINED); 916 917 switch (model) { 918 case PS_MODEL_GAUSS: 919 source->models->type = PS_MODEL_GAUSS; 920 source->models->Nparams = 7; 921 source->models->params = (psF32 *) psAlloc(7 * sizeof(psF32)); 922 source->models->dparams = (psF32 *) psAlloc(7 * sizeof(psF32)); 923 for (psS32 i = 0 ; i < 7 ; i++) { 924 source->models->params[i] = 0.0; 925 source->models->dparams[i] = 0.0; 926 } 927 source->models->params[0] = source->moments->Sky; 928 source->models->params[1] = source->peak->counts - source->moments->Sky; 929 source->models->params[2] = source->moments->x; 930 source->models->params[3] = source->moments->y; 931 source->models->params[4] = sqrt(2.0) / source->moments->Sx; 932 source->models->params[5] = sqrt(2.0) / source->moments->Sy; 933 source->models->params[6] = source->moments->Sxy; 934 source->models->chisq = 0.0; 935 return(true); 936 case PS_MODEL_PGAUSS: 937 source->models->type = PS_MODEL_PGAUSS; 938 source->models->Nparams = 7; 939 source->models->params = (psF32 *) psAlloc(7 * sizeof(psF32)); 940 source->models->dparams = (psF32 *) psAlloc(7 * sizeof(psF32)); 941 for (psS32 i = 0 ; i < 7 ; i++) { 942 source->models->params[i] = 0.0; 943 source->models->dparams[i] = 0.0; 944 } 945 source->models->params[0] = source->moments->Sky; 946 source->models->params[1] = source->peak->counts - source->moments->Sky; 947 source->models->params[2] = source->moments->x; 948 source->models->params[3] = source->moments->y; 949 source->models->params[4] = sqrt(2.0) / source->moments->Sx; 950 source->models->params[5] = sqrt(2.0) / source->moments->Sy; 951 source->models->params[6] = source->moments->Sxy; 952 source->models->chisq = 0.0; 953 return(true); 954 case PS_MODEL_TWIST_GAUSS: 955 source->models->type = PS_MODEL_TWIST_GAUSS; 956 source->models->Nparams = 11; 957 source->models->params = (psF32 *) psAlloc(11 * sizeof(psF32)); 958 source->models->dparams = (psF32 *) psAlloc(11 * sizeof(psF32)); 959 for (psS32 i = 0 ; i < 11 ; i++) { 960 source->models->params[i] = 0.0; 961 source->models->dparams[i] = 0.0; 962 } 963 964 source->models->params[0] = source->moments->Sky; 965 source->models->params[1] = source->peak->counts - source->moments->Sky; 966 source->models->params[2] = source->moments->x; 967 source->models->params[3] = source->moments->y; 968 // XXX: What are these? 969 // source->models->params[4] = SxInner; 970 // source->models->params[5] = SyInner; 971 // source->models->params[6] = SxyInner; 972 // source->models->params[7] = SxOuter; 973 // source->models->params[8] = SyOuter; 974 // source->models->params[9] = SxyOuter; 975 // source->models->params[10] = N; 976 977 source->models->chisq = 0.0; 978 return(true); 979 case PS_MODEL_WAUSS: 980 981 source->models->params[0] = source->moments->Sky; 982 source->models->params[1] = source->peak->counts - source->moments->Sky; 983 source->models->params[2] = source->moments->x; 984 source->models->params[3] = source->moments->y; 985 source->models->params[4] = sqrt(2.0) / source->moments->Sx; 986 source->models->params[5] = sqrt(2.0) / source->moments->Sy; 987 source->models->params[6] = source->moments->Sxy; 988 // XXX: What are these? 989 // source->models->params[7] = B2; 990 // source->models->params[8] = B3; 991 992 source->models->type = PS_MODEL_WAUSS; 993 source->models->Nparams = 9; 994 source->models->params = (psF32 *) psAlloc(9 * sizeof(psF32)); 995 source->models->dparams = (psF32 *) psAlloc(9 * sizeof(psF32)); 996 for (psS32 i = 0 ; i < 9 ; i++) { 997 source->models->params[i] = 0.0; 998 source->models->dparams[i] = 0.0; 999 } 1000 source->models->chisq = 0.0; 1001 return(true); 1002 case PS_MODEL_SERSIC: 1003 source->models->type = PS_MODEL_SERSIC; 1004 source->models->Nparams = 8; 1005 source->models->params = (psF32 *) psAlloc(8 * sizeof(psF32)); 1006 source->models->dparams = (psF32 *) psAlloc(8 * sizeof(psF32)); 1007 for (psS32 i = 0 ; i < 8 ; i++) { 1008 source->models->params[i] = 0.0; 1009 source->models->dparams[i] = 0.0; 1010 } 1011 1012 source->models->params[0] = source->moments->Sky; 1013 source->models->params[1] = source->peak->counts - source->moments->Sky; 1014 source->models->params[2] = source->moments->x; 1015 source->models->params[3] = source->moments->y; 1016 source->models->params[4] = sqrt(2.0) / source->moments->Sx; 1017 source->models->params[5] = sqrt(2.0) / source->moments->Sy; 1018 source->models->params[6] = source->moments->Sxy; 1019 // XXX: What are these? 1020 //source->models->params[7] = Nexp; 1021 1022 source->models->chisq = 0.0; 1023 return(true); 1024 case PS_MODEL_SERSIC_CORE: 1025 source->models->type = PS_MODEL_SERSIC_CORE; 1026 source->models->Nparams = 12; 1027 source->models->params = (psF32 *) psAlloc(12 * sizeof(psF32)); 1028 source->models->dparams = (psF32 *) psAlloc(12 * sizeof(psF32)); 1029 for (psS32 i = 0 ; i < 12 ; i++) { 1030 source->models->params[i] = 0.0; 1031 source->models->dparams[i] = 0.0; 1032 } 1033 1034 source->models->params[0] = source->moments->Sky; 1035 source->models->params[1] = source->peak->counts - source->moments->Sky; 1036 source->models->params[2] = source->moments->x; 1037 source->models->params[3] = source->moments->y; 1038 // XXX: What are these? 1039 //source->models->params[4] SxInner; 1040 //source->models->params[5] SyInner; 1041 //source->models->params[6] SxyInner; 1042 //source->models->params[7] Zd; 1043 //source->models->params[8] SxOuter; 1044 //source->models->params[9] SyOuter; 1045 //source->models->params[10] = SxyOuter; 1046 //source->models->params[11] = Nexp; 1047 1048 source->models->chisq = 0.0; 1049 return(true); 1050 default: 1051 psError(PS_ERR_UNKNOWN, true, "Undefined psModelType"); 1052 return(false); 1053 } 1054 } 1055 1056 1057 /****************************************************************************** 1058 274 1059 *****************************************************************************/ 275 1060 psArray *pmSourceContour(psSource *source, … … 281 1066 } 282 1067 283 /****************************************************************************** 1068 psVector *p_pmMinLM_Gauss2D_Vec(psImage *deriv, psVector *params, psArray *x); 1069 psVector *p_pmMinLM_PsuedoGauss2D_Vec(psImage *deriv, psVector *params, psArray *x); 1070 psVector *p_pmMinLM_Wauss2D_Vec(psImage *deriv, psVector *params, psArray *x); 1071 psVector *p_pmMinLM_TwistGauss2D_Vec(psImage *deriv, psVector *params, psArray *x); 1072 psVector *p_pmMinLM_Sersic_Vec(psImage *deriv, psVector *params, psArray *x); 1073 psVector *p_pmMinLM_SersicCore_Vec(psImage *deriv, psVector *params, psArray *x); 1074 1075 //XXX: What should these values be? 1076 #define PM_SOURCE_FIT_MODEL_NUM_ITERATIONS 100 1077 #define PM_SOURCE_FIT_MODEL_TOLERANCE 1.0 1078 /****************************************************************************** 1079 pmSourceFitModel(source, image): must create the appropiate arguments to the 1080 LM minimization routines for the various p_pmMinLM_XXXXXX_Vec() functions. 1081 1082 XXX: should there be a mask value? 284 1083 *****************************************************************************/ 285 1084 bool pmSourceFitModel(psSource *source, 286 1085 const psImage *image) 287 1086 { 1087 PS_PTR_CHECK_NULL(source, false); 1088 PS_PTR_CHECK_NULL(source->moments, false); 1089 PS_PTR_CHECK_NULL(source->peak, false); 1090 PS_PTR_CHECK_NULL(source->pixels, false); 1091 PS_PTR_CHECK_NULL(source->models, false); 1092 PS_IMAGE_CHECK_NULL(image, false); 1093 PS_IMAGE_CHECK_TYPE(image, PS_TYPE_F32, false); 1094 1095 psBool rc; 1096 psS32 count = 0; 1097 for (psS32 i = 0 ; i < source->pixels->numRows ; i++) { 1098 for (psS32 j = 0 ; j < source->pixels->numCols ; j++) { 1099 if (source->mask->data.U8[i][j] == 0) { 1100 count++; 1101 } 1102 } 1103 } 1104 psArray *x = psArrayAlloc(count); 1105 psVector *y = psVectorAlloc(count, PS_TYPE_F32); 1106 for (psS32 i = 0 ; i < source->pixels->numRows ; i++) { 1107 for (psS32 j = 0 ; j < source->pixels->numCols ; j++) { 1108 if (source->mask->data.U8[i][j] == 0) { 1109 psVector *coord = psVectorAlloc(2, PS_TYPE_F32); 1110 // XXX: Should we use the subimage offsets here, or does it not matter? 1111 coord->data.F32[0] = (psF32) (i); 1112 coord->data.F32[1] = (psF32) (j); 1113 x->data[count] = (psPtr *) coord; 1114 y->data.F32[count] = source->pixels->data.F32[i][j]; 1115 } 1116 } 1117 } 1118 1119 psMinimization *myMin = psMinimizationAlloc(PM_SOURCE_FIT_MODEL_NUM_ITERATIONS, 1120 PM_SOURCE_FIT_MODEL_TOLERANCE); 1121 1122 psVector *params = psVectorAlloc(source->models->Nparams, PS_TYPE_F32); 1123 1124 switch (source->models->type) { 1125 case PS_MODEL_GAUSS: 1126 rc = psMinimizeLMChi2(myMin, NULL, params, NULL, x, y, 1127 NULL, (psMinimizeLMChi2Func) p_pmMinLM_Gauss2D_Vec); 1128 break; 1129 case PS_MODEL_PGAUSS: 1130 rc = psMinimizeLMChi2(myMin, NULL, params, NULL, x, y, 1131 NULL, (psMinimizeLMChi2Func) p_pmMinLM_PsuedoGauss2D_Vec); 1132 break; 1133 case PS_MODEL_TWIST_GAUSS: 1134 rc = psMinimizeLMChi2(myMin, NULL, params, NULL, x, y, 1135 NULL, (psMinimizeLMChi2Func) p_pmMinLM_Wauss2D_Vec); 1136 break; 1137 case PS_MODEL_WAUSS: 1138 rc = psMinimizeLMChi2(myMin, NULL, params, NULL, x, y, 1139 NULL, (psMinimizeLMChi2Func) p_pmMinLM_TwistGauss2D_Vec); 1140 break; 1141 case PS_MODEL_SERSIC: 1142 rc = psMinimizeLMChi2(myMin, NULL, params, NULL, x, y, 1143 NULL, (psMinimizeLMChi2Func) p_pmMinLM_Sersic_Vec); 1144 break; 1145 case PS_MODEL_SERSIC_CORE: 1146 rc = psMinimizeLMChi2(myMin, NULL, params, NULL, x, y, 1147 NULL, (psMinimizeLMChi2Func) p_pmMinLM_SersicCore_Vec); 1148 break; 1149 default: 1150 psError(PS_ERR_UNKNOWN, true, "Undefined psModelType"); 1151 rc = false; 1152 } 1153 1154 psFree(x); 1155 psFree(y); 1156 psFree(myMin); 1157 psFree(params); 1158 return(rc); 1159 } 1160 1161 bool p_pmSourceAddOrSubModel(psImage *image, 1162 psSource *source, 1163 bool center, 1164 psS32 flag) 1165 { 1166 PS_PTR_CHECK_NULL(source, false); 1167 PS_PTR_CHECK_NULL(source->moments, false); 1168 PS_PTR_CHECK_NULL(source->peak, false); 1169 PS_PTR_CHECK_NULL(source->pixels, false); 1170 PS_PTR_CHECK_NULL(source->models, false); 1171 PS_IMAGE_CHECK_NULL(image, false); 1172 PS_IMAGE_CHECK_TYPE(image, PS_TYPE_F32, false); 1173 1174 // XXX: make static, document. 1175 psVector *deriv = psVectorAlloc(100, PS_TYPE_F32); 1176 psVector *params = psVectorAlloc(100, PS_TYPE_F32); 1177 psVector *x = psVectorAlloc(2, PS_TYPE_F32); 1178 for (psS32 i = 0 ; i < source->models->Nparams ; i++) { 1179 params->data.F32[i] = source->models->params[i]; 1180 } 1181 1182 for (psS32 i = 0 ; i < source->pixels->numRows ; i++) { 1183 for (psS32 j = 0 ; j < source->pixels->numCols ; j++) { 1184 psF32 pixelValue; 1185 // XXX: Should you use offsets here? 1186 // XXX: Make sure you have col/row order correct. 1187 x->data.F32[0] = (float) j; 1188 x->data.F32[1] = (float) i; 1189 switch (source->models->type) { 1190 case PS_MODEL_GAUSS: 1191 pixelValue = pmMinLM_Gauss2D(deriv, params, x); 1192 break; 1193 case PS_MODEL_PGAUSS: 1194 pixelValue = pmMinLM_PsuedoGauss2D(deriv, params, x); 1195 break; 1196 case PS_MODEL_TWIST_GAUSS: 1197 pixelValue = pmMinLM_TwistGauss2D(deriv, params, x); 1198 break; 1199 case PS_MODEL_WAUSS: 1200 pixelValue = pmMinLM_Wauss2D(deriv, params, x); 1201 break; 1202 case PS_MODEL_SERSIC: 1203 pixelValue = pmMinLM_Sersic(deriv, params, x); 1204 break; 1205 case PS_MODEL_SERSIC_CORE: 1206 pixelValue = pmMinLM_SersicCore(deriv, params, x); 1207 break; 1208 default: 1209 psError(PS_ERR_UNKNOWN, true, "Undefined psModelType"); 1210 psFree(x); 1211 psFree(deriv); 1212 psFree(params); 1213 return(false); 1214 } 1215 if (flag == 1) { 1216 pixelValue = -pixelValue; 1217 } 1218 1219 // XXX: Must figure out how to calculate the image coordinates and 1220 // how to use the boolean "center" flag. 1221 psS32 imageRow = 0; 1222 psS32 imageCol = 0; 1223 image->data.F32[imageRow][imageCol]+= pixelValue; 1224 } 1225 } 1226 psFree(x); 1227 psFree(deriv); 1228 psFree(params); 288 1229 return(true); 289 1230 } 1231 1232 290 1233 291 1234 /****************************************************************************** … … 295 1238 bool center) 296 1239 { 297 return(true); 298 } 299 300 /****************************************************************************** 301 *****************************************************************************/ 302 bool pmSourceSubModel(psSource *source) 303 { 304 return(true); 305 } 306 307 /****************************************************************************** 308 XXX: Why only *x argument? 309 310 May x[0] is x and x[1] is y? 1240 return(p_pmSourceAddOrSubModel(image, source, center, 0)); 1241 } 1242 1243 /****************************************************************************** 1244 *****************************************************************************/ 1245 bool pmSourceSubModel(psImage *image, 1246 psSource *source, 1247 bool center) 1248 { 1249 return(p_pmSourceAddOrSubModel(image, source, center, 1)); 1250 } 1251 1252 1253 // XXX: Put this is psConstants.h 1254 #define PS_VECTOR_CHECK_SIZE(VEC1, N, RVAL) \ 1255 if (VEC1->n != N) { \ 1256 psError(PS_ERR_BAD_PARAMETER_SIZE, true, \ 1257 "psVector %s has size %d, should be %d.", \ 1258 #VEC1, VEC1->n, N); \ 1259 return(RVAL); \ 1260 } 1261 1262 1263 /****************************************************************************** 1264 pmMinLM_Gauss2D(*deriv, *params, *x): the argument "x" contains a single "x, 1265 y" coordinate pair. This function computes the gaussian, specified by the 1266 parameters in "params" at that x,y point and returns the value. The 1267 derivatives are also caculated and returned in the "deriv" argument. 311 1268 312 1269 params->data.F32[0] = So; … … 317 1274 params->data.F32[5] = sqrt(2.0) / SigmaY; 318 1275 params->data.F32[6] = Sxy; 1276 1277 XXX: Consider getting rid of the parameter checks since this might consume 1278 a significant fraction of this function CPU time. 319 1279 *****************************************************************************/ 320 1280 psF32 pmMinLM_Gauss2D(psVector *deriv, … … 322 1282 psVector *x) 323 1283 { 1284 PS_VECTOR_CHECK_NULL(deriv, NAN); 1285 PS_VECTOR_CHECK_TYPE(deriv, PS_TYPE_F32, NAN); 1286 PS_VECTOR_CHECK_SIZE(deriv, 7, NAN); 1287 PS_VECTOR_CHECK_NULL(params, NAN); 1288 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NAN); 1289 PS_VECTOR_CHECK_SIZE(params, 7, NAN); 1290 PS_VECTOR_CHECK_NULL(x, NAN); 1291 PS_VECTOR_CHECK_TYPE(x, PS_TYPE_F32, NAN); 1292 PS_VECTOR_CHECK_SIZE(x, 2, NAN); 1293 324 1294 psF32 X = x->data.F32[0] - params->data.F32[2]; 325 1295 psF32 Y = x->data.F32[1] - params->data.F32[3]; … … 343 1313 344 1314 /****************************************************************************** 1315 p_pmMinLM_Gauss2D_Vec(*deriv, *params, *x): this function wraps the above 1316 function in a form that is usable in the LM minimization routines. 1317 *****************************************************************************/ 1318 psVector *p_pmMinLM_Gauss2D_Vec(psImage *deriv, 1319 psVector *params, 1320 psArray *x) 1321 { 1322 PS_IMAGE_CHECK_NULL(deriv, NULL); 1323 PS_IMAGE_CHECK_EMPTY(deriv, NULL); 1324 PS_IMAGE_CHECK_TYPE(deriv, PS_TYPE_F32, NULL); 1325 PS_VECTOR_CHECK_NULL(params, NULL); 1326 PS_VECTOR_CHECK_EMPTY(params, NULL); 1327 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NULL); 1328 PS_PTR_CHECK_NULL(x, NULL); 1329 if (deriv->numRows != x->n) { 1330 psError(PS_ERR_UNKNOWN, true, "deriv must have one row for each coordinate set in x."); 1331 } 1332 psVector *tmpVec = psVectorAlloc(x->n, PS_TYPE_F32); 1333 // XXX: use static memory here. 1334 psVector *tmpRow = psVectorAlloc(deriv->numCols, PS_TYPE_F32); 1335 1336 for (psS32 i = 0 ; i < x->n ; i++) { 1337 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1338 tmpRow->data.F32[j] = deriv->data.F32[i][j]; 1339 } 1340 1341 tmpVec->data.F32[i] = pmMinLM_Gauss2D(tmpRow, 1342 params, 1343 (psVector *) x->data[i]); 1344 1345 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1346 deriv->data.F32[i][j] = tmpRow->data.F32[j]; 1347 } 1348 } 1349 1350 psFree(tmpRow); 1351 return(tmpVec); 1352 } 1353 1354 1355 /****************************************************************************** 345 1356 params->data.F32[0] = So; 346 1357 params->data.F32[1] = Zo; … … 355 1366 psVector *x) 356 1367 { 1368 PS_VECTOR_CHECK_NULL(deriv, NAN); 1369 PS_VECTOR_CHECK_TYPE(deriv, PS_TYPE_F32, NAN); 1370 PS_VECTOR_CHECK_SIZE(deriv, 7, NAN); 1371 PS_VECTOR_CHECK_NULL(params, NAN); 1372 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NAN); 1373 PS_VECTOR_CHECK_SIZE(params, 7, NAN); 1374 PS_VECTOR_CHECK_NULL(x, NAN); 1375 PS_VECTOR_CHECK_TYPE(x, PS_TYPE_F32, NAN); 1376 PS_VECTOR_CHECK_SIZE(x, 2, NAN); 1377 357 1378 psF32 X = x->data.F32[0] - params->data.F32[2]; 358 1379 psF32 Y = x->data.F32[1] - params->data.F32[3]; … … 382 1403 383 1404 /****************************************************************************** 1405 p_pmMinLM_PsuedoGauss2D_Vec(*deriv, *params, *x): this function wraps the 1406 above function in a form that is usable in the LM minimization routines. 1407 *****************************************************************************/ 1408 psVector *p_pmMinLM_PsuedoGauss2D_Vec(psImage *deriv, 1409 psVector *params, 1410 psArray *x) 1411 { 1412 PS_IMAGE_CHECK_NULL(deriv, NULL); 1413 PS_IMAGE_CHECK_EMPTY(deriv, NULL); 1414 PS_IMAGE_CHECK_TYPE(deriv, PS_TYPE_F32, NULL); 1415 PS_VECTOR_CHECK_NULL(params, NULL); 1416 PS_VECTOR_CHECK_EMPTY(params, NULL); 1417 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NULL); 1418 PS_PTR_CHECK_NULL(x, NULL); 1419 if (deriv->numRows != x->n) { 1420 psError(PS_ERR_UNKNOWN, true, "deriv must have one row for each coordinate set in x."); 1421 } 1422 psVector *tmpVec = psVectorAlloc(x->n, PS_TYPE_F32); 1423 // XXX: use static memory here. 1424 psVector *tmpRow = psVectorAlloc(deriv->numCols, PS_TYPE_F32); 1425 1426 for (psS32 i = 0 ; i < x->n ; i++) { 1427 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1428 tmpRow->data.F32[j] = deriv->data.F32[i][j]; 1429 } 1430 1431 tmpVec->data.F32[i] = pmMinLM_PsuedoGauss2D(tmpRow, 1432 params, 1433 (psVector *) x->data[i]); 1434 1435 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1436 deriv->data.F32[i][j] = tmpRow->data.F32[j]; 1437 } 1438 } 1439 1440 psFree(tmpRow); 1441 return(tmpVec); 1442 } 1443 1444 1445 1446 1447 /****************************************************************************** 384 1448 params->data.F32[0] = So; 385 1449 params->data.F32[1] = Zo; … … 396 1460 psVector *x) 397 1461 { 1462 PS_VECTOR_CHECK_NULL(deriv, NAN); 1463 PS_VECTOR_CHECK_TYPE(deriv, PS_TYPE_F32, NAN); 1464 PS_VECTOR_CHECK_SIZE(deriv, 9, NAN); 1465 PS_VECTOR_CHECK_NULL(params, NAN); 1466 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NAN); 1467 PS_VECTOR_CHECK_SIZE(params, 9, NAN); 1468 PS_VECTOR_CHECK_NULL(x, NAN); 1469 PS_VECTOR_CHECK_TYPE(x, PS_TYPE_F32, NAN); 1470 PS_VECTOR_CHECK_SIZE(x, 2, NAN); 1471 398 1472 psF32 X = x->data.F32[0] - params->data.F32[2]; 399 1473 psF32 Y = x->data.F32[1] - params->data.F32[2]; … … 424 1498 return(f); 425 1499 } 1500 1501 /****************************************************************************** 1502 p_pmMinLM_Wauss2D_Vec(*deriv, *params, *x): this function wraps the above 1503 function in a form that is usable in the LM minimization routines. 1504 *****************************************************************************/ 1505 psVector *p_pmMinLM_Wauss2D_Vec(psImage *deriv, 1506 psVector *params, 1507 psArray *x) 1508 { 1509 PS_IMAGE_CHECK_NULL(deriv, NULL); 1510 PS_IMAGE_CHECK_EMPTY(deriv, NULL); 1511 PS_IMAGE_CHECK_TYPE(deriv, PS_TYPE_F32, NULL); 1512 PS_VECTOR_CHECK_NULL(params, NULL); 1513 PS_VECTOR_CHECK_EMPTY(params, NULL); 1514 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NULL); 1515 PS_PTR_CHECK_NULL(x, NULL); 1516 if (deriv->numRows != x->n) { 1517 psError(PS_ERR_UNKNOWN, true, "deriv must have one row for each coordinate set in x."); 1518 } 1519 psVector *tmpVec = psVectorAlloc(x->n, PS_TYPE_F32); 1520 // XXX: use static memory here. 1521 psVector *tmpRow = psVectorAlloc(deriv->numCols, PS_TYPE_F32); 1522 1523 for (psS32 i = 0 ; i < x->n ; i++) { 1524 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1525 tmpRow->data.F32[j] = deriv->data.F32[i][j]; 1526 } 1527 1528 tmpVec->data.F32[i] = pmMinLM_Wauss2D(tmpRow, 1529 params, 1530 (psVector *) x->data[i]); 1531 1532 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1533 deriv->data.F32[i][j] = tmpRow->data.F32[j]; 1534 } 1535 } 1536 1537 psFree(tmpRow); 1538 return(tmpVec); 1539 } 1540 1541 1542 1543 1544 426 1545 427 1546 // XXX: What should these be? … … 445 1564 psVector *x) 446 1565 { 1566 PS_VECTOR_CHECK_NULL(deriv, NAN); 1567 PS_VECTOR_CHECK_TYPE(deriv, PS_TYPE_F32, NAN); 1568 PS_VECTOR_CHECK_SIZE(deriv, 11, NAN); 1569 PS_VECTOR_CHECK_NULL(params, NAN); 1570 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NAN); 1571 PS_VECTOR_CHECK_SIZE(params, 11, NAN); 1572 PS_VECTOR_CHECK_NULL(x, NAN); 1573 PS_VECTOR_CHECK_TYPE(x, PS_TYPE_F32, NAN); 1574 PS_VECTOR_CHECK_SIZE(x, 2, NAN); 1575 447 1576 psF32 X = x->data.F32[0] - params->data.F32[2]; 448 1577 psF32 Y = x->data.F32[1] - params->data.F32[3]; … … 489 1618 490 1619 /****************************************************************************** 1620 p_pmMinLM_TwistGauss2D_Vec(*deriv, *params, *x): this function wraps the above 1621 function in a form that is usable in the LM minimization routines. 1622 *****************************************************************************/ 1623 psVector *p_pmMinLM_TwistGauss2D_Vec(psImage *deriv, 1624 psVector *params, 1625 psArray *x) 1626 { 1627 PS_IMAGE_CHECK_NULL(deriv, NULL); 1628 PS_IMAGE_CHECK_EMPTY(deriv, NULL); 1629 PS_IMAGE_CHECK_TYPE(deriv, PS_TYPE_F32, NULL); 1630 PS_VECTOR_CHECK_NULL(params, NULL); 1631 PS_VECTOR_CHECK_EMPTY(params, NULL); 1632 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NULL); 1633 PS_PTR_CHECK_NULL(x, NULL); 1634 if (deriv->numRows != x->n) { 1635 psError(PS_ERR_UNKNOWN, true, "deriv must have one row for each coordinate set in x."); 1636 } 1637 psVector *tmpVec = psVectorAlloc(x->n, PS_TYPE_F32); 1638 // XXX: use static memory here. 1639 psVector *tmpRow = psVectorAlloc(deriv->numCols, PS_TYPE_F32); 1640 1641 for (psS32 i = 0 ; i < x->n ; i++) { 1642 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1643 tmpRow->data.F32[j] = deriv->data.F32[i][j]; 1644 } 1645 1646 tmpVec->data.F32[i] = pmMinLM_TwistGauss2D(tmpRow, 1647 params, 1648 (psVector *) x->data[i]); 1649 1650 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1651 deriv->data.F32[i][j] = tmpRow->data.F32[j]; 1652 } 1653 } 1654 1655 psFree(tmpRow); 1656 return(tmpVec); 1657 } 1658 1659 1660 1661 /****************************************************************************** 491 1662 float Sersic() 492 1663 params->data.F32[0] = So; … … 503 1674 psVector *x) 504 1675 { 1676 PS_VECTOR_CHECK_NULL(deriv, NAN); 1677 PS_VECTOR_CHECK_TYPE(deriv, PS_TYPE_F32, NAN); 1678 PS_VECTOR_CHECK_SIZE(deriv, 8, NAN); 1679 PS_VECTOR_CHECK_NULL(params, NAN); 1680 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NAN); 1681 PS_VECTOR_CHECK_SIZE(params, 8, NAN); 1682 PS_VECTOR_CHECK_NULL(x, NAN); 1683 PS_VECTOR_CHECK_TYPE(x, PS_TYPE_F32, NAN); 1684 PS_VECTOR_CHECK_SIZE(x, 2, NAN); 1685 1686 psError(PS_ERR_UNKNOWN, true, "This function is not implemented yet."); 505 1687 return(0.0); 1688 } 1689 /****************************************************************************** 1690 p_pmMinLM_Sersic_Vec(*deriv, *params, *x): this function wraps the above 1691 function in a form that is usable in the LM minimization routines. 1692 *****************************************************************************/ 1693 psVector *p_pmMinLM_Sersic_Vec(psImage *deriv, 1694 psVector *params, 1695 psArray *x) 1696 { 1697 PS_IMAGE_CHECK_NULL(deriv, NULL); 1698 PS_IMAGE_CHECK_EMPTY(deriv, NULL); 1699 PS_IMAGE_CHECK_TYPE(deriv, PS_TYPE_F32, NULL); 1700 PS_VECTOR_CHECK_NULL(params, NULL); 1701 PS_VECTOR_CHECK_EMPTY(params, NULL); 1702 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NULL); 1703 PS_PTR_CHECK_NULL(x, NULL); 1704 if (deriv->numRows != x->n) { 1705 psError(PS_ERR_UNKNOWN, true, "deriv must have one row for each coordinate set in x."); 1706 } 1707 psVector *tmpVec = psVectorAlloc(x->n, PS_TYPE_F32); 1708 // XXX: use static memory here. 1709 psVector *tmpRow = psVectorAlloc(deriv->numCols, PS_TYPE_F32); 1710 1711 for (psS32 i = 0 ; i < x->n ; i++) { 1712 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1713 tmpRow->data.F32[j] = deriv->data.F32[i][j]; 1714 } 1715 1716 tmpVec->data.F32[i] = pmMinLM_Sersic(tmpRow, 1717 params, 1718 (psVector *) x->data[i]); 1719 1720 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1721 deriv->data.F32[i][j] = tmpRow->data.F32[j]; 1722 } 1723 } 1724 1725 psFree(tmpRow); 1726 return(tmpVec); 506 1727 } 507 1728 … … 525 1746 psVector *x) 526 1747 { 1748 PS_VECTOR_CHECK_NULL(deriv, NAN); 1749 PS_VECTOR_CHECK_TYPE(deriv, PS_TYPE_F32, NAN); 1750 PS_VECTOR_CHECK_SIZE(deriv, 12, NAN); 1751 PS_VECTOR_CHECK_NULL(params, NAN); 1752 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NAN); 1753 PS_VECTOR_CHECK_SIZE(params, 12, NAN); 1754 PS_VECTOR_CHECK_NULL(x, NAN); 1755 PS_VECTOR_CHECK_TYPE(x, PS_TYPE_F32, NAN); 1756 PS_VECTOR_CHECK_SIZE(x, 2, NAN); 1757 1758 psError(PS_ERR_UNKNOWN, true, "This function is not implemented yet."); 527 1759 return(0.0); 528 1760 } 1761 /****************************************************************************** 1762 p_pmMinLM_SersicCore_Vec(*deriv, *params, *x): this function wraps the above 1763 function in a form that is usable in the LM minimization routines. 1764 *****************************************************************************/ 1765 psVector *p_pmMinLM_SersicCore_Vec(psImage *deriv, 1766 psVector *params, 1767 psArray *x) 1768 { 1769 PS_IMAGE_CHECK_NULL(deriv, NULL); 1770 PS_IMAGE_CHECK_EMPTY(deriv, NULL); 1771 PS_IMAGE_CHECK_TYPE(deriv, PS_TYPE_F32, NULL); 1772 PS_VECTOR_CHECK_NULL(params, NULL); 1773 PS_VECTOR_CHECK_EMPTY(params, NULL); 1774 PS_VECTOR_CHECK_TYPE(params, PS_TYPE_F32, NULL); 1775 PS_PTR_CHECK_NULL(x, NULL); 1776 if (deriv->numRows != x->n) { 1777 psError(PS_ERR_UNKNOWN, true, "deriv must have one row for each coordinate set in x."); 1778 } 1779 psVector *tmpVec = psVectorAlloc(x->n, PS_TYPE_F32); 1780 // XXX: use static memory here. 1781 psVector *tmpRow = psVectorAlloc(deriv->numCols, PS_TYPE_F32); 1782 1783 for (psS32 i = 0 ; i < x->n ; i++) { 1784 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1785 tmpRow->data.F32[j] = deriv->data.F32[i][j]; 1786 } 1787 1788 tmpVec->data.F32[i] = pmMinLM_SersicCore(tmpRow, 1789 params, 1790 (psVector *) x->data[i]); 1791 1792 for (psS32 j = 0 ; j < tmpRow->n ; j++) { 1793 deriv->data.F32[i][j] = tmpRow->data.F32[j]; 1794 } 1795 } 1796 1797 psFree(tmpRow); 1798 return(tmpVec); 1799 } 1800 1801 529 1802 530 1803 /****************************************************************************** -
trunk/psModules/src/pmObjects.h
r3089 r3498 5 5 * @author GLG, MHPCC 6 6 * 7 * @version $Revision: 1. 2$ $Name: not supported by cvs2svn $8 * @date $Date: 2005-0 1-25 02:45:43$7 * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2005-03-24 22:36:52 $ 9 9 * 10 10 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 28 28 PM_PEAK_LONE, // Isolated peak. 29 29 PM_PEAK_EDGE, // Peak on edge. 30 PM_PEAK_FLAT // Peak has equal-value neighbors. 30 PM_PEAK_FLAT, // Peak has equal-value neighbors. 31 PM_PEAK_UNDEF // Undefined. 31 32 } psPeakType; 32 33 … … 60 61 PS_MODEL_WAUSS, 61 62 PS_MODEL_SERSIC, 62 PS_MODEL_SERSIC_CORE 63 PS_MODEL_SERSIC_CORE, 64 PS_MODEL_UNDEFINED 63 65 } psModelType; 64 66 … … 75 77 // XXX: What is this enum? 76 78 typedef enum { 77 PS_SOURCE_TYPE_1, 78 PS_SOURCE_TYPE_2, 79 PS_SOURCE_TYPE_3, 80 PS_SOURCE_TYPE_4, 81 PS_SOURCE_TYPE_5, 82 PS_SOURCE_TYPE_6 79 PS_SOURCE_PSFSTAR, 80 PS_SOURCE_GALAXY, 81 PS_SOURCE_DEFECT, 82 PS_SOURCE_SATURATED, 83 PS_SOURCE_SATSTAR, 84 PS_SOURCE_FAINTSTAR, 85 PS_SOURCE_BRIGHTSTAR, 86 PS_SOURCE_OTHER 83 87 } psSourceType; 84 88 … … 94 98 psSource; 95 99 100 psPeak *pmPeakAlloc(psS32 x, 101 psS32 y, 102 psF32 counts, 103 psPeakType class); 104 psMoments *pmMomentsAlloc(); 105 psModel *pmModelAlloc(psModelType type); 106 psSource *pmSourceAlloc(); 96 107 97 108 /****************************************************************************** … … 131 142 psSource *pmSourceLocalSky(const psImage *image, 132 143 const psPeak *peak, 144 psStatsOptions statsOptions, 133 145 psF32 innerRadius, 134 146 psF32 outerRadius); … … 137 149 *****************************************************************************/ 138 150 psSource *pmSourceMoments(psSource *source, 139 const psImage *image,140 151 psF32 radius); 141 152 142 153 /****************************************************************************** 143 pmSourceRoughClass(source, saturate, SNlim, valid): make a guessat the source 144 classification. 145 *****************************************************************************/ 146 psSource *pmSourceRoughClass(psSource *source, 147 psF32 saturate, 148 float SNlim, 149 const psRegion *valid); 150 151 154 pmSourceRoughClass(pmArray *source, psMetaDeta *metadata): make a guess at the 155 source classification. 156 *****************************************************************************/ 157 bool pmSourceRoughClass(psArray *source, 158 psMetadata *metadata); 152 159 /****************************************************************************** 153 160 pmSourceSetPixelCircle(source, image, radius) … … 161 168 *****************************************************************************/ 162 169 bool pmSourceModelGuess(psSource *source, 163 const psImage *image); 170 const psImage *image, 171 psModelType model); 164 172 165 173 /****************************************************************************** … … 183 191 /****************************************************************************** 184 192 *****************************************************************************/ 185 bool pmSourceSubModel(psSource *source); 193 bool pmSourceSubModel(psImage *image, 194 psSource *source, 195 bool center); 186 196 187 197 /******************************************************************************
Note:
See TracChangeset
for help on using the changeset viewer.
