Changeset 27838 for branches/tap_branches/psLib
- Timestamp:
- May 3, 2010, 8:41:49 AM (16 years ago)
- Location:
- branches/tap_branches
- Files:
-
- 3 deleted
- 42 edited
- 3 copied
-
. (modified) (1 prop)
-
psLib (modified) (1 prop)
-
psLib/share/Makefile.am (modified) (1 diff)
-
psLib/src/fits/psFits.c (modified) (2 diffs)
-
psLib/src/fits/psFitsHeader.c (modified) (2 diffs)
-
psLib/src/fits/psFitsImage.c (modified) (2 diffs)
-
psLib/src/fits/psFitsScale.c (modified) (4 diffs)
-
psLib/src/fits/psFitsTable.c (modified) (1 diff)
-
psLib/src/imageops/psImageBackground.c (modified) (5 diffs)
-
psLib/src/imageops/psImageBackground.h (modified) (1 diff)
-
psLib/src/imageops/psImageConvolve.c (modified) (1 diff)
-
psLib/src/imageops/psImageConvolve.h (modified) (1 diff)
-
psLib/src/imageops/psImageCovariance.c (modified) (7 diffs)
-
psLib/src/imageops/psImageCovariance.h (modified) (2 diffs)
-
psLib/src/imageops/psImageInterpolate.c (modified) (1 diff)
-
psLib/src/jpeg/psImageJpeg.c (modified) (1 diff)
-
psLib/src/math/psBinaryOp.c (modified) (1 diff)
-
psLib/src/math/psBinaryOp.h (modified) (1 diff)
-
psLib/src/math/psHistogram.c (modified) (4 diffs)
-
psLib/src/math/psMatrix.c (modified) (20 diffs)
-
psLib/src/math/psMatrix.h (modified) (2 diffs)
-
psLib/src/math/psMinimizeLMM.c (modified) (5 diffs)
-
psLib/src/math/psStats.c (modified) (8 diffs)
-
psLib/src/math/psUnaryOp.c (modified) (1 diff)
-
psLib/src/math/psUnaryOp.h (modified) (1 diff)
-
psLib/src/mathtypes/psImage.h (modified) (1 diff)
-
psLib/src/mathtypes/psVector.c (modified) (1 diff)
-
psLib/src/pslib_strict.h (modified) (1 diff)
-
psLib/src/sys/psErrorCodes.c.in (modified) (1 diff)
-
psLib/src/sys/psMemory.h (modified) (2 diffs)
-
psLib/src/sys/psTrace.c (modified) (1 diff)
-
psLib/src/sys/psType.c (modified) (2 diffs)
-
psLib/src/sys/psType.h (modified) (1 diff)
-
psLib/src/types/Makefile.am (modified) (2 diffs)
-
psLib/src/types/psArray.c (modified) (1 diff)
-
psLib/src/types/psArray.h (modified) (1 diff)
-
psLib/src/types/psBitSet.c (deleted)
-
psLib/src/types/psBitSet.h (deleted)
-
psLib/src/types/psBits.c (copied) (copied from trunk/psLib/src/types/psBits.c )
-
psLib/src/types/psBits.h (copied) (copied from trunk/psLib/src/types/psBits.h )
-
psLib/src/types/psList.c (modified) (2 diffs)
-
psLib/src/types/psLookupTable.c (modified) (4 diffs)
-
psLib/src/types/psMetadata.c (modified) (5 diffs)
-
psLib/src/types/psMetadata.h (modified) (1 diff)
-
psLib/src/types/psMetadataConfig.c (modified) (1 diff)
-
psLib/test/types/Makefile.am (modified) (1 diff)
-
psLib/test/types/tap_psBitSet_all.c (deleted)
-
psLib/test/types/tap_psBits_all.c (copied) (copied from trunk/psLib/test/types/tap_psBits_all.c )
Legend:
- Unmodified
- Added
- Removed
-
branches/tap_branches
- Property svn:mergeinfo changed
-
branches/tap_branches/psLib
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/czw_branch/cleanup/psLib merged eligible /branches/pap/psLib merged eligible /trunk/psLib merged eligible /branches/eam_branches/20090522/psLib 24238-24573 /branches/eam_branches/20090715/psLib 24799-25750 /branches/eam_branches/20090820/psLib 25139-25874 /branches/pap_mops/psLib 25137-25255
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
branches/tap_branches/psLib/share/Makefile.am
r10093 r27838 7 7 tab5.2b.dat \ 8 8 tab5.2c.dat \ 9 finals2000A.dat \ 10 finals_all.dat 9 finals2000A.dat 11 10 -
branches/tap_branches/psLib/src/fits/psFits.c
r25478 r27838 149 149 int thisErrno = errno; // Error number 150 150 char errorBuf[MAX_STRING_LENGTH], *errorMsg; 151 #if (( _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE)151 #if (((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE) || __APPLE__) 152 152 strerror_r(thisErrno, errorBuf, MAX_STRING_LENGTH); 153 153 errorMsg = errorBuf; … … 208 208 int thisErrno = errno; 209 209 char errorBuf[64], *errorMsg; 210 # if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE)210 #if (((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE) || __APPLE__) 211 211 strerror_r (errno, errorBuf, 64); 212 212 errorMsg = errorBuf; -
branches/tap_branches/psLib/src/fits/psFitsHeader.c
r25087 r27838 570 570 // to preserve NAXISn etc for reference, so we don't do this. 571 571 572 if (keywordInList(name, noWriteFitsKeys) || 573 (keyStarts && keywordStartsWith(name, noWriteFitsKeyStarts))) { 574 psTrace("psLib.fits", 3, "Not writing FITS keyword %s", name); 575 continue; 576 } 577 572 578 // Options for compression 573 579 if (compressing) { … … 582 588 } else if (keywordInList(name, noWriteCompressedKeys) || 583 589 (keyStarts && keywordStartsWith(name, noWriteCompressedKeyStarts))) { 584 psTrace("psLib.fits", 3, "Not writing FITS keyword %s", name);585 continue;586 }587 588 if (keywordInList(name, noWriteFitsKeys) ||589 (keyStarts && keywordStartsWith(name, noWriteFitsKeyStarts))) {590 590 psTrace("psLib.fits", 3, "Not writing FITS keyword %s", name); 591 591 continue; -
branches/tap_branches/psLib/src/fits/psFitsImage.c
r25002 r27838 498 498 psImage *inImage; // Image to read in 499 499 if (floatType == PS_FITS_FLOAT_NONE) { 500 inImage = psImageRecycle(outImage, numCols, numRows, info->psDatatype); 501 outImage = psMemIncrRefCounter(inImage); 500 if (!outImage || outImage->type.type == info->psDatatype) { 501 outImage = psImageRecycle(outImage, numCols, numRows, info->psDatatype); 502 inImage = psMemIncrRefCounter(outImage); 503 } else { 504 outImage = psImageRecycle(outImage, numCols, numRows, outImage->type.type); 505 inImage = psImageAlloc(numCols, numRows, info->psDatatype); 506 } 502 507 } else { 503 508 inImage = psImageAlloc(numCols, numRows, info->psDatatype); … … 511 516 return NULL; 512 517 } 513 psFree(info);514 518 515 519 if (floatType != PS_FITS_FLOAT_NONE) { 516 520 outImage = psFitsFloatImageFromDisk(outImage, inImage, floatType); 517 } 521 } else if (outImage->type.type != info->psDatatype) { 522 outImage = psImageCopy(outImage, inImage, outImage->type.type); 523 } 524 psFree(info); 518 525 psFree(inImage); 519 526 -
branches/tap_branches/psLib/src/fits/psFitsScale.c
r25439 r27838 15 15 #include "psImage.h" 16 16 #include "psFits.h" 17 #include "psStats.h" 18 #include "psImageStats.h" 17 19 #include "psImageBackground.h" 18 #include "psStats.h"19 20 #include "psImageStructManip.h" 20 21 … … 29 30 #define MEAN_STAT PS_STAT_ROBUST_MEDIAN // Statistic to use for mean 30 31 #define STDEV_STAT PS_STAT_ROBUST_STDEV // Statistic to use for stdev 32 33 #define DESPERATE_MEAN_STAT PS_STAT_SAMPLE_MEDIAN // Statistic to use for mean when deperate 34 #define DESPERATE_STDEV_STAT PS_STAT_SAMPLE_QUARTILE // Statistic to use for stdev when desperate 31 35 32 36 … … 118 122 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); 119 123 psStats *stats = psStatsAlloc(MEAN_STAT | STDEV_STAT); // Statistics object 124 double mean, stdev; // Mean and standard deviation 120 125 if (!psImageBackground(stats, NULL, image, mask, maskVal, rng)) { 121 psError(PS_ERR_UNKNOWN, false, "Unable to perform statistics on image"); 122 psFree(rng); 123 psFree(stats); 124 return false; 126 // It could be because the image is entirely masked, in which case we don't want to error 127 bool good = false; // Any good pixels? 128 129 130 // Find good pixels in an image, by image type 131 #define GOOD_PIXELS_CASE(TYPE) \ 132 case PS_TYPE_##TYPE: \ 133 for (int y = 0; y < image->numRows && !good; y++) { \ 134 for (int x = 0; x < image->numCols && !good; x++) { \ 135 if (mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal)) { \ 136 continue; \ 137 } \ 138 if (!isfinite(image->data.TYPE[y][x])) { \ 139 continue; \ 140 } \ 141 good = true; \ 142 } \ 143 } \ 144 break; 145 146 switch (image->type.type) { 147 GOOD_PIXELS_CASE(F32); 148 GOOD_PIXELS_CASE(F64); 149 default: 150 psAbort("Unsupported case: %x", image->type.type); 151 } 152 153 if (!good) { 154 psLogMsg("psLib.fits", PS_LOG_DETAIL, "Image has no good pixels, setting BSCALE = 1, BZERO = 0"); 155 psErrorClear(); 156 *bscale = 1.0; 157 *bzero = 0.0; 158 psFree(rng); 159 psFree(stats); 160 return true; 161 } 162 163 // There are some good pixels in there somewhere; psImageBackground just didn't find them 164 psLogMsg("psLib.fits", PS_LOG_DETAIL, 165 "Couldn't measure background statistics for image quantisation; retrying."); 166 psErrorClear(); 167 // Retry using all the available pixels 168 stats->nSubsample = image->numCols * image->numRows + 1; 169 if (!psImageStats(stats, image, mask, maskVal)) { 170 psLogMsg("psLib.fits", PS_LOG_DETAIL, 171 "Couldn't measure background statistics for image quantisation (attempt 2); retrying."); 172 psErrorClear(); 173 // Retry with desperate statistic 174 stats->options = DESPERATE_MEAN_STAT | DESPERATE_STDEV_STAT; 175 if (!psImageStats(stats, image, mask, maskVal)) { 176 psError(PS_ERR_UNKNOWN, false, "Unable to measure background statistics for image"); 177 psFree(rng); 178 psFree(stats); 179 return false; 180 } else { 181 // Desperate retry 182 mean = psStatsGetValue(stats, DESPERATE_MEAN_STAT); 183 stdev = psStatsGetValue(stats, DESPERATE_STDEV_STAT); 184 } 185 } else { 186 // Retry with all available pixels 187 mean = psStatsGetValue(stats, MEAN_STAT); 188 stdev = psStatsGetValue(stats, STDEV_STAT); 189 } 190 } else { 191 // First attempt 192 mean = psStatsGetValue(stats, MEAN_STAT); 193 stdev = psStatsGetValue(stats, STDEV_STAT); 125 194 } 126 195 psFree(rng); 127 128 double mean = psStatsGetValue(stats, MEAN_STAT); // Mean129 double stdev = psStatsGetValue(stats, STDEV_STAT); // Standard deviation130 196 psFree(stats); 131 197 if (!isfinite(mean) || !isfinite(stdev)) { … … 318 384 } else { \ 319 385 value = (value - zero) * scale; \ 320 if (options->fuzz ) { \386 if (options->fuzz && (value - (int)value != 0.0)) { \ 321 387 /* Add random factor [-0.5,0.5): adds a variance of 1/12, */ \ 322 388 /* but preserves the expectation value */ \ -
branches/tap_branches/psLib/src/fits/psFitsTable.c
r24512 r27838 162 162 163 163 switch (typecode) { 164 // TBYTE and TSHORT fall though to read into psS32 164 165 case TBYTE: 165 166 case TSHORT: 166 case TLONGLONG:167 167 READ_TABLE_ROW_CASE(TLONG, long, S32, S32); 168 READ_TABLE_ROW_CASE(TLONGLONG, long, S64, S64); 168 169 READ_TABLE_ROW_CASE(TFLOAT, float, F32, F32); 169 170 READ_TABLE_ROW_CASE(TDOUBLE, double, F64, F64); -
branches/tap_branches/psLib/src/imageops/psImageBackground.c
r24481 r27838 15 15 #include "psRandom.h" 16 16 #include "psError.h" 17 18 static int nFailures = 0; 19 20 void psImageBackgroundInit() { 21 nFailures = 0; 22 return; 23 } 17 24 18 25 // XXX allow the user to choose the stats method? … … 39 46 long ny = image->numRows; 40 47 41 const int Npixels = nx*ny; // Total number of pixels 48 psImage *bad = psImageAlloc(nx, ny, PS_TYPE_U8); // Image with bad pixels 49 psImageInit(bad, 0); 50 51 int Npixels = 0; // Total number of pixels 52 for (int y = 0; y < ny; y++) { 53 for (int x = 0; x < nx; x++) { 54 if (!isfinite(image->data.F32[y][x]) || 55 (mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskValue)) { 56 bad->data.U8[y][x] = 0xFF; 57 } 58 Npixels++; 59 } 60 } 61 42 62 const int Nsubset = (stats->nSubsample == 0) ? Npixels : PS_MIN(stats->nSubsample, Npixels); // Number of pixels in subset 43 63 … … 58 78 long n = 0; // Number of actual pixels in subset 59 79 if (Nsubset >= Npixels) { 60 // if we have an image smaller than Nsubset, just loop over theimage pixels61 for (int iy = 0; iy < ny; iy++) {62 for (int ix = 0; ix < nx; ix++) {63 if (!isfinite(image->data.F32[iy][ix]) || (mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskValue)) {64 continue;65 }80 // if we have an image smaller than Nsubset, just loop over the (good) image pixels 81 for (int iy = 0; iy < ny; iy++) { 82 for (int ix = 0; ix < nx; ix++) { 83 if (bad->data.U8[iy][ix]) { 84 continue; 85 } 66 86 67 float value = image->data.F32[iy][ix];68 min = PS_MIN(value, min);69 max = PS_MAX(value, max);70 values->data.F32[n] = value;71 n++;72 }73 }87 float value = image->data.F32[iy][ix]; 88 min = PS_MIN(value, min); 89 max = PS_MAX(value, max); 90 values->data.F32[n] = value; 91 n++; 92 } 93 } 74 94 } else { 75 for (long i = 0; i < Nsubset; i++) { 76 double frnd = psRandomUniform(rng); 77 int pixel = Npixels * frnd; 78 int ix = pixel % nx; 79 int iy = pixel / nx; 95 // Subsample all pixels 96 // This is not optimal, since there may be a large masked fraction that leaves us with few good pixels. 97 // In that case, you should have set Nsubset....... 98 Npixels = nx * ny; 99 for (long i = 0; i < Nsubset; i++) { 100 double frnd = psRandomUniform(rng); 101 int pixel = Npixels * frnd; 102 int ix = pixel % nx; 103 int iy = pixel / nx; 80 104 81 if (!isfinite(image->data.F32[iy][ix]) || (mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskValue)) {82 continue;83 }105 if (bad->data.U8[iy][ix]) { 106 continue; 107 } 84 108 85 float value = image->data.F32[iy][ix];86 min = PS_MIN(value, min);87 max = PS_MAX(value, max);88 values->data.F32[n] = value;89 n++;90 }109 float value = image->data.F32[iy][ix]; 110 min = PS_MIN(value, min); 111 max = PS_MAX(value, max); 112 values->data.F32[n] = value; 113 n++; 114 } 91 115 } 116 117 psFree(bad); 118 92 119 if (n < 0.01*Nsubset) { 93 psLogMsg("psLib.psImageBackground", PS_LOG_DETAIL, 94 "Unable to measure image background: too few data points (%ld)", n); 120 if ((nFailures < 3) || (nFailures % 100 == 0)) { 121 psLogMsg("psLib.psImageBackground", PS_LOG_DETAIL, "Unable to measure image background: too few data points (%ld) (%d failures)", n, nFailures); 122 } 123 nFailures ++; 95 124 psFree(values); 96 125 return false; … … 108 137 109 138 if (!psVectorSort(values, values)) { 110 psError(PS_ERR_UNKNOWN, false, "Unable to sort values.\n"); 139 if ((nFailures < 3) || (nFailures % 100 == 0)) { 140 psError(PS_ERR_UNKNOWN, false, "Unable to sort values.(%d failures)\n", nFailures); 141 } 142 nFailures ++; 111 143 psFree(values); 112 144 return false; … … 132 164 fclose (f); 133 165 } 134 psError(PS_ERR_UNKNOWN, false, "Unable to measure statistics for image background " 135 "(%dx%d, (row0,col0) = (%d,%d)", 136 image->numRows, image->numCols, image->row0, image->col0); 166 if ((nFailures < 3) || (nFailures % 100 == 0)) { 167 psError(PS_ERR_UNKNOWN, false, "Unable to measure statistics for image background " 168 "(%dx%d, (row0,col0) = (%d,%d) (%d failures)\n", 169 image->numRows, image->numCols, image->row0, image->col0, nFailures); 170 } 171 nFailures ++; 137 172 psFree(values); 138 173 return false; -
branches/tap_branches/psLib/src/imageops/psImageBackground.h
r21183 r27838 22 22 #include <psRandom.h> 23 23 24 void psImageBackgroundInit(); 25 24 26 // Get the background for an image 25 27 bool psImageBackground(psStats *stats, // desired measurement and options -
branches/tap_branches/psLib/src/imageops/psImageConvolve.c
r25383 r27838 246 246 return kernel; 247 247 } 248 249 bool psKernelTruncate(psKernel *kernel, float frac) 250 { 251 PS_ASSERT_KERNEL_NON_NULL(kernel, false); 252 PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(frac, 0.0, false); 253 PS_ASSERT_FLOAT_LESS_THAN(frac, 1.0, false); 254 255 if (frac == 0.0) { 256 // Nothing to do 257 return true; 258 } 259 260 int xMin = kernel->xMin, xMax = kernel->xMax, yMin = kernel->yMin, yMax = kernel->yMax; // Bounds 261 int maxSize = PS_MAX(PS_MAX(PS_MAX(-xMin, xMax), -yMin), yMax); // Maximum size 262 263 // Determine the threshold 264 // Summing absolute values because large negative deviations have power as well 265 double sumKernel = 0.0; // Sum of the kernel 266 for (int y = yMin; y <= yMax; y++) { 267 for (int x = xMin; x <= xMax; x++) { 268 sumKernel += fabsf(kernel->kernel[y][x]); 269 } 270 } 271 272 float threshold = sumKernel * (1.0 - frac); // Threshold for truncation 273 274 // Find truncation size 275 int truncate = 0; // Truncation radius 276 for (int radius = 1; truncate == 0 && radius < maxSize; radius++) { 277 int uMin = PS_MAX(-radius, xMin); 278 int uMax = PS_MIN(radius, xMax); 279 int vMin = PS_MAX(-radius, yMin); 280 int vMax = PS_MIN(radius, yMax); 281 int r2 = PS_SQR(radius); 282 double sum = 0.0; 283 for (int v = vMin; v <= vMax; v++) { 284 int v2 = PS_SQR(v); 285 for (int u = uMin; u <= uMax; u++) { 286 int u2 = PS_SQR(u); 287 if (u2 + v2 <= r2) { 288 sum += fabsf(kernel->kernel[v][u]); 289 } 290 } 291 } 292 if (sum > threshold) { 293 // This is the truncation radius 294 truncate = radius; 295 } 296 } 297 if (truncate == maxSize) { 298 // No truncation possible 299 return true; 300 } 301 302 // Truncate the kernel 303 { 304 int uMin = PS_MAX(-truncate, xMin); 305 int uMax = PS_MIN(truncate, xMax); 306 int vMin = PS_MAX(-truncate, yMin); 307 int vMax = PS_MIN(truncate, yMax); 308 int r2 = PS_SQR(truncate); 309 for (int v = vMin; v <= vMax; v++) { 310 int v2 = PS_SQR(v); 311 for (int u = uMin; u <= uMax; u++) { 312 int u2 = PS_SQR(u); 313 if (u2 + v2 > r2) { 314 kernel->kernel[v][u] = 0.0; 315 } 316 } 317 } 318 } 319 kernel->xMin = PS_MAX(-truncate, kernel->xMin); 320 kernel->xMax = PS_MIN(truncate, kernel->xMax); 321 kernel->yMin = PS_MAX(-truncate, kernel->yMin); 322 kernel->yMax = PS_MIN(truncate, kernel->yMax); 323 324 return true; 325 } 326 327 248 328 249 329 psImage *psImageConvolveDirect(psImage *out, const psImage *in, const psKernel *kernel) -
branches/tap_branches/psLib/src/imageops/psImageConvolve.h
r25383 r27838 138 138 ); 139 139 140 /// Truncate a kernel 141 /// 142 /// Truncates the outer parts of the kernel where the contribution is below the nominated fraction of the 143 /// total kernel. 144 bool psKernelTruncate( 145 psKernel *in, ///< Kernel to be truncated 146 float frac ///< Fraction for truncation threshold 147 ); 148 149 140 150 /// Convolve an image with a kernel, using a direct convolution 141 151 /// -
branches/tap_branches/psLib/src/imageops/psImageCovariance.c
r24832 r27838 14 14 #include "psTrace.h" 15 15 #include "psBinaryOp.h" 16 #include "psScalar.h" 17 #include "psThread.h" 16 18 17 19 #include "psImageCovariance.h" 20 21 static bool threaded = false; // Run threaded? 22 18 23 19 24 psKernel *psImageCovarianceNone(void) … … 24 29 } 25 30 26 27 psKernel *psImageCovarianceCalculate(const psKernel *kernel, const psKernel *covariance) 28 { 29 PS_ASSERT_KERNEL_NON_NULL(kernel, NULL); 30 31 // See http://en.wikipedia.org/wiki/Error_propagation 32 // 33 // If 34 // f_k = sum_i A_ik x_i 35 // is a set of functions, then the covariance matrix for f is given by: 36 // M^f_ij = sum_k sum_l A_ik M^x_kl A_lj 37 // where M^x is the covariance matrix for x. 38 // Note that the errors in f are correlated (covariance) even if the errors in x are not. 39 40 psKernel *covar; // Covariance matrix to use 41 if (covariance) { 42 covar = psMemIncrRefCounter((psKernel*)covariance); // Casting away const 43 } else { 44 covar = psImageCovarianceNone(); 45 } 46 47 // Check for non-finite elements 48 for (int y = kernel->yMin; y <= kernel->yMax; y++) { 49 for (int x = kernel->xMin; x <= kernel->xMax; x++) { 50 if (!isfinite(kernel->kernel[y][x])) { 51 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 52 "Non-finite covariance matrix element in kernel at %d,%d", x, y); 53 psFree(covar); 54 return NULL; 55 } 56 } 57 } 58 for (int y = covar->yMin; y <= covar->yMax; y++) { 59 for (int x = covar->xMin; x <= covar->xMax; x++) { 60 if (!isfinite(covar->kernel[y][x])) { 61 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 62 "Non-finite covariance matrix element in covariance matrix at %d,%d", x, y); 63 psFree(covar); 64 return NULL; 65 } 66 } 67 } 68 69 // The above (double) sum for the covariance matrix means that, for each point in the output covariance 70 // matrix, we need to work out all combinations of getting to the central point via a kernel, input 71 // covariance matrix and another kernel. This means that the resultant covariance matrix has twice the 72 // size of the kernel plus the size of the input covariance matrix. 73 int xMin = kernel->xMin - kernel->xMax + covar->xMin, xMax = kernel->xMax - kernel->xMin + covar->xMax; 74 int yMin = kernel->yMin - kernel->yMax + covar->yMin, yMax = kernel->yMax - kernel->yMin + covar->yMax; 75 psKernel *out = psKernelAlloc(xMin, xMax, yMin, yMax); // Covariance matrix for output 31 /// Calculation of covariance matrix element when convolving 32 static float imageCovarianceCalculate(const psKernel *covar, // Original covariance matrix 33 const psKernel *kernel, // Convolution kernel 34 int x, int y // Coordinates in output covariance matrix 35 ) 36 { 37 psAssert(covar, "Require covariance matrix"); 38 psAssert(kernel, "Require kernel"); 76 39 77 40 // Need to go: … … 89 52 // from the source coordinate), we take the smallest possible (because everything else is zero outside). 90 53 91 double total = 0.0; // Total covariance 54 // Range for v 55 int vMin = PS_MAX(kernel->yMin + covar->yMin, y + kernel->yMin); 56 int vMax = PS_MIN(kernel->yMax + covar->yMax, y + kernel->yMax); 57 // Range for u 58 int uMin = PS_MAX(kernel->xMin + covar->xMin, x + kernel->xMin); 59 int uMax = PS_MIN(kernel->xMax + covar->xMax, x + kernel->xMax); 60 61 double sum = 0.0; // Sum for value of covariance matrix at (x,y) 62 for (int v = vMin; v <= vMax; v++) { 63 // Range for q 64 int qMin = PS_MAX(v + covar->yMin, kernel->yMin); 65 int qMax = PS_MIN(v + covar->yMax, kernel->yMax); 66 for (int u = uMin; u <= uMax; u++) { 67 // Range for p 68 int pMin = PS_MAX(u + covar->xMin, kernel->xMin); 69 int pMax = PS_MIN(u + covar->xMax, kernel->xMax); 70 71 double xyuvValue = kernel->kernel[v-y][u-x]; // Value for (x,y) --> (u,v) 72 73 double uvpqValue = 0.0; // Value for (u,v) --> (p,q) --> (0,0) 74 for (int q = qMin; q <= qMax; q++) { 75 for (int p = pMin; p <= pMax; p++) { 76 uvpqValue += (double)covar->kernel[q-v][p-u] * (double)kernel->kernel[q][p]; 77 } 78 } 79 sum += xyuvValue * uvpqValue; 80 } 81 } 82 83 return sum; 84 } 85 86 /// Thread entry point for calculation of covariance matrix element when convolving 87 static bool imageCovarianceCalculateThread(psThreadJob *job) 88 { 89 PS_ASSERT_THREAD_JOB_NON_NULL(job, false); 90 psAssert(job->args, "No job arguments"); 91 psAssert(job->args->n == 5, "Wrong number of job arguments: %ld", job->args->n); 92 93 psKernel *out = job->args->data[0]; // Output covariance matrix 94 const psKernel *covar = job->args->data[1]; // Input covariance matrix 95 const psKernel *kernel = job->args->data[2]; // Convolution kernel 96 int x = PS_SCALAR_VALUE(job->args->data[3], S32); // x coordinate in output covariance matrix 97 int y = PS_SCALAR_VALUE(job->args->data[4], S32); // y coordinate in output covariance matrix 98 99 out->kernel[y][x] = imageCovarianceCalculate(covar, kernel, x, y); 100 101 return true; 102 } 103 104 105 106 psKernel *psImageCovarianceCalculate(const psKernel *kernel, const psKernel *covariance) 107 { 108 PS_ASSERT_KERNEL_NON_NULL(kernel, NULL); 109 110 // See http://en.wikipedia.org/wiki/Error_propagation 111 // 112 // If 113 // f_k = sum_i A_ik x_i 114 // is a set of functions, then the covariance matrix for f is given by: 115 // M^f_ij = sum_k sum_l A_ik M^x_kl A_lj 116 // where M^x is the covariance matrix for x. 117 // Note that the errors in f are correlated (covariance) even if the errors in x are not. 118 119 psKernel *covar; // Covariance matrix to use 120 if (covariance) { 121 covar = psMemIncrRefCounter((psKernel*)covariance); // Casting away const 122 } else { 123 covar = psImageCovarianceNone(); 124 } 125 126 // Check for non-finite elements 127 for (int y = kernel->yMin; y <= kernel->yMax; y++) { 128 for (int x = kernel->xMin; x <= kernel->xMax; x++) { 129 if (!isfinite(kernel->kernel[y][x])) { 130 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 131 "Non-finite covariance matrix element in kernel at %d,%d", x, y); 132 psFree(covar); 133 return NULL; 134 } 135 } 136 } 137 for (int y = covar->yMin; y <= covar->yMax; y++) { 138 for (int x = covar->xMin; x <= covar->xMax; x++) { 139 if (!isfinite(covar->kernel[y][x])) { 140 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 141 "Non-finite covariance matrix element in covariance matrix at %d,%d", x, y); 142 psFree(covar); 143 return NULL; 144 } 145 } 146 } 147 148 // The above (double) sum for the covariance matrix means that, for each point in the output covariance 149 // matrix, we need to work out all combinations of getting to the central point via a kernel, input 150 // covariance matrix and another kernel. This means that the resultant covariance matrix has twice the 151 // size of the kernel plus the size of the input covariance matrix. 152 int xMin = kernel->xMin - kernel->xMax + covar->xMin, xMax = kernel->xMax - kernel->xMin + covar->xMax; 153 int yMin = kernel->yMin - kernel->yMax + covar->yMin, yMax = kernel->yMax - kernel->yMin + covar->yMax; 154 psKernel *out = psKernelAlloc(xMin, xMax, yMin, yMax); // Covariance matrix for output 155 92 156 for (int y = yMin; y <= yMax; y++) { 93 // Range for v94 int vMin = PS_MAX(kernel->yMin + covar->yMin, y + kernel->yMin);95 int vMax = PS_MIN(kernel->yMax + covar->yMax, y + kernel->yMax);96 157 for (int x = xMin; x <= xMax; x++) { 97 // Range for u 98 int uMin = PS_MAX(kernel->xMin + covar->xMin, x + kernel->xMin); 99 int uMax = PS_MIN(kernel->xMax + covar->xMax, x + kernel->xMax); 100 101 double sum = 0.0; // Sum for value of covariance matrix at (x,y) 102 for (int v = vMin; v <= vMax; v++) { 103 // Range for q 104 int qMin = PS_MAX(v + covar->yMin, kernel->yMin); 105 int qMax = PS_MIN(v + covar->yMax, kernel->yMax); 106 for (int u = uMin; u <= uMax; u++) { 107 // Range for p 108 int pMin = PS_MAX(u + covar->xMin, kernel->xMin); 109 int pMax = PS_MIN(u + covar->xMax, kernel->xMax); 110 111 double xyuvValue = kernel->kernel[v-y][u-x]; // Value for (x,y) --> (u,v) 112 113 double uvpqValue = 0.0; // Value for (u,v) --> (p,q) --> (0,0) 114 for (int q = qMin; q <= qMax; q++) { 115 for (int p = pMin; p <= pMax; p++) { 116 uvpqValue += (double)covar->kernel[q-v][p-u] * (double)kernel->kernel[q][p]; 117 } 118 } 119 sum += xyuvValue * uvpqValue; 158 if (threaded) { 159 psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_COVARIANCE_CALCULATE"); 160 psArrayAdd(job->args, 1, out); 161 psArrayAdd(job->args, 1, covar); 162 psArrayAdd(job->args, 1, (psKernel*)kernel); // Casting away const 163 PS_ARRAY_ADD_SCALAR(job->args, x, PS_TYPE_S32); 164 PS_ARRAY_ADD_SCALAR(job->args, y, PS_TYPE_S32); 165 if (!psThreadJobAddPending(job)) { 166 psFree(covar); 167 return NULL; 120 168 } 121 } 122 out->kernel[y][x] = sum; 123 total += sum; 124 } 125 } 126 psTrace("psLib.imageops", 3, "Total covariance: %lf ; Central variance: %f\n", total, out->kernel[0][0]); 127 169 psFree(job); 170 } else { 171 out->kernel[y][x] = imageCovarianceCalculate(covar, kernel, x, y); 172 } 173 } 174 } 128 175 psFree(covar); 176 177 if (threaded && !psThreadPoolWait(true)) { 178 psError(PS_ERR_UNKNOWN, false, "Error waiting for threads."); 179 return false; 180 } 181 129 182 return out; 130 183 } 184 185 float psImageCovarianceCalculateFactor(const psKernel *kernel, const psKernel *covariance) 186 { 187 psKernel *covar; // Covariance matrix to use 188 if (covariance) { 189 covar = psMemIncrRefCounter((psKernel*)covariance); // Casting away const 190 } else { 191 covar = psImageCovarianceNone(); 192 } 193 194 // Check for non-finite elements 195 for (int y = kernel->yMin; y <= kernel->yMax; y++) { 196 for (int x = kernel->xMin; x <= kernel->xMax; x++) { 197 if (!isfinite(kernel->kernel[y][x])) { 198 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 199 "Non-finite covariance matrix element in kernel at %d,%d", x, y); 200 psFree(covar); 201 return NAN; 202 } 203 } 204 } 205 for (int y = covar->yMin; y <= covar->yMax; y++) { 206 for (int x = covar->xMin; x <= covar->xMax; x++) { 207 if (!isfinite(covar->kernel[y][x])) { 208 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 209 "Non-finite covariance matrix element in covariance matrix at %d,%d", x, y); 210 psFree(covar); 211 return NAN; 212 } 213 } 214 } 215 216 float factor = imageCovarianceCalculate(covar, kernel, 0, 0); // Covariance factor 217 psFree(covar); 218 return factor; 219 } 220 221 // Calculation of covariance matrix element when binning 222 static float imageCovarianceBin(const psKernel *covar, // Original covariance matrix 223 int bin, // Binning factor 224 float binVal, // Convolution kernel value for binning 225 int x, int y // Coordinates in output covariance matrix 226 ) 227 { 228 psAssert(covar, "Require covariance matrix"); 229 psAssert(bin > 0 && binVal > 0, "Require binning: %d %f", bin, binVal); 230 231 int binMin = -(bin - 1) / 2, binMax = bin / 2; // Range of "kernel" 232 233 // Range for v 234 int vMin = PS_MAX(binMin + covar->yMin, bin * y + binMin); 235 int vMax = PS_MIN(binMax + covar->yMax, bin * y + binMax); 236 // Range for u 237 int uMin = PS_MAX(binMin + covar->xMin, bin * x + binMin); 238 int uMax = PS_MIN(binMax + covar->xMax, bin * x + binMax); 239 240 double sum = 0.0; // Sum for value of covariance matrix at (x,y) 241 for (int v = vMin; v <= vMax; v++) { 242 // Range for q 243 int qMin = PS_MAX(v + covar->yMin, binMin); 244 int qMax = PS_MIN(v + covar->yMax, binMax); 245 for (int u = uMin; u <= uMax; u++) { 246 // Range for p 247 int pMin = PS_MAX(u + covar->xMin, binMin); 248 int pMax = PS_MIN(u + covar->xMax, binMax); 249 250 double xyuvValue = binVal; // Value for (x,y) --> (u,v) 251 252 double uvpqValue = 0.0; // Value for (u,v) --> (p,q) --> (0,0) 253 for (int q = qMin; q <= qMax; q++) { 254 for (int p = pMin; p <= pMax; p++) { 255 uvpqValue += (double)covar->kernel[q-v][p-u] * (double)binVal; 256 } 257 } 258 sum += xyuvValue * uvpqValue; 259 } 260 } 261 262 return sum; 263 } 264 265 /// Thread entry point for calculation of covariance matrix element when binning 266 static bool imageCovarianceBinThread(psThreadJob *job) 267 { 268 PS_ASSERT_THREAD_JOB_NON_NULL(job, false); 269 psAssert(job->args, "No job arguments"); 270 psAssert(job->args->n == 6, "Wrong number of job arguments: %ld", job->args->n); 271 272 psKernel *out = job->args->data[0]; // Output covariance matrix 273 const psKernel *covar = job->args->data[1]; // Input covariance matrix 274 int bin = PS_SCALAR_VALUE(job->args->data[2], S32); // Binning factor 275 float binVal = PS_SCALAR_VALUE(job->args->data[3], F32); // Convolution kernel value for binning 276 int x = PS_SCALAR_VALUE(job->args->data[4], S32); // x coordinate in output covariance matrix 277 int y = PS_SCALAR_VALUE(job->args->data[5], S32); // y coordinate in output covariance matrix 278 279 out->kernel[y][x] = imageCovarianceBin(covar, bin, binVal, x, y); 280 281 return true; 282 } 283 131 284 132 285 psKernel *psImageCovarianceBin(int bin, const psKernel *covariance, bool average) … … 165 318 psKernel *out = psKernelAlloc(xMin, xMax, yMin, yMax); // Covariance matrix for output 166 319 167 double total = 0.0; // Total covariance168 320 for (int y = yMin; y <= yMax; y++) { 169 // Range for v170 int vMin = PS_MAX(binMin + covar->yMin, bin * y + binMin);171 int vMax = PS_MIN(binMax + covar->yMax, bin * y + binMax);172 321 for (int x = xMin; x <= xMax; x++) { 173 // Range for u 174 int uMin = PS_MAX(binMin + covar->xMin, bin * x + binMin); 175 int uMax = PS_MIN(binMax + covar->xMax, bin * x + binMax); 176 177 double sum = 0.0; // Sum for value of covariance matrix at (x,y) 178 for (int v = vMin; v <= vMax; v++) { 179 // Range for q 180 int qMin = PS_MAX(v + covar->yMin, binMin); 181 int qMax = PS_MIN(v + covar->yMax, binMax); 182 for (int u = uMin; u <= uMax; u++) { 183 // Range for p 184 int pMin = PS_MAX(u + covar->xMin, binMin); 185 int pMax = PS_MIN(u + covar->xMax, binMax); 186 187 double xyuvValue = binVal; // Value for (x,y) --> (u,v) 188 189 double uvpqValue = 0.0; // Value for (u,v) --> (p,q) --> (0,0) 190 for (int q = qMin; q <= qMax; q++) { 191 for (int p = pMin; p <= pMax; p++) { 192 uvpqValue += (double)covar->kernel[q-v][p-u] * (double)binVal; 193 } 194 } 195 sum += xyuvValue * uvpqValue; 322 if (threaded) { 323 psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_COVARIANCE_BIN"); 324 psArrayAdd(job->args, 1, out); 325 psArrayAdd(job->args, 1, covar); 326 PS_ARRAY_ADD_SCALAR(job->args, bin, PS_TYPE_S32); 327 PS_ARRAY_ADD_SCALAR(job->args, binVal, PS_TYPE_F32); 328 PS_ARRAY_ADD_SCALAR(job->args, x, PS_TYPE_S32); 329 PS_ARRAY_ADD_SCALAR(job->args, y, PS_TYPE_S32); 330 if (!psThreadJobAddPending(job)) { 331 psFree(covar); 332 return NULL; 196 333 } 197 } 198 out->kernel[y][x] = sum; 199 total += sum; 200 } 201 } 202 psTrace("psLib.imageops", 3, "Total covariance: %lf ; Central variance: %f\n", total, out->kernel[0][0]); 203 334 psFree(job); 335 } else { 336 out->kernel[y][x] = imageCovarianceBin(covar, bin, binVal, x, y); 337 } 338 } 339 } 204 340 psFree(covar); 205 341 342 if (threaded && !psThreadPoolWait(true)) { 343 psError(PS_ERR_UNKNOWN, false, "Error waiting for threads."); 344 return false; 345 } 346 206 347 return out; 207 348 } … … 212 353 } 213 354 214 psKernel *psImageCovarianceSum(const psArray *array) 355 float psImageCovarianceFactorForAperture(const psKernel *covar, float radius) 356 { 357 if (!covar) return 1.0; 358 359 float Sum = 0.0; 360 361 for (int y = covar->yMin; y <= covar->yMax; y++) { 362 if (y < -radius) continue; 363 if (y > +radius) continue; 364 for (int x = covar->xMin; x <= covar->xMax; x++) { 365 if (x < -radius) continue; 366 if (x > +radius) continue; 367 368 if (hypot(x, y) > radius) continue; 369 370 psAssert (isfinite(covar->kernel[y][x]), "invalid NAN in covariance matrix"); 371 Sum += covar->kernel[y][x]; 372 } 373 } 374 375 return Sum; 376 } 377 378 float psImageCovarianceSum(const psKernel *covar) 379 { 380 PS_ASSERT_KERNEL_NON_NULL(covar, NAN); 381 382 int xMin = covar->xMin, xMax = covar->xMax, yMin = covar->yMin, yMax = covar->yMax; // Range for covariance 383 double sum = 0.0; // Sum of covariance 384 for (int y = yMin; y <= yMax; y++) { 385 for (int x = xMin; x <= xMax; x++) { 386 sum += covar->kernel[y][x]; 387 } 388 } 389 390 return sum; 391 } 392 393 394 psKernel *psImageCovarianceAverage(const psArray *array) 215 395 { 216 396 PS_ASSERT_ARRAY_NON_NULL(array, NULL); 217 397 PS_ASSERT_ARRAY_NON_EMPTY(array, NULL); 218 398 219 int xMin = INT_MAX, xMax = INT_MIN, yMin = INT_MAX, yMax = INT_MIN; // Range for covariance 220 int num = 0; // Number of good matrices to sum 221 for (int i = 0; i < array->n; i++) { 222 psKernel *covar = array->data[i]; // Covariance matrix 223 if (!covar) { 224 continue; 225 } 226 xMin = PS_MIN(xMin, covar->xMin); 227 xMax = PS_MAX(xMax, covar->xMax); 228 yMin = PS_MIN(yMin, covar->yMin); 229 yMax = PS_MAX(yMax, covar->yMax); 230 num++; 231 } 232 if (num == 0) { 233 psError(PS_ERR_BAD_PARAMETER_SIZE, true, "No covariance matrices supplied for summation"); 234 return NULL; 235 } 236 237 psKernel *sum = psKernelAlloc(xMin, xMax, yMin, yMax); // Summed covariance 238 for (int i = 0; i < array->n; i++) { 239 psKernel *covar = array->data[i]; // Covariance matrix 240 if (!covar) { 241 continue; 242 } 243 for (int y = covar->yMin; y <= covar->yMax; y++) { 244 for (int x = covar->xMin; x <= covar->xMax; x++) { 245 if (!isfinite(covar->kernel[y][x])) { 246 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 247 "Non-finite covariance matrix element at %d,%d for input %d", 248 x, y, i); 249 psFree(sum); 250 return NULL; 251 } 252 sum->kernel[y][x] += covar->kernel[y][x]; 253 } 254 } 255 } 256 257 return sum; 258 } 259 260 261 psKernel *psImageCovarianceAverage(const psArray *array) 262 { 263 PS_ASSERT_ARRAY_NON_NULL(array, NULL); 264 PS_ASSERT_ARRAY_NON_EMPTY(array, NULL); 265 266 int num = 0; // Number of good matrices to average 267 for (int i = 0; i < array->n; i++) { 268 psKernel *covar = array->data[i]; // Covariance matrix 269 if (covar) { 270 num++; 271 } 272 } 273 if (num == 0) { 274 psError(PS_ERR_BAD_PARAMETER_SIZE, true, "No covariance matrices supplied for averaging."); 275 return NULL; 276 } 277 278 psKernel *sum = psImageCovarianceSum(array); // Sum of covariances 279 psBinaryOp(sum->image, sum->image, "/", psScalarAlloc(num, PS_TYPE_F32)); 280 281 return sum; 399 psVector *weights = psVectorAlloc(array->n, PS_TYPE_F32); // Weights to apply 400 psVectorInit(weights, 1.0); 401 psKernel *out = psImageCovarianceAverageWeighted(array, weights); 402 psFree(weights); 403 return out; 282 404 } 283 405 … … 310 432 311 433 psKernel *sum = psKernelAlloc(xMin, xMax, yMin, yMax); // Summed covariance 434 psImageInit(sum->image, 0.0); 312 435 for (int i = 0; i < array->n; i++) { 313 436 psKernel *covar = array->data[i]; // Covariance matrix … … 405 528 return true; 406 529 } 530 531 532 bool psImageCovarianceSetThreads(bool set) 533 { 534 bool old = threaded; // Old value 535 if (set && !threaded) { 536 { 537 psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_COVARIANCE_CALCULATE", 5); 538 task->function = &imageCovarianceCalculateThread; 539 psThreadTaskAdd(task); 540 psFree(task); 541 } 542 { 543 psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_COVARIANCE_BIN", 6); 544 task->function = &imageCovarianceBinThread; 545 psThreadTaskAdd(task); 546 psFree(task); 547 } 548 } else if (!set && threaded) { 549 psThreadTaskRemove("PSLIB_IMAGE_COVARIANCE_CALCULATE"); 550 psThreadTaskRemove("PSLIB_IMAGE_COVARIANCE_BIN"); 551 } 552 threaded = set; 553 return old; 554 } 555 556 bool psImageCovarianceGetThreads(void) 557 { 558 return threaded; 559 } -
branches/tap_branches/psLib/src/imageops/psImageCovariance.h
r24832 r27838 47 47 ); 48 48 49 /// Sum multiple covariance pseudo-matrices 50 psKernel *psImageCovarianceSum( 51 const psArray *array ///< Array of covariance pseudo-matrices 49 /// Return the pixel-to-pixel covariance factor following calculation 50 /// 51 /// This doesn't require calculation of the entire covariance matrix, so is much faster. 52 float psImageCovarianceCalculateFactor( 53 const psKernel *kernel, ///< Convolution kernel 54 const psKernel *covariance ///< Current covariance pseudo-matrix 55 ); 56 57 58 /// Return the covariance factor for an aperture of a given radius 59 float psImageCovarianceFactorForAperture(const psKernel *covar, float radius); 60 61 /// Return the sum of the covariance pseudo-matrix 62 float psImageCovarianceSum( 63 const psKernel *covariance ///< Covariance pseudo-matrix 52 64 ); 53 65 … … 78 90 ); 79 91 92 /// Control threading for image covariance functions 93 /// 94 /// Returns old threading status 95 bool psImageCovarianceSetThreads(bool threaded ///< Run image covariance functions threaded? 96 ); 97 98 /// Return whether image covariance functions are threaded 99 bool psImageCovarianceGetThreads(void); 80 100 81 101 /// @} -
branches/tap_branches/psLib/src/imageops/psImageInterpolate.c
r23231 r27838 197 197 { 198 198 // Casting away const 199 psFree( (psImage*)interp->image);200 psFree( (psImage*)interp->mask);201 psFree( (psImage*)interp->variance);202 psFree( (psImage*)interp->kernel);203 psFree( (psImage*)interp->kernel2);204 psFree( (psVector*)interp->sumKernel2);199 psFree(interp->image); 200 psFree(interp->mask); 201 psFree(interp->variance); 202 psFree(interp->kernel); 203 psFree(interp->kernel2); 204 psFree(interp->sumKernel2); 205 205 } 206 206 -
branches/tap_branches/psLib/src/jpeg/psImageJpeg.c
r24220 r27838 202 202 if (isfinite(row[i])) { 203 203 pixel = PS_JPEG_SCALEVALUE(row[i],zero,scale); 204 outPix[0] = Rpix[pixel];205 outPix[1] = Gpix[pixel];206 outPix[2] = Bpix[pixel];204 outPix[0] = Rpix[pixel]; 205 outPix[1] = Gpix[pixel]; 206 outPix[2] = Bpix[pixel]; 207 207 } else { 208 // XXX NAN value should be set per-color map 209 outPix[0] = 0xff; 210 outPix[1] = 0x00; 211 outPix[2] = 0xff; 212 } 213 } 214 jpeg_write_scanlines(&cinfo, jpegLineList, 1); 208 // XXX NAN value should be set per-color map 209 outPix[0] = 0xff; 210 outPix[1] = 0x00; 211 outPix[2] = 0xff; 212 } 213 } 214 if (jpeg_write_scanlines(&cinfo, jpegLineList, 1) == 0) { 215 psError(PS_ERR_IO, true, "Unable to write line %d to JPEG", j); 216 psFree(jpegLine); 217 return false; 218 } 215 219 } 216 220 217 221 jpeg_finish_compress(&cinfo); 218 fclose(f); 222 if (fclose(f) == EOF) { 223 psError(PS_ERR_IO, true, "Failed to close %s", filename); 224 psFree(jpegLine); 225 return false; 226 } 219 227 jpeg_destroy_compress(&cinfo); 220 228 -
branches/tap_branches/psLib/src/math/psBinaryOp.c
r17050 r27838 379 379 } 380 380 381 psMathType* psBinaryOp(psPtr out, const psPtr in1, const char *op, constpsPtr in2)381 psMathType* psBinaryOp(psPtr out, psPtr in1, const char *op, psPtr in2) 382 382 { 383 383 -
branches/tap_branches/psLib/src/math/psBinaryOp.h
r11248 r27838 55 55 psMathType* psBinaryOp( 56 56 psPtr out, ///< Output type, either psImage or psVector. 57 constpsPtr in1, ///< First input, either psImage or psVector.57 psPtr in1, ///< First input, either psImage or psVector. 58 58 const char *op, ///< Operator. 59 constpsPtr in2 ///< Second input, either psImage or psVector.59 psPtr in2 ///< Second input, either psImage or psVector. 60 60 ); 61 61 -
branches/tap_branches/psLib/src/math/psHistogram.c
r21183 r27838 58 58 psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__); 59 59 psTrace("psLib.math", 5, "(lower, upper, n) is (%f, %f, %d)\n", lower, upper, n); 60 PS_ASSERT_INT_POSITIVE(n, NULL);61 PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(upper, lower, NULL);60 psAssert(n > 0, "Number of bins must be positive"); 61 psAssert(upper >= lower, "Bounds must be sensical"); 62 62 63 63 // Allocate memory for the new histogram structure. If there are N bins, then there are N+1 bounds to … … 127 127 static void histogramFree(psHistogram* myHist) 128 128 { 129 psFree( (void *)myHist->bounds);129 psFree(myHist->bounds); 130 130 psFree(myHist->nums); 131 131 } … … 287 287 double binSize = (out->bounds->data.F32[out->nums->n] - out->bounds->data.F32[0]) / (float) out->nums->n; // Histogram bin size 288 288 binNum = (inF32->data.F32[i] - out->bounds->data.F32[0]) / binSize; 289 binNum = PS_MAX (binNum, 0);290 binNum = PS_MIN (binNum, numBins - 1);291 292 // value is in bin 'i' if bound[i] <= value < bound[i]293 294 // we may slightly overshoot or undershoot. creep up or down on the true bin295 if (inF32->data.F32[i] < out->bounds->data.F32[binNum]) {296 psTrace("psLib.math", 6, "missed target bin, adjusting: %f vs %f to %f\n", inF32->data.F32[i], out->bounds->data.F32[binNum], out->bounds->data.F32[binNum+1]);297 while ((inF32->data.F32[i] < out->bounds->data.F32[binNum]) && (binNum > 0)) {298 binNum --;299 }300 301 }302 if (inF32->data.F32[i] >= out->bounds->data.F32[binNum+1]) {303 psTrace("psLib.math", 6, "missed target bin, adjusting: %f vs %f to %f\n", inF32->data.F32[i], out->bounds->data.F32[binNum], out->bounds->data.F32[binNum+1]);304 while ((inF32->data.F32[i] >= out->bounds->data.F32[binNum+1]) && (binNum < numBins - 1)) {305 binNum ++;306 }307 }289 binNum = PS_MAX (binNum, 0); 290 binNum = PS_MIN (binNum, numBins - 1); 291 292 // value is in bin 'i' if bound[i] <= value < bound[i] 293 294 // we may slightly overshoot or undershoot. creep up or down on the true bin 295 if (inF32->data.F32[i] < out->bounds->data.F32[binNum]) { 296 psTrace("psLib.math", 6, "missed target bin, adjusting: %f vs %f to %f\n", inF32->data.F32[i], out->bounds->data.F32[binNum], out->bounds->data.F32[binNum+1]); 297 while ((inF32->data.F32[i] < out->bounds->data.F32[binNum]) && (binNum > 0)) { 298 binNum --; 299 } 300 301 } 302 if (inF32->data.F32[i] >= out->bounds->data.F32[binNum+1]) { 303 psTrace("psLib.math", 6, "missed target bin, adjusting: %f vs %f to %f\n", inF32->data.F32[i], out->bounds->data.F32[binNum], out->bounds->data.F32[binNum+1]); 304 while ((inF32->data.F32[i] >= out->bounds->data.F32[binNum+1]) && (binNum < numBins - 1)) { 305 binNum ++; 306 } 307 } 308 308 309 309 if (errorsF32) { … … 326 326 // correct bin number requires a bit more work. 327 327 tmpScalar.data.F32 = inF32->data.F32[i]; 328 psVectorBinaryDisectResult result;328 psVectorBinaryDisectResult result; 329 329 binNum = psVectorBinaryDisect(&result, out->bounds, &tmpScalar); 330 if (result != PS_BINARY_DISECT_PASS) {331 continue;332 }333 if (errorsF32 != NULL) {334 if (!UpdateHistogramBins(binNum, out, inF32->data.F32[i], errors->data.F32[i])) {335 psLogMsg(__func__, PS_LOG_WARN, "WARNING: Failed to update the histogram "336 "bins with the errors vector.\n");337 }338 } else {339 out->nums->data.F32[binNum] += 1.0;340 }330 if (result != PS_BINARY_DISECT_PASS) { 331 continue; 332 } 333 if (errorsF32 != NULL) { 334 if (!UpdateHistogramBins(binNum, out, inF32->data.F32[i], errors->data.F32[i])) { 335 psLogMsg(__func__, PS_LOG_WARN, "WARNING: Failed to update the histogram " 336 "bins with the errors vector.\n"); 337 } 338 } else { 339 out->nums->data.F32[binNum] += 1.0; 340 } 341 341 } 342 342 } -
branches/tap_branches/psLib/src/math/psMatrix.c
r24122 r27838 94 94 LHS_NAME.data = RHS_NAME; 95 95 96 97 /*****************************************************************************/ 98 /* FILE STATIC FUNCTIONS */ 99 /*****************************************************************************/ 100 101 static void psVectorToGslVector(gsl_vector *outGslVector, const psVector *inVector); 102 static void gslVectorToPsVector(psVector *outVector, gsl_vector *inGslVector); 103 static void psImageToGslMatrix(gsl_matrix *outGslMatrix, const psImage *inImage); 104 static void gslMatrixToPsImage(psImage *outImage, gsl_matrix *inGslMatrix); 96 //////////////////////////////////////////////////////////////////////////////// 97 // Conversion functions 98 //////////////////////////////////////////////////////////////////////////////// 99 100 // gsl_vector holds *doubles*, so we can directly copy F64, but need to convert F32 105 101 106 102 /** Static function to copy psF32 or psF64 vector data to a GSL vector */ 107 static void psVectorToGslVector(gsl_vector *outGslVector, 108 const psVector *inVector) 109 { 110 psU32 i = 0; 111 psU32 n = 0; 112 113 114 n = inVector->n; 115 for(i=0; i<n; i++) { 116 if(inVector->type.type == PS_TYPE_F32) { 117 outGslVector->data[i] = (psF64)inVector->data.F32[i]; 103 static void vectorPStoGSL(gsl_vector *out, const psVector *in) 104 { 105 psAssert(out->size == in->n, "Sizes don't match!"); 106 107 long n = in->n; // Size of input 108 switch (in->type.type) { 109 case PS_TYPE_F32: 110 for (long i = 0; i < n; i++) { 111 out->data[i] = in->data.F32[i]; 112 } 113 break; 114 case PS_TYPE_F64: 115 memcpy(out->data, in->data.F64, n * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 116 break; 117 default: 118 psAbort("Unsupported vector type: %x\n", in->type.type); 119 } 120 return; 121 } 122 123 /** Static function to copy GSL vector data to a psF32 or psF64 vector */ 124 static void vectorGSLtoPS(psVector *out, const gsl_vector *in) 125 { 126 psAssert(in->size == out->n, "Sizes don't match!"); 127 128 long n = out->n; // Size of output 129 switch (out->type.type) { 130 case PS_TYPE_F32: 131 for (long i = 0; i < n; i++) { 132 out->data.F32[i] = in->data[i]; 133 } 134 break; 135 case PS_TYPE_F64: 136 memcpy(out->data.F64, in->data, n * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 137 break; 138 default: 139 psAbort("Unsupported vector type: %x\n", out->type.type); 140 } 141 return; 142 } 143 144 145 /** Static function to copy psF32 or psF64 image data to a GSL matrix */ 146 static void matrixPStoGSL(gsl_matrix *out, const psImage *in) 147 { 148 psAssert(out->size1 == in->numRows && out->size2 == in->numCols, "Sizes don't match!"); 149 150 int numCols = in->numCols, numRows = in->numRows; // Size of matrix 151 switch (in->type.type) { 152 case PS_TYPE_F32: 153 for (int y = 0, i = 0; y < numRows; y++) { 154 for (int x = 0; x < numCols; x++, i++) { 155 out->data[i] = in->data.F32[y][x]; 156 } 157 } 158 break; 159 case PS_TYPE_F64: 160 if (in->parent|| out->tda != out->size1) { 161 for (int y = 0, i = 0; y < numRows; y++, i += numCols) { 162 memcpy(&out->data[i], in->data.F64[y], numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 163 } 118 164 } else { 119 outGslVector->data[i] = inVector->data.F64[i]; 120 } 121 } 122 } 123 124 /** Static function to copy GSL vector data to a psF32 or psF64 vector */ 125 static void gslVectorToPsVector(psVector *outVector, 126 gsl_vector *inGslVector) 127 { 128 psU32 i = 0; 129 psU32 n = 0; 130 131 132 n = outVector->n; 133 for(i=0; i<n; i++) { 134 if(outVector->type.type == PS_TYPE_F32) { 135 outVector->data.F32[i] = (psF32)inGslVector->data[i]; 165 memcpy(out->data, in->p_rawDataBuffer, numCols * numRows * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 166 } 167 break; 168 default: 169 psAbort("Unsupported vector type: %x\n", in->type.type); 170 } 171 return; 172 } 173 174 /** Static function to copy GSL matrix data to a psF32 or psF64 image */ 175 static void matrixGSLtoPS(psImage *out, const gsl_matrix *in) 176 { 177 psAssert(in->size1 == out->numRows && in->size2 == out->numCols, "Sizes don't match!"); 178 179 int numCols = out->numCols, numRows = out->numRows; // Size of matrix 180 switch (out->type.type) { 181 case PS_TYPE_F32: 182 for (int y = 0, i = 0; y < numRows; y++) { 183 for (int x = 0; x < numCols; x++, i++) { 184 out->data.F32[y][x] = in->data[i]; 185 } 186 } 187 break; 188 case PS_TYPE_F64: 189 if (out->parent || in->tda != in->size1) { 190 for (int y = 0, i = 0; y < numRows; y++, i += numCols) { 191 memcpy(out->data.F64[y], &in->data[i], numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 192 } 136 193 } else { 137 outVector->data.F64[i] = inGslVector->data[i]; 138 } 139 } 140 } 141 142 /** Static function to copy psF32 or psF64 image data to a GSL matrix */ 143 static void psImageToGslMatrix(gsl_matrix *outGslMatrix, 144 const psImage *inImage) 145 { 146 psU32 i = 0; 147 psU32 j = 0; 148 psU32 numRows = 0; 149 psU32 numCols = 0; 150 151 152 numRows = inImage->numRows; 153 numCols = inImage->numCols; 154 if(inImage->type.type == PS_TYPE_F32) { 155 for(i=0; i<numRows; i++) { 156 for(j=0; j<numCols; j++) { 157 outGslMatrix->data[i*numCols+j] = inImage->data.F32[i][j]; 158 } 159 } 160 } else { 161 for(i=0; i<numRows; i++) { 162 for(j=0; j<numCols; j++) { 163 outGslMatrix->data[i*numCols+j] = inImage->data.F64[i][j]; 164 } 165 } 166 } 167 } 168 169 /** Static function to copy GSL matrix data to a psF32 or psF64 image */ 170 static void gslMatrixToPsImage(psImage *outImage, 171 gsl_matrix *inGslMatrix) 172 { 173 psU32 i = 0; 174 psU32 j = 0; 175 psU32 numRows = 0; 176 psU32 numCols = 0; 177 178 179 numRows = outImage->numRows; 180 numCols = outImage->numCols; 181 if(outImage->type.type == PS_TYPE_F32) { 182 for(i=0; i<numRows; i++) { 183 for(j=0; j<numCols; j++) { 184 outImage->data.F32[i][j] = inGslMatrix->data[i*numCols+j]; 185 } 186 } 187 } else { 188 for(i=0; i<numRows; i++) { 189 for(j=0; j<numCols; j++) { 190 outImage->data.F64[i][j] = inGslMatrix->data[i*numCols+j]; 191 } 192 } 193 } 194 memcpy(out->p_rawDataBuffer, in->data, numCols * numRows * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 195 } 196 break; 197 default: 198 psAbort("Unsupported vector type: %x\n", out->type.type); 199 } 200 return; 194 201 } 195 202 … … 245 252 246 253 // Copy psImage data into GSL matrix data 247 psImageToGslMatrix(lu, in);254 matrixPStoGSL(lu, in); 248 255 249 256 // Calculate LU decomposition … … 251 258 252 259 // Copy GSL matrix data to psImage data 253 gslMatrixToPsImage(out, lu);260 matrixGSLtoPS(out, lu); 254 261 255 262 // Free GSL data … … 293 300 // Initialize GSL data 294 301 lu = gsl_matrix_alloc(numRows, numCols); 295 psImageToGslMatrix(lu, LU);302 matrixPStoGSL(lu, LU); 296 303 b = gsl_vector_alloc(RHS->n); 297 psVectorToGslVector(b, RHS);304 vectorPStoGSL(b, RHS); 298 305 x = gsl_vector_alloc(RHS->n); 299 306 … … 306 313 307 314 // Copy GSL vector data to psVector data 308 gslVectorToPsVector(out, x);315 vectorGSLtoPS(out, x); 309 316 310 317 // Free GSL data … … 341 348 // Initialize GSL data 342 349 lu = gsl_matrix_alloc(numRows, numCols); 343 psImageToGslMatrix(lu, LU);350 matrixPStoGSL(lu, LU); 344 351 345 352 permGSL.size = perm->n; … … 352 359 353 360 // Copy GSL vector data to psVector data 354 gslMatrixToPsImage(out, inverse);361 matrixGSLtoPS(out, inverse); 355 362 356 363 // Free GSL data … … 379 386 switch (a->type.type) { 380 387 case PS_TYPE_F32: { 381 psF32 **values = a->data.F32; /* Dereference */382 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */383 for (int i = 0; i < numRows; i++) {384 for (int j = 0; j < numCols; j++) {385 if (!isfinite(values[i][j])) {386 // psError(PS_ERR_BAD_PARAMETER_VALUE, 3,387 // "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n",388 // i, j, values[i][j]);389 return false;390 }391 }392 }393 break;388 psF32 **values = a->data.F32; /* Dereference */ 389 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */ 390 for (int i = 0; i < numRows; i++) { 391 for (int j = 0; j < numCols; j++) { 392 if (!isfinite(values[i][j])) { 393 // psError(PS_ERR_BAD_PARAMETER_VALUE, 3, 394 // "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n", 395 // i, j, values[i][j]); 396 return false; 397 } 398 } 399 } 400 break; 394 401 } 395 402 case PS_TYPE_F64: { 396 psF64 **values = a->data.F64; /* Dereference */397 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */398 for (int i = 0; i < numRows; i++) {399 for (int j = 0; j < numCols; j++) {400 if (!isfinite(values[i][j])) {401 // psError(PS_ERR_BAD_PARAMETER_VALUE, 3,402 // "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n",403 // i, j, values[i][j]);404 return false;405 }406 }407 }408 break;403 psF64 **values = a->data.F64; /* Dereference */ 404 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */ 405 for (int i = 0; i < numRows; i++) { 406 for (int j = 0; j < numCols; j++) { 407 if (!isfinite(values[i][j])) { 408 // psError(PS_ERR_BAD_PARAMETER_VALUE, 3, 409 // "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n", 410 // i, j, values[i][j]); 411 return false; 412 } 413 } 414 } 415 break; 409 416 } 410 // MATRIX_CHECK_NONFINITE_CASE(F32, a);411 // MATRIX_CHECK_NONFINITE_CASE(F64, a);417 // MATRIX_CHECK_NONFINITE_CASE(F32, a); 418 // MATRIX_CHECK_NONFINITE_CASE(F64, a); 412 419 default: 413 psAbort("Should never get here.");420 psAbort("Should never get here."); 414 421 } 415 422 … … 471 478 switch (a->type.type) { 472 479 case PS_TYPE_F32: { 473 psF32 **values = a->data.F32; /* Dereference */474 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */475 for (int i = 0; i < numRows; i++) {476 for (int j = 0; j < numCols; j++) {477 if (!isfinite(values[i][j])) {478 return false;479 }480 }481 }482 break;480 psF32 **values = a->data.F32; /* Dereference */ 481 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */ 482 for (int i = 0; i < numRows; i++) { 483 for (int j = 0; j < numCols; j++) { 484 if (!isfinite(values[i][j])) { 485 return false; 486 } 487 } 488 } 489 break; 483 490 } 484 491 case PS_TYPE_F64: { 485 psF64 **values = a->data.F64; /* Dereference */486 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */487 for (int i = 0; i < numRows; i++) {488 for (int j = 0; j < numCols; j++) {489 if (!isfinite(values[i][j])) {490 return false;491 }492 }493 }494 break;492 psF64 **values = a->data.F64; /* Dereference */ 493 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */ 494 for (int i = 0; i < numRows; i++) { 495 for (int j = 0; j < numCols; j++) { 496 if (!isfinite(values[i][j])) { 497 return false; 498 } 499 } 500 } 501 break; 495 502 } 496 503 default: 497 psAbort("Should never get here.");498 } 499 504 psAbort("Should never get here."); 505 } 506 500 507 // Following the algorithm laid out by Press et al., we loop along the matrix diagonal, but 501 508 // we do not operate on the diagonal elements in order. Instead, we are looking for the … … 511 518 512 519 if (a->type.type == PS_TYPE_F32) { 513 psF32 **A = a->data.F32;514 psF32 *B = b->data.F32;515 int *colIndex = colIndexV->data.S32;516 int *rowIndex = rowIndexV->data.S32;517 int *pivot = pivotV->data.S32;518 psF32 growth = 1.0;519 520 for (int diag = 0; diag < nSquare; diag++) {521 522 psF32 maxval = 0.0;523 int maxrow = 0;524 int maxcol = 0;525 526 // search for the next pivot527 for (int row = 0; row < nSquare; row++) {528 if (!isfinite(A[row][diag])) goto escape;529 530 // if we have already operated on this row (pivot[row] is true), skip it531 if (pivot[row]) continue;532 533 // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row534 for (int col = 0; col < nSquare; col++) {535 if (pivot[col]) continue;536 if (fabs (A[row][col]) < maxval) continue;537 maxval = fabs (A[row][col]);538 maxrow = row;539 maxcol = col;540 }541 }542 543 // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix544 if (pivot[maxcol]) goto escape;545 pivot[maxcol] = 1;546 547 // if the selected pivot is off the diagonal, do a row swap548 if (maxrow != maxcol) {549 for (int col = 0; col < nSquare; col++) PS_SWAP (A[maxrow][col], A[maxcol][col]);550 PS_SWAP (B[maxrow], B[maxcol]);551 }552 rowIndex[diag] = maxrow;553 colIndex[diag] = maxcol;554 if (A[maxcol][maxcol] == 0.0) goto escape;555 // Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow.556 // Here we are going to raise an error if the dynamic range is too large.557 558 /* rescale by pivot reciprocal */559 psF32 tmpval = 1.0 / A[maxcol][maxcol];560 A[maxcol][maxcol] = 1.0;561 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval;562 B[maxcol] *= tmpval;563 564 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow565 growth *= tmpval;566 psTrace ("psLib.math", 4, "growth : %e\n", growth);567 if (fabs(growth) > MAX_RANGE) goto escape;568 569 /* adjust the elements above the pivot */570 for (int row = 0; row < nSquare; row++) {571 if (row == maxcol) continue;572 tmpval = A[row][maxcol];573 A[row][maxcol] = 0.0;574 for (int col = 0; col < nSquare; col++) A[row][col] -= A[maxcol][col]*tmpval;575 B[row] -= B[maxcol]*tmpval;576 }577 }578 579 // swap back the inverse matrix based on the row swaps above580 for (int col = nSquare - 1; col >= 0; col--) {581 if (rowIndex[col] != colIndex[col]) {582 for (int row = 0; row < nSquare; row++) PS_SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]);583 }584 }520 psF32 **A = a->data.F32; 521 psF32 *B = b->data.F32; 522 int *colIndex = colIndexV->data.S32; 523 int *rowIndex = rowIndexV->data.S32; 524 int *pivot = pivotV->data.S32; 525 psF32 growth = 1.0; 526 527 for (int diag = 0; diag < nSquare; diag++) { 528 529 psF32 maxval = 0.0; 530 int maxrow = 0; 531 int maxcol = 0; 532 533 // search for the next pivot 534 for (int row = 0; row < nSquare; row++) { 535 if (!isfinite(A[row][diag])) goto escape; 536 537 // if we have already operated on this row (pivot[row] is true), skip it 538 if (pivot[row]) continue; 539 540 // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row 541 for (int col = 0; col < nSquare; col++) { 542 if (pivot[col]) continue; 543 if (fabs (A[row][col]) < maxval) continue; 544 maxval = fabs (A[row][col]); 545 maxrow = row; 546 maxcol = col; 547 } 548 } 549 550 // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix 551 if (pivot[maxcol]) goto escape; 552 pivot[maxcol] = 1; 553 554 // if the selected pivot is off the diagonal, do a row swap 555 if (maxrow != maxcol) { 556 for (int col = 0; col < nSquare; col++) PS_SWAP (A[maxrow][col], A[maxcol][col]); 557 PS_SWAP (B[maxrow], B[maxcol]); 558 } 559 rowIndex[diag] = maxrow; 560 colIndex[diag] = maxcol; 561 if (A[maxcol][maxcol] == 0.0) goto escape; 562 // Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow. 563 // Here we are going to raise an error if the dynamic range is too large. 564 565 /* rescale by pivot reciprocal */ 566 psF32 tmpval = 1.0 / A[maxcol][maxcol]; 567 A[maxcol][maxcol] = 1.0; 568 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval; 569 B[maxcol] *= tmpval; 570 571 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow 572 growth *= tmpval; 573 psTrace ("psLib.math", 4, "growth : %e\n", growth); 574 if (fabs(growth) > MAX_RANGE) goto escape; 575 576 /* adjust the elements above the pivot */ 577 for (int row = 0; row < nSquare; row++) { 578 if (row == maxcol) continue; 579 tmpval = A[row][maxcol]; 580 A[row][maxcol] = 0.0; 581 for (int col = 0; col < nSquare; col++) A[row][col] -= A[maxcol][col]*tmpval; 582 B[row] -= B[maxcol]*tmpval; 583 } 584 } 585 586 // swap back the inverse matrix based on the row swaps above 587 for (int col = nSquare - 1; col >= 0; col--) { 588 if (rowIndex[col] != colIndex[col]) { 589 for (int row = 0; row < nSquare; row++) PS_SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]); 590 } 591 } 585 592 } else { 586 psF64 **A = a->data.F64;587 psF64 *B = b->data.F64;588 int *colIndex = colIndexV->data.S32;589 int *rowIndex = rowIndexV->data.S32;590 int *pivot = pivotV->data.S32;591 psF64 growth = 1.0;592 593 for (int diag = 0; diag < nSquare; diag++) {594 595 psF64 maxval = 0.0;596 int maxrow = 0;597 int maxcol = 0;598 599 // search for the next pivot600 for (int row = 0; row < nSquare; row++) {601 if (!isfinite(A[row][diag])) goto escape;602 603 // if we have already operated on this row (pivot[row] is true), skip it604 if (pivot[row]) continue;605 606 // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row607 for (int col = 0; col < nSquare; col++) {608 if (pivot[col]) continue;609 if (fabs (A[row][col]) < maxval) continue;610 maxval = fabs (A[row][col]);611 maxrow = row;612 maxcol = col;613 }614 }615 616 // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix617 if (pivot[maxcol]) goto escape;618 pivot[maxcol] = 1;619 620 // if the selected pivot is off the diagonal, do a row swap621 if (maxrow != maxcol) {622 for (int col = 0; col < nSquare; col++) PS_SWAP (A[maxrow][col], A[maxcol][col]);623 PS_SWAP (B[maxrow], B[maxcol]);624 }625 rowIndex[diag] = maxrow;626 colIndex[diag] = maxcol;627 if (A[maxcol][maxcol] == 0.0) goto escape;628 // Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow.629 // Here we are going to raise an error if the dynamic range is too large.630 631 /* rescale by pivot reciprocal */632 psF64 tmpval = 1.0 / A[maxcol][maxcol];633 A[maxcol][maxcol] = 1.0;634 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval;635 B[maxcol] *= tmpval;636 637 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow638 growth *= tmpval;639 psTrace ("psLib.math", 4, "growth : %e\n", growth);640 if (fabs(growth) > MAX_RANGE) goto escape;641 642 /* adjust the elements above the pivot */643 for (int row = 0; row < nSquare; row++) {644 if (row == maxcol) continue;645 tmpval = A[row][maxcol];646 A[row][maxcol] = 0.0;647 for (int col = 0; col < nSquare; col++) A[row][col] -= A[maxcol][col]*tmpval;648 B[row] -= B[maxcol]*tmpval;649 }650 }651 652 // swap back the inverse matrix based on the row swaps above653 for (int col = nSquare - 1; col >= 0; col--) {654 if (rowIndex[col] != colIndex[col]) {655 for (int row = 0; row < nSquare; row++) PS_SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]);656 }657 }593 psF64 **A = a->data.F64; 594 psF64 *B = b->data.F64; 595 int *colIndex = colIndexV->data.S32; 596 int *rowIndex = rowIndexV->data.S32; 597 int *pivot = pivotV->data.S32; 598 psF64 growth = 1.0; 599 600 for (int diag = 0; diag < nSquare; diag++) { 601 602 psF64 maxval = 0.0; 603 int maxrow = 0; 604 int maxcol = 0; 605 606 // search for the next pivot 607 for (int row = 0; row < nSquare; row++) { 608 if (!isfinite(A[row][diag])) goto escape; 609 610 // if we have already operated on this row (pivot[row] is true), skip it 611 if (pivot[row]) continue; 612 613 // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row 614 for (int col = 0; col < nSquare; col++) { 615 if (pivot[col]) continue; 616 if (fabs (A[row][col]) < maxval) continue; 617 maxval = fabs (A[row][col]); 618 maxrow = row; 619 maxcol = col; 620 } 621 } 622 623 // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix 624 if (pivot[maxcol]) goto escape; 625 pivot[maxcol] = 1; 626 627 // if the selected pivot is off the diagonal, do a row swap 628 if (maxrow != maxcol) { 629 for (int col = 0; col < nSquare; col++) PS_SWAP (A[maxrow][col], A[maxcol][col]); 630 PS_SWAP (B[maxrow], B[maxcol]); 631 } 632 rowIndex[diag] = maxrow; 633 colIndex[diag] = maxcol; 634 if (A[maxcol][maxcol] == 0.0) goto escape; 635 // Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow. 636 // Here we are going to raise an error if the dynamic range is too large. 637 638 /* rescale by pivot reciprocal */ 639 psF64 tmpval = 1.0 / A[maxcol][maxcol]; 640 A[maxcol][maxcol] = 1.0; 641 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval; 642 B[maxcol] *= tmpval; 643 644 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow 645 growth *= tmpval; 646 psTrace ("psLib.math", 4, "growth : %e\n", growth); 647 if (fabs(growth) > MAX_RANGE) goto escape; 648 649 /* adjust the elements above the pivot */ 650 for (int row = 0; row < nSquare; row++) { 651 if (row == maxcol) continue; 652 tmpval = A[row][maxcol]; 653 A[row][maxcol] = 0.0; 654 for (int col = 0; col < nSquare; col++) A[row][col] -= A[maxcol][col]*tmpval; 655 B[row] -= B[maxcol]*tmpval; 656 } 657 } 658 659 // swap back the inverse matrix based on the row swaps above 660 for (int col = nSquare - 1; col >= 0; col--) { 661 if (rowIndex[col] != colIndex[col]) { 662 for (int row = 0; row < nSquare; row++) PS_SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]); 663 } 664 } 658 665 } 659 666 … … 701 708 lu = gsl_matrix_alloc(numRows, numCols); 702 709 inv = gsl_matrix_alloc(numRows, numCols); 703 psImageToGslMatrix(lu, in);710 matrixPStoGSL(lu, in); 704 711 705 712 // Invert data and calculate determinant … … 708 715 if (determinant) { 709 716 // XXX this is getting the wrong value: is it the wrong calculation? 710 // it disagrees with the results of 717 // it disagrees with the results of 711 718 // det = (psF32)gsl_linalg_LU_det(lu, signum); 712 719 // used in psMatrixDeterminatn … … 716 723 717 724 // Copy GSL matrix data to psImage data 718 gslMatrixToPsImage(out, inv);725 matrixGSLtoPS(out, inv); 719 726 720 727 // Free GSL structs … … 749 756 perm = gsl_permutation_alloc(numRows); 750 757 lu = gsl_matrix_alloc(numRows, numCols); 751 psImageToGslMatrix(lu, in);758 matrixPStoGSL(lu, in); 752 759 753 760 // Calculate determinant 754 761 gsl_linalg_LU_decomp(lu, perm, &signum); 755 det = (psF32)gsl_linalg_LU_ det(lu, signum);762 det = (psF32)gsl_linalg_LU_lndet(lu); 756 763 757 764 // Free GSL structs … … 877 884 878 885 inGSL = gsl_matrix_alloc(numRows, numCols); 879 psImageToGslMatrix(inGSL, in);886 matrixPStoGSL(inGSL, in); 880 887 outGSL = gsl_matrix_alloc(numRows, numCols); 881 888 … … 892 899 893 900 // Copy GSL matrix data to psImage data 894 gslMatrixToPsImage(out, outGSL);901 matrixGSLtoPS(out, outGSL); 895 902 896 903 // Free GSL structs … … 1026 1033 } 1027 1034 1035 psVector *psMatrixSolveSVD(psVector *out, const psImage *matrix, const psVector *vector, float thresh) 1036 { 1037 #define psMatrixSolveSVD_EXIT {psFree(out); return NULL; } 1038 PS_ASSERT_GENERAL_IMAGE_NON_NULL(matrix, psMatrixSolveSVD_EXIT); 1039 PS_CHECK_DIMEN_AND_TYPE(matrix, PS_DIMEN_IMAGE, psMatrixSolveSVD_EXIT); 1040 PS_ASSERT_GENERAL_VECTOR_NON_NULL(vector, psMatrixSolveSVD_EXIT); 1041 PS_CHECK_DIMEN_AND_TYPE(vector, PS_DIMEN_VECTOR, psMatrixSolveSVD_EXIT); 1042 1043 int numCols = matrix->numCols, numRows = matrix->numRows; // Size of matrix 1044 1045 // Decompose matrix: A = U S V^T 1046 gsl_matrix *A = gsl_matrix_alloc(numRows, numCols); // Input matrix in GSL-speak; becomes matrix U 1047 gsl_matrix *V = gsl_matrix_alloc(numCols, numCols); // Untransposed matrix V 1048 gsl_vector *S = gsl_vector_alloc(numCols); // Singular values 1049 gsl_vector *work = gsl_vector_alloc(numCols); // Work space for GSL 1050 1051 matrixPStoGSL(A, matrix); 1052 1053 int gslStatus = 0; // Status of GSL 1054 if ((gslStatus = gsl_linalg_SV_decomp(A, V, S, work))) { 1055 const char *err = gsl_strerror(gslStatus); 1056 psError(PS_ERR_UNKNOWN, true, "Unable to decompose matrix: %s", err); 1057 gsl_matrix_free(A); 1058 gsl_matrix_free(V); 1059 gsl_vector_free(S); 1060 gsl_vector_free(work); 1061 return NULL; 1062 } 1063 gsl_vector_free(work); 1064 1065 if (isfinite(thresh) && thresh > 0.0) { 1066 // Trim the singular values 1067 double total = 0.0; // Total of singular values 1068 for (int i = 0; i < numCols; i++) { 1069 total += gsl_vector_get(S, i); 1070 } 1071 thresh *= total; 1072 for (int i = 0; i < numCols; i++) { 1073 double value = gsl_vector_get(S, i); // Singular value 1074 if (value < thresh) { 1075 psTrace("psLib.math", 5, "Trimming singular value %d: %lg", i, value); 1076 gsl_vector_set(S, i, 0.0); 1077 #if 0 1078 for (int j = 0; j < numCols; j++) { 1079 // Being thorough; probably unnecessary 1080 gsl_matrix_set(V, j, i, 0.0); 1081 gsl_matrix_set(A, j, i, 0.0); 1082 } 1083 #endif 1084 } else { 1085 psTrace("psLib.math", 5, "Singular value %d: %lg", i, value); 1086 } 1087 } 1088 } 1089 1090 // Solve system (or minimise least-squares if overconstrained): Ax = b 1091 gsl_vector *b = gsl_vector_alloc(numCols); // Vector b 1092 gsl_vector *x = gsl_vector_alloc(numCols); // Solution 1093 1094 vectorPStoGSL(b, vector); 1095 1096 if ((gslStatus = gsl_linalg_SV_solve(A, V, S, b, x))) { 1097 const char *err = gsl_strerror(gslStatus); 1098 psError(PS_ERR_UNKNOWN, true, "Unable to solve matrix equation: %s", err); 1099 gsl_matrix_free(A); 1100 gsl_matrix_free(V); 1101 gsl_vector_free(S); 1102 gsl_vector_free(b); 1103 gsl_vector_free(x); 1104 return NULL; 1105 } 1106 1107 gsl_matrix_free(A); 1108 gsl_matrix_free(V); 1109 gsl_vector_free(S); 1110 gsl_vector_free(b); 1111 1112 out = psVectorRecycle(out, numCols, PS_TYPE_F64); 1113 1114 vectorGSLtoPS(out, x); 1115 gsl_vector_free(x); 1116 1117 return out; 1118 } 1119 1028 1120 // This code supplied by Andy Becker (becker@astro.washington.edu) 1029 psImage *psMatrixSVD (psImage* evec, psVector* eval, const psImage* in)1121 psImage *psMatrixSVD_old(psImage* evec, psVector* eval, const psImage* in) 1030 1122 { 1031 1123 #define psMatrixSVD_EXIT {psFree(evec); psFree(eval); return NULL;} … … 1050 1142 1051 1143 // Copy psImage data into GSL matrix data 1052 psImageToGslMatrix(A, in);1144 matrixPStoGSL(A, in); 1053 1145 1054 1146 // Calculate SVD decomposition … … 1056 1148 1057 1149 // Copy GSL matrix data to psImage data 1058 gslMatrixToPsImage(evec, V);1059 gslVectorToPsVector(eval, S);1150 matrixGSLtoPS(evec, V); 1151 vectorGSLtoPS(eval, S); 1060 1152 1061 1153 // Take the square root of eval … … 1076 1168 return evec; 1077 1169 } 1170 1171 // this is basically a wrapper for the gsl function: gsl_linalg_SV_decomp() SVD decomposes 1172 // matrix A based on the following equation: A = U w V^T . This function (as usual for SVD 1173 // implementations) returns V not V^T. U and V are returned to images; w is returned to a 1174 // vector representing the diagonal of w. The input image A is not modified. U, V, and w may 1175 // be supplied as NULL or may be allocated; their lengths are set here to match the 1176 // dimensionality of A. XXX there is no error handling for the gsl functions (anywhere in 1177 // psMatrix.c) 1178 bool psMatrixSVD(psImage **U, psVector **w, psImage **V, const psImage *A) 1179 { 1180 // Error checks Missing one for eval 1181 PS_ASSERT_PTR_NON_NULL(U, false); 1182 PS_ASSERT_PTR_NON_NULL(w, false); 1183 PS_ASSERT_PTR_NON_NULL(V, false); 1184 PS_ASSERT_PTR_NON_NULL(A, false); 1185 1186 // A is provided with size Nx,Ny = numCols,numRows 1187 // U has size Nx,Ny 1188 // V has size Nx,Nx 1189 // w has size Nx 1190 1191 // Initialize data 1192 int numRows = A->numRows; 1193 int numCols = A->numCols; 1194 1195 *U = psImageRecycle(*U, numCols, numRows, A->type.type); 1196 *V = psImageRecycle(*V, numCols, numCols, A->type.type); 1197 *w = psVectorRecycle(*w, numCols, A->type.type); 1198 1199 gsl_matrix *Agsl = gsl_matrix_alloc(numRows, numCols); 1200 gsl_matrix *Vgsl = gsl_matrix_alloc(numCols, numCols); 1201 gsl_vector *Sgsl = gsl_vector_alloc(numCols); 1202 gsl_vector *work = gsl_vector_alloc(numCols); 1203 1204 // Copy psImage data into GSL matrix data 1205 matrixPStoGSL(Agsl, A); 1206 1207 // Calculate SVD decomposition 1208 gsl_linalg_SV_decomp(Agsl, Vgsl, Sgsl, work); 1209 1210 // Copy GSL matrix data to psImage data 1211 matrixGSLtoPS(*V, Vgsl); 1212 matrixGSLtoPS(*U, Agsl); // gsl_linalg_SV_decomp replaces A with U 1213 vectorGSLtoPS(*w, Sgsl); 1214 1215 // Free GSL data 1216 gsl_matrix_free(Agsl); 1217 gsl_matrix_free(Vgsl); 1218 gsl_vector_free(Sgsl); 1219 gsl_vector_free(work); 1220 1221 return true; 1222 } 1223 -
branches/tap_branches/psLib/src/math/psMatrix.h
r24084 r27838 66 66 */ 67 67 psImage *psMatrixLUInvert( 68 psImage *out, ///< place result here if not NULL69 const psImage* LU, ///< LU-decomposed matrix.70 const psVector* perm ///< Permutation vector resulting from psMatrixLUD function.68 psImage *out, ///< place result here if not NULL 69 const psImage* LU, ///< LU-decomposed matrix. 70 const psVector* perm ///< Permutation vector resulting from psMatrixLUD function. 71 71 ); 72 72 … … 186 186 ); 187 187 188 /// Single value decomposition, provided by Andy Becker 189 psImage *psMatrixSVD(psImage* evec, psVector* eval, const psImage* in); 188 /// Solve a matrix equation using Singular Value Decomposition 189 /// 190 /// Solves Ax = b for x 191 psVector *psMatrixSolveSVD( 192 psVector *solution, ///< Solution to output, or NULL 193 const psImage *matrix, ///< Matrix to be solved 194 const psVector *vector, ///< Vector of values 195 float thresh ///< Threshold relative to maximum for trimming singular values 196 ); 197 198 /// Single value decomposition (original by Andy Becker, updated by EAM) 199 bool psMatrixSVD(psImage **U, psVector **w, psImage **V, const psImage *A); 190 200 191 201 /// @} -
branches/tap_branches/psLib/src/math/psMinimizeLMM.c
r24089 r27838 99 99 100 100 // XXX check that the GJ solver works: 101 # if (TESTGJ) 101 # if (TESTGJ) 102 102 psImage *out = psImageAlloc (alpha->numRows, alpha->numCols, PS_TYPE_F32); 103 103 for (int oy = 0; oy < out->numRows; oy++) { 104 for (int ox = 0; ox < out->numCols; ox++) {105 float value = 0;106 for (int i = 0; i < alpha->numCols; i++) {107 value += alpha->data.F32[i][ox]*Alpha->data.F32[oy][i];108 }109 out->data.F32[oy][ox] = value;110 }104 for (int ox = 0; ox < out->numCols; ox++) { 105 float value = 0; 106 for (int i = 0; i < alpha->numCols; i++) { 107 value += alpha->data.F32[i][ox]*Alpha->data.F32[oy][i]; 108 } 109 out->data.F32[oy][ox] = value; 110 } 111 111 } 112 112 113 113 psVector *vect = psVectorAlloc (beta->n, PS_TYPE_F32); 114 114 for (int oy = 0; oy < vect->n; oy++) { 115 float value = 0;116 for (int i = 0; i < alpha->numCols; i++) {117 value += alpha->data.F32[oy][i]*Beta->data.F32[i];118 }119 vect->data.F32[oy] = value;120 } 121 115 float value = 0; 116 for (int i = 0; i < alpha->numCols; i++) { 117 value += alpha->data.F32[oy][i]*Beta->data.F32[i]; 118 } 119 vect->data.F32[oy] = value; 120 } 121 122 122 psFree (out); 123 123 psFree (vect); … … 223 223 if (isnan(chisq)) { 224 224 psTrace ("psLib.math", 5, "psMinLM_SetABX() returned a NAN chisq.\n"); 225 psVectorInit (delta, NAN);225 psVectorInit (delta, NAN); 226 226 retValue = false; 227 227 } … … 238 238 if (!status) { 239 239 psTrace ("psLib.math", 5, "psMinLM_GuessABP() returned FALSE.\n"); 240 psVectorInit (delta, NAN);240 psVectorInit (delta, NAN); 241 241 retValue = false; 242 242 } … … 301 301 PS_ASSERT_VECTOR_NON_NULL(dy, NAN); 302 302 303 PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, false);303 PS_ASSERT_VECTOR_TYPE(params, PS_TYPE_F32, NAN); 304 304 if (paramMask) { 305 PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_VECTOR_MASK, false);305 PS_ASSERT_VECTOR_TYPE(paramMask, PS_TYPE_VECTOR_MASK, NAN); 306 306 } 307 307 … … 325 325 chisq += PS_SQR(delta) * dy->data.F32[i]; 326 326 327 assert (!isnan(dy->data.F32[i]));328 assert (!isnan(delta));329 assert (!isnan(chisq));327 if (isnan(dy->data.F32[i])) return NAN; 328 if (isnan(delta)) return NAN; 329 if (isnan(chisq)) return NAN; 330 330 331 331 // we track alpha,beta and params,deriv separately -
branches/tap_branches/psLib/src/math/psStats.c
r25884 r27838 749 749 // Iterate to get the best bin size; an iteration limit is enforced at the bottom of the loop. 750 750 for (int iterate = 1; iterate > 0; iterate++) { 751 psTrace(TRACE, 6, 752 "-------------------- Iterating on Bin size. Iteration number %d --------------------\n", 753 iterate); 751 psTrace(TRACE, 6, "-------------------- Iterating on Bin size. Iteration number %d --------------------\n", iterate); 752 753 if (iterate >= PS_ROBUST_MAX_ITERATIONS) { 754 // This occurs when a large number of the values are identical --- a bin size cannot be found 755 // that will spread out the distribution. Therefore, set what we can, and fall over 756 // gracefully. 757 COUNT_WARNING(10, 100, "Maximum number of iterations (%d) exceeded.", PS_ROBUST_MAX_ITERATIONS); 758 goto escape; 759 } 754 760 755 761 // Get the minimum and maximum values … … 791 797 psTrace(TRACE, 6, "Initial robust bin size is %.2f\n", binSize); 792 798 793 // ADD step 0: Construct the histogram with the specified bin size. NOTE: we can not specify the bin 794 // size precisely since the argument to psHistogramAlloc() is the number of bins, not the binSize. If 795 // we get here, we know that binSize != 0.0. 796 long numBins = (max - min) / binSize; // Number of bins 799 // ADD step 0: Construct the histogram with the specified bin size. NOTE: we can 800 // not specify the bin size precisely since the argument to psHistogramAlloc() is 801 // the number of bins, not the binSize. If we get here, we know that binSize != 802 // 0.0. We can also have a floating-point round-off error such that the last bin 803 // of the histogram does not correspond exactly with the value of 'max'. Let's be 804 // a bit generous and extend the histogram by two bins in either direction 805 long numBins = 4 + (max - min) / binSize; // Number of bins 797 806 psTrace(TRACE, 6, "Numbins is %ld\n", numBins); 798 807 psTrace(TRACE, 6, "Creating a robust histogram from data range (%.2f - %.2f)\n", min, max); 799 808 // Generate the histogram 800 histogram = psHistogramAlloc(min , max, numBins);809 histogram = psHistogramAlloc(min - 2.0*binSize, max + 2.0*binSize, numBins); 801 810 // XXXXX we need to consider this step if errors -> variance 802 811 if (!psVectorHistogram(histogram, myVector, errors, mask, maskVal)) { … … 807 816 psFree(statsMinMax); 808 817 psFree(mask); 809 810 818 return false; 811 819 } … … 813 821 PS_VECTOR_PRINT_F32(histogram->bounds); 814 822 PS_VECTOR_PRINT_F32(histogram->nums); 823 } 824 825 // perversity check: if most of the values land in a single bin, then we probably 826 // have a perverse case (eg, small number of points at extremely large / small 827 // values; nearly bi-modal distribution). if so, keep only points within 5? 10? 828 // bins of that excess bin: 829 int nMaxBin = 0; 830 int iMaxBin = 0; 831 for (long i = 1; i < histogram->nums->n; i++) { 832 if (histogram->nums->data.F32[i] > nMaxBin) { 833 nMaxBin = histogram->nums->data.F32[i]; 834 iMaxBin = i; 835 } 836 } 837 if (nMaxBin > numValid / 2) { 838 float minKeep = histogram->bounds->data.F32[iMaxBin] - 10*binSize; 839 float maxKeep = histogram->bounds->data.F32[iMaxBin + 1] + 10*binSize; 840 int nInvalid = 0; 841 for (long i = 0; i < myVector->n; i++) { 842 // skip the already-masked values 843 if (mask->data.PS_TYPE_VECTOR_MASK_DATA[i] & maskVal) continue; 844 bool invalid = false; 845 invalid |= (myVector->data.F32[i] <= minKeep); 846 invalid |= (myVector->data.F32[i] >= maxKeep); 847 invalid |= (!isfinite(myVector->data.F32[i])); 848 if (!invalid) continue; 849 mask->data.PS_TYPE_VECTOR_MASK_DATA[i] = maskVal; 850 nInvalid ++; 851 } 852 853 if (nInvalid) { 854 psTrace(TRACE, 6, "data is concentrated in a single bin, masking %d extreme outliers and retrying\n", nInvalid); 855 psFree(histogram); 856 psFree(cumulative); 857 histogram = NULL; 858 cumulative = NULL; 859 continue; 860 } 861 // if we did not mask anything, give up. 815 862 } 816 863 … … 1007 1054 stats->robustN50 = N50; 1008 1055 psTrace(TRACE, 6, "The robustN50 is %ld.\n", N50); 1056 psTrace(TRACE, 6, "The robust median and stdev are %f, %f\n", stats->robustMedian, stats->robustStdev); 1009 1057 1010 1058 // Clean up … … 1825 1873 COUNT_WARNING(10, 100, "Failed to calculate the min/max of the input vector.\n"); 1826 1874 psFree(statsMinMax); 1875 psFree(histogram); 1827 1876 goto escape; 1828 1877 } … … 1894 1943 1895 1944 if (!status) { 1896 psErrorClear();1945 psErrorClear(); 1897 1946 COUNT_WARNING(10, 100, "Failed to fit a gaussian to the robust histogram.\n"); 1898 1947 psFree(poly); … … 1984 2033 1985 2034 if (!status) { 1986 psErrorClear();2035 psErrorClear(); 1987 2036 COUNT_WARNING(10, 100, "Failed to fit a gaussian to the robust histogram.\n"); 1988 2037 psFree(poly); -
branches/tap_branches/psLib/src/math/psUnaryOp.c
r17050 r27838 211 211 } 212 212 213 psMathType* psUnaryOp(psPtr out, constpsPtr in, const char *op)213 psMathType* psUnaryOp(psPtr out, psPtr in, const char *op) 214 214 { 215 215 #define psUnaryOp_EXIT { \ -
branches/tap_branches/psLib/src/math/psUnaryOp.h
r11248 r27838 59 59 psMathType* psUnaryOp( 60 60 psPtr out, ///< Output type, either psImage or psVector. 61 const psPtr in,///< Input, either psImage or psVector.61 psPtr in, ///< Input, either psImage or psVector. 62 62 const char *op ///< Operator. 63 63 ); -
branches/tap_branches/psLib/src/mathtypes/psImage.h
r19056 r27838 66 66 #define P_PSIMAGE_SET_ROW0(img,r0) {*(int*)&img->row0 = r0;} 67 67 #define P_PSIMAGE_SET_TYPE(img,t) {*(psMathType*)&img->type = t;} 68 #define P_PSIMAGE_GET_TYPE(img) ((img)->type->type) 68 69 69 70 /** Create an image of the specified size and type. -
branches/tap_branches/psLib/src/mathtypes/psVector.c
r24886 r27838 729 729 char line[1024]; 730 730 731 sprintf (line, " vector: %s\n", name);731 sprintf (line, "# vector: %s\n", name); 732 732 if (write(fd, line, strlen(line))) {;} //ignore return value 733 733 -
branches/tap_branches/psLib/src/pslib_strict.h
r23149 r27838 102 102 #include "psType.h" 103 103 #include "psArray.h" 104 #include "psBit Set.h"104 #include "psBits.h" 105 105 #include "psHash.h" 106 106 #include "psList.h" -
branches/tap_branches/psLib/src/sys/psErrorCodes.c.in
r11675 r27838 67 67 static void freeErrorDescription(psErrorDescription* err) 68 68 { 69 psFree( (void *)err->description);69 psFree(err->description); 70 70 } 71 71 -
branches/tap_branches/psLib/src/sys/psMemory.h
r23305 r27838 326 326 327 327 /** Free memory. This operates much like free(). 328 * 328 * 329 329 * @see psAlloc, psRealloc 330 * note: we cast ptr to (void *) in case we are supplied a const pointer. 330 331 */ 331 332 #ifdef DOXYGEN … … 336 337 #ifndef SWIG 337 338 #define psFree(ptr) \ 338 psMemDecrRefCounter(ptr)339 ptr = psMemDecrRefCounter((void *)ptr); 339 340 #endif // ifndef SWIG 340 341 #endif // ifdef DOXYGEN -
branches/tap_branches/psLib/src/sys/psTrace.c
r20546 r27838 119 119 120 120 psMemSetPersistent((psPtr)comp->name,false); 121 psFree( (void *)comp->name);121 psFree(comp->name); 122 122 } 123 123 -
branches/tap_branches/psLib/src/sys/psType.c
r11617 r27838 20 20 21 21 #include "psType.h" 22 #include "psBit Set.h"22 #include "psBits.h" 23 23 #include "psFits.h" 24 24 #include "psPixels.h" … … 45 45 } 46 46 break; 47 case PS_DATA_BITS ET:48 if (psMemCheckBit Set(ptr)) {47 case PS_DATA_BITS: 48 if (psMemCheckBits(ptr)) { 49 49 return true; 50 50 } -
branches/tap_branches/psLib/src/sys/psType.h
r25256 r27838 107 107 PS_DATA_STRING = 0x10000, ///< psString (char *) 108 108 PS_DATA_ARRAY, ///< psArray 109 PS_DATA_BITS ET, ///< psBitSet109 PS_DATA_BITS, ///< psBits 110 110 PS_DATA_CUBE, ///< psCube 111 111 PS_DATA_FITS, ///< psFits -
branches/tap_branches/psLib/src/types/Makefile.am
r23148 r27838 6 6 libpslibtypes_la_SOURCES = \ 7 7 psArray.c \ 8 psBit Set.c \8 psBits.c \ 9 9 psHash.c \ 10 10 psList.c \ … … 23 23 pkginclude_HEADERS = \ 24 24 psArray.h \ 25 psBit Set.h \25 psBits.h \ 26 26 psHash.h \ 27 27 psList.h \ -
branches/tap_branches/psLib/src/types/psArray.c
r15714 r27838 166 166 // drop an item from the array and free it 167 167 bool psArrayRemoveData(psArray* array, 168 constpsPtr data)168 psPtr data) 169 169 { 170 170 PS_ASSERT_ARRAY_NON_NULL(array, false); -
branches/tap_branches/psLib/src/types/psArray.h
r19056 r27838 186 186 bool psArrayRemoveData( 187 187 psArray* array, ///< array to operate on 188 const psPtr data///< the data pointer to remove from psArray188 psPtr data ///< the data pointer to remove from psArray 189 189 ); 190 190 -
branches/tap_branches/psLib/src/types/psList.c
r18955 r27838 210 210 } 211 211 212 // XXX remove this as an error 212 213 if (location < 0 || location >= (int)list->n) { 213 214 psError(PS_ERR_BAD_PARAMETER_VALUE, true, … … 446 447 psListIterator* iterator = list->iterators->data[0]; 447 448 449 // XXX remove this as an eror 448 450 if (! psListIteratorSet(iterator,location)) { 449 451 psError(PS_ERR_BAD_PARAMETER_VALUE, true, -
branches/tap_branches/psLib/src/types/psLookupTable.c
r17447 r27838 31 31 #include "psString.h" 32 32 #include "psError.h" 33 #include "psString.h" 34 #include "psSlurp.h" 33 35 #include "psLookupTable.h" 34 36 … … 153 155 char *end = NULL; \ 154 156 ps##TYPE value = FUNC(strValue, &end, 0); \ 155 if (*end != '\0' && !isspace(*end)) { \ 157 if (*end != '\0' && *end != '\n' && !isspace(*end)) { \ 158 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Characters left over after parsing %s: %s", \ 159 strValue, end); \ 156 160 *status = PS_PARSE_ERROR_VALUE; \ 157 161 } \ … … 164 168 char *end = NULL; \ 165 169 ps##TYPE value = FUNC(strValue, &end); \ 166 if (*end != '\0' && !isspace(*end)) { \ 170 if (*end != '\0' && *end != '\n' && !isspace(*end)) { \ 171 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Characters left over after parsing %s: %s", \ 172 strValue, end); \ 167 173 *status = PS_PARSE_ERROR_VALUE; \ 168 174 } \ … … 244 250 } 245 251 246 psArray *psVectorsReadFromFile(const char *filename, 247 const char *format) 252 psArray *psVectorsReadFromFile(const char *filename, const char *format) 248 253 { 249 254 PS_ASSERT_STRING_NON_EMPTY(filename, NULL); 250 255 PS_ASSERT_STRING_NON_EMPTY(format, NULL); 251 256 252 psArray* outputArray = NULL; 253 psVector* colVector = NULL; 254 char* strValue = NULL; 255 char* strNum = NULL; 256 char* line = NULL; 257 char* linePtr = NULL; 258 int numCols = 0; 259 int numRows = 0; 260 FILE* fp = NULL; 261 const char* tempFormat = NULL; 262 psParseErrorType parseStatus = PS_PARSE_SUCCESS; 263 264 // Create temp pointer which can then be used several times 265 tempFormat = format; 266 267 // Create output array and set array elements to zero 268 outputArray = psArrayAllocEmpty(INITIAL_NUM); 269 270 // Parse the format string to determine how many vectors 271 // and whether the format string is valid 272 while ((strValue = getToken((char**)&tempFormat, " \t", &parseStatus))) { 273 274 // Check for %d format sub string 257 psArray *outputArray = psArrayAllocEmpty(INITIAL_NUM); // Array of vectors to return 258 psParseErrorType parseStatus = PS_PARSE_SUCCESS; // Status of parsing 259 260 // Parse the format string to determine how many vectors and whether the format string is valid 261 const char *tempFormat = format; // Pointer into format 262 psString strValue; // Format of interest 263 int numCols = 0; // Number of columns found in format 264 while ((strValue = getToken((char**)&tempFormat, " \t", &parseStatus)) && 265 parseStatus == PS_PARSE_SUCCESS) { 266 if (strstr(strValue,"\%*") != 0) { 267 // Don't increase number of columns 268 continue; 269 } 270 psElemType type; // Type specified 275 271 if (strcmp(strValue,"\%d") == 0 ) { 276 numCols++; 277 colVector = psVectorAlloc(1,PS_TYPE_S32); 278 outputArray = psArrayAdd(outputArray, ARRAY_STRIDE, colVector); 279 psFree(colVector); 272 type = PS_TYPE_S32; 280 273 } else if (strcmp(strValue,"\%ld") == 0) { 281 numCols++; 282 colVector = psVectorAlloc(1,PS_TYPE_S64); 283 outputArray = psArrayAdd(outputArray, ARRAY_STRIDE, colVector); 284 psFree(colVector); 274 type = PS_TYPE_S64; 285 275 } else if (strcmp(strValue,"\%f") == 0) { 286 numCols++; 287 colVector = psVectorAlloc(1,PS_TYPE_F32); 288 outputArray = psArrayAdd(outputArray, ARRAY_STRIDE, colVector); 289 psFree(colVector); 276 type = PS_TYPE_F32; 290 277 } else if (strcmp(strValue,"\%lf") == 0) { 291 numCols++; 292 colVector = psVectorAlloc(1,PS_TYPE_F64); 293 outputArray = psArrayAdd(outputArray, ARRAY_STRIDE, colVector); 294 psFree(colVector); 295 } else if (strstr(strValue,"\%*") != 0) { 296 // Don't increase number of columns 278 type = PS_TYPE_F64; 297 279 } else { 298 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 299 "Invalid format specifier"); 280 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Invalid format specifier: %s", strValue); 300 281 psFree(strValue); 301 numCols = 0; 302 break; 303 } 282 psFree(outputArray); 283 return NULL; 284 } 285 psVector *colVector = psVectorAllocEmpty(1, type); // Vector for type 286 outputArray = psArrayAdd(outputArray, ARRAY_STRIDE, colVector); 287 psFree(colVector); 288 numCols++; 304 289 psFree(strValue); 290 } 291 if (parseStatus != PS_PARSE_SUCCESS) { 292 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Failed to parse format at column %d: %s", 293 numCols, strValue); 294 psFree(strValue); 295 psFree(outputArray); 296 return NULL; 297 } 298 299 if (numCols == 0) { 300 // Format string parse error detected 301 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Format string was not parsed sucessfully"); 302 psFree(outputArray); 303 return NULL; 305 304 } 306 305 307 306 // If the format string was parsed successfully and return numCols the 308 307 // prepare to open file and read values 309 if (numCols > 0) { 310 311 // Open specified file 312 if ((fp=fopen(filename, "r")) == NULL) { 313 psError(PS_ERR_BAD_PARAMETER_VALUE, true, _("Failed to open file %s."), 314 filename); 315 psFree(outputArray); 316 return NULL; 317 } else { 318 // Initialize array index 319 int arrayIndex = 0; 320 321 // Create reusable line for continuous read 322 line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char)); 323 324 // Loop through file to get numRows, numCols, and column data types 325 while ((fgets(line, MAX_STRING_LENGTH, fp) != NULL) && 326 (parseStatus == PS_PARSE_SUCCESS)) { 327 328 // Copy pointer to line for parsing 329 linePtr = line; 330 331 // If line is not a comment or blank, then extract data 332 if (!ignoreLine(linePtr)) { 333 numRows++; 334 335 // Copy format pointer for parsing 336 tempFormat = format; 337 arrayIndex = 0; 338 parseStatus = PS_PARSE_SUCCESS; 339 340 // Loop through format and line strings to get values in text table file 341 while ((strValue=getToken((char**)&tempFormat," \t",&parseStatus)) 342 && (strNum=getToken((char**)&linePtr," \t",&parseStatus)) ) { 343 // Set column vector 344 colVector = outputArray->data[arrayIndex]; 345 346 // Set column entries based on format string defining the type 347 if (strcmp(strValue,"\%d") == 0 ) { 348 colVector = psVectorRecycle(colVector, numRows, 349 colVector->type.type); 350 parseValue(colVector,numRows-1,strNum,&parseStatus); 351 arrayIndex++; 352 } else if (strcmp(strValue,"\%ld") == 0) { 353 colVector = psVectorRecycle(colVector, numRows, 354 colVector->type.type); 355 parseValue(colVector,numRows-1,strNum,&parseStatus); 356 arrayIndex++; 357 } else if (strcmp(strValue,"\%f") == 0) { 358 colVector = psVectorRecycle(colVector, numRows, 359 colVector->type.type); 360 parseValue(colVector,numRows-1,strNum,&parseStatus); 361 arrayIndex++; 362 } else if (strcmp(strValue,"\%lf") == 0) { 363 colVector = psVectorRecycle(colVector, numRows, 364 colVector->type.type); 365 parseValue(colVector,numRows-1,strNum,&parseStatus); 366 arrayIndex++; 367 } else if (strstr(strValue,"\%*") != 0) { 368 // Don't increase number of columns 369 } 370 psFree(strValue); 371 psFree(strNum); 372 373 // If the file line was not parsed successful report 374 // error and return NULL 375 if (parseStatus != PS_PARSE_SUCCESS) { 376 psError(PS_ERR_UNKNOWN, true, 377 "Parsing text file failed."); 378 fclose(fp); 379 psFree(outputArray); 380 psFree(line); 381 return NULL; 382 } 383 } 384 if (strValue != NULL && strNum == NULL) { 385 psError(PS_ERR_UNKNOWN, true, 386 "Parsing text file failed - missing table value(s)."); 387 fclose(fp); 388 psFree(outputArray); 389 psFree(line); 390 psFree(strValue); 391 return NULL; 392 } 393 } // ignore line 308 309 psString file = psSlurpFilename(filename); // Contents of file 310 if (!file) { 311 psError(psErrorCodeLast(), false, "Unable to read file of vectors"); 312 psFree(outputArray); 313 return NULL; 314 } 315 316 psArray *lines = psStringSplitArray(file, "\n", false); // Lines of file 317 psFree(file); 318 long numRows = 0; // Number of rows 319 for (long i = 0; i < lines->n; i++) { 320 psString line = lines->data[i]; // Line of interest 321 if (ignoreLine(line)) { 322 continue; 323 } 324 numRows++; 325 326 char *linePtr = line; // Pointer into line 327 328 // Copy format pointer for parsing 329 const char *tempFormat = format; // Pointer into format 330 long arrayIndex = 0; // Index in array 331 parseStatus = PS_PARSE_SUCCESS; 332 333 // Loop through format and line strings to get values in text table file 334 char *strNum; // Number within line 335 while ((strValue=getToken((char**)&tempFormat," \t",&parseStatus)) && 336 (strNum=getToken((char**)&linePtr," \t",&parseStatus)) && 337 parseStatus == PS_PARSE_SUCCESS) { 338 if (strstr(strValue,"\%*") != 0) { 339 continue; 394 340 } 395 341 396 //Return NULL for an empty table 397 if (numRows == 0) { 398 psError(PS_ERR_UNKNOWN, true, 399 "Parsing text file failed - input table is empty."); 400 fclose(fp); 342 // Set column vector 343 psVector *colVector = outputArray->data[arrayIndex]; // Column vector of interest 344 345 outputArray->data[arrayIndex] = colVector = psVectorRecycle(colVector, numRows, 346 colVector->type.type); 347 parseValue(colVector, numRows - 1, strNum, &parseStatus); 348 arrayIndex++; 349 350 if (parseStatus != PS_PARSE_SUCCESS) { 351 psError(PS_ERR_UNKNOWN, false, "Parsing text file failed: %s as %s", strNum, strValue); 401 352 psFree(outputArray); 402 psFree(line); 353 psFree(lines); 354 psFree(strNum); 355 psFree(strValue); 403 356 return NULL; 404 357 } 405 406 // Read on the lines in the file - close file pointer 407 fclose(fp); 408 psFree(line); 409 } 410 } else { 411 // Format string parse error detected 412 psError(PS_ERR_UNKNOWN, true, 413 "Format string was not parsed sucessfully"); 358 psFree(strValue); 359 psFree(strNum); 360 361 } 362 if (strValue != NULL && strNum == NULL) { 363 psError(PS_ERR_UNKNOWN, true, 364 "Parsing text file failed - missing table value(s)."); 365 psFree(outputArray); 366 psFree(lines); 367 psFree(strValue); 368 return NULL; 369 } 370 } 371 if (parseStatus != PS_PARSE_SUCCESS) { 372 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Failed to parse format at column %d: %s", 373 numCols, strValue); 374 psFree(strValue); 414 375 psFree(outputArray); 415 376 return NULL; 416 377 } 378 379 psFree(lines); 417 380 418 381 // Return populated array -
branches/tap_branches/psLib/src/types/psMetadata.c
r25383 r27838 280 280 } 281 281 case PS_DATA_ARRAY: // psArray 282 case PS_DATA_BITS ET: // psBitSet282 case PS_DATA_BITS: // psBits 283 283 case PS_DATA_CUBE: // psCube 284 284 case PS_DATA_FITS: // psFits … … 622 622 623 623 // may need to extend this to change the keyname in the copy 624 bool psMetadataItemSupplement(psMetadata *out, 624 bool psMetadataItemSupplement(bool *status, 625 psMetadata *out, 625 626 const psMetadata *in, 626 627 const char *key) … … 632 633 psMetadataItem *item = psMetadataLookup(in, key); 633 634 if (!item) { 634 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Could not find '%s' in metadata.\n", key); 635 if (status) { 636 *status = false; 637 } else { 638 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Could not find '%s' in metadata.\n", key); 639 } 635 640 return false; 636 641 } … … 968 973 } 969 974 970 psMetadataItem* psMetadataLookup(const psMetadata *md, 975 // Get entry by index 976 psMetadataItem *psMetadataGetIndex(psMetadata *md, long location) 977 { 978 PS_ASSERT_METADATA_NON_NULL(md, false); 979 return psListGet(md->list, location); 980 } 981 982 psMetadataItem *psMetadataLookup(const psMetadata *md, 971 983 const char *key) 972 984 { … … 1147 1159 PS_ASSERT_METADATA_NON_NULL(md,NULL); 1148 1160 1161 // XXX remove this as an error 1149 1162 entry = (psMetadataItem*) psListGet(md->list, location); 1150 1163 if (entry == NULL) { -
branches/tap_branches/psLib/src/types/psMetadata.h
r25383 r27838 545 545 */ 546 546 bool psMetadataItemSupplement( 547 bool *status, ///< if supplied, returns true/false if key is found (suppresses the error) 547 548 psMetadata *out, ///< output Metadata container for copying. 548 549 const psMetadata *in, ///< Metadata collection from which to copy. -
branches/tap_branches/psLib/src/types/psMetadataConfig.c
r23859 r27838 1649 1649 return false; 1650 1650 } 1651 fprintf(file, "%s", fileString); 1651 if (fprintf(file, "%s", fileString) != strlen(fileString)) { 1652 psError(PS_ERR_IO, true, "Failed to write contents of configuration file %s", filename); 1653 psFree(fileString); 1654 fclose(file); 1655 return false; 1656 } 1652 1657 psFree(fileString); 1653 1658 if (fclose(file) == EOF) { -
branches/tap_branches/psLib/test/types/Makefile.am
r18145 r27838 29 29 tap_psPixels_all \ 30 30 tap_psHash_all \ 31 tap_psBit Set_all \31 tap_psBits_all \ 32 32 tap_psList_all \ 33 33 tap_psLookupTable_all \
Note:
See TracChangeset
for help on using the changeset viewer.
