Changeset 26747 for branches/eam_branches/psModules.stack.20100120
- Timestamp:
- Jan 31, 2010, 5:00:42 PM (16 years ago)
- Location:
- branches/eam_branches/psModules.stack.20100120
- Files:
-
- 30 edited
- 2 copied
-
. (modified) (1 prop)
-
src/camera/pmFPAMaskWeight.c (modified) (4 diffs)
-
src/config/Makefile.am (modified) (2 diffs)
-
src/config/pmConfigRecipeValue.c (copied) (copied from branches/eam_branches/20091201/psModules/src/config/pmConfigRecipeValue.c )
-
src/config/pmConfigRecipeValue.h (copied) (copied from branches/eam_branches/20091201/psModules/src/config/pmConfigRecipeValue.h )
-
src/detrend/pmPattern.c (modified) (2 diffs)
-
src/imcombine/pmStackReject.c (modified) (3 diffs)
-
src/imcombine/pmSubtraction.c (modified) (7 diffs)
-
src/imcombine/pmSubtraction.h (modified) (2 diffs)
-
src/imcombine/pmSubtractionAnalysis.c (modified) (2 diffs)
-
src/imcombine/pmSubtractionEquation.c (modified) (28 diffs)
-
src/imcombine/pmSubtractionEquation.h (modified) (4 diffs)
-
src/imcombine/pmSubtractionIO.c (modified) (4 diffs)
-
src/imcombine/pmSubtractionKernels.c (modified) (28 diffs)
-
src/imcombine/pmSubtractionKernels.h (modified) (17 diffs)
-
src/imcombine/pmSubtractionMask.c (modified) (3 diffs)
-
src/imcombine/pmSubtractionMask.h (modified) (1 diff)
-
src/imcombine/pmSubtractionMatch.c (modified) (22 diffs)
-
src/imcombine/pmSubtractionMatch.h (modified) (1 diff)
-
src/imcombine/pmSubtractionParams.c (modified) (3 diffs)
-
src/imcombine/pmSubtractionParams.h (modified) (1 diff)
-
src/imcombine/pmSubtractionStamps.c (modified) (23 diffs)
-
src/imcombine/pmSubtractionStamps.h (modified) (8 diffs)
-
src/objects/pmDetections.c (modified) (2 diffs)
-
src/objects/pmDetections.h (modified) (1 diff)
-
src/objects/pmSource.c (modified) (5 diffs)
-
src/objects/pmSource.h (modified) (2 diffs)
-
src/objects/pmSourceIO.c (modified) (4 diffs)
-
src/objects/pmSourcePlotApResid.c (modified) (3 diffs)
-
src/objects/pmSourcePlotMoments.c (modified) (3 diffs)
-
src/objects/pmSourcePlotPSFModel.c (modified) (3 diffs)
-
src/psmodules.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/psModules.stack.20100120
- Property svn:mergeinfo changed
/branches/eam_branches/20091201/psModules (added) merged: 26686-26687,26693,26702-26703,26731-26735,26737,26739,26741-26743
- Property svn:mergeinfo changed
-
branches/eam_branches/psModules.stack.20100120/src/camera/pmFPAMaskWeight.c
r26076 r26747 370 370 371 371 psImage *image = readout->image, *mask = readout->mask, *variance = readout->variance; // Readout parts 372 373 372 int numCols = image->numCols, numRows = image->numRows; // Size of image 374 int numPix = numCols * numRows; // Number of pixels 375 int num = PS_MAX(sample, numPix); // Number we care about 373 374 int xMin, xMax, yMin, yMax; // Bounds of image 375 if (mask) { 376 xMin = numCols; 377 xMax = 0; 378 yMin = numRows; 379 yMax = 0; 380 for (int y = 0; y < numRows; y++) { 381 for (int x = 0; x < numCols; x++) { 382 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) { 383 continue; 384 } 385 xMin = PS_MIN(xMin, x); 386 xMax = PS_MAX(xMax, x); 387 yMin = PS_MIN(yMin, y); 388 yMax = PS_MAX(yMax, y); 389 } 390 } 391 } else { 392 xMin = 0; 393 xMax = numCols; 394 yMin = 0; 395 yMax = numRows; 396 } 397 398 int xNum = xMax - xMin, yNum = yMax - yMin; // Number of pixels 399 400 int numPix = xNum * yNum; // Number of pixels 401 int num = PS_MAX(sample, numPix); // Number we care about 376 402 psVector *signoise = psVectorAllocEmpty(num, PS_TYPE_F32); // Signal-to-noise values 377 403 … … 379 405 // We have an image smaller than Nsubset, so just loop over the image pixels 380 406 int index = 0; // Index for vector 381 for (int y = 0; y < numRows; y++) {382 for (int x = 0; x < numCols; x++) {407 for (int y = yMin; y < yMax; y++) { 408 for (int x = xMin; x < xMax; x++) { 383 409 if ((mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) || 384 410 !isfinite(image->data.F32[y][x]) || !isfinite(variance->data.F32[y][x])) { … … 397 423 // Pixel coordinates 398 424 int pixel = numPix * psRandomUniform(rng); 399 int x = pixel % numCols;400 int y = pixel / numCols;425 int x = xMin + pixel % xNum; 426 int y = yMin + pixel / xNum; 401 427 402 428 if ((mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) || … … 433 459 } 434 460 435 psBinaryOp(variance, variance, "*", psScalarAlloc(PS_SQR(correction), PS_TYPE_F32)); 461 psImage *subImage = psImageSubset(variance, psRegionSet(xMin, xMax, yMin, yMax)); // Smaller image 462 psBinaryOp(subImage, subImage, "*", psScalarAlloc(PS_SQR(correction), PS_TYPE_F32)); 463 psFree(subImage); 436 464 437 465 pmHDU *hdu = pmHDUFromReadout(readout); // HDU for readout -
branches/eam_branches/psModules.stack.20100120/src/config/Makefile.am
r23794 r26747 32 32 pmConfigDump.c \ 33 33 pmConfigRun.c \ 34 pmConfigRecipeValue.c \ 34 35 pmVersion.c \ 35 36 pmErrorCodes.c … … 43 44 pmConfigDump.h \ 44 45 pmConfigRun.h \ 46 pmConfigRecipeValue.h \ 45 47 pmVersion.h \ 46 48 pmErrorCodes.h -
branches/eam_branches/psModules.stack.20100120/src/detrend/pmPattern.c
r24905 r26747 63 63 float lower = stats->robustMedian - thresh * stats->robustStdev; // Lower bound for data 64 64 float upper = stats->robustMedian + thresh * stats->robustStdev; // Upper bound for data 65 float background = stats->robustMedian; 65 66 psFree(stats); 66 67 psFree(rng); … … 113 114 114 115 for (int x = 0; x < numCols; x++) { 115 image->data.F32[y][x] -= solution->data.F32[x];116 image->data.F32[y][x] += (background - solution->data.F32[x]); 116 117 } 117 118 psFree(solution); -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmStackReject.c
r25468 r26747 35 35 { 36 36 int size = kernels->size; // Half-size of convolution kernel 37 psImage *polyValues = p_pmSubtractionPolynomialFromCoords(NULL, kernels, numCols, numRows,38 xMin + size + 1,yMin + size + 1); // Polynomial37 psImage *polyValues = p_pmSubtractionPolynomialFromCoords(NULL, kernels, xMin + size + 1, 38 yMin + size + 1); // Polynomial 39 39 int box = p_pmSubtractionBadRadius(NULL, kernels, polyValues, false, poorFrac); // Radius of bad box 40 40 psTrace("psModules.imcombine", 10, "Growing by %d", box); … … 150 150 pmReadout *inRO = pmReadoutAlloc(NULL); // Readout with input image 151 151 inRO->image = image; 152 convRO->image = psImageAlloc(image->numCols, image->numRows, PS_TYPE_F32); 152 153 for (int i = 0; i < numRegions; i++) { 153 154 psRegion *region = subRegions->data[i]; // Region of interest … … 165 166 166 167 // Image of the kernel at the centre of the region 167 float xNorm = (region->x0 + 0.5 * (region->x1 - region->x0) - kernels->numCols/2.0) /168 (float)kernels->numCols;169 float yNorm = (region->y0 + 0.5 * (region->y1 - region->y0) - kernels->numRows/2.0) /170 (float)kernels->numRows;168 float xNorm, yNorm; // Normalised coordinates 169 p_pmSubtractionPolynomialNormCoords(&xNorm, &yNorm, 0.5 * (region->x1 - region->x0), 170 0.5 * (region->y1 - region->y0), 171 kernels->xMin, kernels->xMax, kernels->yMin, kernels->yMax); 171 172 psImage *kernel = pmSubtractionKernelImage(kernels, xNorm, yNorm, false); 172 173 if (!kernel) { -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtraction.c
r26667 r26747 424 424 } else if (*source & subConvPoor) { 425 425 *target |= maskPoor; 426 } else { 427 *target &= ~maskBad & ~maskPoor; 426 428 } 427 429 } … … 574 576 } 575 577 578 void p_pmSubtractionPolynomialNormCoords(float *xOut, float *yOut, float xIn, float yIn, 579 int xMin, int xMax, int yMin, int yMax) 580 { 581 float xNormSize = xMax - xMin, yNormSize = yMax - yMin; // Size to use for normalisation 582 *xOut = 2.0 * (float)(xIn - xMin - xNormSize/2.0) / xNormSize; 583 *yOut = 2.0 * (float)(yIn - yMin - yNormSize/2.0) / yNormSize; 584 return; 585 } 586 576 587 psImage *p_pmSubtractionPolynomialFromCoords(psImage *output, const pmSubtractionKernels *kernels, 577 int numCols, int numRows, intx, int y)588 int x, int y) 578 589 { 579 590 assert(kernels); 580 assert(numCols > 0 && numRows > 0); 581 582 // Size to use when calculating normalised coordinates (different from actual size when convolving 583 // subimage) 584 int xNormSize = (kernels->numCols > 0 ? kernels->numCols : numCols); 585 int yNormSize = (kernels->numRows > 0 ? kernels->numRows : numRows); 586 587 // Normalised coordinates 588 float yNorm = 2.0 * (float)(y - yNormSize/2.0) / (float)yNormSize; 589 float xNorm = 2.0 * (float)(x - xNormSize/2.0) / (float)xNormSize; 590 591 592 float xNorm, yNorm; // Normalised coordinates 593 p_pmSubtractionPolynomialNormCoords(&xNorm, &yNorm, x, y, 594 kernels->xMin, kernels->xMax, kernels->yMin, kernels->yMax); 591 595 return p_pmSubtractionPolynomial(output, kernels->spatialOrder, xNorm, yNorm); 592 596 } … … 1072 1076 // Only generate polynomial values every kernel footprint, since we have already assumed 1073 1077 // (with the stamps) that it does not vary rapidly on this scale. 1074 psImage *polyValues = p_pmSubtractionPolynomialFromCoords(NULL, kernels, numCols, numRows, 1075 xMin + x0 + size + 1, 1076 yMin + y0 + size + 1); 1078 psImage *polyValues = p_pmSubtractionPolynomialFromCoords(NULL, kernels, xMin + x0 + size + 1, 1079 yMin + y0 + size + 1); // Polynomial 1077 1080 float background = doBG ? p_pmSubtractionSolutionBackground(kernels, polyValues) : 0.0; // Background term 1078 1081 … … 1158 1161 PM_ASSERT_READOUT_NON_NULL(ro1, false); 1159 1162 PM_ASSERT_READOUT_IMAGE(ro1, false); 1163 PM_ASSERT_READOUT_IMAGE(out1, false); 1160 1164 numCols = ro1->image->numCols; 1161 1165 numRows = ro1->image->numRows; … … 1167 1171 PM_ASSERT_READOUT_NON_NULL(ro2, false); 1168 1172 PM_ASSERT_READOUT_IMAGE(ro2, false); 1173 PM_ASSERT_READOUT_IMAGE(out2, false); 1169 1174 if (numCols == 0 && numRows == 0) { 1170 1175 numCols = ro2->image->numCols; … … 1200 1205 bool threaded = pmSubtractionThreaded(); // Running threaded? 1201 1206 1202 // Outputs1203 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {1204 if (!out1->image) {1205 out1->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);1206 }1207 if (ro1->variance) {1208 if (!out1->variance) {1209 out1->variance = psImageAlloc(numCols, numRows, PS_TYPE_F32);1210 }1211 psImageInit(out1->variance, 0.0);1212 }1213 }1214 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {1215 if (!out2->image) {1216 out2->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);1217 }1218 if (ro2->variance) {1219 if (!out2->variance) {1220 out2->variance = psImageAlloc(numCols, numRows, PS_TYPE_F32);1221 }1222 psImageInit(out2->variance, 0.0);1223 }1224 }1225 1207 psImage *convMask = NULL; // Convolved mask image (common to inputs 1 and 2) 1226 1208 if (subMask) { 1227 1209 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1228 if (!out1->mask) {1229 out1->mask = psImageAlloc(numCols, numRows, PS_TYPE_IMAGE_MASK);1230 }1231 psImageInit(out1->mask, 0);1232 1210 convMask = out1->mask; 1233 1211 } 1234 1212 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1235 if (!out2->mask) {1236 out2->mask = psImageAlloc(numCols, numRows, PS_TYPE_IMAGE_MASK);1237 }1238 psImageInit(out2->mask, 0);1239 1213 if (!convMask) { 1240 1214 convMask = out2->mask; … … 1256 1230 1257 1231 // Get region for convolution: [xMin:xMax,yMin:yMax] 1258 int xMin = size, xMax = numCols- size;1259 int yMin = size, yMax = numRows- size;1232 int xMin = kernels->xMin + size, xMax = kernels->xMax - size; 1233 int yMin = kernels->yMin + size, yMax = kernels->yMax - size; 1260 1234 if (region) { 1261 1235 xMin = PS_MAX(region->x0, xMin); -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtraction.h
r25279 r26747 127 127 ); 128 128 129 /// Return normalised coordinates 130 void p_pmSubtractionPolynomialNormCoords( 131 float *xOut, float *yOut, ///< Normalised coordinates, returned 132 float xIn, float yIn, ///< Input coordinates 133 int xMin, int xMax, int yMin, int yMax ///< Bounds of validity 134 ); 135 129 136 /// Given (normalised) coordinates (x,y), generate a matrix where the elements (i,j) are x^i * y^j 130 137 psImage *p_pmSubtractionPolynomial(psImage *output, ///< Output matrix, or NULL … … 138 145 psImage *p_pmSubtractionPolynomialFromCoords(psImage *output, ///< Output matrix, or NULL 139 146 const pmSubtractionKernels *kernels, ///< Kernel parameters 140 int numCols, int numRows, ///< Size of image of interest141 147 int x, int y ///< Position of interest 142 148 ); -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionAnalysis.c
r26593 r26747 118 118 119 119 // sample difference images 120 { 120 { 121 121 psMetadataAddArray(analysis, PS_LIST_TAIL, "SUBTRACTION.SAMPLE.STAMP.SET", PS_META_DUPLICATE_OK, "Sample Difference Stamps", kernels->sampleStamps); 122 122 } … … 273 273 // Difference in background 274 274 { 275 psImage *polyValues = p_pmSubtractionPolynomialFromCoords(NULL, kernels, numCols, numRows, 276 numCols / 2.0, numRows / 2.0); // Polynomial 275 psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, 0.0, 0.0); // Polynomial 277 276 float bg = p_pmSubtractionSolutionBackground(kernels, polyValues); // Background difference 278 277 -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionEquation.c
r26667 r26747 28 28 static bool calculateMatrixVector(psImage *matrix, // Least-squares matrix, updated 29 29 psVector *vector, // Least-squares vector, updated 30 double *norm, // Normalisation, updated 30 31 const psKernel *input, // Input image (target) 31 32 const psKernel *reference, // Reference image (convolution source) … … 36 37 const psImage *polyValues, // Spatial polynomial values 37 38 int footprint, // (Half-)Size of stamp 39 int normWindow, // Window (half-)size for normalisation measurement 38 40 const pmSubtractionEquationCalculationMode mode 39 41 ) … … 156 158 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 157 159 vector->data.F64[iIndex] = sumIC * poly[iTerm]; 158 // XXX TEST for Hermitians: do not calculate A - norm*B - \sum(k x B), 159 // instead, calculate A - \sum(k x B), with full hermitians 160 if (0 && !(mode & PM_SUBTRACTION_EQUATION_NORM)) { 160 if (!(mode & PM_SUBTRACTION_EQUATION_NORM)) { 161 161 // subtract norm * sumRC * poly[iTerm] 162 162 psAssert (kernels->solution1, "programming error: define solution first!"); … … 174 174 double sumR = 0.0; // Sum of the reference 175 175 double sumI = 0.0; // Sum of the input 176 double normI1 = 0.0, normI2 = 0.0; // Sum of I_1 and I_2 within the normalisation window 176 177 for (int y = - footprint; y <= footprint; y++) { 177 178 for (int x = - footprint; x <= footprint; x++) { … … 181 182 double rr = PS_SQR(ref); 182 183 double one = 1.0; 184 185 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow)) { 186 normI1 += ref; 187 normI2 += in; 188 } 189 183 190 if (weight) { 184 191 float wtVal = weight->kernel[y][x]; … … 204 211 } 205 212 } 213 214 *norm = normI2 / normI1; 215 206 216 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 207 217 matrix->data.F64[normIndex][normIndex] = sumRR; … … 217 227 matrix->data.F64[bgIndex][normIndex] = sumR; 218 228 } 229 230 // check for any NAN values in the result, skip if found: 231 for (int iy = 0; iy < matrix->numRows; iy++) { 232 for (int ix = 0; ix < matrix->numCols; ix++) { 233 if (!isfinite(matrix->data.F64[iy][ix])) { 234 fprintf (stderr, "WARNING: NAN in matrix\n"); 235 return false; 236 } 237 } 238 } 239 for (int ix = 0; ix < vector->n; ix++) { 240 if (!isfinite(vector->data.F64[ix])) { 241 fprintf (stderr, "WARNING: NAN in vector\n"); 242 return false; 243 } 244 } 245 219 246 return true; 220 247 } … … 224 251 static bool calculateDualMatrixVector(psImage *matrix, // Least-squares matrix, updated 225 252 psVector *vector, // Least-squares vector, updated 253 double *norm, // Normalisation, updated 226 254 const psKernel *image1, // Image 1 227 255 const psKernel *image2, // Image 2 … … 232 260 const pmSubtractionKernels *kernels, // Kernels 233 261 const psImage *polyValues, // Spatial polynomial values 234 int footprint // (Half-)Size of stamp 262 int footprint, // (Half-)Size of stamp 263 int normWindow, // Window (half-)size for normalisation measurement 264 const pmSubtractionEquationCalculationMode mode 235 265 ) 236 266 { … … 272 302 } 273 303 304 305 // initialize the matrix and vector for NOP on all coeffs. we only fill in the coeffs we 306 // choose to calculate 307 psImageInit(matrix, 0.0); 308 psVectorInit(vector, 1.0); 309 for (int i = 0; i < matrix->numCols; i++) { 310 matrix->data.F64[i][i] = 1.0; 311 } 274 312 275 313 for (int i = 0; i < numKernels; i++) { … … 306 344 } 307 345 308 // Spatial variation 309 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 310 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 311 double aa = sumAA * poly2[iTerm][jTerm]; 312 double bb = sumBB * poly2[iTerm][jTerm]; 313 double ab = sumAB * poly2[iTerm][jTerm]; 314 315 matrix->data.F64[iIndex][jIndex] = aa; 316 matrix->data.F64[jIndex][iIndex] = aa; 317 318 matrix->data.F64[iIndex + numParams][jIndex + numParams] = bb; 319 matrix->data.F64[jIndex + numParams][iIndex + numParams] = bb; 320 321 matrix->data.F64[iIndex][jIndex + numParams] = ab; 322 matrix->data.F64[jIndex + numParams][iIndex] = ab; 346 // Spatial variation of kernel coeffs 347 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 348 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 349 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 350 double aa = sumAA * poly2[iTerm][jTerm]; 351 double bb = sumBB * poly2[iTerm][jTerm]; 352 double ab = sumAB * poly2[iTerm][jTerm]; 353 354 matrix->data.F64[iIndex][jIndex] = aa; 355 matrix->data.F64[jIndex][iIndex] = aa; 356 357 matrix->data.F64[iIndex + numParams][jIndex + numParams] = bb; 358 matrix->data.F64[jIndex + numParams][iIndex + numParams] = bb; 359 360 matrix->data.F64[iIndex][jIndex + numParams] = ab; 361 matrix->data.F64[jIndex + numParams][iIndex] = ab; 362 } 323 363 } 324 364 } … … 340 380 } 341 381 342 // Spatial variation 343 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 344 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 345 double ab = sumAB * poly2[iTerm][jTerm]; 346 matrix->data.F64[iIndex][jIndex + numParams] = ab; 347 matrix->data.F64[jIndex + numParams][iIndex] = ab; 382 // Spatial variation of kernel coeffs 383 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 384 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 385 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 386 double ab = sumAB * poly2[iTerm][jTerm]; 387 matrix->data.F64[iIndex][jIndex + numParams] = ab; 388 matrix->data.F64[jIndex + numParams][iIndex] = ab; 389 } 348 390 } 349 391 } … … 403 445 double bi2 = sumBI2 * poly[iTerm]; 404 446 double ai1 = sumAI1 * poly[iTerm]; 405 double a = sumA * poly[iTerm];447 double a = sumA * poly[iTerm]; 406 448 double bi1 = sumBI1 * poly[iTerm]; 407 double b = sumB * poly[iTerm]; 408 409 matrix->data.F64[iIndex][normIndex] = ai1; 410 matrix->data.F64[normIndex][iIndex] = ai1; 411 matrix->data.F64[iIndex][bgIndex] = a; 412 matrix->data.F64[bgIndex][iIndex] = a; 413 matrix->data.F64[iIndex + numParams][normIndex] = bi1; 414 matrix->data.F64[normIndex][iIndex + numParams] = bi1; 415 matrix->data.F64[iIndex + numParams][bgIndex] = b; 416 matrix->data.F64[bgIndex][iIndex + numParams] = b; 417 vector->data.F64[iIndex] = ai2; 418 vector->data.F64[iIndex + numParams] = bi2; 449 double b = sumB * poly[iTerm]; 450 451 if ((mode & PM_SUBTRACTION_EQUATION_NORM) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) { 452 matrix->data.F64[iIndex][normIndex] = ai1; 453 matrix->data.F64[normIndex][iIndex] = ai1; 454 matrix->data.F64[iIndex + numParams][normIndex] = bi1; 455 matrix->data.F64[normIndex][iIndex + numParams] = bi1; 456 } 457 if ((mode & PM_SUBTRACTION_EQUATION_BG) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) { 458 matrix->data.F64[iIndex][bgIndex] = a; 459 matrix->data.F64[bgIndex][iIndex] = a; 460 matrix->data.F64[iIndex + numParams][bgIndex] = b; 461 matrix->data.F64[bgIndex][iIndex + numParams] = b; 462 } 463 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 464 vector->data.F64[iIndex] = ai2; 465 vector->data.F64[iIndex + numParams] = bi2; 466 if (!(mode & PM_SUBTRACTION_EQUATION_NORM)) { 467 // subtract norm * sumRC * poly[iTerm] 468 psAssert (kernels->solution1, "programming error: define solution first!"); 469 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 470 double norm = fabs(kernels->solution1->data.F64[normIndex]); // Normalisation 471 vector->data.F64[iIndex] -= norm * ai1; 472 vector->data.F64[iIndex + numParams] -= norm * bi1; 473 } 474 } 419 475 } 420 476 } … … 425 481 double sumI2 = 0.0; // Sum of I_2 (for vector, background) 426 482 double sumI1I2 = 0.0; // Sum of I_1.I_2 (for vector, normalisation) 483 double normI1 = 0.0, normI2 = 0.0; // Sum of I_1 and I_2 within the normalisation window 427 484 for (int y = - footprint; y <= footprint; y++) { 428 485 for (int x = - footprint; x <= footprint; x++) { … … 433 490 double one = 1.0; 434 491 double i1i2 = i1 * i2; 492 493 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(normWindow)) { 494 normI1 += i1; 495 normI2 += i2; 496 } 435 497 436 498 if (weight) { … … 457 519 } 458 520 } 459 matrix->data.F64[bgIndex][normIndex] = sumI1; 460 matrix->data.F64[normIndex][bgIndex] = sumI1; 461 matrix->data.F64[normIndex][normIndex] = sumI1I1; 462 matrix->data.F64[bgIndex][bgIndex] = sum1; 463 vector->data.F64[bgIndex] = sumI2; 464 vector->data.F64[normIndex] = sumI1I2; 521 522 *norm = normI2 / normI1; 523 524 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 525 matrix->data.F64[normIndex][normIndex] = sumI1I1; 526 vector->data.F64[normIndex] = sumI1I2; 527 } 528 if (mode & PM_SUBTRACTION_EQUATION_BG) { 529 matrix->data.F64[bgIndex][bgIndex] = sum1; 530 vector->data.F64[bgIndex] = sumI2; 531 } 532 if ((mode & PM_SUBTRACTION_EQUATION_NORM) && (mode & PM_SUBTRACTION_EQUATION_BG)) { 533 matrix->data.F64[bgIndex][normIndex] = sumI1; 534 matrix->data.F64[normIndex][bgIndex] = sumI1; 535 } 536 537 // check for any NAN values in the result, skip if found: 538 for (int iy = 0; iy < matrix->numRows; iy++) { 539 for (int ix = 0; ix < matrix->numCols; ix++) { 540 if (!isfinite(matrix->data.F64[iy][ix])) { 541 fprintf (stderr, "WARNING: NAN in matrix\n"); 542 return false; 543 } 544 } 545 } 546 for (int ix = 0; ix < vector->n; ix++) { 547 if (!isfinite(vector->data.F64[ix])) { 548 fprintf (stderr, "WARNING: NAN in vector\n"); 549 return false; 550 } 551 } 552 465 553 466 554 return true; … … 469 557 #if 1 470 558 // Add in penalty term to least-squares vector 471 staticbool calculatePenalty(psImage *matrix, // Matrix to which to add in penalty term559 bool calculatePenalty(psImage *matrix, // Matrix to which to add in penalty term 472 560 psVector *vector, // Vector to which to add in penalty term 473 561 const pmSubtractionKernels *kernels, // Kernel parameters … … 482 570 int spatialOrder = kernels->spatialOrder; // Order of spatial variations 483 571 int numKernels = kernels->num; // Number of kernel components 572 int numSpatial = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of spatial variations 573 int numParams = numKernels * numSpatial; // Number of kernel parameters 574 575 // order is : 576 // [p_0,x_0,y_0 p_1,x_0,y_0, p_2,x_0,y_0] 577 // [p_0,x_1,y_0 p_1,x_1,y_0, p_2,x_1,y_0] 578 // [p_0,x_0,y_1 p_1,x_0,y_1, p_2,x_0,y_1] 579 // [norm] 580 // [bg] 581 // [q_0,x_0,y_0 q_1,x_0,y_0, q_2,x_0,y_0] 582 // [q_0,x_1,y_0 q_1,x_1,y_0, q_2,x_1,y_0] 583 // [q_0,x_0,y_1 q_1,x_0,y_1, q_2,x_0,y_1] 584 484 585 for (int i = 0; i < numKernels; i++) { 485 586 for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) { … … 488 589 psAssert(isfinite(penalties->data.F32[i]), "Invalid penalty"); 489 590 matrix->data.F64[index][index] += norm * penalties->data.F32[i]; 591 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 592 matrix->data.F64[index + numParams + 2][index + numParams + 2] += norm * penalties->data.F32[i]; 593 // matrix[i][i] is ~ (k_i * I_1)(k_i * I_1) 594 // penalties scale with second moments 595 // 596 } 490 597 } 491 598 } … … 668 775 switch (kernels->mode) { 669 776 case PM_SUBTRACTION_MODE_1: 670 status = calculateMatrixVector(stamp->matrix, stamp->vector, stamp->image2, stamp->image1,777 status = calculateMatrixVector(stamp->matrix, stamp->vector, &stamp->norm, stamp->image2, stamp->image1, 671 778 weight, window, stamp->convolutions1, kernels, 672 polyValues, footprint, mode);779 polyValues, footprint, stamps->normWindow, mode); 673 780 break; 674 781 case PM_SUBTRACTION_MODE_2: 675 status = calculateMatrixVector(stamp->matrix, stamp->vector, stamp->image1, stamp->image2,782 status = calculateMatrixVector(stamp->matrix, stamp->vector, &stamp->norm, stamp->image1, stamp->image2, 676 783 weight, window, stamp->convolutions2, kernels, 677 polyValues, footprint, mode);784 polyValues, footprint, stamps->normWindow, mode); 678 785 break; 679 786 case PM_SUBTRACTION_MODE_DUAL: 680 status = calculateDualMatrixVector(stamp->matrix, stamp->vector,stamp->image1, stamp->image2, 787 status = calculateDualMatrixVector(stamp->matrix, stamp->vector, &stamp->norm, 788 stamp->image1, stamp->image2, 681 789 weight, window, stamp->convolutions1, stamp->convolutions2, 682 kernels, polyValues, footprint );790 kernels, polyValues, footprint, stamps->normWindow, mode); 683 791 break; 684 792 default: … … 721 829 } 722 830 723 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, const pmSubtractionKernels *kernels, const pmSubtractionEquationCalculationMode mode) 831 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, const pmSubtractionKernels *kernels, 832 const pmSubtractionEquationCalculationMode mode) 724 833 { 725 834 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); … … 843 952 psVectorInit(sumVector, 0.0); 844 953 psImageInit(sumMatrix, 0.0); 845 int numStamps = 0; // Number of good stamps 846 for (int i = 0; i < stamps->num; i++) { 847 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 848 849 if (stamp->status == PM_SUBTRACTION_STAMP_USED) { 850 851 #ifdef TESTING 852 // XXX double-check for NAN in data: 853 for (int iy = 0; iy < stamp->matrix->numRows; iy++) { 854 for (int ix = 0; ix < stamp->matrix->numCols; ix++) { 855 if (!isfinite(stamp->matrix->data.F64[iy][ix])) { 856 fprintf (stderr, "WARNING: NAN in matrix\n"); 857 } 858 } 859 } 860 for (int ix = 0; ix < stamp->vector->n; ix++) { 861 if (!isfinite(stamp->vector->data.F64[ix])) { 862 fprintf (stderr, "WARNING: NAN in vector\n"); 863 } 864 } 865 #endif 866 867 (void)psBinaryOp(sumMatrix, sumMatrix, "+", stamp->matrix); 868 (void)psBinaryOp(sumVector, sumVector, "+", stamp->vector); 869 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green"); 870 numStamps++; 871 } else if (stamp->status == PM_SUBTRACTION_STAMP_REJECTED) { 872 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red"); 873 } 874 } 875 876 #ifdef TESTING 877 for (int ix = 0; ix < sumVector->n; ix++) { 878 if (!isfinite(sumVector->data.F64[ix])) { 879 fprintf (stderr, "WARNING: NAN in vector\n"); 880 } 881 } 882 #endif 883 884 #if 0 885 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 886 calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[bgIndex][bgIndex]); 887 #endif 888 889 #ifdef TESTING 890 for (int ix = 0; ix < sumVector->n; ix++) { 891 if (!isfinite(sumVector->data.F64[ix])) { 892 fprintf (stderr, "WARNING: NAN in vector\n"); 893 } 894 } 895 { 896 psImage *inverse = psMatrixInvert(NULL, sumMatrix, NULL); 897 psFitsWriteImageSimple("matrixInv.fits", inverse, NULL); 898 psFree(inverse); 899 } 900 { 901 psImage *X = psMatrixInvert(NULL, sumMatrix, NULL); 902 psImage *Xt = psMatrixTranspose(NULL, X); 903 psImage *XtX = psMatrixMultiply(NULL, Xt, X); 904 psFitsWriteImageSimple("matrixErr.fits", XtX, NULL); 905 psFree(X); 906 psFree(Xt); 907 psFree(XtX); 908 } 909 #endif 910 911 # define SVD_ANALYSIS 0 912 # define COEFF_SIG 0.0 913 # define SVD_TOL 0.0 914 915 psVector *solution = NULL; 916 psVector *solutionErr = NULL; 917 918 #ifdef TESTING 919 psFitsWriteImageSimple("A.fits", sumMatrix, NULL); 920 psVectorWriteFile ("B.dat", sumVector); 921 #endif 922 923 // Use SVD to determine the kernel coeffs (and validate) 924 if (SVD_ANALYSIS) { 925 926 // We have sumVector and sumMatrix. we are trying to solve the following equation: 927 // sumMatrix * x = sumVector. 928 929 // we can use any standard matrix inversion to solve this. However, the basis 930 // functions in general have substantial correlation, so that the solution may be 931 // somewhat poorly determined or unstable. If not numerically ill-conditioned, the 932 // system of equations may be statistically ill-conditioned. Noise in the image 933 // will drive insignificant, but correlated, terms in the solution. To avoid these 934 // problems, we can use SVD to identify numerically unconstrained values and to 935 // avoid statistically badly determined value. 936 937 // A = sumMatrix, B = sumVector 938 // SVD: A = U w V^T -> A^{-1} = V (1/w) U^T 939 // x = V (1/w) (U^T B) 940 // \sigma_x = sqrt(diag(A^{-1})) 941 // solve for x and A^{-1} to get x & dx 942 // identify the elements of (1/w) that are nan (1/0.0) -> set to 0.0 943 // identify the elements of x that are insignificant (x / dx < 1.0? < 0.5?) -> set to 0.0 944 945 // If I use the SVD trick to re-condition the matrix, I need to break out the 946 // kernel and normalization terms from the background term. 947 // XXX is this true? or was this due to an error in the analysis? 948 949 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 950 951 // now pull out the kernel elements into their own square matrix 952 psImage *kernelMatrix = psImageAlloc (sumMatrix->numCols - 1, sumMatrix->numRows - 1, PS_TYPE_F64); 953 psVector *kernelVector = psVectorAlloc (sumMatrix->numCols - 1, PS_TYPE_F64); 954 955 for (int ix = 0, kx = 0; ix < sumMatrix->numCols; ix++) { 956 if (ix == bgIndex) continue; 957 for (int iy = 0, ky = 0; iy < sumMatrix->numRows; iy++) { 958 if (iy == bgIndex) continue; 959 kernelMatrix->data.F64[ky][kx] = sumMatrix->data.F64[iy][ix]; 960 ky++; 961 } 962 kernelVector->data.F64[kx] = sumVector->data.F64[ix]; 963 kx++; 964 } 965 966 psImage *U = NULL; 967 psImage *V = NULL; 968 psVector *w = NULL; 969 if (!psMatrixSVD (&U, &w, &V, kernelMatrix)) { 970 psError(PS_ERR_UNKNOWN, false, "failed to perform SVD on sumMatrix\n"); 971 return NULL; 972 } 973 974 // calculate A_inverse: 975 // Ainv = V * w * U^T 976 psImage *wUt = p_pmSubSolve_wUt (w, U); 977 psImage *Ainv = p_pmSubSolve_VwUt (V, wUt); 978 psImage *Xvar = NULL; 979 psFree (wUt); 980 981 # ifdef TESTING 982 // kernel terms: 983 for (int i = 0; i < w->n; i++) { 984 fprintf (stderr, "w: %f\n", w->data.F64[i]); 985 } 986 # endif 987 // loop over w adding in more and more of the values until chisquare is no longer 988 // dropping significantly. 989 // XXX this does not seem to work very well: we seem to need all terms even for 990 // simple cases... 991 992 psVector *Xsvd = NULL; 993 { 994 psVector *Ax = NULL; 995 psVector *UtB = NULL; 996 psVector *wUtB = NULL; 997 998 psVector *wApply = psVectorAlloc(w->n, PS_TYPE_F64); 999 psVector *wMask = psVectorAlloc(w->n, PS_TYPE_U8); 1000 psVectorInit (wMask, 1); // start by masking everything 1001 1002 double chiSquareLast = NAN; 1003 int maxWeight = 0; 1004 1005 double Axx, Bx, y2; 1006 1007 // XXX this is an attempt to exclude insignificant modes. 1008 // it was not successful with the ISIS kernel set: removing even 1009 // the least significant mode leaves additional ringing / noise 1010 // because the terms are so coupled. 1011 for (int k = 0; false && (k < w->n); k++) { 1012 1013 // unmask the k-th weight 1014 wMask->data.U8[k] = 0; 1015 p_pmSubSolve_SetWeights(wApply, w, wMask); 1016 1017 // solve for x: 1018 // x = V * w * (U^T * B) 1019 p_pmSubSolve_UtB (&UtB, U, kernelVector); 1020 p_pmSubSolve_wUtB (&wUtB, wApply, UtB); 1021 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB); 1022 1023 // chi-square for this system of equations: 1024 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^2 1025 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^2 1026 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd); 1027 p_pmSubSolve_VdV (&Axx, Ax, Xsvd); 1028 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd); 1029 p_pmSubSolve_y2 (&y2, kernels, stamps); 1030 1031 // apparently, this works (compare with the brute force value below 1032 double chiSquare = Axx - 2.0*Bx + y2; 1033 double deltaChi = (k == 0) ? chiSquare : chiSquareLast - chiSquare; 1034 chiSquareLast = chiSquare; 1035 1036 // fprintf (stderr, "chi square = %f, delta: %f\n", chiSquare, deltaChi); 1037 if (k && !maxWeight && (deltaChi < 1.0)) { 1038 maxWeight = k; 1039 } 1040 } 1041 1042 // keep all terms or we get extra ringing 1043 maxWeight = w->n; 1044 psVectorInit (wMask, 1); 1045 for (int k = 0; k < maxWeight; k++) { 1046 wMask->data.U8[k] = 0; 1047 } 1048 p_pmSubSolve_SetWeights(wApply, w, wMask); 1049 1050 // solve for x: 1051 // x = V * w * (U^T * B) 1052 p_pmSubSolve_UtB (&UtB, U, kernelVector); 1053 p_pmSubSolve_wUtB (&wUtB, wApply, UtB); 1054 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB); 1055 1056 // chi-square for this system of equations: 1057 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^2 1058 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^2 1059 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd); 1060 p_pmSubSolve_VdV (&Axx, Ax, Xsvd); 1061 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd); 1062 p_pmSubSolve_y2 (&y2, kernels, stamps); 1063 1064 // apparently, this works (compare with the brute force value below 1065 double chiSquare = Axx - 2.0*Bx + y2; 1066 psLogMsg ("psModules.imcombine", PS_LOG_INFO, "model kernel with %d terms; chi square = %f\n", maxWeight, chiSquare); 1067 1068 // re-calculate A^{-1} to get new variances: 1069 // Ainv = V * w * U^T 1070 // XXX since we keep all terms, this is identical to Ainv 1071 psImage *wUt = p_pmSubSolve_wUt (wApply, U); 1072 Xvar = p_pmSubSolve_VwUt (V, wUt); 1073 psFree (wUt); 1074 1075 psFree (Ax); 1076 psFree (UtB); 1077 psFree (wUtB); 1078 psFree (wApply); 1079 psFree (wMask); 1080 } 1081 1082 // copy the kernel solutions to the full solution vector: 1083 solution = psVectorAlloc(sumVector->n, PS_TYPE_F64); 1084 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64); 1085 1086 for (int ix = 0, kx = 0; ix < sumVector->n; ix++) { 1087 if (ix == bgIndex) { 1088 solution->data.F64[ix] = 0; 1089 solutionErr->data.F64[ix] = 0.001; 1090 continue; 1091 } 1092 solutionErr->data.F64[ix] = sqrt(Ainv->data.F64[kx][kx]); 1093 solution->data.F64[ix] = Xsvd->data.F64[kx]; 1094 kx++; 1095 } 1096 1097 psFree (kernelMatrix); 1098 psFree (kernelVector); 1099 1100 psFree (U); 1101 psFree (V); 1102 psFree (w); 1103 1104 psFree (Ainv); 1105 psFree (Xsvd); 1106 } else { 1107 psVector *permutation = NULL; // Permutation vector, required for LU decomposition 1108 psImage *luMatrix = psMatrixLUDecomposition(NULL, &permutation, sumMatrix); 1109 if (!luMatrix) { 1110 psError(PS_ERR_UNKNOWN, true, "LU Decomposition of least-squares matrix failed.\n"); 1111 psFree(solution); 1112 psFree(sumVector); 1113 psFree(sumMatrix); 1114 psFree(luMatrix); 1115 psFree(permutation); 1116 return NULL; 1117 } 1118 1119 solution = psMatrixLUSolution(NULL, luMatrix, sumVector, permutation); 1120 psFree(luMatrix); 1121 psFree(permutation); 1122 if (!solution) { 1123 psError(PS_ERR_UNKNOWN, true, "Failed to solve the least-squares system.\n"); 1124 psFree(solution); 1125 psFree(sumVector); 1126 psFree(sumMatrix); 1127 return NULL; 1128 } 1129 1130 // XXX LUD does not provide A^{-1}? fake the error for now 1131 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64); 1132 for (int ix = 0; ix < sumVector->n; ix++) { 1133 solutionErr->data.F64[ix] = 0.1*solution->data.F64[ix]; 1134 } 1135 } 1136 1137 if (!kernels->solution1) { 1138 kernels->solution1 = psVectorAlloc (sumVector->n, PS_TYPE_F64); 1139 psVectorInit (kernels->solution1, 0.0); 1140 } 1141 1142 // only update the solutions that we chose to calculate: 1143 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 1144 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1145 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex]; 1146 } 1147 if (mode & PM_SUBTRACTION_EQUATION_BG) { 1148 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 1149 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex]; 1150 } 1151 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 1152 int numKernels = kernels->num; 1153 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 1154 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 1155 for (int i = 0; i < numKernels * numPoly; i++) { 1156 // XXX fprintf (stderr, "%f +/- %f (%f) -> ", solution->data.F64[i], solutionErr->data.F64[i], fabs(solution->data.F64[i]/solutionErr->data.F64[i])); 1157 if (fabs(solution->data.F64[i] / solutionErr->data.F64[i]) < COEFF_SIG) { 1158 // XXX fprintf (stderr, "drop\n"); 1159 kernels->solution1->data.F64[i] = 0.0; 1160 } else { 1161 // XXX fprintf (stderr, "keep\n"); 1162 kernels->solution1->data.F64[i] = solution->data.F64[i]; 1163 } 1164 } 1165 } 1166 // double chiSquare = p_pmSubSolve_ChiSquare (kernels, stamps); 1167 // fprintf (stderr, "chi square Brute = %f\n", chiSquare); 1168 1169 psFree(solution); 1170 psFree(sumVector); 1171 psFree(sumMatrix); 1172 1173 #ifdef TESTING 1174 // XXX double-check for NAN in data: 1175 for (int ix = 0; ix < kernels->solution1->n; ix++) { 1176 if (!isfinite(kernels->solution1->data.F64[ix])) { 1177 fprintf (stderr, "WARNING: NAN in vector\n"); 1178 } 1179 } 1180 #endif 1181 1182 } else { 1183 // Dual convolution solution 1184 1185 // Accumulation of stamp matrices/vectors 1186 psImage *sumMatrix = psImageAlloc(numParams, numParams, PS_TYPE_F64); 1187 psVector *sumVector = psVectorAlloc(numParams, PS_TYPE_F64); 1188 psImageInit(sumMatrix, 0.0); 1189 psVectorInit(sumVector, 0.0); 954 955 psVector *norms = psVectorAllocEmpty(stamps->num, PS_TYPE_F64); // Normalisations 1190 956 1191 957 int numStamps = 0; // Number of good stamps … … 1195 961 (void)psBinaryOp(sumMatrix, sumMatrix, "+", stamp->matrix); 1196 962 (void)psBinaryOp(sumVector, sumVector, "+", stamp->vector); 963 psVectorAppend(norms, stamp->norm); 964 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green"); 965 numStamps++; 966 } else if (stamp->status == PM_SUBTRACTION_STAMP_REJECTED) { 967 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "red"); 968 } 969 } 970 971 #if 0 972 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 973 calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[bgIndex][bgIndex]); 974 #endif 975 976 psVector *solution = NULL; // Solution to equation! 977 solution = psVectorAlloc(numParams, PS_TYPE_F64); 978 psVectorInit(solution, 0); 979 980 #if 0 981 // Regular, straight-forward solution 982 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 983 #else 984 { 985 // Solve normalisation and background separately 986 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 987 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 988 989 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for norm 990 if (!psVectorStats(stats, norms, NULL, NULL, 0)) { 991 psError(PS_ERR_UNKNOWN, false, "Unable to determine median normalisation"); 992 psFree(stats); 993 psFree(sumMatrix); 994 psFree(sumVector); 995 psFree(norms); 996 return false; 997 } 998 999 double normValue = stats->robustMedian; 1000 // double bgValue = 0.0; 1001 1002 psFree(stats); 1003 1004 fprintf(stderr, "Norm: %lf\n", normValue); 1005 1006 // Solve kernel components 1007 for (int i = 0; i < numSolution1; i++) { 1008 sumVector->data.F64[i] -= normValue * sumMatrix->data.F64[normIndex][i]; 1009 1010 sumMatrix->data.F64[i][normIndex] = 0.0; 1011 sumMatrix->data.F64[normIndex][i] = 0.0; 1012 } 1013 sumVector->data.F64[bgIndex] -= normValue * sumMatrix->data.F64[normIndex][bgIndex]; 1014 sumMatrix->data.F64[bgIndex][normIndex] = 0.0; 1015 sumMatrix->data.F64[normIndex][bgIndex] = 0.0; 1016 1017 sumMatrix->data.F64[normIndex][normIndex] = 1.0; 1018 sumVector->data.F64[normIndex] = 0.0; 1019 1020 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1021 1022 solution->data.F64[normIndex] = normValue; 1023 } 1024 # endif 1025 1026 if (!kernels->solution1) { 1027 kernels->solution1 = psVectorAlloc(sumVector->n, PS_TYPE_F64); 1028 psVectorInit(kernels->solution1, 0.0); 1029 } 1030 1031 // only update the solutions that we chose to calculate: 1032 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 1033 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1034 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex]; 1035 } 1036 if (mode & PM_SUBTRACTION_EQUATION_BG) { 1037 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 1038 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex]; 1039 } 1040 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 1041 int numKernels = kernels->num; 1042 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 1043 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 1044 for (int i = 0; i < numKernels * numPoly; i++) { 1045 kernels->solution1->data.F64[i] = solution->data.F64[i]; 1046 } 1047 } 1048 1049 psFree(solution); 1050 psFree(sumVector); 1051 psFree(sumMatrix); 1052 1053 #ifdef TESTING 1054 // XXX double-check for NAN in data: 1055 for (int ix = 0; ix < kernels->solution1->n; ix++) { 1056 if (!isfinite(kernels->solution1->data.F64[ix])) { 1057 fprintf (stderr, "WARNING: NAN in vector\n"); 1058 } 1059 } 1060 #endif 1061 1062 } else { 1063 // Dual convolution solution 1064 1065 // Accumulation of stamp matrices/vectors 1066 psImage *sumMatrix = psImageAlloc(numParams, numParams, PS_TYPE_F64); 1067 psVector *sumVector = psVectorAlloc(numParams, PS_TYPE_F64); 1068 psImageInit(sumMatrix, 0.0); 1069 psVectorInit(sumVector, 0.0); 1070 1071 psVector *norms = psVectorAllocEmpty(stamps->num, PS_TYPE_F64); // Normalisations 1072 1073 int numStamps = 0; // Number of good stamps 1074 for (int i = 0; i < stamps->num; i++) { 1075 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest 1076 if (stamp->status == PM_SUBTRACTION_STAMP_USED) { 1077 (void)psBinaryOp(sumMatrix, sumMatrix, "+", stamp->matrix); 1078 (void)psBinaryOp(sumVector, sumVector, "+", stamp->vector); 1079 1080 psVectorAppend(norms, stamp->norm); 1197 1081 1198 1082 pmSubtractionStampPrint(ds9, stamp->x, stamp->y, stamps->footprint, "green"); … … 1207 1091 1208 1092 #if 1 1209 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 1210 calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[bgIndex][bgIndex]); 1093 // int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 1094 // calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[bgIndex][bgIndex]); 1095 1096 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1097 calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[normIndex][normIndex] / 1000.0); 1211 1098 #endif 1212 1099 … … 1216 1103 1217 1104 #if 0 1105 // Regular, straight-forward solution 1106 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1107 #else 1218 1108 { 1219 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1220 if (!solution) { 1221 psError(PS_ERR_UNKNOWN, false, "SVD solution of least-squares equation failed.\n"); 1109 // Solve normalisation and background separately 1110 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1111 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 1112 1113 #if 0 1114 psImage *normMatrix = psImageAlloc(2, 2, PS_TYPE_F64); 1115 psVector *normVector = psVectorAlloc(2, PS_TYPE_F64); 1116 1117 normMatrix->data.F64[0][0] = sumMatrix->data.F64[normIndex][normIndex]; 1118 normMatrix->data.F64[1][1] = sumMatrix->data.F64[bgIndex][bgIndex]; 1119 normMatrix->data.F64[0][1] = normMatrix->data.F64[1][0] = sumMatrix->data.F64[normIndex][bgIndex]; 1120 1121 normVector->data.F64[0] = sumVector->data.F64[normIndex]; 1122 normVector->data.F64[1] = sumVector->data.F64[bgIndex]; 1123 1124 psVector *normSolution = psMatrixSolveSVD(NULL, normMatrix, normVector, NAN); 1125 1126 double normValue = normSolution->data.F64[0]; 1127 double bgValue = normSolution->data.F64[1]; 1128 1129 psFree(normMatrix); 1130 psFree(normVector); 1131 psFree(normSolution); 1132 #endif 1133 1134 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); // Statistics for norm 1135 if (!psVectorStats(stats, norms, NULL, NULL, 0)) { 1136 psError(PS_ERR_UNKNOWN, false, "Unable to determine median normalisation"); 1137 psFree(stats); 1222 1138 psFree(sumMatrix); 1223 1139 psFree(sumVector); 1224 return NULL; 1225 } 1226 1227 #ifdef TESTING 1228 for (int i = 0; i < numParams; i++) { 1229 fprintf(stderr, "Solution %d: %lf\n", i, solution->data.F64[i]); 1230 } 1231 #endif 1232 1233 int numSpatial = PM_SUBTRACTION_POLYTERMS(kernels->spatialOrder); // Number of spatial variations 1234 int numKernels = kernels->num; // Number of kernel basis functions 1235 1236 #define MASK_BASIS(INDEX) \ 1237 { \ 1238 for (int j = 0, index = INDEX; j < numSpatial; j++, index += numKernels) { \ 1239 for (int k = 0; k < numParams; k++) { \ 1240 sumMatrix->data.F64[index][k] = sumMatrix->data.F64[k][index] = 0.0; \ 1241 } \ 1242 sumMatrix->data.F64[index][index] = 1.0; \ 1243 sumVector->data.F64[index] = 0.0; \ 1244 } \ 1245 } 1246 1247 #define TOL 1.0e-3 1248 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1249 double norm = fabs(solution->data.F64[normIndex]); // Normalisation 1250 double thresh = norm * TOL; // Threshold for low parameters 1251 for (int i = 0; i < numKernels; i++) { 1252 // Getting 0th order parameter value. In the presence of spatial variation, the actual value 1253 // of the parameter will vary over the image. We are in effect getting the value in the 1254 // centre of the image. If we use different polynomial functions (e.g., Chebyshev), we may 1255 // have to change this to properly determine the value of the parameter at the centre. 1256 double param1 = solution->data.F64[i], 1257 param2 = solution->data.F64[numSolution1 + i]; // Parameters of interest 1258 bool mask1 = false, mask2 = false; // Masked the parameter? 1259 if (fabs(param1) < thresh) { 1260 psTrace("psModules.imcombine", 7, "Parameter %d: 1 below threshold\n", i); 1261 MASK_BASIS(i); 1262 mask1 = true; 1263 } 1264 if (fabs(param2) < thresh) { 1265 psTrace("psModules.imcombine", 7, "Parameter %d: 2 below threshold\n", i); 1266 MASK_BASIS(numSolution1 + i); 1267 mask2 = true; 1268 } 1269 1270 if (!mask1 && !mask2) { 1271 if (fabs(param1) > fabs(param2)) { 1272 psTrace("psModules.imcombine", 7, "Parameter %d: 1 > 2\n", i); 1273 MASK_BASIS(numSolution1 + i); 1274 } else { 1275 psTrace("psModules.imcombine", 7, "Parameter %d: 2 > 1\n", i); 1276 MASK_BASIS(i); 1277 } 1278 } 1279 } 1280 1281 #ifdef TESTING 1282 psFitsWriteImageSimple ("sumMatrixFix.fits", sumMatrix, NULL); 1283 psVectorWriteFile("sumVectorFix.dat", sumVector); 1284 #endif 1285 } 1286 #endif /*** kernel-masking block ***/ 1287 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1140 psFree(norms); 1141 return false; 1142 } 1143 1144 double normValue = stats->robustMedian; 1145 1146 psFree(stats); 1147 1148 fprintf(stderr, "Norm: %lf\n", normValue); 1149 1150 // Solve kernel components 1151 for (int i = 0; i < numSolution2; i++) { 1152 sumVector->data.F64[i] -= normValue * sumMatrix->data.F64[normIndex][i]; 1153 sumVector->data.F64[i + numSolution1] -= normValue * sumMatrix->data.F64[normIndex][i + numSolution1]; 1154 1155 sumMatrix->data.F64[i][normIndex] = 0.0; 1156 sumMatrix->data.F64[normIndex][i] = 0.0; 1157 1158 sumMatrix->data.F64[i + numSolution1][normIndex] = 0.0; 1159 sumMatrix->data.F64[normIndex][i + numSolution1] = 0.0; 1160 } 1161 sumVector->data.F64[bgIndex] -= normValue * sumMatrix->data.F64[normIndex][bgIndex]; 1162 sumMatrix->data.F64[bgIndex][normIndex] = 0.0; 1163 sumMatrix->data.F64[normIndex][bgIndex] = 0.0; 1164 1165 sumMatrix->data.F64[normIndex][normIndex] = 1.0; 1166 1167 sumVector->data.F64[normIndex] = 0.0; 1168 1169 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1170 1171 solution->data.F64[normIndex] = normValue; 1172 } 1173 #endif 1174 1288 1175 1289 1176 #ifdef TESTING … … 1296 1183 psFree(sumVector); 1297 1184 1185 psFree(norms); 1186 1298 1187 if (!kernels->solution1) { 1299 1188 kernels->solution1 = psVectorAlloc(numSolution1, PS_TYPE_F64); 1189 psVectorInit (kernels->solution1, 0.0); 1300 1190 } 1301 1191 if (!kernels->solution2) { 1302 1192 kernels->solution2 = psVectorAlloc(numSolution2, PS_TYPE_F64); 1303 } 1193 psVectorInit (kernels->solution2, 0.0); 1194 } 1195 1196 // only update the solutions that we chose to calculate: 1197 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 1198 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1199 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex]; 1200 } 1201 if (mode & PM_SUBTRACTION_EQUATION_BG) { 1202 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 1203 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex]; 1204 } 1205 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 1206 int numKernels = kernels->num; 1207 for (int i = 0; i < numKernels * numSpatial; i++) { 1208 // XXX fprintf (stderr, "keep\n"); 1209 kernels->solution1->data.F64[i] = solution->data.F64[i]; 1210 kernels->solution2->data.F64[i] = solution->data.F64[i + numSolution1]; 1211 } 1212 } 1213 1304 1214 1305 1215 memcpy(kernels->solution1->data.F64, solution->data.F64, … … 1364 1274 } 1365 1275 float sigma = sqrt(dflux2 / npix - PS_SQR(dflux1/npix)); 1276 if (!isfinite(sum)) return false; 1277 if (!isfinite(dmax)) return false; 1278 if (!isfinite(dmin)) return false; 1279 if (!isfinite(peak)) return false; 1280 1366 1281 // fprintf (stderr, "sum: %f, peak: %f, sigma: %f, fsigma: %f, fmax: %f, fmin: %f\n", sum, peak, sigma, sigma/sum, dmax/peak, dmin/peak); 1367 1282 psVectorAppend(fSigRes, sigma/sum); … … 1973 1888 } 1974 1889 1890 1891 # if 0 1892 1893 #ifdef TESTING 1894 psFitsWriteImageSimple("A.fits", sumMatrix, NULL); 1895 psVectorWriteFile ("B.dat", sumVector); 1896 #endif 1897 1898 # define SVD_ANALYSIS 0 1899 # define COEFF_SIG 0.0 1900 # define SVD_TOL 0.0 1901 1902 // Use SVD to determine the kernel coeffs (and validate) 1903 if (SVD_ANALYSIS) { 1904 1905 // We have sumVector and sumMatrix. we are trying to solve the following equation: 1906 // sumMatrix * x = sumVector. 1907 1908 // we can use any standard matrix inversion to solve this. However, the basis 1909 // functions in general have substantial correlation, so that the solution may be 1910 // somewhat poorly determined or unstable. If not numerically ill-conditioned, the 1911 // system of equations may be statistically ill-conditioned. Noise in the image 1912 // will drive insignificant, but correlated, terms in the solution. To avoid these 1913 // problems, we can use SVD to identify numerically unconstrained values and to 1914 // avoid statistically badly determined value. 1915 1916 // A = sumMatrix, B = sumVector 1917 // SVD: A = U w V^T -> A^{-1} = V (1/w) U^T 1918 // x = V (1/w) (U^T B) 1919 // \sigma_x = sqrt(diag(A^{-1})) 1920 // solve for x and A^{-1} to get x & dx 1921 // identify the elements of (1/w) that are nan (1/0.0) -> set to 0.0 1922 // identify the elements of x that are insignificant (x / dx < 1.0? < 0.5?) -> set to 0.0 1923 1924 // If I use the SVD trick to re-condition the matrix, I need to break out the 1925 // kernel and normalization terms from the background term. 1926 // XXX is this true? or was this due to an error in the analysis? 1927 1928 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 1929 1930 // now pull out the kernel elements into their own square matrix 1931 psImage *kernelMatrix = psImageAlloc (sumMatrix->numCols - 1, sumMatrix->numRows - 1, PS_TYPE_F64); 1932 psVector *kernelVector = psVectorAlloc (sumMatrix->numCols - 1, PS_TYPE_F64); 1933 1934 for (int ix = 0, kx = 0; ix < sumMatrix->numCols; ix++) { 1935 if (ix == bgIndex) continue; 1936 for (int iy = 0, ky = 0; iy < sumMatrix->numRows; iy++) { 1937 if (iy == bgIndex) continue; 1938 kernelMatrix->data.F64[ky][kx] = sumMatrix->data.F64[iy][ix]; 1939 ky++; 1940 } 1941 kernelVector->data.F64[kx] = sumVector->data.F64[ix]; 1942 kx++; 1943 } 1944 1945 psImage *U = NULL; 1946 psImage *V = NULL; 1947 psVector *w = NULL; 1948 if (!psMatrixSVD (&U, &w, &V, kernelMatrix)) { 1949 psError(PS_ERR_UNKNOWN, false, "failed to perform SVD on sumMatrix\n"); 1950 return NULL; 1951 } 1952 1953 // calculate A_inverse: 1954 // Ainv = V * w * U^T 1955 psImage *wUt = p_pmSubSolve_wUt (w, U); 1956 psImage *Ainv = p_pmSubSolve_VwUt (V, wUt); 1957 psImage *Xvar = NULL; 1958 psFree (wUt); 1959 1960 # ifdef TESTING 1961 // kernel terms: 1962 for (int i = 0; i < w->n; i++) { 1963 fprintf (stderr, "w: %f\n", w->data.F64[i]); 1964 } 1965 # endif 1966 // loop over w adding in more and more of the values until chisquare is no longer 1967 // dropping significantly. 1968 // XXX this does not seem to work very well: we seem to need all terms even for 1969 // simple cases... 1970 1971 psVector *Xsvd = NULL; 1972 { 1973 psVector *Ax = NULL; 1974 psVector *UtB = NULL; 1975 psVector *wUtB = NULL; 1976 1977 psVector *wApply = psVectorAlloc(w->n, PS_TYPE_F64); 1978 psVector *wMask = psVectorAlloc(w->n, PS_TYPE_U8); 1979 psVectorInit (wMask, 1); // start by masking everything 1980 1981 double chiSquareLast = NAN; 1982 int maxWeight = 0; 1983 1984 double Axx, Bx, y2; 1985 1986 // XXX this is an attempt to exclude insignificant modes. 1987 // it was not successful with the ISIS kernel set: removing even 1988 // the least significant mode leaves additional ringing / noise 1989 // because the terms are so coupled. 1990 for (int k = 0; false && (k < w->n); k++) { 1991 1992 // unmask the k-th weight 1993 wMask->data.U8[k] = 0; 1994 p_pmSubSolve_SetWeights(wApply, w, wMask); 1995 1996 // solve for x: 1997 // x = V * w * (U^T * B) 1998 p_pmSubSolve_UtB (&UtB, U, kernelVector); 1999 p_pmSubSolve_wUtB (&wUtB, wApply, UtB); 2000 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB); 2001 2002 // chi-square for this system of equations: 2003 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^2 2004 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^2 2005 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd); 2006 p_pmSubSolve_VdV (&Axx, Ax, Xsvd); 2007 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd); 2008 p_pmSubSolve_y2 (&y2, kernels, stamps); 2009 2010 // apparently, this works (compare with the brute force value below 2011 double chiSquare = Axx - 2.0*Bx + y2; 2012 double deltaChi = (k == 0) ? chiSquare : chiSquareLast - chiSquare; 2013 chiSquareLast = chiSquare; 2014 2015 // fprintf (stderr, "chi square = %f, delta: %f\n", chiSquare, deltaChi); 2016 if (k && !maxWeight && (deltaChi < 1.0)) { 2017 maxWeight = k; 2018 } 2019 } 2020 2021 // keep all terms or we get extra ringing 2022 maxWeight = w->n; 2023 psVectorInit (wMask, 1); 2024 for (int k = 0; k < maxWeight; k++) { 2025 wMask->data.U8[k] = 0; 2026 } 2027 p_pmSubSolve_SetWeights(wApply, w, wMask); 2028 2029 // solve for x: 2030 // x = V * w * (U^T * B) 2031 p_pmSubSolve_UtB (&UtB, U, kernelVector); 2032 p_pmSubSolve_wUtB (&wUtB, wApply, UtB); 2033 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB); 2034 2035 // chi-square for this system of equations: 2036 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^2 2037 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^2 2038 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd); 2039 p_pmSubSolve_VdV (&Axx, Ax, Xsvd); 2040 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd); 2041 p_pmSubSolve_y2 (&y2, kernels, stamps); 2042 2043 // apparently, this works (compare with the brute force value below 2044 double chiSquare = Axx - 2.0*Bx + y2; 2045 psLogMsg ("psModules.imcombine", PS_LOG_INFO, "model kernel with %d terms; chi square = %f\n", maxWeight, chiSquare); 2046 2047 // re-calculate A^{-1} to get new variances: 2048 // Ainv = V * w * U^T 2049 // XXX since we keep all terms, this is identical to Ainv 2050 psImage *wUt = p_pmSubSolve_wUt (wApply, U); 2051 Xvar = p_pmSubSolve_VwUt (V, wUt); 2052 psFree (wUt); 2053 2054 psFree (Ax); 2055 psFree (UtB); 2056 psFree (wUtB); 2057 psFree (wApply); 2058 psFree (wMask); 2059 } 2060 2061 // copy the kernel solutions to the full solution vector: 2062 solution = psVectorAlloc(sumVector->n, PS_TYPE_F64); 2063 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64); 2064 2065 for (int ix = 0, kx = 0; ix < sumVector->n; ix++) { 2066 if (ix == bgIndex) { 2067 solution->data.F64[ix] = 0; 2068 solutionErr->data.F64[ix] = 0.001; 2069 continue; 2070 } 2071 solutionErr->data.F64[ix] = sqrt(Ainv->data.F64[kx][kx]); 2072 solution->data.F64[ix] = Xsvd->data.F64[kx]; 2073 kx++; 2074 } 2075 2076 psFree (kernelMatrix); 2077 psFree (kernelVector); 2078 2079 psFree (U); 2080 psFree (V); 2081 psFree (w); 2082 2083 psFree (Ainv); 2084 psFree (Xsvd); 2085 } else { 2086 psVector *permutation = NULL; // Permutation vector, required for LU decomposition 2087 psImage *luMatrix = psMatrixLUDecomposition(NULL, &permutation, sumMatrix); 2088 if (!luMatrix) { 2089 psError(PS_ERR_UNKNOWN, true, "LU Decomposition of least-squares matrix failed.\n"); 2090 psFree(solution); 2091 psFree(sumVector); 2092 psFree(sumMatrix); 2093 psFree(luMatrix); 2094 psFree(permutation); 2095 return NULL; 2096 } 2097 2098 solution = psMatrixLUSolution(NULL, luMatrix, sumVector, permutation); 2099 psFree(luMatrix); 2100 psFree(permutation); 2101 if (!solution) { 2102 psError(PS_ERR_UNKNOWN, true, "Failed to solve the least-squares system.\n"); 2103 psFree(solution); 2104 psFree(sumVector); 2105 psFree(sumMatrix); 2106 return NULL; 2107 } 2108 2109 // XXX LUD does not provide A^{-1}? fake the error for now 2110 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64); 2111 for (int ix = 0; ix < sumVector->n; ix++) { 2112 solutionErr->data.F64[ix] = 0.1*solution->data.F64[ix]; 2113 } 2114 } 2115 2116 if (!kernels->solution1) { 2117 kernels->solution1 = psVectorAlloc (sumVector->n, PS_TYPE_F64); 2118 psVectorInit (kernels->solution1, 0.0); 2119 } 2120 2121 // only update the solutions that we chose to calculate: 2122 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 2123 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 2124 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex]; 2125 } 2126 if (mode & PM_SUBTRACTION_EQUATION_BG) { 2127 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 2128 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex]; 2129 } 2130 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 2131 int numKernels = kernels->num; 2132 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 2133 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 2134 for (int i = 0; i < numKernels * numPoly; i++) { 2135 // XXX fprintf (stderr, "%f +/- %f (%f) -> ", solution->data.F64[i], solutionErr->data.F64[i], fabs(solution->data.F64[i]/solutionErr->data.F64[i])); 2136 if (fabs(solution->data.F64[i] / solutionErr->data.F64[i]) < COEFF_SIG) { 2137 // XXX fprintf (stderr, "drop\n"); 2138 kernels->solution1->data.F64[i] = 0.0; 2139 } else { 2140 // XXX fprintf (stderr, "keep\n"); 2141 kernels->solution1->data.F64[i] = solution->data.F64[i]; 2142 } 2143 } 2144 } 2145 // double chiSquare = p_pmSubSolve_ChiSquare (kernels, stamps); 2146 // fprintf (stderr, "chi square Brute = %f\n", chiSquare); 2147 2148 psFree(solution); 2149 psFree(sumVector); 2150 psFree(sumMatrix); 2151 # endif 2152 2153 #ifdef TESTING 2154 // XXX double-check for NAN in data: 2155 for (int iy = 0; iy < stamp->matrix->numRows; iy++) { 2156 for (int ix = 0; ix < stamp->matrix->numCols; ix++) { 2157 if (!isfinite(stamp->matrix->data.F64[iy][ix])) { 2158 fprintf (stderr, "WARNING: NAN in matrix\n"); 2159 } 2160 } 2161 } 2162 for (int ix = 0; ix < stamp->vector->n; ix++) { 2163 if (!isfinite(stamp->vector->data.F64[ix])) { 2164 fprintf (stderr, "WARNING: NAN in vector\n"); 2165 } 2166 } 2167 #endif 2168 2169 #ifdef TESTING 2170 for (int ix = 0; ix < sumVector->n; ix++) { 2171 if (!isfinite(sumVector->data.F64[ix])) { 2172 fprintf (stderr, "WARNING: NAN in vector\n"); 2173 } 2174 } 2175 #endif 2176 2177 #ifdef TESTING 2178 for (int ix = 0; ix < sumVector->n; ix++) { 2179 if (!isfinite(sumVector->data.F64[ix])) { 2180 fprintf (stderr, "WARNING: NAN in vector\n"); 2181 } 2182 } 2183 { 2184 psImage *inverse = psMatrixInvert(NULL, sumMatrix, NULL); 2185 psFitsWriteImageSimple("matrixInv.fits", inverse, NULL); 2186 psFree(inverse); 2187 } 2188 { 2189 psImage *X = psMatrixInvert(NULL, sumMatrix, NULL); 2190 psImage *Xt = psMatrixTranspose(NULL, X); 2191 psImage *XtX = psMatrixMultiply(NULL, Xt, X); 2192 psFitsWriteImageSimple("matrixErr.fits", XtX, NULL); 2193 psFree(X); 2194 psFree(Xt); 2195 psFree(XtX); 2196 } 2197 #endif 2198 -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionEquation.h
r26577 r26747 10 10 PM_SUBTRACTION_EQUATION_BG = 0x02, 11 11 PM_SUBTRACTION_EQUATION_KERNELS = 0x04, 12 PM_SUBTRACTION_EQUATION_ALL = 0x0 5, // value should be NORM | BG | KERNELS12 PM_SUBTRACTION_EQUATION_ALL = 0x07, // value should be NORM | BG | KERNELS 13 13 } pmSubtractionEquationCalculationMode; 14 14 … … 21 21 const pmSubtractionKernels *kernels, ///< Kernel parameters 22 22 int index, ///< Index of stamp 23 const pmSubtractionEquationCalculationMode mode23 const pmSubtractionEquationCalculationMode mode 24 24 ); 25 25 … … 27 27 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, ///< Stamps 28 28 const pmSubtractionKernels *kernels, ///< Kernel parameters 29 const pmSubtractionEquationCalculationMode mode29 const pmSubtractionEquationCalculationMode mode 30 30 ); 31 31 … … 33 33 bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, ///< Kernel parameters 34 34 const pmSubtractionStampList *stamps, ///< Stamps 35 const pmSubtractionEquationCalculationMode mode35 const pmSubtractionEquationCalculationMode mode 36 36 ); 37 37 -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionIO.c
r23378 r26747 80 80 while ((item = psMetadataGetAndIncrement(iter))) { 81 81 assert(item->type == PS_DATA_UNKNOWN); 82 // Set the normalisation dimensions, since these will be otherwise unavailable when reading the83 // images by scans.84 82 pmSubtractionKernels *kernel = item->data.V; // Kernel used in subtraction 85 kernel->numCols = ro->image->numCols;86 kernel->numRows = ro->image->numRows;87 88 83 kernels = psArrayAdd(kernels, ARRAY_BUFFER, kernel); 89 84 } … … 126 121 kernel->bgOrder); 127 122 psMetadataAddS32(row, PS_LIST_TAIL, NAME_MODE, 0, "Matching mode (enum)", kernel->mode); 128 psMetadataAddS32(row, PS_LIST_TAIL, NAME_COLS, 0, "Number of columns", kernel->numCols);129 psMetadataAddS32(row, PS_LIST_TAIL, NAME_ROWS, 0, "Number of rows", kernel->numRows);130 123 if (kernel->mode == PM_SUBTRACTION_MODE_1 || kernel->mode == PM_SUBTRACTION_MODE_2) { 131 124 psMetadataAddVector(row, PS_LIST_TAIL, NAME_SOL1, 0, "Solution vector 1", kernel->solution1); … … 318 311 319 312 TABLE_LOOKUP(int, S32, bg, NAME_BG); 320 TABLE_LOOKUP(int, S32, numCols, NAME_COLS);321 TABLE_LOOKUP(int, S32, numRows, NAME_ROWS);322 313 323 314 TABLE_LOOKUP(float, F32, mean, NAME_MEAN); … … 325 316 TABLE_LOOKUP(int, S32, numStamps, NAME_NUMSTAMPS); 326 317 327 pmSubtractionKernels *kernels = pmSubtractionKernelsFromDescription(description, bg, mode); 328 kernels->numCols = numCols; 329 kernels->numRows = numRows; 318 pmSubtractionKernels *kernels = pmSubtractionKernelsFromDescription(description, bg, *region, mode); 330 319 kernels->mean = mean; 331 320 kernels->rms = rms; -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionKernels.c
r26657 r26747 276 276 pmSubtractionKernels *p_pmSubtractionKernelsRawISIS(int size, int spatialOrder, 277 277 const psVector *fwhmsIN, const psVector *ordersIN, 278 float penalty, p mSubtractionMode mode)278 float penalty, psRegion bounds, pmSubtractionMode mode) 279 279 { 280 280 PS_ASSERT_VECTOR_NON_NULL(fwhmsIN, NULL); … … 306 306 307 307 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_ISIS, size, 308 spatialOrder, penalty, mode); // The kernels308 spatialOrder, penalty, bounds, mode); // Kernels 309 309 psStringAppend(&kernels->description, "ISIS(%d,%s,%d,%.2e)", size, params, spatialOrder, penalty); 310 310 … … 332 332 pmSubtractionKernels *pmSubtractionKernelsISIS_RADIAL(int size, int spatialOrder, 333 333 const psVector *fwhmsIN, const psVector *ordersIN, 334 float penalty, p mSubtractionMode mode)334 float penalty, psRegion bounds, pmSubtractionMode mode) 335 335 { 336 336 PS_ASSERT_VECTOR_NON_NULL(fwhmsIN, NULL); … … 362 362 } 363 363 364 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_ISIS_RADIAL, size, spatialOrder, penalty, mode); // The kernels 364 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_ISIS_RADIAL, size, 365 spatialOrder, penalty, bounds, mode); // Kernels 365 366 psStringAppend(&kernels->description, "ISIS_RADIAL(%d,%s,%d,%.2e)", size, params, spatialOrder, penalty); 366 367 … … 389 390 pmSubtractionKernels *pmSubtractionKernelsHERM(int size, int spatialOrder, 390 391 const psVector *fwhmsIN, const psVector *ordersIN, 391 float penalty, p mSubtractionMode mode)392 float penalty, psRegion bounds, pmSubtractionMode mode) 392 393 { 393 394 PS_ASSERT_VECTOR_NON_NULL(fwhmsIN, NULL); … … 418 419 } 419 420 420 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_HERM, size, spatialOrder, penalty, mode); // The kernels 421 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_HERM, size, 422 spatialOrder, penalty, bounds, mode); // Kernels 421 423 psStringAppend(&kernels->description, "HERM(%d,%s,%d,%.2e)", size, params, spatialOrder, penalty); 422 424 423 psLogMsg("psModules.imcombine", PS_LOG_INFO, "HERM kernel: %s,%d --> %d elements", params, spatialOrder, num); 425 psLogMsg("psModules.imcombine", PS_LOG_INFO, "HERM kernel: %s,%d --> %d elements", 426 params, spatialOrder, num); 424 427 psFree(params); 425 428 … … 440 443 441 444 pmSubtractionKernels *pmSubtractionKernelsDECONV_HERM(int size, int spatialOrder, 442 const psVector *fwhmsIN, const psVector *ordersIN,443 float penalty, pmSubtractionMode mode)445 const psVector *fwhmsIN, const psVector *ordersIN, 446 float penalty, psRegion bounds, pmSubtractionMode mode) 444 447 { 445 448 PS_ASSERT_VECTOR_NON_NULL(fwhmsIN, NULL); … … 470 473 } 471 474 472 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_DECONV_HERM, size, spatialOrder, penalty, mode); // The kernels 475 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_DECONV_HERM, size, 476 spatialOrder, penalty, bounds, mode); // Kernels 473 477 psStringAppend(&kernels->description, "DECONV_HERM(%d,%s,%d,%.2e)", size, params, spatialOrder, penalty); 474 478 … … 545 549 546 550 pmSubtractionKernels *pmSubtractionKernelsAlloc(int numBasisFunctions, pmSubtractionKernelsType type, 547 int size, int spatialOrder, float penalty, 551 int size, int spatialOrder, float penalty, psRegion bounds, 548 552 pmSubtractionMode mode) 549 553 { … … 559 563 kernels->uStop = NULL; 560 564 kernels->vStop = NULL; 565 kernels->xMin = bounds.x0; 566 kernels->xMax = bounds.x1; 567 kernels->yMin = bounds.y0; 568 kernels->yMax = bounds.y1; 561 569 kernels->preCalc = psArrayAlloc(numBasisFunctions); 562 570 kernels->penalty = penalty; … … 567 575 kernels->bgOrder = 0; 568 576 kernels->mode = mode; 569 kernels->numCols = 0;570 kernels->numRows = 0;571 577 kernels->solution1 = NULL; 572 578 kernels->solution2 = NULL; … … 641 647 } 642 648 643 pmSubtractionKernels *pmSubtractionKernelsPOIS(int size, int spatialOrder, float penalty, 649 pmSubtractionKernels *pmSubtractionKernelsPOIS(int size, int spatialOrder, float penalty, psRegion bounds, 644 650 pmSubtractionMode mode) 645 651 { … … 650 656 651 657 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(0, PM_SUBTRACTION_KERNEL_POIS, size, 652 spatialOrder, penalty, mode); // The kernels658 spatialOrder, penalty, bounds, mode); // Kernels 653 659 psStringAppend(&kernels->description, "POIS(%d,%d,%.2e)", size, spatialOrder, penalty); 654 660 psLogMsg("psModules.imcombine", PS_LOG_INFO, "POIS kernel: %d,%d --> %d elements", … … 665 671 pmSubtractionKernels *pmSubtractionKernelsISIS(int size, int spatialOrder, 666 672 const psVector *fwhms, const psVector *orders, 667 float penalty, p mSubtractionMode mode)673 float penalty, psRegion bounds, pmSubtractionMode mode) 668 674 { 669 675 pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, fwhms, orders, 670 penalty, mode); // Kernels676 penalty, bounds, mode); // Kernels 671 677 if (!kernels) { 672 678 return NULL; … … 677 683 678 684 pmSubtractionKernels *pmSubtractionKernelsSPAM(int size, int spatialOrder, int inner, int binning, 679 float penalty, p mSubtractionMode mode)685 float penalty, psRegion bounds, pmSubtractionMode mode) 680 686 { 681 687 PS_ASSERT_INT_POSITIVE(size, NULL); … … 698 704 699 705 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_SPAM, size, 700 spatialOrder, penalty, mode); // The kernels706 spatialOrder, penalty, bounds, mode); // Kernels 701 707 kernels->inner = inner; 702 708 psStringAppend(&kernels->description, "SPAM(%d,%d,%d,%d,%.2e)", size, inner, binning, spatialOrder, … … 769 775 770 776 pmSubtractionKernels *pmSubtractionKernelsFRIES(int size, int spatialOrder, int inner, float penalty, 771 p mSubtractionMode mode)777 psRegion bounds, pmSubtractionMode mode) 772 778 { 773 779 PS_ASSERT_INT_POSITIVE(size, NULL); … … 796 802 797 803 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_FRIES, size, 798 spatialOrder, penalty, mode); // The kernels804 spatialOrder, penalty, bounds, mode); // Kernels 799 805 kernels->inner = inner; 800 806 psStringAppend(&kernels->description, "FRIES(%d,%d,%d,%.2e)", size, inner, spatialOrder, penalty); … … 865 871 pmSubtractionKernels *pmSubtractionKernelsGUNK(int size, int spatialOrder, const psVector *fwhms, 866 872 const psVector *orders, int inner, float penalty, 867 p mSubtractionMode mode)873 psRegion bounds, pmSubtractionMode mode) 868 874 { 869 875 PS_ASSERT_INT_POSITIVE(size, NULL); … … 878 884 879 885 pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, fwhms, orders, 880 penalty, mode); // Kernels886 penalty, bounds, mode); // Kernels 881 887 kernels->type = PM_SUBTRACTION_KERNEL_GUNK; 882 888 psStringPrepend(&kernels->description, "GUNK="); … … 894 900 // RINGS --- just what it says 895 901 pmSubtractionKernels *pmSubtractionKernelsRINGS(int size, int spatialOrder, int inner, int ringsOrder, 896 float penalty, p mSubtractionMode mode)902 float penalty, psRegion bounds, pmSubtractionMode mode) 897 903 { 898 904 PS_ASSERT_INT_POSITIVE(size, NULL); … … 925 931 926 932 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_RINGS, size, 927 spatialOrder, penalty, mode); // The kernels933 spatialOrder, penalty, bounds, mode); // Kernels 928 934 kernels->inner = inner; 929 935 psStringAppend(&kernels->description, "RINGS(%d,%d,%d,%d,%.2e)", size, inner, ringsOrder, spatialOrder, … … 1047 1053 pmSubtractionKernels *pmSubtractionKernelsGenerate(pmSubtractionKernelsType type, int size, int spatialOrder, 1048 1054 const psVector *fwhms, const psVector *orders, int inner, 1049 int binning, int ringsOrder, float penalty, 1055 int binning, int ringsOrder, float penalty, psRegion bounds, 1050 1056 pmSubtractionMode mode) 1051 1057 { 1052 1058 switch (type) { 1053 1059 case PM_SUBTRACTION_KERNEL_POIS: 1054 return pmSubtractionKernelsPOIS(size, spatialOrder, penalty, mode);1060 return pmSubtractionKernelsPOIS(size, spatialOrder, penalty, bounds, mode); 1055 1061 case PM_SUBTRACTION_KERNEL_ISIS: 1056 return pmSubtractionKernelsISIS(size, spatialOrder, fwhms, orders, penalty, mode);1062 return pmSubtractionKernelsISIS(size, spatialOrder, fwhms, orders, penalty, bounds, mode); 1057 1063 case PM_SUBTRACTION_KERNEL_ISIS_RADIAL: 1058 return pmSubtractionKernelsISIS_RADIAL(size, spatialOrder, fwhms, orders, penalty, mode);1064 return pmSubtractionKernelsISIS_RADIAL(size, spatialOrder, fwhms, orders, penalty, bounds, mode); 1059 1065 case PM_SUBTRACTION_KERNEL_HERM: 1060 return pmSubtractionKernelsHERM(size, spatialOrder, fwhms, orders, penalty, mode);1066 return pmSubtractionKernelsHERM(size, spatialOrder, fwhms, orders, penalty, bounds, mode); 1061 1067 case PM_SUBTRACTION_KERNEL_DECONV_HERM: 1062 return pmSubtractionKernelsDECONV_HERM(size, spatialOrder, fwhms, orders, penalty, mode);1068 return pmSubtractionKernelsDECONV_HERM(size, spatialOrder, fwhms, orders, penalty, bounds, mode); 1063 1069 case PM_SUBTRACTION_KERNEL_SPAM: 1064 return pmSubtractionKernelsSPAM(size, spatialOrder, inner, binning, penalty, mode);1070 return pmSubtractionKernelsSPAM(size, spatialOrder, inner, binning, penalty, bounds, mode); 1065 1071 case PM_SUBTRACTION_KERNEL_FRIES: 1066 return pmSubtractionKernelsFRIES(size, spatialOrder, inner, penalty, mode);1072 return pmSubtractionKernelsFRIES(size, spatialOrder, inner, penalty, bounds, mode); 1067 1073 case PM_SUBTRACTION_KERNEL_GUNK: 1068 return pmSubtractionKernelsGUNK(size, spatialOrder, fwhms, orders, inner, penalty, mode);1074 return pmSubtractionKernelsGUNK(size, spatialOrder, fwhms, orders, inner, penalty, bounds, mode); 1069 1075 case PM_SUBTRACTION_KERNEL_RINGS: 1070 return pmSubtractionKernelsRINGS(size, spatialOrder, inner, ringsOrder, penalty, mode);1076 return pmSubtractionKernelsRINGS(size, spatialOrder, inner, ringsOrder, penalty, bounds, mode); 1071 1077 default: 1072 1078 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unknown kernel type: %x", type); … … 1104 1110 1105 1111 pmSubtractionKernels *pmSubtractionKernelsFromDescription(const char *description, int bgOrder, 1106 p mSubtractionMode mode)1112 psRegion bounds, pmSubtractionMode mode) 1107 1113 { 1108 1114 PS_ASSERT_STRING_NON_EMPTY(description, NULL); … … 1129 1135 1130 1136 type = pmSubtractionKernelsTypeFromString (description); 1131 char *ptr = strchr(description, '(') ;1137 char *ptr = strchr(description, '(') + 1; 1132 1138 psAssert (ptr, "description is missing kernel parameters"); 1133 1139 … … 1157 1163 PARSE_STRING_NUMBER(spatialOrder, ptr, ',', parseStringInt); 1158 1164 penalty = parseStringFloat(ptr); 1159 1160 return pmSubtractionKernelsGenerate(type, size, spatialOrder, fwhms, orders, inner, binning, ringsOrder, penalty, mode); 1161 1165 break; 1162 1166 case PM_SUBTRACTION_KERNEL_RINGS: 1163 1167 PARSE_STRING_NUMBER(size, ptr, ',', parseStringInt); … … 1166 1170 PARSE_STRING_NUMBER(spatialOrder, ptr, ',', parseStringInt); 1167 1171 PARSE_STRING_NUMBER(penalty, ptr, ')', parseStringInt); 1168 return pmSubtractionKernelsGenerate(type, size, spatialOrder, fwhms, orders, inner, binning, ringsOrder, penalty, mode);1172 break; 1169 1173 default: 1170 1174 psAbort("Deciphering kernels other than ISIS, HERM, DECONV_HERM or RINGS is not currently supported."); 1171 1175 } 1172 return NULL; 1176 1177 return pmSubtractionKernelsGenerate(type, size, spatialOrder, fwhms, orders, inner, binning, 1178 ringsOrder, penalty, bounds, mode); 1173 1179 } 1174 1180 … … 1246 1252 out->bgOrder = in->bgOrder; 1247 1253 out->mode = in->mode; 1248 out->numCols = in->numCols; 1249 out->numRows = in->numRows; 1254 out->xMin = in->xMin; 1255 out->xMax = in->xMax; 1256 out->yMin = in->yMin; 1257 out->yMax = in->yMax; 1250 1258 out->solution1 = in->solution1 ? psVectorCopy(NULL, in->solution1, PS_TYPE_F64) : NULL; 1251 1259 out->solution2 = in->solution2 ? psVectorCopy(NULL, in->solution2, PS_TYPE_F64) : NULL; -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionKernels.h
r26593 r26747 12 12 PM_SUBTRACTION_KERNEL_ISIS_RADIAL, ///< ISIS + higher-order radial Hermitians 13 13 PM_SUBTRACTION_KERNEL_HERM, ///< Hermitian polynomial kernels 14 PM_SUBTRACTION_KERNEL_DECONV_HERM, ///< Deconvolved Hermitian polynomial kernels14 PM_SUBTRACTION_KERNEL_DECONV_HERM, ///< Deconvolved Hermitian polynomial kernels 15 15 PM_SUBTRACTION_KERNEL_SPAM, ///< Summed Pixels for Advanced Matching --- summed delta functions 16 16 PM_SUBTRACTION_KERNEL_FRIES, ///< Fibonacci Radius Increases Excellence of Subtraction … … 32 32 pmSubtractionKernelsType type; ///< Type of kernels --- allowing the use of multiple kernels 33 33 psString description; ///< Description of the kernel parameters 34 int xMin, xMax, yMin, yMax; ///< Bounds of image (for normalisation) 34 35 long num; ///< Number of kernel components (not including the spatial ones) 35 36 psVector *u, *v; ///< Offset (for POIS) or polynomial order (for ISIS, HERM or DECONV_HERM) … … 44 45 int bgOrder; ///< The order for the background fitting 45 46 pmSubtractionMode mode; ///< Mode for subtraction 46 int numCols, numRows; ///< Size of image (for normalisation), or zero to use image provided47 47 psVector *solution1, *solution2; ///< Solution for the PSF matching 48 48 // Quality information 49 49 float mean, rms; ///< Mean and RMS of chi^2 from stamps 50 50 int numStamps; ///< Number of good stamps 51 float fSigResMean; ///< mean fractional stdev of residuals52 float fSigResStdev; ///< stdev of fractional stdev of residuals53 float fMaxResMean; ///< mean fractional positive swing in residuals54 float fMaxResStdev; ///< stdev of fractional positive swing in residuals55 float fMinResMean; ///< mean fractional negative swing in residuals56 float fMinResStdev; ///< stdev of fractional negative swing in residuals57 psArray *sampleStamps; ///< array of brightest set of stamps for output visualizations51 float fSigResMean; ///< mean fractional stdev of residuals 52 float fSigResStdev; ///< stdev of fractional stdev of residuals 53 float fMaxResMean; ///< mean fractional positive swing in residuals 54 float fMaxResStdev; ///< stdev of fractional positive swing in residuals 55 float fMinResMean; ///< mean fractional negative swing in residuals 56 float fMinResStdev; ///< stdev of fractional negative swing in residuals 57 psArray *sampleStamps; ///< array of brightest set of stamps for output visualizations 58 58 } pmSubtractionKernels; 59 59 60 60 // pmSubtractionKernels->preCalc is an array of pmSubtractionKernelPreCalc structures 61 61 typedef struct { 62 psVector *uCoords; // used by RINGS63 psVector *vCoords; // used by RINGS64 psVector *poly; // used by RINGS65 66 psVector *xKernel; // used by ISIS, HERM, DECONV_HERM67 psVector *yKernel; // used by ISIS, HERM, DECONV_HERM68 psKernel *kernel; // used by ISIS, HERM, DECONV_HERM62 psVector *uCoords; // used by RINGS 63 psVector *vCoords; // used by RINGS 64 psVector *poly; // used by RINGS 65 66 psVector *xKernel; // used by ISIS, HERM, DECONV_HERM 67 psVector *yKernel; // used by ISIS, HERM, DECONV_HERM 68 psKernel *kernel; // used by ISIS, HERM, DECONV_HERM 69 69 } pmSubtractionKernelPreCalc; 70 70 … … 162 162 int spatialOrder, ///< Order of spatial variations 163 163 float penalty, ///< Penalty for wideness 164 psRegion bounds, ///< Bounds for validity 164 165 pmSubtractionMode mode ///< Mode for subtraction 165 166 ); … … 168 169 pmSubtractionKernelPreCalc *pmSubtractionKernelPreCalcAlloc( 169 170 pmSubtractionKernelsType type, ///< type of kernel to allocate (not all can be pre-calculated) 170 int uOrder, ///< order in x-direction171 int vOrder, ///< order in x-direction172 int size, ///< Half-size of the kernel173 float sigma ///< sigma of gaussian kernel171 int uOrder, ///< order in x-direction 172 int vOrder, ///< order in x-direction 173 int size, ///< Half-size of the kernel 174 float sigma ///< sigma of gaussian kernel 174 175 ); 175 176 … … 179 180 int spatialOrder, ///< Order of spatial variations 180 181 float penalty, ///< Penalty for wideness 182 psRegion bounds, ///< Bounds for validity 181 183 pmSubtractionMode mode ///< Mode for subtraction 182 184 ); … … 188 190 const psVector *orders, ///< Polynomial order of gaussians 189 191 float penalty, ///< Penalty for wideness 192 psRegion bounds, ///< Bounds for validity 190 193 pmSubtractionMode mode ///< Mode for subtraction 191 194 ); … … 197 200 const psVector *orders, ///< Polynomial order of gaussians 198 201 float penalty, ///< Penalty for wideness 202 psRegion bounds, ///< Bounds for validity 199 203 pmSubtractionMode mode ///< Mode for subtraction 200 204 ); … … 202 206 /// Generate ISIS + RADIAL_HERM kernels 203 207 pmSubtractionKernels *pmSubtractionKernelsISIS_RADIAL(int size, ///< Half-size of the kernel 204 int spatialOrder, ///< Order of spatial variations 205 const psVector *fwhms, ///< Gaussian FWHMs 206 const psVector *orders, ///< Polynomial order of gaussians 207 float penalty, ///< Penalty for wideness 208 pmSubtractionMode mode ///< Mode for subtraction 208 int spatialOrder, ///< Order of spatial variations 209 const psVector *fwhms, ///< Gaussian FWHMs 210 const psVector *orders, ///< Polynomial order of gaussians 211 float penalty, ///< Penalty for wideness 212 psRegion bounds, ///< Bounds for validity 213 pmSubtractionMode mode ///< Mode for subtraction 209 214 ); 210 215 … … 215 220 const psVector *orders, ///< order of hermitian polynomials 216 221 float penalty, ///< Penalty for wideness 222 psRegion bounds, ///< Bounds for validity 217 223 pmSubtractionMode mode ///< Mode for subtraction 218 224 ); … … 220 226 /// Generate DECONV_HERM kernels 221 227 pmSubtractionKernels *pmSubtractionKernelsDECONV_HERM(int size, ///< Half-size of the kernel 222 int spatialOrder, ///< Order of spatial variations 223 const psVector *fwhms, ///< Gaussian FWHMs 224 const psVector *orders, ///< order of hermitian polynomials 225 float penalty, ///< Penalty for wideness 226 pmSubtractionMode mode ///< Mode for subtraction 228 int spatialOrder, ///< Order of spatial variations 229 const psVector *fwhms, ///< Gaussian FWHMs 230 const psVector *orders, ///< order of hermitian polynomials 231 float penalty, ///< Penalty for wideness 232 psRegion bounds, ///< Bounds for validity 233 pmSubtractionMode mode ///< Mode for subtraction 227 234 ); 228 235 … … 233 240 int binning, ///< Kernel binning factor 234 241 float penalty, ///< Penalty for wideness 242 psRegion bounds, ///< Bounds for validity 235 243 pmSubtractionMode mode ///< Mode for subtraction 236 244 ); … … 241 249 int inner, ///< Inner radius to preserve unbinned 242 250 float penalty, ///< Penalty for wideness 251 psRegion bounds, ///< Bounds for validity 243 252 pmSubtractionMode mode ///< Mode for subtraction 244 253 ); … … 251 260 int inner, ///< Inner radius containing grid of delta functions 252 261 float penalty, ///< Penalty for wideness 262 psRegion bounds, ///< Bounds for validity 253 263 pmSubtractionMode mode ///< Mode for subtraction 254 264 ); … … 260 270 int ringsOrder, ///< Polynomial order 261 271 float penalty, ///< Penalty for wideness 272 psRegion bounds, ///< Bounds for validity 262 273 pmSubtractionMode mode ///< Mode for subtraction 263 274 ); … … 274 285 int ringsOrder, ///< Polynomial order for RINGS 275 286 float penalty, ///< Penalty for wideness 287 psRegion bounds, ///< Bounds for validity 276 288 pmSubtractionMode mode ///< Mode for subtraction 277 289 ); … … 281 293 const char *description, ///< Description of kernel 282 294 int bgOrder, ///< Polynomial order for background fitting 295 psRegion bounds, ///< Bounds for validity 283 296 pmSubtractionMode mode ///< Mode for subtraction 284 297 ); -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionMask.c
r24257 r26747 38 38 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 39 39 40 psImage *pmSubtractionMask(const psImage *mask1, const psImage *mask2, psImageMaskType maskVal, 41 int size, int footprint, float badFrac, pmSubtractionMode mode) 42 { 43 PS_ASSERT_IMAGE_NON_NULL(mask1, NULL); 44 PS_ASSERT_IMAGE_TYPE(mask1, PS_TYPE_IMAGE_MASK, NULL); 45 if (mask2) { 46 PS_ASSERT_IMAGE_NON_NULL(mask2, NULL); 47 PS_ASSERT_IMAGE_TYPE(mask2, PS_TYPE_IMAGE_MASK, NULL); 48 PS_ASSERT_IMAGES_SIZE_EQUAL(mask2, mask1, NULL); 49 } 40 psImage *pmSubtractionMask(psRegion *bounds, const pmReadout *ro1, const pmReadout *ro2, 41 psImageMaskType maskVal, int size, int footprint, float badFrac, 42 pmSubtractionMode mode) 43 { 44 PM_ASSERT_READOUT_NON_NULL(ro1, NULL); 45 PM_ASSERT_READOUT_IMAGE(ro1, NULL); 46 PM_ASSERT_READOUT_MASK(ro1, NULL); 47 PM_ASSERT_READOUT_NON_NULL(ro2, NULL); 48 PM_ASSERT_READOUT_IMAGE(ro2, NULL); 49 PM_ASSERT_READOUT_MASK(ro2, NULL); 50 PS_ASSERT_IMAGES_SIZE_EQUAL(ro1->image, ro2->image, NULL); 50 51 PS_ASSERT_INT_NONNEGATIVE(size, NULL); 51 52 PS_ASSERT_INT_NONNEGATIVE(footprint, NULL); … … 55 56 } 56 57 57 int numCols = mask1->numCols, numRows = mask1->numRows; // Size of the images58 int numCols = ro1->image->numCols, numRows = ro1->image->numRows; // Size of the images 58 59 59 60 // Dereference inputs for convenience 60 psImageMaskType **data1 = mask1->data.PS_TYPE_IMAGE_MASK_DATA; 61 psImageMaskType **data2 = NULL; 62 if (mask2) { 63 data2 = mask2->data.PS_TYPE_IMAGE_MASK_DATA; 64 } 61 psF32 **imageData1 = ro1->image->data.F32, **imageData2 = ro2->image->data.F32; 62 psImageMaskType **maskData1 = ro1->mask->data.PS_TYPE_IMAGE_MASK_DATA, 63 **maskData2 = ro2->mask->data.PS_TYPE_IMAGE_MASK_DATA; 65 64 66 65 // First, a pass through to determine the fraction of bad pixels 67 if (isfinite(badFrac) && badFrac != 1.0) { 66 if (bounds || (isfinite(badFrac) && badFrac != 1.0)) { 67 int xMin = numCols, xMax = 0, yMin = numRows, yMax = 0; // Bounds of good pixels 68 68 int numBad = 0; // Number of bad pixels 69 69 for (int y = 0; y < numRows; y++) { 70 70 for (int x = 0; x < numCols; x++) { 71 if ( data1[y][x] & maskVal) {71 if ((maskData1[y][x] & maskVal) || !isfinite(imageData1[y][x])) { 72 72 numBad++; 73 73 continue; 74 74 } 75 if ( data2 && data2[y][x] & maskVal) {75 if ((maskData2[y][x] & maskVal) || !isfinite(imageData2[y][x])) { 76 76 numBad++; 77 continue; 77 78 } 78 } 79 } 80 if (numBad > badFrac * numCols * numRows) { 79 xMin = PS_MIN(xMin, x); 80 xMax = PS_MAX(xMax, x); 81 yMin = PS_MIN(yMin, y); 82 yMax = PS_MAX(yMax, y); 83 } 84 } 85 if (bounds) { 86 bounds->x0 = xMin; 87 bounds->x1 = xMax; 88 bounds->y0 = yMin; 89 bounds->y1 = yMax; 90 } 91 if (isfinite(badFrac) && badFrac != 1.0 && numBad > badFrac * numCols * numRows) { 81 92 psError(PM_ERR_SMALL_AREA, true, 82 93 "Fraction of bad pixels (%d/%d=%f) exceeds limit (%f)\n", … … 117 128 for (int y = 0; y < numRows; y++) { 118 129 for (int x = 0; x < numCols; x++) { 119 if ( data1[y][x] & maskVal) {130 if (maskData1[y][x] & maskVal) { 120 131 maskData[y][x] |= PM_SUBTRACTION_MASK_BAD_1; 121 132 } 122 if ( data2 && data2[y][x] & maskVal) {133 if (maskData2[y][x] & maskVal) { 123 134 maskData[y][x] |= PM_SUBTRACTION_MASK_BAD_2; 124 135 } -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionMask.h
r23851 r26747 5 5 6 6 /// Generate a mask for use in the subtraction process 7 psImage *pmSubtractionMask(const psImage *refMask, ///< Mask for the reference image (will be convolved) 8 const psImage *inMask, ///< Mask for the input image, or NULL 9 psImageMaskType maskVal, ///< Value to mask out 10 int size, ///< Half-size of the kernel (pmSubtractionKernels.size) 11 int footprint, ///< Half-size of the kernel footprint 12 float badFrac, ///< Maximum fraction of bad input pixels to accept 13 pmSubtractionMode mode ///< Subtraction mode 7 psImage *pmSubtractionMask( 8 psRegion *bounds, ///< Bounds of valid pixels (or NULL), returned 9 const pmReadout *ro1, ///< Readout 1 10 const pmReadout *ro2, ///< Readout 2 11 psImageMaskType maskVal, ///< Value to mask out 12 int size, ///< Half-size of the kernel (pmSubtractionKernels.size) 13 int footprint, ///< Half-size of the kernel footprint 14 float badFrac, ///< Maximum fraction of bad input pixels to accept 15 pmSubtractionMode mode ///< Subtraction mode 14 16 ); 15 17 -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionMatch.c
r26667 r26747 33 33 # else 34 34 # define SUBMODE PM_SUBTRACTION_EQUATION_ALL 35 // # define SUBMODE PM_SUBTRACTION_EQUATION_KERNELS36 35 # endif 37 36 … … 71 70 const psImage *subMask, // Mask for subtraction, or NULL 72 71 psImage *variance, // Variance map 73 const psRegion *region, // Region of interest , or NULL72 const psRegion *region, // Region of interest 74 73 float thresh1, // Threshold for stamp finding on readout 1 75 74 float thresh2, // Threshold for stamp finding on readout 2 76 75 float stampSpacing, // Spacing between stamps 76 float normFrac, // Fraction of flux in window for normalisation window 77 77 float sysError, // Relative systematic error in images 78 78 float skyError, // Relative systematic error in images … … 82 82 ) 83 83 { 84 PS_ASSERT_PTR_NON_NULL(stamps, false); 85 PM_ASSERT_READOUT_NON_NULL(ro1, false); 86 PM_ASSERT_READOUT_NON_NULL(ro2, false); 87 PS_ASSERT_IMAGE_NON_NULL(subMask, false); 88 PS_ASSERT_IMAGE_NON_NULL(variance, false); 89 PS_ASSERT_PTR_NON_NULL(region, false); 90 84 91 psTrace("psModules.imcombine", 3, "Finding stamps...\n"); 85 92 … … 87 94 88 95 *stamps = pmSubtractionStampsFind(*stamps, image1, image2, subMask, region, thresh1, thresh2, 89 size, footprint, stampSpacing, sysError, skyError, mode);96 size, footprint, stampSpacing, normFrac, sysError, skyError, mode); 90 97 if (!*stamps) { 91 98 psError(psErrorCodeLast(), false, "Unable to find stamps."); … … 96 103 97 104 psTrace("psModules.imcombine", 3, "Extracting stamps...\n"); 98 if (!pmSubtractionStampsExtract(*stamps, ro1->image, ro2 ? ro2->image : NULL, variance, size)) {105 if (!pmSubtractionStampsExtract(*stamps, ro1->image, ro2->image, variance, size, *region)) { 99 106 psError(PS_ERR_UNKNOWN, false, "Unable to extract stamps."); 100 107 return false; … … 110 117 const pmReadout *ro1, const pmReadout *ro2, // Input images 111 118 int stride, // Size for convolution patches 119 float normFrac, // Fraction of window for normalisation window 112 120 float sysError, // Systematic error in images 113 121 float skyError, // Systematic error in images … … 158 166 PS_ASSERT_IMAGES_SIZE_EQUAL(ro1->image, ro2->image, false); 159 167 PS_ASSERT_INT_NONNEGATIVE(stride, false); 168 if (isfinite(normFrac)) { 169 PS_ASSERT_FLOAT_LARGER_THAN(normFrac, 0.0, false); 170 PS_ASSERT_FLOAT_LESS_THAN(normFrac, 1.0, false); 171 } 160 172 if (isfinite(sysError)) { 161 173 PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(sysError, 0.0, false); … … 210 222 } 211 223 224 bool pmSubtractionMaskInvalid (const pmReadout *readout, psImageMaskType maskVal) { 225 226 if (!readout) return true; 227 228 psImage *image = readout->image; 229 psImage *mask = readout->mask; 230 psImage *variance = readout->variance; 231 for (int y = 0; y < image->numRows; y++) { 232 for (int x = 0; x < image->numCols; x++) { 233 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) continue; 234 bool valid = false; 235 valid = isfinite(image->data.F32[y][x]); 236 if (variance) { 237 valid &= isfinite(variance->data.F32[y][x]); 238 } 239 if (valid) continue; 240 mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = maskVal; 241 } 242 } 243 244 return true; 245 } 212 246 213 247 bool pmSubtractionMatchPrecalc(pmReadout *conv1, pmReadout *conv2, const pmReadout *ro1, const pmReadout *ro2, … … 282 316 } 283 317 284 if (!subtractionMatchCheck(conv1, conv2, ro1, ro2, stride, NAN, NAN, kernelError,318 if (!subtractionMatchCheck(conv1, conv2, ro1, ro2, stride, NAN, NAN, NAN, kernelError, 285 319 maskVal, maskBad, maskPoor, poorFrac, badFrac, mode)) { 286 320 psFree(kernels); … … 289 323 } 290 324 291 psImage *subMask = pmSubtractionMask(ro1->mask, ro2 ? ro2->mask : NULL, maskVal, size, 0, 325 pmSubtractionMaskInvalid(ro1, maskVal); 326 pmSubtractionMaskInvalid(ro2, maskVal); 327 328 psRegion bounds = psRegionSet(NAN, NAN, NAN, NAN); // Bounds of valid pixels 329 330 psImage *subMask = pmSubtractionMask(&bounds, ro1, ro2, maskVal, size, 0, 292 331 badFrac, mode); // Subtraction mask 293 332 if (!subMask) { … … 348 387 int inner, int ringsOrder, int binning, float penalty, 349 388 bool optimum, const psVector *optFWHMs, int optOrder, float optThreshold, 350 int iter, float rej, float sysError, float skyError, float kernelError, psImageMaskType maskVal,351 psImageMaskType maskBad, psImageMaskType maskPoor, float poorFrac,352 float badFrac, pmSubtractionMode subMode)389 int iter, float rej, float normFrac, float sysError, float skyError, 390 float kernelError, psImageMaskType maskVal, psImageMaskType maskBad, 391 psImageMaskType maskPoor, float poorFrac, float badFrac, pmSubtractionMode subMode) 353 392 { 354 if (!subtractionMatchCheck(conv1, conv2, ro1, ro2, stride, sysError, skyError, kernelError,393 if (!subtractionMatchCheck(conv1, conv2, ro1, ro2, stride, normFrac, sysError, skyError, kernelError, 355 394 maskVal, maskBad, maskPoor, poorFrac, badFrac, subMode)) { 356 395 return false; … … 411 450 // Putting important variable declarations here, since they are freed after a "goto" if there is an error. 412 451 psImage *subMask = NULL; // Mask for subtraction 413 psRegion *region = NULL;// Iso-kernel region452 psRegion *region = psRegionAlloc(NAN, NAN, NAN, NAN); // Iso-kernel region 414 453 psString regionString = NULL; // String for region 415 454 pmSubtractionStampList *stamps = NULL; // Stamps for matching PSF … … 424 463 memCheck("start"); 425 464 426 subMask = pmSubtractionMask(ro1->mask, ro2 ? ro2->mask : NULL, maskVal, size, footprint, 427 badFrac, subMode); 465 pmSubtractionMaskInvalid(ro1, maskVal); 466 pmSubtractionMaskInvalid(ro2, maskVal); 467 468 psRegion bounds = psRegionSet(NAN, NAN, NAN, NAN); // Bounds of valid pixels 469 470 subMask = pmSubtractionMask(&bounds, ro1, ro2, maskVal, size, footprint, badFrac, subMode); 428 471 if (!subMask) { 429 472 psError(psErrorCodeLast(), false, "Unable to generate subtraction mask."); … … 435 478 // Get region of interest 436 479 int xRegions = 1, yRegions = 1; // Number of iso-kernel regions 437 float xRegionSize = 0, yRegionSize = 0; // Size of iso-kernel regions480 float xRegionSize = NAN, yRegionSize = NAN; // Size of iso-kernel regions 438 481 if (isfinite(regionSize) && regionSize != 0.0) { 439 xRegions = numCols / regionSize + 1; 440 yRegions = numRows / regionSize + 1; 441 xRegionSize = (float)numCols / (float)xRegions; 442 yRegionSize = (float)numRows / (float)yRegions; 443 region = psRegionAlloc(NAN, NAN, NAN, NAN); 444 } 445 482 xRegions = (bounds.x1 - bounds.x0) / regionSize + 1; 483 yRegions = (bounds.y1 - bounds.y0) / regionSize + 1; 484 xRegionSize = (float)(bounds.x1 - bounds.x0) / (float)xRegions; 485 yRegionSize = (float)(bounds.y1 - bounds.y0) / (float)yRegions; 486 } else { 487 xRegionSize = bounds.x1 - bounds.x0; 488 yRegionSize = bounds.y1 - bounds.y0; 489 } 490 491 // General background subtraction and measurement of stamp threshold 446 492 float stampThresh1 = NAN, stampThresh2 = NAN; // Stamp thresholds for images 447 493 { 448 psStats *bg = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics for backgroun 494 psStats *bg = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); // Statistics for background 449 495 if (ro1) { 496 psStatsInit(bg); 450 497 if (!psImageBackground(bg, NULL, ro1->image, ro1->mask, maskVal, rng)) { 451 498 psError(PS_ERR_UNKNOWN, false, "Unable to measure background statistics."); … … 453 500 goto MATCH_ERROR; 454 501 } 455 stampThresh1 = bg->robustMedian + threshold * bg->robustStdev; 502 stampThresh1 = threshold * bg->robustStdev; 503 psBinaryOp(ro1->image, ro1->image, "-", psScalarAlloc((float)bg->robustMedian, PS_TYPE_F32)); 456 504 } 457 505 if (ro2) { 506 psStatsInit(bg); 458 507 if (!psImageBackground(bg, NULL, ro2->image, ro2->mask, maskVal, rng)) { 459 508 psError(PS_ERR_UNKNOWN, false, "Unable to measure background statistics."); … … 461 510 goto MATCH_ERROR; 462 511 } 463 stampThresh2 = bg->robustMedian + threshold * bg->robustStdev; 464 } 512 stampThresh2 = threshold * bg->robustStdev; 513 psBinaryOp(ro2->image, ro2->image, "-", psScalarAlloc((float)bg->robustMedian, PS_TYPE_F32)); 514 } 465 515 psFree(bg); 466 516 } 517 518 // Just in case the iso-kernel region doesn't cover the entire image... 519 if (subMode == PM_SUBTRACTION_MODE_1 || subMode == PM_SUBTRACTION_MODE_UNSURE || 520 subMode == PM_SUBTRACTION_MODE_DUAL) { 521 if (!conv1->image) { 522 conv1->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 523 } 524 psImageInit(conv1->image, NAN); 525 if (ro1->variance) { 526 if (!conv1->variance) { 527 conv1->variance = psImageAlloc(numCols, numRows, PS_TYPE_F32); 528 } 529 psImageInit(conv1->variance, NAN); 530 } 531 if (subMask) { 532 if (!conv1->mask) { 533 conv1->mask = psImageAlloc(numCols, numRows, PS_TYPE_IMAGE_MASK); 534 } 535 psImageInit(conv1->mask, maskBad); 536 } 537 } 538 if (subMode == PM_SUBTRACTION_MODE_2 || subMode == PM_SUBTRACTION_MODE_UNSURE || 539 subMode == PM_SUBTRACTION_MODE_DUAL) { 540 if (!conv2->image) { 541 conv2->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 542 } 543 psImageInit(conv2->image, NAN); 544 if (ro2->variance) { 545 if (!conv2->variance) { 546 conv2->variance = psImageAlloc(numCols, numRows, PS_TYPE_F32); 547 } 548 psImageInit(conv2->variance, NAN); 549 } 550 if (subMask) { 551 if (!conv2->mask) { 552 conv2->mask = psImageAlloc(numCols, numRows, PS_TYPE_IMAGE_MASK); 553 } 554 psImageInit(conv2->mask, maskBad); 555 } 556 } 557 467 558 468 559 // Iterate over iso-kernel regions … … 471 562 psTrace("psModules.imcombine", 1, "Subtracting region %d of %d...\n", 472 563 j * xRegions + i + 1, xRegions * yRegions); 473 if (region) {474 *region = psRegionSet((int)(i * xRegionSize),(int)((i + 1) * xRegionSize),475 (int)(j * yRegionSize), (int)((j + 1) * yRegionSize));476 psFree(regionString);477 regionString = psRegionToString(*region);478 psTrace("psModules.imcombine", 3, "Iso-kernel region: %s out of %d,%d\n",479 regionString, numCols, numRows);480 }564 *region = psRegionSet(bounds.x0 + (int)(i * xRegionSize), 565 bounds.x0 + (int)((i + 1) * xRegionSize), 566 bounds.y0 + (int)(j * yRegionSize), 567 bounds.y0 + (int)((j + 1) * yRegionSize)); 568 psFree(regionString); 569 regionString = psRegionToString(*region); 570 psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "Iso-kernel region: %s out of %d,%d\n", 571 regionString, numCols, numRows); 481 572 482 573 if (stampsName && strlen(stampsName) > 0) { 483 574 stamps = pmSubtractionStampsSetFromFile(stampsName, ro1->image, subMask, region, size, 484 footprint, stampSpacing, sysError, skyError, subMode); 575 footprint, stampSpacing, normFrac, 576 sysError, skyError, subMode); 485 577 } else if (sources) { 486 578 stamps = pmSubtractionStampsSetFromSources(sources, ro1->image, subMask, region, size, 487 footprint, stampSpacing, sysError, skyError, subMode); 579 footprint, stampSpacing, normFrac, 580 sysError, skyError, subMode); 488 581 } 489 582 490 583 // We get the stamps here; we will also attempt to get stamps at the first iteration, but it 491 584 // doesn't matter. 492 if (!subtractionGetStamps(&stamps, ro1, ro2, subMask, variance, NULL, stampThresh1, stampThresh2,493 stampSpacing, sysError, skyError, size, footprint, subMode)) {585 if (!subtractionGetStamps(&stamps, ro1, ro2, subMask, variance, region, stampThresh1, stampThresh2, 586 stampSpacing, normFrac, sysError, skyError, size, footprint, subMode)) { 494 587 goto MATCH_ERROR; 495 588 } … … 498 591 // generate the window function from the set of stamps 499 592 if (!pmSubtractionStampsGetWindow(stamps, size)) { 593 psError(PS_ERR_UNKNOWN, false, "Unable to get stamp window."); 500 594 goto MATCH_ERROR; 501 595 } … … 503 597 // Define kernel basis functions 504 598 if (optimum && (type == PM_SUBTRACTION_KERNEL_ISIS || type == PM_SUBTRACTION_KERNEL_GUNK)) { 505 kernels = pmSubtractionKernelsOptimumISIS(type, size, inner, spatialOrder, optFWHMs, optOrder, 506 stamps, footprint, optThreshold, penalty, subMode); 599 kernels = pmSubtractionKernelsOptimumISIS(type, size, inner, spatialOrder, 600 optFWHMs, optOrder, stamps, footprint, 601 optThreshold, penalty, bounds, subMode); 507 602 if (!kernels) { 508 603 psErrorClear(); … … 513 608 // Not an ISIS/GUNK kernel, or the optimum kernel search failed 514 609 kernels = pmSubtractionKernelsGenerate(type, size, spatialOrder, isisWidths, isisOrders, 515 inner, binning, ringsOrder, penalty, subMode);610 inner, binning, ringsOrder, penalty, bounds, subMode); 516 611 // pmSubtractionVisualShowKernels(kernels); 517 612 } … … 563 658 564 659 if (!subtractionGetStamps(&stamps, ro1, ro2, subMask, variance, region, 565 stampThresh1, stampThresh2, stampSpacing, sysError, skyError,566 s ize, footprint, subMode)) {660 stampThresh1, stampThresh2, stampSpacing, normFrac, 661 sysError, skyError, size, footprint, subMode)) { 567 662 goto MATCH_ERROR; 568 663 } … … 570 665 // generate the window function from the set of stamps 571 666 if (!pmSubtractionStampsGetWindow(stamps, size)) { 667 psError(PS_ERR_UNKNOWN, false, "Unable to get stamps window."); 572 668 goto MATCH_ERROR; 573 669 } -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionMatch.h
r26667 r26747 39 39 int iter, ///< Rejection iterations 40 40 float rej, ///< Rejection threshold 41 float normFrac, ///< Fraction of flux in window for normalisation window 41 42 float sysError, ///< Relative systematic error in images 42 43 float skyError, ///< Relative systematic error in images -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionParams.c
r26491 r26747 204 204 int spatialOrder, const psVector *fwhms, int maxOrder, 205 205 const pmSubtractionStampList *stamps, int footprint, 206 float tolerance, float penalty, pmSubtractionMode mode) 206 float tolerance, float penalty, psRegion bounds, 207 pmSubtractionMode mode) 207 208 { 208 209 if (type != PM_SUBTRACTION_KERNEL_ISIS && type != PM_SUBTRACTION_KERNEL_GUNK) { … … 232 233 psVectorInit(orders, maxOrder); 233 234 pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, fwhms, orders, 234 penalty, mode); // Kernels235 penalty, bounds, mode); // Kernels 235 236 psFree(orders); 236 237 psFree(kernels->description); … … 483 484 if (type == PM_SUBTRACTION_KERNEL_ISIS) { 484 485 485 // XXX in r26035, this code was just wrong. we had:486 487 // psKernel *subtract = kernels->preCalc->data[0]488 489 // but, kernels->preCalc was an array of psArray, not an array of kernels. It is now490 // an array of pmSubtractionKernelPreCalc.486 // XXX in r26035, this code was just wrong. we had: 487 488 // psKernel *subtract = kernels->preCalc->data[0] 489 490 // but, kernels->preCalc was an array of psArray, not an array of kernels. It is now 491 // an array of pmSubtractionKernelPreCalc. 491 492 492 493 pmSubtractionKernelPreCalc *subtract = kernels->preCalc->data[0]; // Kernel to subtract from the rest -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionParams.h
r18287 r26747 17 17 float tolerance, ///< Maximum difference in chi^2 18 18 float penalty, ///< Penalty for wideness 19 pmSubtractionMode mode // Mode for subtraction 19 psRegion bounds, ///< Bounds of validity 20 pmSubtractionMode mode ///< Mode for subtraction 20 21 ); 21 22 -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionStamps.c
r26562 r26747 176 176 177 177 pmSubtractionStampList *pmSubtractionStampListAlloc(int numCols, int numRows, const psRegion *region, 178 int footprint, float spacing, float sysErr, float skyErr) 178 int footprint, float spacing, float normFrac, 179 float sysErr, float skyErr) 179 180 { 180 181 pmSubtractionStampList *list = psAlloc(sizeof(pmSubtractionStampList)); // Stamp list to return … … 217 218 list->flux = NULL; 218 219 list->window = NULL; 220 list->normFrac = normFrac; 221 list->normWindow = 0; 219 222 list->footprint = footprint; 220 223 list->sysErr = sysErr; … … 239 242 out->window = psMemIncrRefCounter(in->window); 240 243 out->footprint = in->footprint; 244 out->normWindow = in->normWindow; 241 245 242 246 for (int i = 0; i < num; i++) { … … 308 312 stamp->matrix = NULL; 309 313 stamp->vector = NULL; 314 stamp->norm = NAN; 310 315 311 316 return stamp; … … 316 321 const psImage *image2, const psImage *subMask, 317 322 const psRegion *region, float thresh1, float thresh2, 318 int size, int footprint, float spacing, float sysErr, float skyErr,319 pmSubtractionMode mode)323 int size, int footprint, float spacing, float normFrac, 324 float sysErr, float skyErr, pmSubtractionMode mode) 320 325 { 321 326 if (!image1 && !image2) { … … 373 378 374 379 if (!stamps) { 375 stamps = pmSubtractionStampListAlloc(numCols, numRows, region, footprint, spacing, sysErr, skyErr); 380 stamps = pmSubtractionStampListAlloc(numCols, numRows, region, footprint, spacing, 381 normFrac, sysErr, skyErr); 376 382 } 377 383 … … 407 413 // Take stamps off the top of the (sorted) list 408 414 for (int j = xList->n - 1; j >= 0 && !goodStamp; j--) { 409 int xCentre = xList->data.F32[j] + 0.5, yCentre = yList->data.F32[j] + 0.5;// Stamp centre410 411 415 // Chop off the top of the list 412 416 xList->n = j; … … 414 418 fluxList->n = j; 415 419 420 #if 0 416 421 // Fish around a bit to see if we can find a pixel that isn't masked 422 // This is not a good idea if we're using the window feature 417 423 psTrace("psModules.imcombine", 7, "Searching for stamp %d around %d,%d\n", 418 424 i, xCentre, yCentre); 419 425 420 426 // Search bounds 427 int xCentre = xList->data.F32[j] + 0.5, yCentre = yList->data.F32[j] + 0.5;// Stamp centre 421 428 int search = footprint - size; // Search radius 422 429 int xMin = PS_MAX(border, xCentre - search); … … 427 434 goodStamp = stampSearch(&xStamp, &yStamp, &fluxStamp, image1, image2, thresh1, thresh2, 428 435 subMask, xMin, xMax, yMin, yMax, numCols, numRows, border); 429 430 // XXX reset for a test: 431 xStamp = xList->data.F32[j]; 432 yStamp = yList->data.F32[j]; 436 #else 437 // Only search the exact centre pixel 438 goodStamp = stampSearch(&xStamp, &yStamp, &fluxStamp, image1, image2, thresh1, thresh2, 439 subMask, xList->data.F32[j], xList->data.F32[j], 440 yList->data.F32[j], yList->data.F32[j], numCols, numRows, border); 441 #endif 433 442 // fprintf (stderr, "find: %d %d ==> %5.1f %5.1f\n", xCentre, yCentre, xStamp, yStamp); 434 443 } … … 486 495 const psImage *image, const psImage *subMask, 487 496 const psRegion *region, int size, int footprint, 488 float spacing, float sysErr, float skyErr, pmSubtractionMode mode) 497 float spacing, float normFrac, float sysErr, float skyErr, 498 pmSubtractionMode mode) 489 499 490 500 { … … 507 517 pmSubtractionStampList *stamps = pmSubtractionStampListAlloc(subMask->numCols, subMask->numRows, 508 518 region, footprint, spacing, 509 sysErr, skyErr); // Stamp list519 normFrac, sysErr, skyErr); // Stamp list 510 520 int numStamps = stamps->num; // Number of stamps 511 521 … … 612 622 PS_ASSERT_INT_NONNEGATIVE(kernelSize, false); 613 623 614 int size = kernelSize +stamps->footprint; // Size of postage stamps624 int size = stamps->footprint; // Size of postage stamps 615 625 616 626 psFree (stamps->window); … … 641 651 // storage vector for flux data 642 652 psStats *stats = psStatsAlloc (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 643 psVector *flux = psVectorAllocEmpty(2*stamps->num, PS_TYPE_F32); 644 645 double maxValue = 0.0; 653 psVector *flux1 = psVectorAllocEmpty(2*stamps->num, PS_TYPE_F32); 654 psVector *flux2 = psVectorAllocEmpty(2*stamps->num, PS_TYPE_F32); 646 655 647 656 // generate the window pixels 657 double sum = 0.0; // Sum inside the window 658 float maxValue = 0.0; // Maximum value, for normalisation 648 659 for (int y = -size; y <= size; y++) { 649 660 for (int x = -size; x <= size; x++) { 650 661 651 flux->n = 0; 662 flux1->n = 0; 663 flux2->n = 0; 652 664 for (int i = 0; i < stamps->num; i++) { 653 665 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest … … 656 668 if (!stamp->image2) continue; 657 669 658 psVectorAppend (flux, stamp->image1->kernel[y][x] / norm1->data.F32[i]);659 psVectorAppend (flux, stamp->image2->kernel[y][x] / norm2->data.F32[i]);670 psVectorAppend(flux1, stamp->image1->kernel[y][x] / norm1->data.F32[i]); 671 psVectorAppend(flux2, stamp->image2->kernel[y][x] / norm2->data.F32[i]); 660 672 } 661 673 662 674 psStatsInit (stats); 663 if (!psVectorStats (stats, flux , NULL, NULL, 0)) {675 if (!psVectorStats (stats, flux1, NULL, NULL, 0)) { 664 676 psAbort ("failed to generate stats"); 665 677 } 666 stamps->window->kernel[y][x] = stats->robustMedian; 667 if (maxValue < stats->robustMedian) { 668 maxValue = stats->robustMedian; 669 } 670 } 678 float f1 = stats->robustMedian; 679 psStatsInit (stats); 680 if (!psVectorStats (stats, flux2, NULL, NULL, 0)) { 681 psAbort ("failed to generate stats"); 682 } 683 float f2 = stats->robustMedian; 684 685 stamps->window->kernel[y][x] = f1 + f2; 686 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(size)) { 687 sum += stamps->window->kernel[y][x]; 688 } 689 maxValue = PS_MAX(maxValue, stamps->window->kernel[y][x]); 690 } 691 } 692 693 psTrace("psModules.imcombine", 3, "Window total: %f, threshold: %f\n", 694 sum, (1.0 - stamps->normFrac) * sum); 695 bool done = false; 696 for (int radius = 1; radius <= size && !done; radius++) { 697 double within = 0.0; 698 for (int y = -radius; y <= radius; y++) { 699 for (int x = -radius; x <= radius; x++) { 700 if (PS_SQR(x) + PS_SQR(y) <= PS_SQR(radius)) { 701 within += stamps->window->kernel[y][x]; 702 } 703 } 704 } 705 psTrace("psModules.imcombine", 5, "Radius %d: %f\n", radius, within); 706 if (within > (1.0 - stamps->normFrac) * sum) { 707 stamps->normWindow = radius; 708 done = true; 709 } 710 } 711 712 psTrace("psModules.imcombine", 3, "Normalisation window radius set to %d\n", stamps->normWindow); 713 if (stamps->normWindow == 0 || stamps->normWindow >= size) { 714 psError(PS_ERR_UNKNOWN, true, "Unable to determine normalisation window size."); 715 return false; 671 716 } 672 717 … … 678 723 } 679 724 680 # ifdef TESTING725 #if 0 681 726 { 682 727 psFits *fits = psFitsOpen ("window.fits", "w"); … … 684 729 psFitsClose (fits); 685 730 } 686 # endif731 #endif 687 732 688 733 psFree (stats); 689 psFree (flux); 734 psFree (flux1); 735 psFree(flux2); 690 736 psFree (norm1); 691 737 psFree (norm2); … … 694 740 695 741 bool pmSubtractionStampsExtract(pmSubtractionStampList *stamps, psImage *image1, psImage *image2, 696 psImage *variance, int kernelSize )742 psImage *variance, int kernelSize, psRegion bounds) 697 743 { 698 744 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); … … 711 757 } 712 758 713 int numCols = image1->numCols, numRows = image1->numRows; // Size of images714 759 int size = kernelSize + stamps->footprint; // Size of postage stamps 715 760 … … 720 765 } 721 766 722 if (isnan(stamp->xNorm)) { 723 stamp->xNorm = 2.0 * (stamp->x - (float)numCols/2.0) / (float)numCols; 724 } 725 if (isnan(stamp->yNorm)) { 726 stamp->yNorm = 2.0 * (stamp->y - (float)numRows/2.0) / (float)numRows; 727 } 767 p_pmSubtractionPolynomialNormCoords(&stamp->xNorm, &stamp->yNorm, stamp->x, stamp->y, 768 bounds.x0, bounds.x1, bounds.y0, bounds.y1); 728 769 729 770 int x = stamp->x + 0.5, y = stamp->y + 0.5; // Stamp coordinates 730 if (x < size || x > numCols - size || y < size || y > numRows- size) {731 psError(PS_ERR_UNKNOWN, false, "Stamp %d (%d,%d) is within the imageborder.\n", i, x, y);771 if (x < bounds.x0 + size || x > bounds.x1 - size || y < bounds.y0 + size || y > bounds.y1 - size) { 772 psError(PS_ERR_UNKNOWN, false, "Stamp %d (%d,%d) is within the region border.\n", i, x, y); 732 773 return false; 733 774 } … … 788 829 pmSubtractionStampList *pmSubtractionStampsSetFromSources(const psArray *sources, const psImage *image, 789 830 const psImage *subMask, const psRegion *region, 790 int size, int footprint, float spacing, float sysErr, float skyErr, 831 int size, int footprint, float spacing, 832 float normFrac, float sysErr, float skyErr, 791 833 pmSubtractionMode mode) 792 834 { … … 819 861 820 862 pmSubtractionStampList *stamps = pmSubtractionStampsSet(x, y, image, subMask, region, size, 821 footprint, spacing, sysErr, skyErr, mode); // Stamps 863 footprint, spacing, normFrac, 864 sysErr, skyErr, mode); // Stamps 822 865 psFree(x); 823 866 psFree(y); … … 833 876 pmSubtractionStampList *pmSubtractionStampsSetFromFile(const char *filename, const psImage *image, 834 877 const psImage *subMask, const psRegion *region, 835 int size, int footprint, float spacing, float sysErr, float skyErr,836 pmSubtractionMode mode)878 int size, int footprint, float spacing, float normFrac, 879 float sysErr, float skyErr, pmSubtractionMode mode) 837 880 { 838 881 PS_ASSERT_STRING_NON_EMPTY(filename, NULL); … … 851 894 852 895 pmSubtractionStampList *stamps = pmSubtractionStampsSet(x, y, image, subMask, region, size, footprint, 853 spacing, sysErr, skyErr, mode);896 spacing, normFrac, sysErr, skyErr, mode); 854 897 psFree(data); 855 898 -
branches/eam_branches/psModules.stack.20100120/src/imcombine/pmSubtractionStamps.h
r26578 r26747 25 25 int footprint; ///< Half-size of stamps 26 26 psKernel *window; ///< window function generated from ensemble of stamps 27 float normFrac; ///< Fraction of flux in window for normalisation window 28 int normWindow; ///< Size of window for measuring normalisation 27 29 float sysErr; ///< Systematic error 28 30 float skyErr; ///< increase effective readnoise … … 30 32 31 33 /// Allocate a list of stamps 32 pmSubtractionStampList *pmSubtractionStampListAlloc(int numCols, // Number of columns in image 33 int numRows, // Number of rows in image 34 const psRegion *region, // Region for stamps, or NULL 35 int footprint, // Half-size of stamps 36 float spacing, // Rough average spacing between stamps 37 float sysErr, // Relative systematic error or NAN 38 float skyErr // Relative systematic error or NAN 34 pmSubtractionStampList *pmSubtractionStampListAlloc( 35 int numCols, // Number of columns in image 36 int numRows, // Number of rows in image 37 const psRegion *region, // Region for stamps, or NULL 38 int footprint, // Half-size of stamps 39 float spacing, // Rough average spacing between stamps 40 float normFrac, // Fraction of flux in window for normalisation window 41 float sysErr, // Relative systematic error or NAN 42 float skyErr // Relative systematic error or NAN 39 43 ); 40 44 … … 78 82 psImage *matrix; ///< Least-squares matrix, or NULL 79 83 psVector *vector; ///< Least-squares vector, or NULL 84 double norm; ///< Normalisation difference 80 85 pmSubtractionStampStatus status; ///< Status of stamp 81 86 } pmSubtractionStamp; … … 85 90 86 91 /// Find stamps on an image 87 pmSubtractionStampList *pmSubtractionStampsFind(pmSubtractionStampList *stamps, ///< Output stamps, or NULL 88 const psImage *image1, ///< Image for which to find stamps 89 const psImage *image2, ///< Image for which to find stamps 90 const psImage *mask, ///< Mask, or NULL 91 const psRegion *region, ///< Region to search, or NULL 92 float thresh1, ///< Threshold for stamps in image 1 93 float thresh2, ///< Threshold for stamps in image 2 94 int size, ///< Kernel half-size 95 int footprint, ///< Half-size for stamps 96 float spacing, ///< Rough spacing for stamps 97 float sysErr, ///< Relative systematic error in images 98 float skyErr, ///< Relative systematic error in images 99 pmSubtractionMode mode ///< Mode for subtraction 92 pmSubtractionStampList *pmSubtractionStampsFind( 93 pmSubtractionStampList *stamps, ///< Output stamps, or NULL 94 const psImage *image1, ///< Image for which to find stamps 95 const psImage *image2, ///< Image for which to find stamps 96 const psImage *mask, ///< Mask, or NULL 97 const psRegion *region, ///< Region to search, or NULL 98 float thresh1, ///< Threshold for stamps in image 1 99 float thresh2, ///< Threshold for stamps in image 2 100 int size, ///< Kernel half-size 101 int footprint, ///< Half-size for stamps 102 float spacing, ///< Rough spacing for stamps 103 float normFrac, // Fraction of flux in window for normalisation window 104 float sysErr, ///< Relative systematic error in images 105 float skyErr, ///< Relative systematic error in images 106 pmSubtractionMode mode ///< Mode for subtraction 100 107 ); 101 108 102 109 /// Set stamps based on a list of x,y 103 pmSubtractionStampList *pmSubtractionStampsSet(const psVector *x, ///< x coordinates for each stamp 104 const psVector *y, ///< y coordinates for each stamp 105 const psImage *image, ///< Image for flux of stamp 106 const psImage *mask, ///< Mask, or NULL 107 const psRegion *region, ///< Region to search, or NULL 108 int size, ///< Kernel half-size 109 int footprint, ///< Half-size for stamps 110 float spacing, ///< Rough spacing for stamps 111 float sysErr, ///< Systematic error in images 112 float skyErr, ///< Systematic error in images 113 pmSubtractionMode mode ///< Mode for subtraction 110 pmSubtractionStampList *pmSubtractionStampsSet( 111 const psVector *x, ///< x coordinates for each stamp 112 const psVector *y, ///< y coordinates for each stamp 113 const psImage *image, ///< Image for flux of stamp 114 const psImage *mask, ///< Mask, or NULL 115 const psRegion *region, ///< Region to search, or NULL 116 int size, ///< Kernel half-size 117 int footprint, ///< Half-size for stamps 118 float spacing, ///< Rough spacing for stamps 119 float normFrac, // Fraction of flux in window for normalisation window 120 float sysErr, ///< Systematic error in images 121 float skyErr, ///< Systematic error in images 122 pmSubtractionMode mode ///< Mode for subtraction 114 123 ); 115 124 … … 123 132 int footprint, ///< Half-size for stamps 124 133 float spacing, ///< Rough spacing for stamps 134 float normFrac, // Fraction of flux in window for normalisation window 125 135 float sysErr, ///< Systematic error in images 126 136 float skyErr, ///< Systematic error in images … … 137 147 int footprint, ///< Half-size for stamps 138 148 float spacing, ///< Rough spacing for stamps 149 float normFrac, // Fraction of flux in window for normalisation window 139 150 float sysErr, ///< Systematic error in images 140 151 float skyErr, ///< Systematic error in images … … 142 153 ); 143 154 144 bool pmSubtractionStampsGetWindow(pmSubtractionStampList *stamps, int kernelSize); 155 /// Calculate the window and normalisation window from the stamps 156 bool pmSubtractionStampsGetWindow( 157 pmSubtractionStampList *stamps, ///< List of stamps 158 int kernelSize ///< Half-size of kernel 159 ); 145 160 146 161 /// Extract stamps from the images … … 149 164 psImage *image2, ///< Input image (or NULL) 150 165 psImage *variance, ///< Variance map 151 int kernelSize ///< Kernel half-size 166 int kernelSize, ///< Kernel half-size 167 psRegion bounds ///< Bounds of validity 152 168 ); 153 169 -
branches/eam_branches/psModules.stack.20100120/src/objects/pmDetections.c
r26632 r26747 27 27 psFree (detections->oldPeaks); 28 28 psFree (detections->oldFootprints); 29 30 psFree (detections->newSources); 31 psFree (detections->allSources); 29 32 return; 30 33 } … … 40 43 detections->oldPeaks = NULL; 41 44 detections->oldFootprints = NULL; 45 detections->newSources = NULL; 46 detections->allSources = NULL; 42 47 detections->last = 0; 43 48 -
branches/eam_branches/psModules.stack.20100120/src/objects/pmDetections.h
r26631 r26747 21 21 typedef struct { 22 22 psArray *footprints; // collection of footprints in the image 23 psArray *oldFootprints; // collection of footprints previously found 23 24 psArray *peaks; // collection of all peaks contained by the footprints 24 25 psArray *oldPeaks; // collection of all peaks previously found 25 psArray *oldFootprints; // collection of footprints previously found 26 psArray *newSources; // collection of sources 27 psArray *allSources; // collection of sources 26 28 int last; 27 29 } pmDetections; -
branches/eam_branches/psModules.stack.20100120/src/objects/pmSource.c
r26623 r26747 275 275 // psphot-specific function which applies the recipe values 276 276 // only apply selection to sources within specified region 277 pmPSFClump pmSourcePSFClump(ps Region *region, psArray *sources, psMetadata *recipe)277 pmPSFClump pmSourcePSFClump(psImage **savedImage, psRegion *region, psArray *sources, float PSF_SN_LIM, float PSF_CLUMP_GRID_SCALE, psF32 SX_MAX, psF32 SY_MAX, psF32 AR_MAX) 278 278 { 279 279 psTrace("psModules.objects", 10, "---- begin ----\n"); … … 285 285 286 286 PS_ASSERT_PTR_NON_NULL(sources, errorClump); 287 PS_ASSERT_PTR_NON_NULL(recipe, errorClump);288 289 bool status = true; // Status of MD lookup290 float PSF_SN_LIM = psMetadataLookupF32(&status, recipe, "PSF_SN_LIM");291 if (!status) {292 PSF_SN_LIM = 0;293 }294 float PSF_CLUMP_GRID_SCALE = psMetadataLookupF32(&status, recipe, "PSF_CLUMP_GRID_SCALE");295 if (!status) {296 PSF_CLUMP_GRID_SCALE = 0.1;297 }298 287 299 288 // find the sigmaX, sigmaY clump 300 289 { 301 psF32 SX_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_SX_MAX");302 if (!status) {303 psWarning("MOMENTS_SX_MAX not set in recipe");304 SX_MAX = 10.0;305 }306 psF32 SY_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_SY_MAX");307 if (!status) {308 psWarning("MOMENTS_SY_MAX not set in recipe");309 SY_MAX = 10.0;310 }311 psF32 AR_MAX = psMetadataLookupF32(&status, recipe, "MOMENTS_AR_MAX");312 if (!status) {313 psWarning("MOMENTS_AR_MAX not set in recipe");314 AR_MAX = 3.0;315 }316 290 psF32 AR_MIN = 1.0 / AR_MAX; 317 291 … … 399 373 psfClump.nSigma = stats->sampleStdev; 400 374 401 const bool keep_psf_clump = psMetadataLookupBool(NULL, recipe, "KEEP_PSF_CLUMP"); 402 if (keep_psf_clump) 403 { 404 psMetadataAdd(recipe, PS_LIST_TAIL, 405 "PSF_CLUMP", PS_DATA_IMAGE, "Image of PSF coefficients", splane); 375 if (savedImage) { 376 *savedImage = psMemIncrRefCounter(splane); 406 377 } 407 378 psFree (splane); … … 530 501 *****************************************************************************/ 531 502 532 bool pmSourceRoughClass(psRegion *region, psArray *sources, psMetadata *recipe, pmPSFClump clump, psImageMaskType maskSat)503 bool pmSourceRoughClass(psRegion *region, psArray *sources, float PSF_SN_LIM, float PSF_CLUMP_NSIGMA, pmPSFClump clump, psImageMaskType maskSat) 533 504 { 534 505 psTrace("psModules.objects", 10, "---- begin ----"); 535 506 536 507 PS_ASSERT_PTR_NON_NULL(sources, false); 537 PS_ASSERT_PTR_NON_NULL(recipe, false);538 508 539 509 int Nsat = 0; … … 548 518 psVector *starsn_peaks = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 549 519 psVector *starsn_moments = psVectorAllocEmpty (sources->n, PS_TYPE_F32); 550 551 // get basic parameters, or set defaults552 bool status;553 float PSF_SN_LIM = psMetadataLookupF32 (&status, recipe, "PSF_SN_LIM");554 if (!status) PSF_SN_LIM = 20.0;555 float PSF_CLUMP_NSIGMA = psMetadataLookupF32 (&status, recipe, "PSF_CLUMP_NSIGMA");556 if (!status) PSF_CLUMP_NSIGMA = 1.5;557 558 // float INNER_RADIUS = psMetadataLookupF32 (&status, recipe, "SKY_INNER_RADIUS");559 520 560 521 pmSourceMode noMoments = PM_SOURCE_MODE_MOMENTS_FAILURE | PM_SOURCE_MODE_SKYVAR_FAILURE | PM_SOURCE_MODE_SKY_FAILURE | PM_SOURCE_MODE_BELOW_MOMENTS_SN; -
branches/eam_branches/psModules.stack.20100120/src/objects/pmSource.h
r26594 r26747 176 176 * 177 177 * The return value indicates the success (TRUE) of the operation. 178 * 179 * XXX: Limit the S/N of the candidate sources (part of Metadata)? (TBD). 180 * XXX: Save the clump parameters on the Metadata (TBD) 181 * 182 */ 178 */ 179 183 180 pmPSFClump pmSourcePSFClump( 181 psImage **savedImage, 184 182 psRegion *region, ///< restrict measurement to specified region 185 183 psArray *source, ///< The input pmSource 186 psMetadata *metadata ///< Contains classification parameters 184 float PSF_SN_LIM, 185 float PSF_CLUMP_GRID_SCALE, 186 psF32 SX_MAX, 187 psF32 SY_MAX, 188 psF32 AR_MAX 187 189 ); 188 190 … … 200 202 psRegion *region, ///< restrict measurement to specified region 201 203 psArray *sources, ///< The input pmSources 202 psMetadata *metadata, ///< Contains classification parameters 204 float PSF_SN_LIM, ///< min S/N for source to be used for PSF model 205 float PSF_CLUMP_NSIGMA, ///< size of region around peak of clump for PSF stars 203 206 pmPSFClump clump, ///< Statistics about the PSF clump 204 207 psImageMaskType maskSat ///< Mask value for saturated pixels -
branches/eam_branches/psModules.stack.20100120/src/objects/pmSourceIO.c
r26260 r26747 40 40 #include "pmPSF.h" 41 41 #include "pmModel.h" 42 #include "pmDetections.h" 42 43 #include "pmSource.h" 43 44 #include "pmModelClass.h" … … 344 345 345 346 // if sources is NULL, write out an empty table 346 // input / output sources are stored on the readout->analysis as "PSPHOT.SOURCES" -- a better name might be something like PM_SOURCE_DATA 347 psArray *sources = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.SOURCES"); 347 // input / output sources are stored on the readout->analysis as "PSPHOT.DETECTIONS" 348 349 psArray *sources = NULL; 350 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 351 if (detections) { 352 sources = detections->allSources; 353 } 348 354 if (!sources) { 355 detections = pmDetectionsAlloc(); 349 356 sources = psArrayAlloc(0); 350 psMetadataAddArray(readout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_META_REPLACE, "Blank array of sources", sources); 351 psFree(sources); // Held onto by the metadata, so we can continue to use 357 detections->allSources = sources; 358 psMetadataAddPtr(readout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_DATA_UNKNOWN | PS_META_REPLACE, "Blank array of sources", detections); 359 psFree(detections); // Held onto by the metadata, so we can continue to use 352 360 } 353 361 … … 1031 1039 } 1032 1040 readout->data_exists = true; 1033 status = psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.SOURCES", PS_DATA_ARRAY, "input sources", sources); 1034 psFree (sources); 1041 1042 pmDetections *detections = pmDetectionsAlloc(); 1043 detections->allSources = sources; 1044 status = psMetadataAdd (readout->analysis, PS_LIST_TAIL, "PSPHOT.DETECTIONS", PS_DATA_ARRAY, "input sources", detections); 1045 psFree (detections); 1035 1046 return true; 1036 1047 } … … 1124 1135 bool status; 1125 1136 1126 // select the psf of interest 1127 pmPSF *psf = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.SOURCES"); 1128 if (!psf) return false; 1129 return true; 1130 } 1131 1132 1137 // select the detections of interest 1138 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 1139 if (!detections) return false; 1140 if (!detections->allSources) return false; 1141 return true; 1142 } 1143 1144 -
branches/eam_branches/psModules.stack.20100120/src/objects/pmSourcePlotApResid.c
r20937 r26747 34 34 #include "pmPSF.h" 35 35 #include "pmModel.h" 36 #include "pmDetections.h" 36 37 #include "pmSource.h" 37 38 #include "pmSourcePlots.h" … … 53 54 PS_ASSERT_PTR_NON_NULL(layout, false); 54 55 56 bool status; 55 57 Graphdata graphdata; 56 58 KapaSection section; … … 61 63 pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT"); 62 64 63 psArray *sources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES"); 64 if (sources == NULL) 65 return false; 65 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 66 if (detections == NULL) return false; 67 68 psArray *sources = detections->allSources; 69 if (sources == NULL) return false; 66 70 67 71 int kapa = pmKapaOpen (false); -
branches/eam_branches/psModules.stack.20100120/src/objects/pmSourcePlotMoments.c
r20937 r26747 37 37 #include "pmPSF.h" 38 38 #include "pmModel.h" 39 #include "pmDetections.h" 39 40 #include "pmSource.h" 40 41 #include "pmSourcePlots.h" … … 54 55 PS_ASSERT_PTR_NON_NULL(layout, false); 55 56 57 bool status; 56 58 Graphdata graphdata; 57 59 KapaSection section; … … 62 64 pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT"); 63 65 64 psArray *sources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES"); 65 if (sources == NULL) 66 return false; 66 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 67 if (detections == NULL) return false; 68 69 psArray *sources = detections->allSources; 70 if (sources == NULL) return false; 67 71 68 72 int kapa = pmKapaOpen (false); -
branches/eam_branches/psModules.stack.20100120/src/objects/pmSourcePlotPSFModel.c
r20937 r26747 37 37 #include "pmPSF.h" 38 38 #include "pmModel.h" 39 #include "pmDetections.h" 39 40 #include "pmSource.h" 40 41 #include "pmSourcePlots.h" … … 56 57 PS_ASSERT_PTR_NON_NULL(layout, false); 57 58 59 bool status; 58 60 Graphdata graphdata; 59 61 KapaSection section; … … 64 66 pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT"); 65 67 66 psArray *sources = psMetadataLookupPtr (NULL, readout->analysis, "PSPHOT.SOURCES"); 67 if (sources == NULL) 68 return false; 68 pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS"); 69 if (detections == NULL) return false; 70 71 psArray *sources = detections->allSources; 72 if (sources == NULL) return false; 69 73 70 74 int kapa = pmKapaOpen (false); -
branches/eam_branches/psModules.stack.20100120/src/psmodules.h
r26486 r26747 29 29 #include <pmConfigDump.h> 30 30 #include <pmConfigRun.h> 31 #include <pmConfigRecipeValue.h> 31 32 #include <pmVersion.h> 32 33
Note:
See TracChangeset
for help on using the changeset viewer.
