Changeset 14801 for trunk/psModules/src/imcombine/pmSubtractionStamps.c
- Timestamp:
- Sep 10, 2007, 10:10:05 AM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/imcombine/pmSubtractionStamps.c
r14701 r14801 9 9 #include "pmSubtractionStamps.h" 10 10 11 #define STAMP_LIST_BUFFER 20 // Number of stamps to add to list at a time 12 11 13 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 14 // Private (file-static) functions 13 15 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 16 17 // Free function for pmSubtractionStampList 18 static void subtractionStampListFree(pmSubtractionStampList *list // Stamp list to free 19 ) 20 { 21 psFree(list->stamps); 22 psFree(list->regions); 23 psFree(list->x); 24 psFree(list->y); 25 psFree(list->flux); 26 } 27 15 28 // Free function for pmSubtractionStamp 16 void subtractionStampFree(pmSubtractionStamp *stamp // Stamp to free17 )29 static void subtractionStampFree(pmSubtractionStamp *stamp // Stamp to free 30 ) 18 31 { 19 32 psFree(stamp->matrix); … … 28 41 static bool checkStampRegion(int x, int y, // Coordinates of stamp 29 42 const psRegion *region // Region of interest 30 )43 ) 31 44 { 32 45 if (!region) { … … 40 53 static bool checkStampMask(int x, int y, // Coordinates of stamp 41 54 const psImage *mask 42 )55 ) 43 56 { 44 57 if (!mask) { … … 54 67 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 55 68 56 pmSubtractionStamp *pmSubtractionStampAlloc(pmSubtractionStampStatus status) 69 pmSubtractionStampList *pmSubtractionStampListAlloc(int numCols, int numRows, const psRegion *region, 70 float spacing) 71 { 72 pmSubtractionStampList *list = psAlloc(sizeof(pmSubtractionStampList)); // Stamp list to return 73 psMemSetDeallocator(list, (psFreeFunc)subtractionStampListFree); 74 75 // Get region in which to find stamps: [xMin:xMax,yMin:yMax] 76 int xMin = 0, xMax = numCols, yMin = 0, yMax = numRows; 77 if (region) { 78 xMin = PS_MAX(region->x0, xMin); 79 xMax = PS_MIN(region->x1, xMax); 80 yMin = PS_MAX(region->y0, yMin); 81 yMax = PS_MIN(region->y1, yMax); 82 } 83 int xSize = xMax - xMin, ySize = yMax - yMin; // Size of region of interest 84 int xStamps = xSize / spacing + 1, yStamps = ySize / spacing + 1; // Number of stamps in x and y 85 86 list->num = xStamps * yStamps; 87 list->stamps = psArrayAlloc(list->num); 88 list->regions = psArrayAlloc(list->num); 89 90 for (int y = 0, index = 0; y < yStamps; y++) { 91 int yStart = yMin + y * ySize / (yStamps + 1); // Subregion starts here 92 int yStop = yMin + (y + 1) * ySize / (yStamps + 1) - 1; // Subregion stops here 93 assert(yStart >= yMin && yStop < yMax); 94 95 for (int x = 0; x < xStamps; x++, index++) { 96 int xStart = xMin + x * xSize / (xStamps + 1); // Subregion starts here 97 int xStop = xMin + (x + 1) * xSize / (xStamps + 1) - 1; // Subregion stops here 98 assert(xStart >= xMin && xStop < xMax); 99 100 list->stamps->data[index] = pmSubtractionStampAlloc(); 101 list->regions->data[index] = psRegionAlloc(xStart, xStop, yStart, yStop); 102 } 103 } 104 105 list->x = NULL; 106 list->y = NULL; 107 list->flux = NULL; 108 109 return list; 110 } 111 112 pmSubtractionStamp *pmSubtractionStampAlloc(void) 57 113 { 58 114 pmSubtractionStamp *stamp = psAlloc(sizeof(pmSubtractionStamp)); // Stamp to return … … 66 122 stamp->matrix = NULL; 67 123 stamp->vector = NULL; 68 stamp->status = status;124 stamp->status = PM_SUBTRACTION_STAMP_INIT; 69 125 70 126 stamp->reference = NULL; … … 77 133 78 134 79 psArray *pmSubtractionFindStamps(psArray *stamps, const psImage *image, const psImage *subMask, 80 const psRegion *region, float threshold, float spacing) 135 pmSubtractionStampList *pmSubtractionFindStamps(pmSubtractionStampList *stamps, const psImage *image, 136 const psImage *subMask, const psRegion *region, 137 float threshold, float spacing) 81 138 { 82 139 PS_ASSERT_IMAGE_NON_NULL(image, NULL); … … 107 164 int numRows = image->numRows, numCols = image->numCols; // Size of image 108 165 109 // Get region in which to find stamps: [xMin:xMax,yMin:yMax] 110 int xMin = 0, xMax = numCols, yMin = 0, yMax = numRows; 111 if (region) { 112 xMin = PS_MAX(region->x0, xMin); 113 xMax = PS_MIN(region->x1, xMax); 114 yMin = PS_MAX(region->y0, yMin); 115 yMax = PS_MIN(region->y1, yMax); 116 } 117 int xSize = xMax - xMin, ySize = yMax - yMin; // Size of region of interest 118 119 // Number of stamps 120 int xNumStamps = xSize / spacing + 1; 121 int yNumStamps = ySize / spacing + 1; 122 166 if (!stamps) { 167 stamps = pmSubtractionStampListAlloc(numCols, numRows, region, spacing); 168 } 169 170 int numStamps = stamps->num; // Number of stamp regions 123 171 int numFound = 0; // Number of stamps found 124 125 if (stamps) { 126 PS_ASSERT_INT_EQUAL(stamps->n, xNumStamps * yNumStamps, NULL); 127 // Just in case, check for NULL stamps 128 for (int i = 0; i < xNumStamps * yNumStamps; i++) { 129 if (!stamps->data[i]) { 130 stamps->data[i] = pmSubtractionStampAlloc(PM_SUBTRACTION_STAMP_REJECTED); 172 for (int i = 0; i < numStamps; i++) { 173 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 174 175 // Only find a new stamp if we need to 176 if (stamp->status != PM_SUBTRACTION_STAMP_REJECTED && stamp->status != PM_SUBTRACTION_STAMP_INIT) { 177 continue; 178 } 179 180 float xStamp = 0, yStamp = 0; // Coordinates of stamp 181 float fluxStamp = NAN; // Flux of stamp 182 bool goodStamp = false; // Found a good stamp? 183 184 // A couple different ways of finding stamps: 185 if (stamps->x && stamps->y) { 186 // Get the next stamp from the list 187 psVector *xList = stamps->x->data[i], *yList = stamps->y->data[i]; // Coordinate lists 188 psVector *fluxList = stamps->flux->data[i]; // List of stamp fluxes 189 190 // Take stamp off the top of the (sorted) list 191 if (xList->n > 0) { 192 int index = xList->n - 1; // Index of new stamp 193 xStamp = xList->data.F32[index]; 194 yStamp = yList->data.F32[index]; 195 fluxStamp = fluxList->data.F32[index]; 196 197 // Chop off the top of the list 198 xList->n = index; 199 yList->n = index; 200 fluxList->n = index; 201 202 goodStamp = true; 131 203 } 132 } 133 } else { 134 stamps = psArrayAlloc(xNumStamps * yNumStamps); 135 for (int i = 0; i < xNumStamps * yNumStamps ; i++) { 136 stamps->data[i] = pmSubtractionStampAlloc(PM_SUBTRACTION_STAMP_INIT); 137 } 138 } 139 140 for (int j = 0, index = 0; j < yNumStamps; j++) { 141 for (int i = 0; i < xNumStamps; i++, index++) { 142 pmSubtractionStamp *stamp = stamps->data[index]; // Stamp of interest 143 144 // Only find a new stamp if we need to 145 if (stamp->status == PM_SUBTRACTION_STAMP_REJECTED || 146 stamp->status == PM_SUBTRACTION_STAMP_INIT) { 147 148 // Find maximum non-masked value in the image section, 149 // but don't include a footprint around the edge 150 float fluxBest = threshold; // Flux of best stamp pixel 151 int xBest = 0, yBest = 0; // Coordinates of best stamp 152 153 // Bounds of region to search for stamp 154 int yStart = yMin + j * ySize / (yNumStamps + 1); 155 int yStop = yMin + (j + 1) * ySize / (yNumStamps + 1) - 1; 156 int xStart = xMin + i * xSize / (xNumStamps + 1); 157 int xStop = xMin + (i + 1) * xSize / (xNumStamps + 1) - 1; 158 assert(yStop < numRows && xStop < numCols && yStart >= 0 && xStart >= 0); 159 160 for (int y = yStart; y <= yStop ; y++) { 161 for (int x = xStart; x <= xStop ; x++) { 162 if (checkStampMask(x, y, subMask) && image->data.F32[y][x] > fluxBest) { 163 fluxBest = image->data.F32[y][x]; 164 xBest = x; 165 yBest = y; 166 } 204 } else { 205 // Use a simple method of automatically finding stamps --- take the highest pixel in the subregion 206 fluxStamp = threshold; 207 psRegion *subRegion = stamps->regions->data[i]; // Sub-region of interest 208 for (int y = subRegion->y0; y <= subRegion->y1 ; y++) { 209 for (int x = subRegion->x0; x <= subRegion->y1 ; x++) { 210 if (checkStampMask(x, y, subMask) && image->data.F32[y][x] > fluxStamp) { 211 fluxStamp = image->data.F32[y][x]; 212 xStamp = x; 213 yStamp = y; 214 goodStamp = true; 167 215 } 168 216 } 169 170 stamp->x = xBest;171 stamp->y = yBest;172 stamp->flux = fluxBest;173 174 // Reset the postage stamps since we're making a new stamp175 psFree(stamp->reference);176 psFree(stamp->input);177 psFree(stamp->weight);178 stamp->reference = stamp->input = stamp->weight = NULL;179 180 if (fluxBest > threshold) {181 stamp->status = PM_SUBTRACTION_STAMP_CALCULATE;182 numFound++;183 psTrace("psModules.imcombine", 5, "Found stamp in region (%d,%d): %d,%d\n",184 i, j, (int)stamp->x, (int)stamp->y);185 } else {186 stamp->status = PM_SUBTRACTION_STAMP_NONE;187 }188 217 } 189 218 } 190 } 191 192 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Found %d stamps in %dx%d regions", 193 numFound, xNumStamps, yNumStamps); 219 220 if (goodStamp) { 221 stamp->x = xStamp; 222 stamp->y = yStamp; 223 stamp->flux = fluxStamp; 224 225 // Reset the postage stamps since we're making a new stamp 226 psFree(stamp->reference); 227 psFree(stamp->input); 228 psFree(stamp->weight); 229 stamp->reference = stamp->input = stamp->weight = NULL; 230 231 stamp->status = PM_SUBTRACTION_STAMP_CALCULATE; 232 numFound++; 233 psTrace("psModules.imcombine", 5, "Found stamp in subregion %d: %d,%d\n", 234 i, (int)stamp->x, (int)stamp->y); 235 } else { 236 stamp->status = PM_SUBTRACTION_STAMP_NONE; 237 } 238 } 239 240 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Found %d stamps", numFound); 194 241 195 242 return stamps; … … 197 244 198 245 199 psArray *pmSubtractionSetStamps(const psVector *x, const psVector *y, const psVector *flux, 200 const psImage *subMask, const psRegion *region) 246 pmSubtractionStampList *pmSubtractionSetStamps(const psVector *x, const psVector *y, const psVector *flux, 247 const psImage *image, const psImage *subMask, 248 const psRegion *region, float spacing, int exclusionZone) 201 249 { 202 250 PS_ASSERT_VECTOR_NON_NULL(x, false); … … 209 257 PS_ASSERT_VECTOR_TYPE(flux, PS_TYPE_F32, false); 210 258 PS_ASSERT_VECTORS_SIZE_EQUAL(flux, x, false); 259 } else { 260 PS_ASSERT_IMAGE_NON_NULL(image, false); 211 261 } 212 262 if (subMask) { 213 263 PS_ASSERT_IMAGE_NON_NULL(subMask, false); 214 264 PS_ASSERT_IMAGE_TYPE(subMask, PS_TYPE_MASK, false); 215 } 216 217 int num = x->n; // Number of stamps 218 psArray *stamps = psArrayAllocEmpty(num); // Stamps, to return 219 220 for (int i = 0; i < num; i++) { 221 int xStamp = x->data.F32[i] + 0.5, yStamp = y->data.F32[i] + 0.5; // Pixel coords of stamp 222 if (!checkStampRegion(xStamp, yStamp, region)) { 223 continue; 224 } 225 if (!checkStampMask(xStamp, yStamp, subMask)) { 226 continue; 227 } 228 229 pmSubtractionStamp *stamp = pmSubtractionStampAlloc(PM_SUBTRACTION_STAMP_CALCULATE); // Stamp 230 stamp->x = x->data.F32[i]; 231 stamp->y = y->data.F32[i]; 232 if (flux) { 233 stamp->flux = flux->data.F32[i]; 234 } 235 stamps->data[stamps->n++] = stamp; 236 } 265 if (image) { 266 PS_ASSERT_IMAGE_NON_NULL(image, false); 267 PS_ASSERT_IMAGES_SIZE_EQUAL(image, subMask, false); 268 } 269 } 270 271 int numStars = x->n; // Number of stars 272 psVector *exclude = psVectorAlloc(numStars, PS_TYPE_U8); // Exclude a star? 273 psVectorInit(exclude, 0); 274 275 // Apply exclusion zone around each star --- important when we're convolving to a specified PSF; less so 276 // when we're trying to get a good subtraction. 277 if (exclusionZone > 0) { 278 psTrace("psModules.imcombine", 2, "Applying exclusion zone of %d pixels for stamps\n", exclusionZone); 279 // We use something resembling a binary search --- coordinates are sorted in the x dimension, and then 280 // to exclude stars within a nominated distance, we need only examine (i.e., calculate the 281 // 2-dimensional distance to) other stars in the list that are within that distance of the x 282 // coordinate of the star of interest. By marking both stars when we find a violation of the 283 // exclusion zone, we need only search upwards from the x coordinate of the star of interest. 284 285 int minDistance2 = PS_SQR(exclusionZone); // Minimum square distance for other stars 286 psVector *indexes = psVectorSortIndex(NULL, x); // Indices for sorting in x 287 for (int i = 0; i < numStars; i++) { 288 int iIndex = indexes->data.S32[i]; // Index for star i 289 if (exclude->data.U8[iIndex]) { 290 continue; 291 } 292 float ix = x->data.F32[iIndex], iy = y->data.F32[iIndex]; // Coordinates for star i 293 float jx, jy; // Coordinates for star j 294 for (int j = i + 1, jIndex = indexes->data.S32[j]; 295 (jx = x->data.F32[jIndex]) < ix + exclusionZone && j < numStars; 296 j++, jIndex = indexes->data.S32[j]) { 297 jy = y->data.F32[jIndex]; 298 if (PS_SQR(ix - jx) + PS_SQR(iy - jy) < minDistance2) { 299 exclude->data.U8[iIndex] = 0xff; 300 exclude->data.U8[jIndex] = 0xff; 301 psTrace("psModules.imcombine", 5, "Excluding stamps %d,%d and %d,%d\n", 302 (int)x->data.F32[iIndex], (int)y->data.F32[iIndex], 303 (int)x->data.F32[jIndex], (int)y->data.F32[jIndex]); 304 // Would 'break' here, but there might be more stamps within the exclusion zone. 305 } 306 } 307 } 308 psFree(indexes); 309 } 310 311 pmSubtractionStampList *stamps = pmSubtractionStampListAlloc(subMask->numCols, subMask->numRows, 312 region, spacing); // Stamp list 313 int numStamps = stamps->num; // Number of stamps 314 315 // Initialise the lists 316 stamps->x = psArrayAlloc(numStamps); 317 stamps->y = psArrayAlloc(numStamps); 318 stamps->flux = psArrayAlloc(numStamps); 319 for (int i = 0; i < numStamps; i++) { 320 stamps->x->data[i] = psVectorAllocEmpty(STAMP_LIST_BUFFER, PS_TYPE_F32); 321 stamps->y->data[i] = psVectorAllocEmpty(STAMP_LIST_BUFFER, PS_TYPE_F32); 322 stamps->flux->data[i] = psVectorAllocEmpty(STAMP_LIST_BUFFER, PS_TYPE_F32); 323 } 324 325 // Put the stars into their appropriate subregions 326 for (int i = 0; i < numStars; i++) { 327 if (exclude->data.U8[i]) { 328 // Star has been excluded 329 continue; 330 } 331 float xStamp = x->data.F32[i], yStamp = y->data.F32[i]; // Coordinates of stamp 332 int xPix = xStamp + 0.5, yPix = yStamp + 0.5; // Pixel coordinate of stamp 333 if (!checkStampRegion(xPix, yPix, region)) { 334 // It's not in the big region 335 continue; 336 } 337 if (!checkStampMask(xPix, yPix, subMask)) { 338 // Not a good stamp 339 continue; 340 } 341 342 for (int j = 0; j < numStamps; j++) { 343 psRegion *subRegion = stamps->regions->data[j]; // Subregion of interest 344 if (checkStampRegion(xPix, yPix, subRegion)) { 345 psVector *xList = stamps->x->data[j], *yList = stamps->y->data[j]; // Pixel lists 346 psVector *fluxList = stamps->flux->data[j]; // Flux list 347 348 int index = xList->n; // Index of new stamp candidate 349 xList->data.F32[index] = xStamp; 350 yList->data.F32[index] = yStamp; 351 352 if (flux) { 353 fluxList->data.F32[index] = flux->data.F32[i]; 354 } else { 355 fluxList->data.F32[index] = image->data.F32[yPix][xPix]; 356 } 357 358 psVectorExtend(xList, STAMP_LIST_BUFFER, 1); 359 psVectorExtend(yList, STAMP_LIST_BUFFER, 1); 360 psVectorExtend(fluxList, STAMP_LIST_BUFFER, 1); 361 362 break; 363 } 364 } 365 } 366 psFree(exclude); 367 368 // Sort the list by flux, with the brightest last 369 for (int i = 0; i < numStamps; i++) { 370 psVector *xList = stamps->x->data[i], *yList = stamps->y->data[i]; // Pixel lists 371 psVector *fluxList = stamps->flux->data[i]; // Flux list 372 373 psVector *indexes = psVectorSortIndex(NULL, fluxList); // Indices to sort flux 374 int num = indexes->n; // Number of candidate stamps in this subregion 375 376 psVector *xSorted = psVectorAlloc(num, PS_TYPE_F32); // Sorted version of x list 377 psVector *ySorted = psVectorAlloc(num, PS_TYPE_F32); // Sorted version of y list 378 psVector *fluxSorted = psVectorAlloc(num, PS_TYPE_F32); // Sorted version of flux list 379 for (int j = 0; j < num; j++) { 380 int k = indexes->data.S32[j]; // Sorted index 381 xSorted->data.F32[j] = xList->data.F32[k]; 382 ySorted->data.F32[j] = yList->data.F32[k]; 383 fluxSorted->data.F32[j] = fluxList->data.F32[k]; 384 } 385 psFree(indexes); 386 387 psFree(stamps->x->data[i]); 388 psFree(stamps->y->data[i]); 389 psFree(stamps->flux->data[i]); 390 391 stamps->x->data[i] = xSorted; 392 stamps->y->data[i] = ySorted; 393 stamps->flux->data[i] = fluxSorted; 394 } 395 237 396 238 397 return stamps; … … 240 399 241 400 242 bool pmSubtractionExtractStamps(p sArray *stamps, psImage *reference, psImage *input, psImage *weight,243 int footprint, int kernelSize)244 { 245 P S_ASSERT_ARRAY_NON_NULL(stamps, false);401 bool pmSubtractionExtractStamps(pmSubtractionStampList *stamps, psImage *reference, psImage *input, 402 psImage *weight, int footprint, int kernelSize) 403 { 404 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); 246 405 PS_ASSERT_IMAGE_NON_NULL(reference, false); 247 406 PS_ASSERT_IMAGE_TYPE(reference, PS_TYPE_F32, false); … … 263 422 264 423 if (!weight) { 265 // Use the input as a rough approximation to the variance map, and HOPE that it's positive. 424 // Use the input (or if I must, the reference) as a rough approximation to the variance map, and HOPE 425 // that it's positive. 266 426 weight = input ? input : reference; 267 427 } 268 428 269 for (int i = 0; i < stamps->n ; i++) {270 pmSubtractionStamp *stamp = stamps-> data[i]; // Stamp of interest429 for (int i = 0; i < stamps->num; i++) { 430 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 271 431 if (!stamp || stamp->status != PM_SUBTRACTION_STAMP_CALCULATE) { 272 432 continue; … … 307 467 308 468 309 bool pmSubtractionGenerateStamps(p sArray*stamps, float fwhm, int footprint, int kernelSize)310 { 311 P S_ASSERT_ARRAY_NON_NULL(stamps, false);469 bool pmSubtractionGenerateStamps(pmSubtractionStampList *stamps, float fwhm, int footprint, int kernelSize) 470 { 471 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); 312 472 PS_ASSERT_FLOAT_LARGER_THAN(fwhm, 0.0, false); 313 473 PS_ASSERT_INT_NONNEGATIVE(footprint, false); 474 PS_ASSERT_INT_NONNEGATIVE(kernelSize, false); 314 475 315 476 int size = kernelSize + footprint; // Size of postage stamps 316 int num = stamps->n ;// Number of stamps477 int num = stamps->num; // Number of stamps 317 478 float sigma = fwhm / (2.0 * sqrtf(2.0 * log(2.0))); // Gaussian sigma 318 479 319 480 for (int i = 0; i < num; i++) { 320 pmSubtractionStamp *stamp = stamps-> data[i]; // Stamp of interest481 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 321 482 if (!(stamp->status & PM_SUBTRACTION_STAMP_CALCULATE)) { 322 483 continue; … … 347 508 } 348 509 349 return stamps;350 } 510 return true; 511 }
Note:
See TracChangeset
for help on using the changeset viewer.
