Changeset 1361 for trunk/psLib/src/math/psStats.c
- Timestamp:
- Jul 31, 2004, 3:16:01 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psStats.c (modified) (43 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psStats.c
r1341 r1361 32 32 #define MAX_ITERATIONS 10 33 33 34 void p_psVectorRobustStats( const psVector *restrict myVector,35 const psVector *restrict maskVector,36 unsigned int maskVal,37 psStats *stats);38 34 void p_psVectorRobustStats( const psVector *restrict myVector, 35 const psVector *restrict maskVector, 36 unsigned int maskVal, 37 psStats *stats ); 38 39 39 /** Preprocessor macro to generate error on an incorrect type */ 40 40 #define PS_CHECK_VECTOR_TYPE(NAME, TYPE) \ 41 41 if (NAME->type.type != TYPE) { \ 42 psError(__func__,"Invalid operation: %s has incorrect type.", #NAME); \43 }44 42 psError(__func__,"Invalid operation: %s has incorrect type.", #NAME); \ 43 } 44 45 45 /** Preprocessor macro to generate error on a NULL vector */ 46 46 #define PS_CHECK_NULL_VECTOR(NAME) \ 47 47 if (NAME == NULL || NAME->data.V == NULL) { \ 48 psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME); \49 }50 48 psError(__func__,"Invalid operation: %s or its data is NULL.", #NAME); \ 49 } 50 51 51 /** Preprocessor macro to generate error for zero length vector */ 52 52 #define PS_CHECK_EMPTY_VECTOR(NAME) \ 53 53 if (NAME->n < 1) { \ 54 psError(__func__,"Invalid operation: %s has zero n value.", #NAME); \55 }56 54 psError(__func__,"Invalid operation: %s has zero n value.", #NAME); \ 55 } 56 57 57 /** Preprocessor macro to generate error on differing size vectors */ 58 58 #define PS_CHECK_VECTOR_SIZE_EQUAL(VEC1, VEC2) \ 59 59 if (VEC1->n != VEC2->n) { \ 60 psError(__func__,"Vector %s has size %d, Vector %s has size %d.", #VEC1, VEC1->n, #VEC2, VEC2->n); \61 }62 60 psError(__func__,"Vector %s has size %d, Vector %s has size %d.", #VEC1, VEC1->n, #VEC2, VEC2->n); \ 61 } 62 63 63 #define PS_PRINT_VECTOR(NAME) \ 64 64 for (int my_i=0;my_i<NAME->n;my_i++) { \ 65 printf("%s->data.F32[%d] is %f\n", #NAME, my_i, NAME->data.F32[my_i]); \66 } \65 printf("%s->data.F32[%d] is %f\n", #NAME, my_i, NAME->data.F32[my_i]); \ 66 } \ 67 67 printf("\n"); \ 68 68 … … 87 87 /*****************************************************************************/ 88 88 89 bool p_psGetStatValue( const psStats* stats, double* value)90 { 91 92 switch ( stats->options &93 ~ (PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE | PS_STAT_ROBUST_FOR_SAMPLE)) {94 case PS_STAT_SAMPLE_MEAN:95 *value = stats->sampleMean;96 return true;97 98 case PS_STAT_SAMPLE_MEDIAN:99 *value = stats->sampleMedian;100 return true;101 102 case PS_STAT_SAMPLE_STDEV:103 *value = stats->sampleStdev;104 return true;105 106 case PS_STAT_ROBUST_MEAN:107 *value = stats->robustMean;108 return true;109 110 case PS_STAT_ROBUST_MEDIAN:111 *value = stats->robustMedian;112 return true;113 114 case PS_STAT_ROBUST_MODE:115 *value = stats->robustMode;116 return true;117 118 case PS_STAT_ROBUST_STDEV:119 *value = stats->robustStdev;120 return true;121 122 case PS_STAT_CLIPPED_MEAN:123 *value = stats->clippedMean;124 return true;125 126 case PS_STAT_CLIPPED_STDEV:127 *value = stats->clippedStdev;128 return true;129 130 case PS_STAT_MAX:131 *value = stats->max;132 return true;133 134 case PS_STAT_MIN:135 *value = stats->min;136 return true;137 138 default:139 return false;140 }89 bool p_psGetStatValue( const psStats* stats, double* value ) 90 { 91 92 switch ( stats->options & 93 ~ ( PS_STAT_USE_RANGE | PS_STAT_USE_BINSIZE | PS_STAT_ROBUST_FOR_SAMPLE ) ) { 94 case PS_STAT_SAMPLE_MEAN: 95 *value = stats->sampleMean; 96 return true; 97 98 case PS_STAT_SAMPLE_MEDIAN: 99 *value = stats->sampleMedian; 100 return true; 101 102 case PS_STAT_SAMPLE_STDEV: 103 *value = stats->sampleStdev; 104 return true; 105 106 case PS_STAT_ROBUST_MEAN: 107 *value = stats->robustMean; 108 return true; 109 110 case PS_STAT_ROBUST_MEDIAN: 111 *value = stats->robustMedian; 112 return true; 113 114 case PS_STAT_ROBUST_MODE: 115 *value = stats->robustMode; 116 return true; 117 118 case PS_STAT_ROBUST_STDEV: 119 *value = stats->robustStdev; 120 return true; 121 122 case PS_STAT_CLIPPED_MEAN: 123 *value = stats->clippedMean; 124 return true; 125 126 case PS_STAT_CLIPPED_STDEV: 127 *value = stats->clippedStdev; 128 return true; 129 130 case PS_STAT_MAX: 131 *value = stats->max; 132 return true; 133 134 case PS_STAT_MIN: 135 *value = stats->min; 136 return true; 137 138 default: 139 return false; 140 } 141 141 } 142 142 … … 147 147 *****************************************************************************/ 148 148 149 void p_psVectorPrint( psVector *myVector,150 psVector *maskVector,151 unsigned int maskVal,152 psStats *stats)149 void p_psVectorPrint( psVector *myVector, 150 psVector *maskVector, 151 unsigned int maskVal, 152 psStats *stats ) 153 153 { 154 154 int i = 0; // Loop index variable. 155 156 for ( i=0;i<myVector->n;i++) {157 if (maskVector != NULL)158 printf("Element %d is %f (mask is %d)\n", i, myVector->data.F32[i], maskVector->data.U8[i]);159 else160 printf("Element %d is %f\n", i, myVector->data.F32[i]);161 }155 156 for ( i = 0;i < myVector->n;i++ ) { 157 if ( maskVector != NULL ) 158 printf( "Element %d is %f (mask is %d)\n", i, myVector->data.F32[ i ], maskVector->data.U8[ i ] ); 159 else 160 printf( "Element %d is %f\n", i, myVector->data.F32[ i ] ); 161 } 162 162 } 163 163 … … 194 194 *****************************************************************************/ 195 195 196 void p_psVectorSampleMean( const psVector *restrict myVector,197 const psVector *restrict maskVector,198 unsigned int maskVal,199 psStats *stats)196 void p_psVectorSampleMean( const psVector *restrict myVector, 197 const psVector *restrict maskVector, 198 unsigned int maskVal, 199 psStats *stats ) 200 200 { 201 201 int i = 0; // Loop index variable … … 204 204 float rangeMin = 0.0; // Exclude data below this 205 205 float rangeMax = 0.0; // Exclude date above this 206 206 207 207 // If PS_STAT_USE_RANGE is requested, then we enter a slightly different 208 208 // loop. 209 if (stats->options & PS_STAT_USE_RANGE) { 210 rangeMin = stats->min; 211 rangeMax = stats->max; 212 if (maskVector != NULL) { 213 for (i=0;i<myVector->n;i++) { 214 // Check if the data is with the specified range 215 if (!(maskVal & maskVector->data.U8[i]) && 216 (rangeMin <= myVector->data.F32[i]) && 217 (myVector->data.F32[i] <= rangeMax)) { 218 mean+= myVector->data.F32[i]; 219 count++; 220 } 221 } 222 mean/= (float) count; 209 if ( stats->options & PS_STAT_USE_RANGE ) { 210 rangeMin = stats->min; 211 rangeMax = stats->max; 212 if ( maskVector != NULL ) { 213 for ( i = 0;i < myVector->n;i++ ) { 214 // Check if the data is with the specified range 215 if ( !( maskVal & maskVector->data.U8[ i ] ) && 216 ( rangeMin <= myVector->data.F32[ i ] ) && 217 ( myVector->data.F32[ i ] <= rangeMax ) ) { 218 mean += myVector->data.F32[ i ]; 219 count++; 220 } 221 } 222 mean /= ( float ) count; 223 } else { 224 for ( i = 0;i < myVector->n;i++ ) { 225 if ( ( rangeMin <= myVector->data.F32[ i ] ) && 226 ( myVector->data.F32[ i ] <= rangeMax ) ) { 227 mean += myVector->data.F32[ i ]; 228 count++; 229 } 230 } 231 mean /= ( float ) count; 232 } 223 233 } else { 224 for (i=0;i<myVector->n;i++) { 225 if ((rangeMin <= myVector->data.F32[i]) && 226 (myVector->data.F32[i] <= rangeMax)) { 227 mean+= myVector->data.F32[i]; 228 count++; 229 } 230 } 231 mean/= (float) count; 232 } 233 } else { 234 if (maskVector != NULL) { 235 for (i=0;i<myVector->n;i++) { 236 if (!(maskVal & maskVector->data.U8[i])) { 237 mean+= myVector->data.F32[i]; 238 count++; 239 } 240 } 241 mean/= (float) count; 242 } else { 243 for (i=0;i<myVector->n;i++) { 244 mean+= myVector->data.F32[i]; 245 } 246 mean/= (float) myVector->n; 247 } 248 } 249 234 if ( maskVector != NULL ) { 235 for ( i = 0;i < myVector->n;i++ ) { 236 if ( !( maskVal & maskVector->data.U8[ i ] ) ) { 237 mean += myVector->data.F32[ i ]; 238 count++; 239 } 240 } 241 mean /= ( float ) count; 242 } else { 243 for ( i = 0;i < myVector->n;i++ ) { 244 mean += myVector->data.F32[ i ]; 245 } 246 mean /= ( float ) myVector->n; 247 } 248 } 249 250 250 stats->sampleMean = mean; 251 251 } … … 262 262 NULL 263 263 *****************************************************************************/ 264 void p_psVectorMax( const psVector *restrict myVector,265 const psVector *restrict maskVector,266 unsigned int maskVal,267 psStats *stats)264 void p_psVectorMax( const psVector *restrict myVector, 265 const psVector *restrict maskVector, 266 unsigned int maskVal, 267 psStats *stats ) 268 268 { 269 269 int i = 0; // Loop index variable … … 271 271 float rangeMin = 0.0; // Exclude data below this 272 272 float rangeMax = 0.0; // Exclude date above this 273 273 274 274 // If PS_STAT_USE_RANGE is requested, then we enter a different loop. 275 if (stats->options & PS_STAT_USE_RANGE) { 276 rangeMin = stats->min; 277 rangeMax = stats->max; 278 if (maskVector != NULL) { 279 for (i=0;i<myVector->n;i++) { 280 if (!(maskVal & maskVector->data.U8[i])) { 281 if ((myVector->data.F32[i] > max) && 282 (rangeMin <= myVector->data.F32[i]) && 283 (myVector->data.F32[i] <= rangeMax)) { 284 max = myVector->data.F32[i]; 285 } 286 } 287 } 275 if ( stats->options & PS_STAT_USE_RANGE ) { 276 rangeMin = stats->min; 277 rangeMax = stats->max; 278 if ( maskVector != NULL ) { 279 for ( i = 0;i < myVector->n;i++ ) { 280 if ( !( maskVal & maskVector->data.U8[ i ] ) ) { 281 if ( ( myVector->data.F32[ i ] > max ) && 282 ( rangeMin <= myVector->data.F32[ i ] ) && 283 ( myVector->data.F32[ i ] <= rangeMax ) ) { 284 max = myVector->data.F32[ i ]; 285 } 286 } 287 } 288 } else { 289 for ( i = 0;i < myVector->n;i++ ) { 290 if ( ( myVector->data.F32[ i ] > max ) && 291 ( rangeMin <= myVector->data.F32[ i ] ) && 292 ( myVector->data.F32[ i ] <= rangeMax ) ) { 293 max = myVector->data.F32[ i ]; 294 } 295 } 296 } 288 297 } else { 289 for (i=0;i<myVector->n;i++) { 290 if ((myVector->data.F32[i] > max) && 291 (rangeMin <= myVector->data.F32[i]) && 292 (myVector->data.F32[i] <= rangeMax)) { 293 max = myVector->data.F32[i]; 294 } 295 } 296 } 297 } else { 298 if (maskVector != NULL) { 299 for (i=0;i<myVector->n;i++) { 300 if (!(maskVal & maskVector->data.U8[i])) { 301 if (myVector->data.F32[i] > max) { 302 max = myVector->data.F32[i]; 303 } 304 } 305 } 306 } else { 307 for (i=0;i<myVector->n;i++) { 308 if (myVector->data.F32[i] > max) { 309 max = myVector->data.F32[i]; 310 } 311 } 312 } 313 } 314 298 if ( maskVector != NULL ) { 299 for ( i = 0;i < myVector->n;i++ ) { 300 if ( !( maskVal & maskVector->data.U8[ i ] ) ) { 301 if ( myVector->data.F32[ i ] > max ) { 302 max = myVector->data.F32[ i ]; 303 } 304 } 305 } 306 } else { 307 for ( i = 0;i < myVector->n;i++ ) { 308 if ( myVector->data.F32[ i ] > max ) { 309 max = myVector->data.F32[ i ]; 310 } 311 } 312 } 313 } 314 315 315 stats->max = max; 316 316 } … … 327 327 NULL 328 328 *****************************************************************************/ 329 void p_psVectorMin( const psVector *restrict myVector,330 const psVector *restrict maskVector,331 unsigned int maskVal,332 psStats *stats)329 void p_psVectorMin( const psVector *restrict myVector, 330 const psVector *restrict maskVector, 331 unsigned int maskVal, 332 psStats *stats ) 333 333 { 334 334 int i = 0; // Loop index variable … … 336 336 float rangeMin = 0.0; // Exclude data below this 337 337 float rangeMax = 0.0; // Exclude date above this 338 339 if (stats->options & PS_STAT_USE_RANGE) { 340 rangeMin = stats->min; 341 rangeMax = stats->max; 342 if (maskVector != NULL) { 343 for (i=0;i<myVector->n;i++) { 344 if (!(maskVal & maskVector->data.U8[i])) { 345 if ((myVector->data.F32[i] < min) && 346 (rangeMin <= myVector->data.F32[i]) && 347 (myVector->data.F32[i] <= rangeMax)) { 348 min = myVector->data.F32[i]; 349 } 350 } 351 } 338 339 if ( stats->options & PS_STAT_USE_RANGE ) { 340 rangeMin = stats->min; 341 rangeMax = stats->max; 342 if ( maskVector != NULL ) { 343 for ( i = 0;i < myVector->n;i++ ) { 344 if ( !( maskVal & maskVector->data.U8[ i ] ) ) { 345 if ( ( myVector->data.F32[ i ] < min ) && 346 ( rangeMin <= myVector->data.F32[ i ] ) && 347 ( myVector->data.F32[ i ] <= rangeMax ) ) { 348 min = myVector->data.F32[ i ]; 349 } 350 } 351 } 352 } else { 353 for ( i = 0;i < myVector->n;i++ ) { 354 if ( ( myVector->data.F32[ i ] < min ) && 355 ( rangeMin <= myVector->data.F32[ i ] ) && 356 ( myVector->data.F32[ i ] <= rangeMax ) ) { 357 min = myVector->data.F32[ i ]; 358 } 359 } 360 } 352 361 } else { 353 for (i=0;i<myVector->n;i++) { 354 if ((myVector->data.F32[i] < min) && 355 (rangeMin <= myVector->data.F32[i]) && 356 (myVector->data.F32[i] <= rangeMax)) { 357 min = myVector->data.F32[i]; 358 } 359 } 360 } 361 } else { 362 if (maskVector != NULL) { 363 for (i=0;i<myVector->n;i++) { 364 if (!(maskVal & maskVector->data.U8[i])) { 365 if (myVector->data.F32[i] < min) { 366 min = myVector->data.F32[i]; 367 } 368 } 369 } 370 } else { 371 for (i=0;i<myVector->n;i++) { 372 if (myVector->data.F32[i] < min) { 373 min = myVector->data.F32[i]; 374 } 375 } 376 } 377 } 378 362 if ( maskVector != NULL ) { 363 for ( i = 0;i < myVector->n;i++ ) { 364 if ( !( maskVal & maskVector->data.U8[ i ] ) ) { 365 if ( myVector->data.F32[ i ] < min ) { 366 min = myVector->data.F32[ i ]; 367 } 368 } 369 } 370 } else { 371 for ( i = 0;i < myVector->n;i++ ) { 372 if ( myVector->data.F32[ i ] < min ) { 373 min = myVector->data.F32[ i ]; 374 } 375 } 376 } 377 } 378 379 379 stats->min = min; 380 380 } … … 392 392 NULL 393 393 *****************************************************************************/ 394 int p_psVectorNValues( const psVector *restrict myVector,395 const psVector *restrict maskVector,396 unsigned int maskVal,397 psStats *stats)394 int p_psVectorNValues( const psVector *restrict myVector, 395 const psVector *restrict maskVector, 396 unsigned int maskVal, 397 psStats *stats ) 398 398 { 399 399 int i = 0; // Loop index variable … … 401 401 float rangeMin = 0.0; // Exclude data below this 402 402 float rangeMax = 0.0; // Exclude date above this 403 404 if (stats->options & PS_STAT_USE_RANGE) { 405 rangeMin = stats->min; 406 rangeMax = stats->max; 407 if (maskVector != NULL) { 408 for (i=0;i<myVector->n;i++) { 409 if (!(maskVal & maskVector->data.U8[i]) && 410 (rangeMin <= myVector->data.F32[i]) && 411 (myVector->data.F32[i] <= rangeMax)) { 412 numData++; 413 } 414 } 403 404 if ( stats->options & PS_STAT_USE_RANGE ) { 405 rangeMin = stats->min; 406 rangeMax = stats->max; 407 if ( maskVector != NULL ) { 408 for ( i = 0;i < myVector->n;i++ ) { 409 if ( !( maskVal & maskVector->data.U8[ i ] ) && 410 ( rangeMin <= myVector->data.F32[ i ] ) && 411 ( myVector->data.F32[ i ] <= rangeMax ) ) { 412 numData++; 413 } 414 } 415 } else { 416 for ( i = 0;i < myVector->n;i++ ) { 417 if ( ( rangeMin <= myVector->data.F32[ i ] ) && 418 ( myVector->data.F32[ i ] <= rangeMax ) ) { 419 numData++; 420 } 421 } 422 } 415 423 } else { 416 for (i=0;i<myVector->n;i++) { 417 if ((rangeMin <= myVector->data.F32[i]) && 418 (myVector->data.F32[i] <= rangeMax)) { 419 numData++; 420 } 421 } 422 } 423 } else { 424 rangeMin = stats->min; 425 rangeMax = stats->max; 426 if (maskVector != NULL) { 427 for (i=0;i<myVector->n;i++) { 428 if (!(maskVal & maskVector->data.U8[i])) { 429 numData++; 430 } 431 } 432 } else { 433 numData = myVector->n; 434 } 435 } 436 return(numData); 424 rangeMin = stats->min; 425 rangeMax = stats->max; 426 if ( maskVector != NULL ) { 427 for ( i = 0;i < myVector->n;i++ ) { 428 if ( !( maskVal & maskVector->data.U8[ i ] ) ) { 429 numData++; 430 } 431 } 432 } else { 433 numData = myVector->n; 434 } 435 } 436 return ( numData ); 437 437 } 438 438 … … 450 450 NULL 451 451 *****************************************************************************/ 452 void p_psVectorSampleMedian( const psVector *restrict myVector,453 const psVector *restrict maskVector,454 unsigned int maskVal,455 psStats *stats)456 { 457 psVector * unsortedVector = NULL; // Temporary vector452 void p_psVectorSampleMedian( const psVector *restrict myVector, 453 const psVector *restrict maskVector, 454 unsigned int maskVal, 455 psStats *stats ) 456 { 457 psVector * unsortedVector = NULL; // Temporary vector 458 458 psVector *sortedVector = NULL; // Temporary vector 459 459 int i = 0; // Loop index variable … … 462 462 float rangeMin = 0.0; // Exclude data below this 463 463 float rangeMax = 0.0; // Exclude date above this 464 465 464 465 466 466 // Determine if the number of data points exceed a threshold which will 467 467 // cause to generate robust stats, as opposed to exact stats. … … 488 488 } 489 489 */ 490 490 491 491 // Determine how many data points fit inside this min/max range 492 492 // and are not masked, IF the maskVector is not NULL> 493 nValues = p_psVectorNValues( myVector, maskVector, maskVal, stats);494 493 nValues = p_psVectorNValues( myVector, maskVector, maskVal, stats ); 494 495 495 // Allocate temporary vectors for the data. 496 unsortedVector = psVectorAlloc( nValues, PS_TYPE_F32);496 unsortedVector = psVectorAlloc( nValues, PS_TYPE_F32 ); 497 497 unsortedVector->n = unsortedVector->nalloc; 498 499 sortedVector = psVectorAlloc(nValues, PS_TYPE_F32);498 499 sortedVector = psVectorAlloc( nValues, PS_TYPE_F32 ); 500 500 sortedVector->n = sortedVector->nalloc; 501 501 502 502 // Determine if we must only use data points within a min/max range. 503 if (stats->options & PS_STAT_USE_RANGE) { 504 rangeMin = stats->min; 505 rangeMax = stats->max; 506 507 // Store all non-masked data points within the min/max range 508 // into the temporary vectors. 509 count = 0; 510 if (maskVector != NULL) { 511 for (i=0;i<myVector->n;i++) { 512 if (!(maskVal & maskVector->data.U8[i]) && 513 (rangeMin <= myVector->data.F32[i]) && 514 (myVector->data.F32[i] <= rangeMax)) { 515 unsortedVector->data.F32[count++] = maskVector->data.F32[i]; 516 } 517 } 503 if ( stats->options & PS_STAT_USE_RANGE ) { 504 rangeMin = stats->min; 505 rangeMax = stats->max; 506 507 // Store all non-masked data points within the min/max range 508 // into the temporary vectors. 509 count = 0; 510 if ( maskVector != NULL ) { 511 for ( i = 0;i < myVector->n;i++ ) { 512 if ( !( maskVal & maskVector->data.U8[ i ] ) && 513 ( rangeMin <= myVector->data.F32[ i ] ) && 514 ( myVector->data.F32[ i ] <= rangeMax ) ) { 515 unsortedVector->data.F32[ count++ ] = maskVector->data.F32[ i ]; 516 } 517 } 518 } else { 519 for ( i = 0;i < myVector->n;i++ ) { 520 if ( ( rangeMin <= myVector->data.F32[ i ] ) && 521 ( myVector->data.F32[ i ] <= rangeMax ) ) { 522 unsortedVector->data.F32[ count++ ] = myVector->data.F32[ i ]; 523 } 524 } 525 } 518 526 } else { 519 for (i=0;i<myVector->n;i++) { 520 if ((rangeMin <= myVector->data.F32[i]) && 521 (myVector->data.F32[i] <= rangeMax)) { 522 unsortedVector->data.F32[count++] = myVector->data.F32[i]; 523 } 524 } 525 } 526 } else { 527 // Store all non-masked data points into the temporary vectors. 528 count = 0; 529 if (maskVector != NULL) { 530 for (i=0;i<myVector->n;i++) { 531 if (!(maskVal & maskVector->data.U8[i])) { 532 unsortedVector->data.F32[count++] = myVector->data.F32[i]; 533 } 534 } 535 } else { 536 for (i=0;i<myVector->n;i++) { 537 unsortedVector->data.F32[i] = myVector->data.F32[i]; 538 } 539 } 540 } 527 // Store all non-masked data points into the temporary vectors. 528 count = 0; 529 if ( maskVector != NULL ) { 530 for ( i = 0;i < myVector->n;i++ ) { 531 if ( !( maskVal & maskVector->data.U8[ i ] ) ) { 532 unsortedVector->data.F32[ count++ ] = myVector->data.F32[ i ]; 533 } 534 } 535 } else { 536 for ( i = 0;i < myVector->n;i++ ) { 537 unsortedVector->data.F32[ i ] = myVector->data.F32[ i ]; 538 } 539 } 540 } 541 541 // Sort the temporary vectors. 542 psVectorSort( sortedVector, unsortedVector);543 542 psVectorSort( sortedVector, unsortedVector ); 543 544 544 // Calculate the median exactly. 545 545 // XXX: Is this the correct action? 546 if ( 0 == (nValues % 2)) {547 stats->sampleMedian = 0.5 * (sortedVector->data.F32[(nValues/2)-1] +548 sortedVector->data.F32[nValues/2]);549 } else {550 stats->sampleMedian = sortedVector->data.F32[nValues/2];551 }552 546 if ( 0 == ( nValues % 2 ) ) { 547 stats->sampleMedian = 0.5 * ( sortedVector->data.F32[ ( nValues / 2 ) - 1 ] + 548 sortedVector->data.F32[ nValues / 2 ] ); 549 } else { 550 stats->sampleMedian = sortedVector->data.F32[ nValues / 2 ]; 551 } 552 553 553 // Free the temporary data structures. 554 psFree( unsortedVector);555 psFree( sortedVector);554 psFree( unsortedVector ); 555 psFree( sortedVector ); 556 556 } 557 557 … … 568 568 XXX: use a static variable for gaussianCoefs[] and compute them once. 569 569 *****************************************************************************/ 570 psVector *p_psVectorsmoothHistGaussian( psHistogram *robustHistogram,571 float sigma)570 psVector *p_psVectorsmoothHistGaussian( psHistogram *robustHistogram, 571 float sigma ) 572 572 { 573 573 int i = 0; // Loop index variable … … 575 575 float denom = 0.0; // Temporary variable 576 576 float expo = 0.0; // Temporary variable 577 float gaussianCoefs[ 1 + (2 * GAUSS_WIDTH)]; // The Gaussian Coefficients578 psVector *smooth = psVectorAlloc( robustHistogram->nums->n, PS_TYPE_F32);579 580 for (i=0;i<(1 + (2 * GAUSS_WIDTH));i++) {581 if (fabs(sigma) >= FLT_EPSILON) {582 // If sigma does not equal zero, then we use Gaussian smoothing.583 #ifdef DARWIN584 denom = (float) sqrt(2.0 * M_PI * sigma * sigma);585 #else586 587 denom = sqrtf(2.0 * M_PI * sigma * sigma);588 #endif589 590 expo = - (float) ((i-GAUSS_WIDTH) * (i-GAUSS_WIDTH));591 expo/= (2.0 * sigma * sigma);592 gaussianCoefs[i] = exp(expo/denom);593 594 // NOTE: Gaussian smoothing just isn't working with low sigma595 // values. The problem is that the Gaussian coefficients are596 // all zero, except for the middle coefficient, which is exactly597 // one. Therefore, I'm using boxcar smoothing.598 gaussianCoefs[i] = 1.0 / (1.0 + (2.0 * (float) GAUSS_WIDTH));599 // printf("gaussianCoefs[%d] is %f\n", i, gaussianCoefs[i]);600 } else {601 /* If sigma equals zero (all pixels have the same value)602 * the above code will divide by zero. Therefore, we don't need603 * to smooth the data.604 */605 for(i=0;i<robustHistogram->nums->n;i++) {606 smooth->data.F32[i] = (float) robustHistogram->nums->data.S32[i];607 }608 return(smooth);609 }610 }611 577 float gaussianCoefs[ 1 + ( 2 * GAUSS_WIDTH ) ]; // The Gaussian Coefficients 578 psVector *smooth = psVectorAlloc( robustHistogram->nums->n, PS_TYPE_F32 ); 579 580 for ( i = 0;i < ( 1 + ( 2 * GAUSS_WIDTH ) );i++ ) { 581 if ( fabs( sigma ) >= FLT_EPSILON ) { 582 // If sigma does not equal zero, then we use Gaussian smoothing. 583 #ifdef DARWIN 584 denom = ( float ) sqrt( 2.0 * M_PI * sigma * sigma ); 585 #else 586 587 denom = sqrtf( 2.0 * M_PI * sigma * sigma ); 588 #endif 589 590 expo = - ( float ) ( ( i - GAUSS_WIDTH ) * ( i - GAUSS_WIDTH ) ); 591 expo /= ( 2.0 * sigma * sigma ); 592 gaussianCoefs[ i ] = exp( expo / denom ); 593 594 // NOTE: Gaussian smoothing just isn't working with low sigma 595 // values. The problem is that the Gaussian coefficients are 596 // all zero, except for the middle coefficient, which is exactly 597 // one. Therefore, I'm using boxcar smoothing. 598 gaussianCoefs[ i ] = 1.0 / ( 1.0 + ( 2.0 * ( float ) GAUSS_WIDTH ) ); 599 // printf("gaussianCoefs[%d] is %f\n", i, gaussianCoefs[i]); 600 } else { 601 /* If sigma equals zero (all pixels have the same value) 602 * the above code will divide by zero. Therefore, we don't need 603 * to smooth the data. 604 */ 605 for ( i = 0;i < robustHistogram->nums->n;i++ ) { 606 smooth->data.F32[ i ] = ( float ) robustHistogram->nums->data.S32[ i ]; 607 } 608 return ( smooth ); 609 } 610 } 611 612 612 // Perform the actual smoothing. 613 for (i=0;i<robustHistogram->nums->n;i++) {614 smooth->data.F32[i] = 0.0;615 for (j=-GAUSS_WIDTH;j<=+GAUSS_WIDTH;j++) {616 if (((j+i) >= 0) && ((j+i) < smooth->n)) {617 smooth->data.F32[i]+= (gaussianCoefs[j+GAUSS_WIDTH] *618 (float) robustHistogram->nums->data.S32[j+i]);619 }620 }621 }622 return (smooth);613 for ( i = 0;i < robustHistogram->nums->n;i++ ) { 614 smooth->data.F32[ i ] = 0.0; 615 for ( j = -GAUSS_WIDTH;j <= + GAUSS_WIDTH;j++ ) { 616 if ( ( ( j + i ) >= 0 ) && ( ( j + i ) < smooth->n ) ) { 617 smooth->data.F32[ i ] += ( gaussianCoefs[ j + GAUSS_WIDTH ] * 618 ( float ) robustHistogram->nums->data.S32[ j + i ] ); 619 } 620 } 621 } 622 return ( smooth ); 623 623 } 624 624 … … 634 634 NULL 635 635 *****************************************************************************/ 636 void p_psVectorSampleQuartiles( const psVector *restrict myVector,637 const psVector *restrict maskVector,638 unsigned int maskVal,639 psStats *stats)640 { 641 psVector * unsortedVector = NULL; // Temporary vector636 void p_psVectorSampleQuartiles( const psVector *restrict myVector, 637 const psVector *restrict maskVector, 638 unsigned int maskVal, 639 psStats *stats ) 640 { 641 psVector * unsortedVector = NULL; // Temporary vector 642 642 psVector *sortedVector = NULL; // Temporary vector 643 643 int i = 0; // Loop index variable … … 646 646 float rangeMin = 0.0; // Exclude data below this 647 647 float rangeMax = 0.0; // Exclude date above this 648 648 649 649 // Determine how many data points fit inside this min/max range 650 650 // and are not maxed, IF the maskVector is not NULL> 651 nValues = p_psVectorNValues( myVector, maskVector, maskVal, stats);652 651 nValues = p_psVectorNValues( myVector, maskVector, maskVal, stats ); 652 653 653 // Allocate temporary vectors for the data. 654 unsortedVector = psVectorAlloc( nValues, PS_TYPE_F32);654 unsortedVector = psVectorAlloc( nValues, PS_TYPE_F32 ); 655 655 unsortedVector->n = unsortedVector->nalloc; 656 sortedVector = psVectorAlloc(nValues, PS_TYPE_F32);656 sortedVector = psVectorAlloc( nValues, PS_TYPE_F32 ); 657 657 sortedVector->n = sortedVector->nalloc; 658 658 659 659 // Determine if we must only use data points within a min/max range. 660 if (stats->options & PS_STAT_USE_RANGE) { 661 rangeMin = stats->min; 662 rangeMax = stats->max; 663 // Store all non-masked data points within the min/max range 664 // into the temporary vectors. 665 count = 0; 666 if (maskVector != NULL) { 667 for (i=0;i<myVector->n;i++) { 668 if (!(maskVal & maskVector->data.U8[i]) && 669 (rangeMin <= myVector->data.F32[i]) && 670 (myVector->data.F32[i] <= rangeMax)) { 671 unsortedVector->data.F32[count++] = myVector->data.F32[i]; 672 } 673 } 660 if ( stats->options & PS_STAT_USE_RANGE ) { 661 rangeMin = stats->min; 662 rangeMax = stats->max; 663 // Store all non-masked data points within the min/max range 664 // into the temporary vectors. 665 count = 0; 666 if ( maskVector != NULL ) { 667 for ( i = 0;i < myVector->n;i++ ) { 668 if ( !( maskVal & maskVector->data.U8[ i ] ) && 669 ( rangeMin <= myVector->data.F32[ i ] ) && 670 ( myVector->data.F32[ i ] <= rangeMax ) ) { 671 unsortedVector->data.F32[ count++ ] = myVector->data.F32[ i ]; 672 } 673 } 674 } else { 675 for ( i = 0;i < myVector->n;i++ ) { 676 if ( ( rangeMin <= myVector->data.F32[ i ] ) && 677 ( myVector->data.F32[ i ] <= rangeMax ) ) { 678 unsortedVector->data.F32[ count++ ] = myVector->data.F32[ i ]; 679 } 680 } 681 } 674 682 } else { 675 for (i=0;i<myVector->n;i++) { 676 if ((rangeMin <= myVector->data.F32[i]) && 677 (myVector->data.F32[i] <= rangeMax)) { 678 unsortedVector->data.F32[count++] = myVector->data.F32[i]; 679 } 680 } 681 } 682 } else { 683 // Store all non-masked data points into the temporary vectors. 684 count = 0; 685 if (maskVector != NULL) { 686 for (i=0;i<myVector->n;i++) { 687 if (!(maskVal & maskVector->data.U8[i])) { 688 unsortedVector->data.F32[count++] = myVector->data.F32[i]; 689 } 690 } 691 } else { 692 for (i=0;i<myVector->n;i++) { 693 unsortedVector->data.F32[i] = myVector->data.F32[i]; 694 } 695 } 696 } 697 683 // Store all non-masked data points into the temporary vectors. 684 count = 0; 685 if ( maskVector != NULL ) { 686 for ( i = 0;i < myVector->n;i++ ) { 687 if ( !( maskVal & maskVector->data.U8[ i ] ) ) { 688 unsortedVector->data.F32[ count++ ] = myVector->data.F32[ i ]; 689 } 690 } 691 } else { 692 for ( i = 0;i < myVector->n;i++ ) { 693 unsortedVector->data.F32[ i ] = myVector->data.F32[ i ]; 694 } 695 } 696 } 697 698 698 // Sort the temporary vectors. 699 psVectorSort( sortedVector, unsortedVector);700 699 psVectorSort( sortedVector, unsortedVector ); 700 701 701 // Calculate the quartile points exactly. 702 stats->sampleUQ = sortedVector->data.F32[ 3 * (nValues / 4)];703 stats->sampleLQ = sortedVector->data.F32[ nValues / 4];704 702 stats->sampleUQ = sortedVector->data.F32[ 3 * ( nValues / 4 ) ]; 703 stats->sampleLQ = sortedVector->data.F32[ nValues / 4 ]; 704 705 705 // Free the temporary data structures. 706 psFree( unsortedVector);707 psFree( sortedVector);706 psFree( unsortedVector ); 707 psFree( sortedVector ); 708 708 } 709 709 … … 721 721 722 722 *****************************************************************************/ 723 void p_psVectorSampleStdev( const psVector *restrict myVector,724 const psVector *restrict maskVector,725 unsigned int maskVal,726 psStats *stats)723 void p_psVectorSampleStdev( const psVector *restrict myVector, 724 const psVector *restrict maskVector, 725 unsigned int maskVal, 726 psStats *stats ) 727 727 { 728 728 int i = 0; // Loop index variable … … 735 735 float rangeMin = 0.0; // Exclude data below this 736 736 float rangeMax = 0.0; // Exclude date above this 737 737 738 738 // This procedure requires the mean. If it has not been already 739 739 // calculated, then call p_psVectorSampleMean() 740 if ( 0 != isnan(stats->sampleMean)) {741 p_psVectorSampleMean(myVector, maskVector, maskVal, stats);742 }740 if ( 0 != isnan( stats->sampleMean ) ) { 741 p_psVectorSampleMean( myVector, maskVector, maskVal, stats ); 742 } 743 743 mean = stats->sampleMean; 744 745 if (stats->options & PS_STAT_USE_RANGE) { 746 if (maskVector != NULL) { 747 for (i=0;i<myVector->n;i++) { 748 if (!(maskVal & maskVector->data.U8[i]) && 749 (rangeMin <= myVector->data.F32[i]) && 750 (myVector->data.F32[i] <= rangeMax)) { 751 diff = myVector->data.F32[i] - mean; 752 sumSquares+= (diff * diff); 753 sumDiffs+= diff; 754 countInt++; 755 } 756 } 744 745 if ( stats->options & PS_STAT_USE_RANGE ) { 746 if ( maskVector != NULL ) { 747 for ( i = 0;i < myVector->n;i++ ) { 748 if ( !( maskVal & maskVector->data.U8[ i ] ) && 749 ( rangeMin <= myVector->data.F32[ i ] ) && 750 ( myVector->data.F32[ i ] <= rangeMax ) ) { 751 diff = myVector->data.F32[ i ] - mean; 752 sumSquares += ( diff * diff ); 753 sumDiffs += diff; 754 countInt++; 755 } 756 } 757 } else { 758 for ( i = 0;i < myVector->n;i++ ) { 759 if ( ( rangeMin <= myVector->data.F32[ i ] ) && 760 ( myVector->data.F32[ i ] <= rangeMax ) ) { 761 diff = myVector->data.F32[ i ] - mean; 762 sumSquares += ( diff * diff ); 763 sumDiffs += diff; 764 countInt++; 765 } 766 } 767 countInt = myVector->n; 768 } 757 769 } else { 758 for (i=0;i<myVector->n;i++) { 759 if ((rangeMin <= myVector->data.F32[i]) && 760 (myVector->data.F32[i] <= rangeMax)) { 761 diff = myVector->data.F32[i] - mean; 762 sumSquares+= (diff * diff); 763 sumDiffs+= diff; 764 countInt++; 765 } 766 } 767 countInt = myVector->n; 768 } 769 } else { 770 if (maskVector != NULL) { 771 for (i=0;i<myVector->n;i++) { 772 if (!(maskVal & maskVector->data.U8[i])) { 773 diff = myVector->data.F32[i] - mean; 774 sumSquares+= (diff * diff); 775 sumDiffs+= diff; 776 countInt++; 777 } 778 } 779 } else { 780 for (i=0;i<myVector->n;i++) { 781 diff = myVector->data.F32[i] - mean; 782 sumSquares+= (diff * diff); 783 sumDiffs+= diff; 784 countInt++; 785 } 786 countInt = myVector->n; 787 } 788 } 789 countFloat = (float) countInt; 790 770 if ( maskVector != NULL ) { 771 for ( i = 0;i < myVector->n;i++ ) { 772 if ( !( maskVal & maskVector->data.U8[ i ] ) ) { 773 diff = myVector->data.F32[ i ] - mean; 774 sumSquares += ( diff * diff ); 775 sumDiffs += diff; 776 countInt++; 777 } 778 } 779 } else { 780 for ( i = 0;i < myVector->n;i++ ) { 781 diff = myVector->data.F32[ i ] - mean; 782 sumSquares += ( diff * diff ); 783 sumDiffs += diff; 784 countInt++; 785 } 786 countInt = myVector->n; 787 } 788 } 789 countFloat = ( float ) countInt; 790 791 791 #ifdef DARWIN 792 793 stats->sampleStdev = ( float) sqrt( (sumSquares-(sumDiffs *794 sumDiffs/countFloat))/ (countFloat-1));792 793 stats->sampleStdev = ( float ) sqrt( ( sumSquares - ( sumDiffs * 794 sumDiffs / countFloat ) ) / ( countFloat - 1 ) ); 795 795 #else 796 797 stats->sampleStdev = sqrtf( ( sumSquares-(sumDiffs *798 sumDiffs/countFloat))/ (countFloat-1));796 797 stats->sampleStdev = sqrtf( ( sumSquares - ( sumDiffs * 798 sumDiffs / countFloat ) ) / ( countFloat - 1 ) ); 799 799 #endif 800 800 } … … 812 812 NULL 813 813 *****************************************************************************/ 814 void p_psVectorClippedStats( const psVector *restrict myVector,815 const psVector *restrict maskVector,816 unsigned int maskVal,817 psStats *stats)814 void p_psVectorClippedStats( const psVector *restrict myVector, 815 const psVector *restrict maskVector, 816 unsigned int maskVal, 817 psStats *stats ) 818 818 { 819 819 int i = 0; // Loop index variable … … 824 824 float oldStanStdev = 0.0; // Temporary variable 825 825 psVector *tmpMask = NULL; // Temporary vector 826 826 827 827 // Endure that stats->clipIter is within the proper range. 828 if ( !((CLIPPED_NUM_ITER_LB <= stats->clipIter ) &&829 ( stats->clipIter <= CLIPPED_NUM_ITER_UB))) {830 psAbort(__func__, "Unallowed value for clipIter (%d).\n",831 stats->clipIter);832 }833 828 if ( !( ( CLIPPED_NUM_ITER_LB <= stats->clipIter ) && 829 ( stats->clipIter <= CLIPPED_NUM_ITER_UB ) ) ) { 830 psAbort( __func__, "Unallowed value for clipIter (%d).\n", 831 stats->clipIter ); 832 } 833 834 834 // Endure that stats->clipSigma is within the proper range. 835 if ( !((CLIPPED_SIGMA_LB <= stats->clipSigma ) &&836 ( stats->clipSigma <= CLIPPED_SIGMA_UB))) {837 psAbort(__func__, "Unallowed value for clipSigma (%f).\n",838 stats->clipSigma);839 }840 835 if ( !( ( CLIPPED_SIGMA_LB <= stats->clipSigma ) && 836 ( stats->clipSigma <= CLIPPED_SIGMA_UB ) ) ) { 837 psAbort( __func__, "Unallowed value for clipSigma (%f).\n", 838 stats->clipSigma ); 839 } 840 841 841 // We allocate a temporary mask vector since during the iterative 842 842 // steps that follow, we will be masking off additional data points. 843 843 // However, we do no want to modify the original mask vector. 844 tmpMask = psVectorAlloc( myVector->n, PS_TYPE_U8);844 tmpMask = psVectorAlloc( myVector->n, PS_TYPE_U8 ); 845 845 tmpMask->n = myVector->n; 846 846 847 847 // If we were called with a mask vector, then initialize the temporary 848 848 // mask vector with those values. 849 if ( maskVector != NULL) {850 for (i=0;i<tmpMask->n;i++) {851 tmpMask->data.U8[i] = maskVector->data.U8[i];852 }853 }854 849 if ( maskVector != NULL ) { 850 for ( i = 0;i < tmpMask->n;i++ ) { 851 tmpMask->data.U8[ i ] = maskVector->data.U8[ i ]; 852 } 853 } 854 855 855 // 1. Compute the sample median. 856 856 // NOTE: This seems odd. Verify with IfA that we want to calculate the 857 857 // median here, not the mean. 858 p_psVectorSampleMedian( myVector, maskVector, maskVal, stats);859 858 p_psVectorSampleMedian( myVector, maskVector, maskVal, stats ); 859 860 860 // 2. Compute the sample standard deviation. 861 p_psVectorSampleStdev( myVector, maskVector, maskVal, stats);862 861 p_psVectorSampleStdev( myVector, maskVector, maskVal, stats ); 862 863 863 // 3. Use the sample median as the first estimator of the mean X. 864 864 clippedMean = stats->sampleMean; 865 865 866 866 // 4. Use the sample stdev as the first estimator of the mean stdev. 867 867 clippedStdev = stats->sampleStdev; 868 868 869 869 // Must save the old sampleMean and sampleStdev since the following code 870 870 // block overwrites them. 871 871 oldStanMean = stats->sampleMean; 872 872 oldStanStdev = stats->sampleStdev; 873 873 874 874 // 5. Repeat N times: 875 for ( i=0;i<stats->clipIter;i++) {876 for (j=0;j<myVector->n;j++) {877 // a) Exclude all values x_i for which |x_i - x| > K * stdev878 if (fabs(myVector->data.F32[j] - clippedMean) >879 (stats->clipSigma * clippedStdev)) {880 tmpMask->data.U8[i] = 0xff;881 }882 // b) compute new mean and stdev883 p_psVectorSampleMedian(myVector, tmpMask, maskVal, stats);884 p_psVectorSampleStdev(myVector, tmpMask, maskVal, stats);885 886 // c) Use the new mean for x887 clippedMean = stats->sampleMean;888 889 // d) Use the new stdev for stdev890 clippedStdev = stats->sampleStdev;891 }892 893 }875 for ( i = 0;i < stats->clipIter;i++ ) { 876 for ( j = 0;j < myVector->n;j++ ) { 877 // a) Exclude all values x_i for which |x_i - x| > K * stdev 878 if ( fabs( myVector->data.F32[ j ] - clippedMean ) > 879 ( stats->clipSigma * clippedStdev ) ) { 880 tmpMask->data.U8[ i ] = 0xff; 881 } 882 // b) compute new mean and stdev 883 p_psVectorSampleMedian( myVector, tmpMask, maskVal, stats ); 884 p_psVectorSampleStdev( myVector, tmpMask, maskVal, stats ); 885 886 // c) Use the new mean for x 887 clippedMean = stats->sampleMean; 888 889 // d) Use the new stdev for stdev 890 clippedStdev = stats->sampleStdev; 891 } 892 893 } 894 894 stats->sampleMean = oldStanMean; 895 stats->sampleStdev = oldStanStdev;896 895 stats->sampleStdev = oldStanStdev; 896 897 897 // 7. The last calcuated value of x is the cliped mean. 898 if ( stats->options & PS_STAT_CLIPPED_MEAN) {899 stats->clippedMean = clippedMean;900 }901 898 if ( stats->options & PS_STAT_CLIPPED_MEAN ) { 899 stats->clippedMean = clippedMean; 900 } 901 902 902 // 8. The last calcuated value of stdev is the cliped stdev. 903 if ( stats->options & PS_STAT_CLIPPED_STDEV) {904 stats->clippedStdev = clippedStdev;905 }906 907 psFree( tmpMask);903 if ( stats->options & PS_STAT_CLIPPED_STDEV ) { 904 stats->clippedStdev = clippedStdev; 905 } 906 907 psFree( tmpMask ); 908 908 } 909 909 … … 912 912 elements of a vector to a range between 0.0 and 1.0. 913 913 *****************************************************************************/ 914 void p_psNormalizeVector( psVector *myData)915 { 916 float min = ( float) HUGE;917 float max = ( float) -HUGE;914 void p_psNormalizeVector( psVector *myData ) 915 { 916 float min = ( float ) HUGE; 917 float max = ( float ) - HUGE; 918 918 float range = 0.0; 919 919 int i = 0; 920 921 for ( i=0;i<myData->n;i++) {922 if (myData->data.F32[i] < min) {923 min = myData->data.F32[i];924 }925 if (myData->data.F32[i] > max) {926 max = myData->data.F32[i];927 }928 }929 920 921 for ( i = 0;i < myData->n;i++ ) { 922 if ( myData->data.F32[ i ] < min ) { 923 min = myData->data.F32[ i ]; 924 } 925 if ( myData->data.F32[ i ] > max ) { 926 max = myData->data.F32[ i ]; 927 } 928 } 929 930 930 range = max - min; 931 for ( i=0;i<myData->n;i++) {932 myData->data.F32[i] = (myData->data.F32[i] - min) / range;933 }931 for ( i = 0;i < myData->n;i++ ) { 932 myData->data.F32[ i ] = ( myData->data.F32[ i ] - min ) / range; 933 } 934 934 } 935 935 … … 940 940 specified data point. 941 941 *****************************************************************************/ 942 float p_psGaussian( const psVector *restrict myData,943 const psVector *restrict myParams)944 { 945 float x = myData->data.F32[ 0];946 float mean = myParams->data.F32[ 0];947 float stdev = myParams->data.F32[ 1];948 float tmp = exp( -((x-mean) * (x-mean)) / (2.0 * stdev * stdev));949 tmp /= ((float)sqrt(2.0 * M_PI * (stdev * stdev)));950 942 float p_psGaussian( const psVector *restrict myData, 943 const psVector *restrict myParams ) 944 { 945 float x = myData->data.F32[ 0 ]; 946 float mean = myParams->data.F32[ 0 ]; 947 float stdev = myParams->data.F32[ 1 ]; 948 float tmp = exp( -( ( x - mean ) * ( x - mean ) ) / ( 2.0 * stdev * stdev ) ); 949 tmp /= ( ( float ) sqrt( 2.0 * M_PI * ( stdev * stdev ) ) ); 950 951 951 // printf("p_psGaussian((%.2f), %.2f, %.2f) is %.2f\n", x, mean, stdev, tmp); 952 return (tmp);952 return ( tmp ); 953 953 } 954 954 … … 957 957 calculates the specified partial derivative of the above Gaussian function. 958 958 *****************************************************************************/ 959 float p_psGaussianDeriv( const psVector *restrict myData,960 const psVector *restrict myParams,961 int whichParam)962 { 963 float x = myData->data.F32[ 0];964 float mean = myParams->data.F32[ 0];965 float stdev = myParams->data.F32[ 1];959 float p_psGaussianDeriv( const psVector *restrict myData, 960 const psVector *restrict myParams, 961 int whichParam ) 962 { 963 float x = myData->data.F32[ 0 ]; 964 float mean = myParams->data.F32[ 0 ]; 965 float stdev = myParams->data.F32[ 1 ]; 966 966 float tmp = 0.0; 967 968 if ( whichParam == 0) {969 // Return the derivative w.r.t. the mean.970 tmp = (x - mean) * p_psGaussian(myData, myParams);971 tmp/= (stdev * stdev);972 } else if (whichParam == 1) {973 // Return the derivative w.r.t. the stdev.974 tmp = (x - mean) * (x - mean) * p_psGaussian(myData, myParams);975 tmp/= (stdev * stdev * stdev);976 }977 printf( "p_psGaussianDeriv((%.2f), %.2f, %.2f, (%d)) is %.2f\n", x, mean, stdev, whichParam, tmp);978 979 return (tmp);967 968 if ( whichParam == 0 ) { 969 // Return the derivative w.r.t. the mean. 970 tmp = ( x - mean ) * p_psGaussian( myData, myParams ); 971 tmp /= ( stdev * stdev ); 972 } else if ( whichParam == 1 ) { 973 // Return the derivative w.r.t. the stdev. 974 tmp = ( x - mean ) * ( x - mean ) * p_psGaussian( myData, myParams ); 975 tmp /= ( stdev * stdev * stdev ); 976 } 977 printf( "p_psGaussianDeriv((%.2f), %.2f, %.2f, (%d)) is %.2f\n", x, mean, stdev, whichParam, tmp ); 978 979 return ( tmp ); 980 980 } 981 981 … … 986 986 specified data point. 987 987 *****************************************************************************/ 988 float p_psQuadratic( const psVector *restrict myParams,989 const psVector *restrict myCoords)990 { 991 float x = myCoords->data.F32[ 0];992 float A = myParams->data.F32[ 0];993 float B = myParams->data.F32[ 1];994 float C = myParams->data.F32[ 2];988 float p_psQuadratic( const psVector *restrict myParams, 989 const psVector *restrict myCoords ) 990 { 991 float x = myCoords->data.F32[ 0 ]; 992 float A = myParams->data.F32[ 0 ]; 993 float B = myParams->data.F32[ 1 ]; 994 float C = myParams->data.F32[ 2 ]; 995 995 float tmp = 0.0; 996 997 tmp = ( A * x * x) + (B * x) + C;998 return (tmp);996 997 tmp = ( A * x * x ) + ( B * x ) + C; 998 return ( tmp ); 999 999 } 1000 1000 … … 1003 1003 calculates the specified partial derivative of the above quadratic function. 1004 1004 *****************************************************************************/ 1005 float p_psQuadraticDeriv( const psVector *restrict myParams,1006 const psVector *restrict myCoords,1007 int whichParamDeriv)1008 { 1009 float x = myCoords->data.F32[ 0];1005 float p_psQuadraticDeriv( const psVector *restrict myParams, 1006 const psVector *restrict myCoords, 1007 int whichParamDeriv ) 1008 { 1009 float x = myCoords->data.F32[ 0 ]; 1010 1010 float tmp = 0.0; 1011 1012 if ( whichParamDeriv == 0) {1013 tmp = x * x;1014 } else if (whichParamDeriv == 1) {1015 tmp = x;1016 } else if (whichParamDeriv == 2) {1017 tmp = 1.0;1018 }1019 1020 return (tmp);1011 1012 if ( whichParamDeriv == 0 ) { 1013 tmp = x * x; 1014 } else if ( whichParamDeriv == 1 ) { 1015 tmp = x; 1016 } else if ( whichParamDeriv == 2 ) { 1017 tmp = 1.0; 1018 } 1019 1020 return ( tmp ); 1021 1021 } 1022 1022 … … 1030 1030 decreasing within that range. 1031 1031 *****************************************************************************/ 1032 float p_ps1DPolyMedian( psPolynomial1D *myPoly,1033 float rangeLow,1034 float rangeHigh,1035 float getThisValue)1036 { 1037 int numIterations =0;1032 float p_ps1DPolyMedian( psPolynomial1D *myPoly, 1033 float rangeLow, 1034 float rangeHigh, 1035 float getThisValue ) 1036 { 1037 int numIterations = 0; 1038 1038 float midpoint = 0.0; 1039 1039 float oldMidpoint = 1.0; 1040 1040 float f = 0.0; 1041 1041 1042 1042 // printf("p_ps1DPolyMedian(%f, %f, %f) \n", rangeLow, rangeHigh, getThisValue); 1043 1044 while ( numIterations < MAX_ITERATIONS) {1045 midpoint = (rangeHigh + rangeLow) / 2.0;1046 if (fabs(midpoint - oldMidpoint) <= FLT_EPSILON) {1047 return(midpoint);1048 }1049 oldMidpoint = midpoint;1050 1051 f = psPolynomial1DEval(midpoint, myPoly);1052 // printf("p_ps1DPolyMedian() iteration %d. f(%f) is %f\n", numIterations, midpoint, f);1053 if (fabs(f - getThisValue) <= FLT_EPSILON) {1054 return(midpoint);1055 }1056 1057 if (f > getThisValue) {1058 rangeHigh = midpoint;1059 } else {1060 rangeLow = midpoint;1061 }1062 numIterations++;1063 }1064 return (midpoint);1043 1044 while ( numIterations < MAX_ITERATIONS ) { 1045 midpoint = ( rangeHigh + rangeLow ) / 2.0; 1046 if ( fabs( midpoint - oldMidpoint ) <= FLT_EPSILON ) { 1047 return ( midpoint ); 1048 } 1049 oldMidpoint = midpoint; 1050 1051 f = psPolynomial1DEval( midpoint, myPoly ); 1052 // printf("p_ps1DPolyMedian() iteration %d. f(%f) is %f\n", numIterations, midpoint, f); 1053 if ( fabs( f - getThisValue ) <= FLT_EPSILON ) { 1054 return ( midpoint ); 1055 } 1056 1057 if ( f > getThisValue ) { 1058 rangeHigh = midpoint; 1059 } else { 1060 rangeLow = midpoint; 1061 } 1062 numIterations++; 1063 } 1064 return ( midpoint ); 1065 1065 } 1066 1066 … … 1073 1073 XXX: This function is currently not being used. 1074 1074 *****************************************************************************/ 1075 float p_psFitQuadratic( psHistogram *histogram,1076 psVector *cumulativeSums,1077 int binNum,1078 float fitFloat)1079 { 1080 psVector * x = psVectorAlloc(3, PS_TYPE_F64);1081 psVector *y = psVectorAlloc( 3, PS_TYPE_F64);1082 psVector *yErr = psVectorAlloc( 3, PS_TYPE_F64);1083 psPolynomial1D *myPoly = psPolynomial1DAlloc( 2);1084 1085 if ( (binNum > 0) &&1086 ( binNum < (histogram->nums->n+1))) {1087 x->data.F64[0] = (double) 0.5 *1088 (histogram->bounds->data.F32[binNum-1] +1089 histogram->bounds->data.F32[binNum]);1090 x->data.F64[1] = (double) 0.5 *1091 (histogram->bounds->data.F32[binNum] +1092 histogram->bounds->data.F32[binNum+1]);1093 x->data.F64[2] = (double) 0.5 *1094 (histogram->bounds->data.F32[binNum+1] +1095 histogram->bounds->data.F32[binNum+2]);1096 1097 y->data.F64[0] = cumulativeSums->data.F32[binNum-1];1098 y->data.F64[1] = cumulativeSums->data.F32[binNum];1099 y->data.F64[2] = cumulativeSums->data.F32[binNum+1];1100 1101 if (!((y->data.F64[0] <= fitFloat) &&1102 (fitFloat <= y->data.F64[2]))) {1103 psAbort(__func__, "p_psVectorRobustStats(0): midpoint not within y-range\n");1104 }1105 1106 yErr->data.F64[0] = 1.0;1107 yErr->data.F64[1] = 1.0;1108 yErr->data.F64[2] = 1.0;1109 1110 myPoly = psGetArrayPolynomial(myPoly, x, y, yErr);1111 return(p_ps1DPolyMedian(myPoly, x->data.F64[0], x->data.F64[2],1112 fitFloat));1113 } else {1114 return(0.5 * (histogram->bounds->data.F32[binNum+1] +1115 histogram->bounds->data.F32[binNum]));1116 }1117 1118 psFree( x);1119 psFree( y);1120 psFree( yErr);1121 psFree( myPoly);1122 return (0.0);1075 float p_psFitQuadratic( psHistogram *histogram, 1076 psVector *cumulativeSums, 1077 int binNum, 1078 float fitFloat ) 1079 { 1080 psVector * x = psVectorAlloc( 3, PS_TYPE_F64 ); 1081 psVector *y = psVectorAlloc( 3, PS_TYPE_F64 ); 1082 psVector *yErr = psVectorAlloc( 3, PS_TYPE_F64 ); 1083 psPolynomial1D *myPoly = psPolynomial1DAlloc( 2 ); 1084 1085 if ( ( binNum > 0 ) && 1086 ( binNum < ( histogram->nums->n + 1 ) ) ) { 1087 x->data.F64[ 0 ] = ( double ) 0.5 * 1088 ( histogram->bounds->data.F32[ binNum - 1 ] + 1089 histogram->bounds->data.F32[ binNum ] ); 1090 x->data.F64[ 1 ] = ( double ) 0.5 * 1091 ( histogram->bounds->data.F32[ binNum ] + 1092 histogram->bounds->data.F32[ binNum + 1 ] ); 1093 x->data.F64[ 2 ] = ( double ) 0.5 * 1094 ( histogram->bounds->data.F32[ binNum + 1 ] + 1095 histogram->bounds->data.F32[ binNum + 2 ] ); 1096 1097 y->data.F64[ 0 ] = cumulativeSums->data.F32[ binNum - 1 ]; 1098 y->data.F64[ 1 ] = cumulativeSums->data.F32[ binNum ]; 1099 y->data.F64[ 2 ] = cumulativeSums->data.F32[ binNum + 1 ]; 1100 1101 if ( !( ( y->data.F64[ 0 ] <= fitFloat ) && 1102 ( fitFloat <= y->data.F64[ 2 ] ) ) ) { 1103 psAbort( __func__, "p_psVectorRobustStats(0): midpoint not within y-range\n" ); 1104 } 1105 1106 yErr->data.F64[ 0 ] = 1.0; 1107 yErr->data.F64[ 1 ] = 1.0; 1108 yErr->data.F64[ 2 ] = 1.0; 1109 1110 myPoly = psVectorFitPolynomial1D( myPoly, x, y, yErr ); 1111 return ( p_ps1DPolyMedian( myPoly, x->data.F64[ 0 ], x->data.F64[ 2 ], 1112 fitFloat ) ); 1113 } else { 1114 return ( 0.5 * ( histogram->bounds->data.F32[ binNum + 1 ] + 1115 histogram->bounds->data.F32[ binNum ] ) ); 1116 } 1117 1118 psFree( x ); 1119 psFree( y ); 1120 psFree( yErr ); 1121 psFree( myPoly ); 1122 return ( 0.0 ); 1123 1123 } 1124 1124 … … 1147 1147 NULL 1148 1148 *****************************************************************************/ 1149 void p_psVectorRobustStats( const psVector *restrict myVector,1150 const psVector *restrict maskVector,1151 unsigned int maskVal,1152 psStats *stats)1153 { 1154 psHistogram * robustHistogram = NULL;1149 void p_psVectorRobustStats( const psVector *restrict myVector, 1150 const psVector *restrict maskVector, 1151 unsigned int maskVal, 1152 psStats *stats ) 1153 { 1154 psHistogram * robustHistogram = NULL; 1155 1155 psVector *robustHistogramVector = NULL; 1156 1156 float binSize = 0.0; // Size of the histogram bins … … 1162 1162 float dL = 0.0; 1163 1163 int numBins = 0; 1164 psStats *tmpStats = psStatsAlloc( PS_STAT_CLIPPED_STDEV|PS_STAT_CLIPPED_MEAN);1164 psStats *tmpStats = psStatsAlloc( PS_STAT_CLIPPED_STDEV | PS_STAT_CLIPPED_MEAN ); 1165 1165 // psImage *domain; 1166 1166 // psVector *errors; … … 1177 1177 float sumSquares = 0.0; 1178 1178 float sumDiffs = 0.0; 1179 psVector *x = psVectorAlloc( 3, PS_TYPE_F64);1180 psVector *y = psVectorAlloc( 3, PS_TYPE_F64);1181 psVector *yErr = psVectorAlloc( 3, PS_TYPE_F64);1182 psPolynomial1D *myPoly = psPolynomial1DAlloc( 2);1179 psVector *x = psVectorAlloc( 3, PS_TYPE_F64 ); 1180 psVector *y = psVectorAlloc( 3, PS_TYPE_F64 ); 1181 psVector *yErr = psVectorAlloc( 3, PS_TYPE_F64 ); 1182 psPolynomial1D *myPoly = psPolynomial1DAlloc( 2 ); 1183 1183 psVector *cumulativeRobustSumsFullRange = NULL; 1184 1184 psVector *cumulativeRobustSumsDlRange = NULL; … … 1187 1187 float sumNfit = 0.0; 1188 1188 float cumulativeMedian = 0.0; 1189 1189 1190 1190 // Compute the initial bin size of the robust histogram. This is done 1191 1191 // by computing the clipped standard deviation of the vector, and dividing 1192 1192 // that by 10.0; 1193 p_psVectorClippedStats( myVector, maskVector, maskVal, tmpStats);1193 p_psVectorClippedStats( myVector, maskVector, maskVal, tmpStats ); 1194 1194 binSize = tmpStats->clippedStdev / 10.0f; 1195 1195 1196 1196 // If stats->clippedStdev == 0.0, then all data elements have the same 1197 1197 // value. Therefore, we can set the appropiate results and return. 1198 if ( fabs(binSize) <= FLT_EPSILON) {1199 if (stats->options & PS_STAT_ROBUST_MEAN) {1200 stats->robustMean = stats->clippedMean;1201 }1202 if (stats->options & PS_STAT_ROBUST_MEDIAN) {1203 stats->robustMedian = stats->clippedMean;1204 }1205 if (stats->options & PS_STAT_ROBUST_MODE) {1206 stats->robustMode = stats->clippedMean;1207 }1208 if (stats->options & PS_STAT_ROBUST_STDEV) {1209 stats->robustStdev = 0.0;1210 }1211 if (stats->options & PS_STAT_ROBUST_QUARTILE) {1212 stats->robustUQ = stats->clippedMean;1213 stats->robustLQ = stats->clippedMean;1214 }1215 // XXX: Set these to the number of unmasked data points?1216 stats->robustNfit = 0.0;1217 stats->robustN50 = 0.0;1218 psFree(tmpStats);1219 return;1220 }1221 1198 if ( fabs( binSize ) <= FLT_EPSILON ) { 1199 if ( stats->options & PS_STAT_ROBUST_MEAN ) { 1200 stats->robustMean = stats->clippedMean; 1201 } 1202 if ( stats->options & PS_STAT_ROBUST_MEDIAN ) { 1203 stats->robustMedian = stats->clippedMean; 1204 } 1205 if ( stats->options & PS_STAT_ROBUST_MODE ) { 1206 stats->robustMode = stats->clippedMean; 1207 } 1208 if ( stats->options & PS_STAT_ROBUST_STDEV ) { 1209 stats->robustStdev = 0.0; 1210 } 1211 if ( stats->options & PS_STAT_ROBUST_QUARTILE ) { 1212 stats->robustUQ = stats->clippedMean; 1213 stats->robustLQ = stats->clippedMean; 1214 } 1215 // XXX: Set these to the number of unmasked data points? 1216 stats->robustNfit = 0.0; 1217 stats->robustN50 = 0.0; 1218 psFree( tmpStats ); 1219 return ; 1220 } 1221 1222 1222 // Determine minimum and maximum values in the data vector. 1223 if ( isnan(stats->min)) {1224 p_psVectorMin(myVector, maskVector, maskVal, stats);1225 }1226 if ( isnan(stats->max)) {1227 p_psVectorMax(myVector, maskVector, maskVal, stats);1228 }1229 1223 if ( isnan( stats->min ) ) { 1224 p_psVectorMin( myVector, maskVector, maskVal, stats ); 1225 } 1226 if ( isnan( stats->max ) ) { 1227 p_psVectorMax( myVector, maskVector, maskVal, stats ); 1228 } 1229 1230 1230 // Create the histogram structure. NOTE: we can not specify the bin size 1231 1231 // precisely since the argument to psHistogramAlloc() is the number of 1232 1232 // bins, not the binSize. Also, if we get here, we know that 1233 1233 // binSize != 0.0. 1234 numBins = ( int) ((stats->max - stats->min) / binSize);1235 robustHistogram = psHistogramAlloc( stats->min,1236 stats->max,1237 numBins);1238 1234 numBins = ( int ) ( ( stats->max - stats->min ) / binSize ); 1235 robustHistogram = psHistogramAlloc( stats->min, 1236 stats->max, 1237 numBins ); 1238 1239 1239 // Populate the histogram array. 1240 psVectorHistogram( robustHistogram, myVector, maskVector, maskVal);1241 1240 psVectorHistogram( robustHistogram, myVector, maskVector, maskVal ); 1241 1242 1242 // Smooth the histogram. 1243 1243 // XXX: is that the right stdev? 1244 robustHistogramVector = p_psVectorsmoothHistGaussian( robustHistogram,1245 tmpStats->clippedStdev /4.0f);1246 1244 robustHistogramVector = p_psVectorsmoothHistGaussian( robustHistogram, 1245 tmpStats->clippedStdev / 4.0f ); 1246 1247 1247 // The following was necessary to fit a gaussian to the data, since 1248 1248 // gaussian functions produce data between 0.0 and 1.0. 1249 1249 // p_psNormalizeVector(robustHistogramVector); 1250 1250 1251 1251 /************************************************************************** 1252 1252 Determine the lower/upper quartiles. 1253 **************************************************************************/ 1253 **************************************************************************/ 1254 1254 // We define a vector called "cumulativeRobustSums..." where the value at 1255 1255 // index position i is equal to the sum of bins 0:i. This will be used 1256 1256 // now and later in determining the lower/upper quartiles. 1257 cumulativeRobustSumsFullRange = psVectorAlloc( robustHistogramVector->n, PS_TYPE_F32);1258 cumulativeRobustSumsFullRange->data.F32[ 0] = robustHistogramVector->data.F32[0];1259 for ( i=1;i<robustHistogramVector->n;i++) {1260 cumulativeRobustSumsFullRange->data.F32[i] =1261 cumulativeRobustSumsFullRange->data.F32[i-1] +1262 robustHistogramVector->data.F32[i];1263 }1264 sumRobust = cumulativeRobustSumsFullRange->data.F32[ robustHistogramVector->n-1];1265 1257 cumulativeRobustSumsFullRange = psVectorAlloc( robustHistogramVector->n, PS_TYPE_F32 ); 1258 cumulativeRobustSumsFullRange->data.F32[ 0 ] = robustHistogramVector->data.F32[ 0 ]; 1259 for ( i = 1;i < robustHistogramVector->n;i++ ) { 1260 cumulativeRobustSumsFullRange->data.F32[ i ] = 1261 cumulativeRobustSumsFullRange->data.F32[ i - 1 ] + 1262 robustHistogramVector->data.F32[ i ]; 1263 } 1264 sumRobust = cumulativeRobustSumsFullRange->data.F32[ robustHistogramVector->n - 1 ]; 1265 1266 1266 // Determine the bin number containing the lower quartile point. 1267 1267 LQBinNum = -1; 1268 for ( i=0;i<cumulativeRobustSumsFullRange->n;i++) {1269 if (cumulativeRobustSumsFullRange->data.F32[i] >= (sumRobust/4.0)) {1270 LQBinNum = i;1271 break;1272 }1273 }1274 1268 for ( i = 0;i < cumulativeRobustSumsFullRange->n;i++ ) { 1269 if ( cumulativeRobustSumsFullRange->data.F32[ i ] >= ( sumRobust / 4.0 ) ) { 1270 LQBinNum = i; 1271 break; 1272 } 1273 } 1274 1275 1275 // Determine the bin number containing the upper quartile point. 1276 1276 UQBinNum = -1; 1277 for ( i=cumulativeRobustSumsFullRange->n-1;i>=0;i--) {1278 if (cumulativeRobustSumsFullRange->data.F32[i] <= (3.0*sumRobust/4.0)) {1279 UQBinNum = i;1280 break;1281 }1282 }1283 1284 if ( (LQBinNum == -1) ||1285 ( UQBinNum == -1)) {1286 psAbort(__func__, "Could not determine the robust lower/upper quartiles.");1287 }1277 for ( i = cumulativeRobustSumsFullRange->n - 1;i >= 0;i-- ) { 1278 if ( cumulativeRobustSumsFullRange->data.F32[ i ] <= ( 3.0 * sumRobust / 4.0 ) ) { 1279 UQBinNum = i; 1280 break; 1281 } 1282 } 1283 1284 if ( ( LQBinNum == -1 ) || 1285 ( UQBinNum == -1 ) ) { 1286 psAbort( __func__, "Could not determine the robust lower/upper quartiles." ); 1287 } 1288 1288 /************************************************************************** 1289 1289 Determine the mode in the range LQ:UQ. 1290 **************************************************************************/ 1290 **************************************************************************/ 1291 1291 // Determine the bin with the peak value in the range LQ to UQ. 1292 1292 maxBinNum = LQBinNum; 1293 maxBinCount = robustHistogramVector->data.F32[ LQBinNum];1294 sumN50 = ( float) robustHistogram->nums->data.S32[LQBinNum];1295 for ( i=LQBinNum+1;i<=UQBinNum;i++) {1296 if (robustHistogramVector->data.F32[i] > maxBinCount) {1297 maxBinNum = i;1298 maxBinCount = robustHistogramVector->data.F32[i];1299 }1300 sumN50+= (float) robustHistogram->nums->data.S32[i];1301 }1302 1293 maxBinCount = robustHistogramVector->data.F32[ LQBinNum ]; 1294 sumN50 = ( float ) robustHistogram->nums->data.S32[ LQBinNum ]; 1295 for ( i = LQBinNum + 1;i <= UQBinNum;i++ ) { 1296 if ( robustHistogramVector->data.F32[ i ] > maxBinCount ) { 1297 maxBinNum = i; 1298 maxBinCount = robustHistogramVector->data.F32[ i ]; 1299 } 1300 sumN50 += ( float ) robustHistogram->nums->data.S32[ i ]; 1301 } 1302 1303 1303 // XXX: is dL defined as the value at the LQ/UQ, or the bin number? 1304 dL = ( UQBinNum - LQBinNum) / 4;1305 1306 printf( "(LQBinNum, UQBinNum, maxBinNum) is (%d, %d, %d)\n", LQBinNum, UQBinNum, maxBinNum);1307 1304 dL = ( UQBinNum - LQBinNum ) / 4; 1305 1306 printf( "(LQBinNum, UQBinNum, maxBinNum) is (%d, %d, %d)\n", LQBinNum, UQBinNum, maxBinNum ); 1307 1308 1308 /************************************************************************** 1309 1309 Determine the mean/stdev for the bins in the range mode-dL to mode+dL 1310 1310 **************************************************************************/ 1311 cumulativeRobustSumsDlRange = psVectorAlloc( robustHistogramVector->n, PS_TYPE_F32);1312 for ( i=0;i<robustHistogramVector->n;i++) {1313 cumulativeRobustSumsDlRange->data.F32[i] = 0.0;1314 }1311 cumulativeRobustSumsDlRange = psVectorAlloc( robustHistogramVector->n, PS_TYPE_F32 ); 1312 for ( i = 0;i < robustHistogramVector->n;i++ ) { 1313 cumulativeRobustSumsDlRange->data.F32[ i ] = 0.0; 1314 } 1315 1315 sumNfit = 0.0; 1316 1316 cumulativeMedian = 0.0; 1317 for ( i=maxBinNum-dL;i<=maxBinNum+dL;i++) {1318 if ((0 <= i) && (i < robustHistogramVector->n)) {1319 cumulativeRobustSumsDlRange->data.F32[i] =1320 cumulativeRobustSumsDlRange->data.F32[i-1] +1321 robustHistogramVector->data.F32[i];1322 cumulativeMedian+= robustHistogramVector->data.F32[i];1323 sumNfit+= (float) robustHistogram->nums->data.S32[i];1324 }1325 }1326 1317 for ( i = maxBinNum - dL;i <= maxBinNum + dL;i++ ) { 1318 if ( ( 0 <= i ) && ( i < robustHistogramVector->n ) ) { 1319 cumulativeRobustSumsDlRange->data.F32[ i ] = 1320 cumulativeRobustSumsDlRange->data.F32[ i - 1 ] + 1321 robustHistogramVector->data.F32[ i ]; 1322 cumulativeMedian += robustHistogramVector->data.F32[ i ]; 1323 sumNfit += ( float ) robustHistogram->nums->data.S32[ i ]; 1324 } 1325 } 1326 1327 1327 // Calculate the mean of the smoothed robust histogram in the range 1328 1328 // mode-dL to mode+dL. We use the midpoint of each bin as the mean for 1329 1329 // that bin (this is a non-exact approximation). 1330 1330 myMean = 0.0; 1331 for ( i=maxBinNum-dL;i<=maxBinNum+dL;i++) {1332 if ((0 <= i) && (i < robustHistogramVector->n)) {1333 myMean+= (robustHistogramVector->data.F32[i]) * 0.5 *1334 (robustHistogram->bounds->data.F32[i+1] +1335 robustHistogram->bounds->data.F32[i]);1336 countFloat+= robustHistogramVector->data.F32[i];1337 }1338 }1339 myMean /= countFloat;1340 1331 for ( i = maxBinNum - dL;i <= maxBinNum + dL;i++ ) { 1332 if ( ( 0 <= i ) && ( i < robustHistogramVector->n ) ) { 1333 myMean += ( robustHistogramVector->data.F32[ i ] ) * 0.5 * 1334 ( robustHistogram->bounds->data.F32[ i + 1 ] + 1335 robustHistogram->bounds->data.F32[ i ] ); 1336 countFloat += robustHistogramVector->data.F32[ i ]; 1337 } 1338 } 1339 myMean /= countFloat; 1340 1341 1341 // Calculate the stdev of the smoothed robust histogram in the range 1342 1342 // mode-dL to mode+dL. We use the midpoint of each bin as the mean for 1343 1343 // that bin. 1344 for ( i=maxBinNum-dL;i<=maxBinNum+dL;i++) {1345 if ((0 <= i) && (i < robustHistogramVector->n)) {1346 diff = (0.5 * (robustHistogram->bounds->data.F32[i+1] +1347 robustHistogram->bounds->data.F32[i])) - myMean;1348 sumSquares+= diff * diff * robustHistogramVector->data.F32[i];1349 sumDiffs+= diff * robustHistogramVector->data.F32[i];1350 }1351 }1352 myStdev = sqrt( (sumSquares-(sumDiffs * sumDiffs/countFloat))/ (countFloat-1));1353 1344 for ( i = maxBinNum - dL;i <= maxBinNum + dL;i++ ) { 1345 if ( ( 0 <= i ) && ( i < robustHistogramVector->n ) ) { 1346 diff = ( 0.5 * ( robustHistogram->bounds->data.F32[ i + 1 ] + 1347 robustHistogram->bounds->data.F32[ i ] ) ) - myMean; 1348 sumSquares += diff * diff * robustHistogramVector->data.F32[ i ]; 1349 sumDiffs += diff * robustHistogramVector->data.F32[ i ]; 1350 } 1351 } 1352 myStdev = sqrt( ( sumSquares - ( sumDiffs * sumDiffs / countFloat ) ) / ( countFloat - 1 ) ); 1353 1354 1354 /************************************************************************** 1355 1355 Set the appropriate members in the output stats struct. 1356 1356 **************************************************************************/ 1357 if ( stats->options & PS_STAT_ROBUST_MEAN) {1358 stats->robustMean = myMean;1359 }1360 1361 if (stats->options & PS_STAT_ROBUST_MODE) {1362 stats->robustMode = 0.5 *1363 (robustHistogram->bounds->data.F32[maxBinNum] +1364 robustHistogram->bounds->data.F32[maxBinNum+1]);1365 }1366 1367 if (stats->options & PS_STAT_ROBUST_STDEV) {1368 stats->robustStdev = myStdev;1369 }1370 1357 if ( stats->options & PS_STAT_ROBUST_MEAN ) { 1358 stats->robustMean = myMean; 1359 } 1360 1361 if ( stats->options & PS_STAT_ROBUST_MODE ) { 1362 stats->robustMode = 0.5 * 1363 ( robustHistogram->bounds->data.F32[ maxBinNum ] + 1364 robustHistogram->bounds->data.F32[ maxBinNum + 1 ] ); 1365 } 1366 1367 if ( stats->options & PS_STAT_ROBUST_STDEV ) { 1368 stats->robustStdev = myStdev; 1369 } 1370 1371 1371 // To determine the median (and later, the lower/upper quartile), we fit 1372 1372 // a quadratic to the three bins surrounding the bin containing the median. … … 1374 1374 // the cumulative number of data points in all bins up to, and including, 1375 1375 // this bin. We then solve the quadratic for 1376 1377 if (stats->options & PS_STAT_ROBUST_MEDIAN) {1378 if ((maxBinNum > 0) && (maxBinNum < (robustHistogram->nums->n-1))) {1379 x->data.F64[0] = (double) 0.5 *1380 (robustHistogram->bounds->data.F32[maxBinNum-1] +1381 robustHistogram->bounds->data.F32[maxBinNum]);1382 x->data.F64[1] = (double) 0.5 *1383 (robustHistogram->bounds->data.F32[maxBinNum] +1384 robustHistogram->bounds->data.F32[maxBinNum+1]);1385 x->data.F64[2] = (double) 0.5 *1386 (robustHistogram->bounds->data.F32[maxBinNum+1] +1387 robustHistogram->bounds->data.F32[maxBinNum+2]);1388 1389 y->data.F64[0] = cumulativeRobustSumsDlRange->data.F32[maxBinNum-1];1390 y->data.F64[1] = cumulativeRobustSumsDlRange->data.F32[maxBinNum];1391 y->data.F64[2] = cumulativeRobustSumsDlRange->data.F32[maxBinNum+1];1392 1393 // Ensure that cumulativeMedian/2 is actually within the range of the bins1394 // we are using.1395 cumulativeMedian*= 0.5;1396 if (!((y->data.F64[0] <= cumulativeMedian) &&1397 (cumulativeMedian <= y->data.F64[2]))) {1398 printf("((%f), %f, %f)\n", cumulativeMedian, y->data.F64[0], y->data.F64[2]);1399 psAbort(__func__, "p_psVectorRobustStats(1): midpoint not within y-range\n");1400 }1401 // XXX: yErr is not currently used by psGetArrayPolynomial(). We1402 // may have to set this meaningfully later.1403 yErr->data.F64[0] = 1.0;1404 yErr->data.F64[1] = 1.0;1405 yErr->data.F64[2] = 1.0;1406 1407 // Determine the coefficients of the polynomial.1408 myPoly = psGetArrayPolynomial(myPoly, x, y, yErr);1409 // Call p_ps1DPolyMedian(), which does a binary search on the1410 // polynomial, looking for the value x such that1411 // f(x) = cumulativeMedian.1412 stats->robustMedian = p_ps1DPolyMedian(myPoly, x->data.F64[0],1413 x->data.F64[2], cumulativeMedian);1414 } else {1415 // If the mode is the first/last histogram bin, then simply use1416 // the midpoint of that bin.1417 stats->robustMedian = 0.5 * (robustHistogram->bounds->data.F32[maxBinNum+1] +1418 robustHistogram->bounds->data.F32[maxBinNum]);1419 }1420 }1421 1376 1377 if ( stats->options & PS_STAT_ROBUST_MEDIAN ) { 1378 if ( ( maxBinNum > 0 ) && ( maxBinNum < ( robustHistogram->nums->n - 1 ) ) ) { 1379 x->data.F64[ 0 ] = ( double ) 0.5 * 1380 ( robustHistogram->bounds->data.F32[ maxBinNum - 1 ] + 1381 robustHistogram->bounds->data.F32[ maxBinNum ] ); 1382 x->data.F64[ 1 ] = ( double ) 0.5 * 1383 ( robustHistogram->bounds->data.F32[ maxBinNum ] + 1384 robustHistogram->bounds->data.F32[ maxBinNum + 1 ] ); 1385 x->data.F64[ 2 ] = ( double ) 0.5 * 1386 ( robustHistogram->bounds->data.F32[ maxBinNum + 1 ] + 1387 robustHistogram->bounds->data.F32[ maxBinNum + 2 ] ); 1388 1389 y->data.F64[ 0 ] = cumulativeRobustSumsDlRange->data.F32[ maxBinNum - 1 ]; 1390 y->data.F64[ 1 ] = cumulativeRobustSumsDlRange->data.F32[ maxBinNum ]; 1391 y->data.F64[ 2 ] = cumulativeRobustSumsDlRange->data.F32[ maxBinNum + 1 ]; 1392 1393 // Ensure that cumulativeMedian/2 is actually within the range of the bins 1394 // we are using. 1395 cumulativeMedian *= 0.5; 1396 if ( !( ( y->data.F64[ 0 ] <= cumulativeMedian ) && 1397 ( cumulativeMedian <= y->data.F64[ 2 ] ) ) ) { 1398 printf( "((%f), %f, %f)\n", cumulativeMedian, y->data.F64[ 0 ], y->data.F64[ 2 ] ); 1399 psAbort( __func__, "p_psVectorRobustStats(1): midpoint not within y-range\n" ); 1400 } 1401 // XXX: yErr is not currently used by psVectorFitPolynomial1D(). We 1402 // may have to set this meaningfully later. 1403 yErr->data.F64[ 0 ] = 1.0; 1404 yErr->data.F64[ 1 ] = 1.0; 1405 yErr->data.F64[ 2 ] = 1.0; 1406 1407 // Determine the coefficients of the polynomial. 1408 myPoly = psVectorFitPolynomial1D( myPoly, x, y, yErr ); 1409 // Call p_ps1DPolyMedian(), which does a binary search on the 1410 // polynomial, looking for the value x such that 1411 // f(x) = cumulativeMedian. 1412 stats->robustMedian = p_ps1DPolyMedian( myPoly, x->data.F64[ 0 ], 1413 x->data.F64[ 2 ], cumulativeMedian ); 1414 } else { 1415 // If the mode is the first/last histogram bin, then simply use 1416 // the midpoint of that bin. 1417 stats->robustMedian = 0.5 * ( robustHistogram->bounds->data.F32[ maxBinNum + 1 ] + 1418 robustHistogram->bounds->data.F32[ maxBinNum ] ); 1419 } 1420 } 1421 1422 1422 // The lower/upper quartile calculations are very similar to the median 1423 1423 // calculations. We fit a quadratic to the array containing the … … 1425 1425 // f(x) equals the lower/upper quartile exactly. 1426 1426 // 1427 if (stats->options & PS_STAT_ROBUST_QUARTILE) {1428 countFloat = cumulativeRobustSumsFullRange->data.F32[robustHistogramVector->n-1];1429 1430 if ((LQBinNum > 0) && (LQBinNum < (robustHistogram->nums->n-1))) {1431 x->data.F64[0] = (double) 0.5 *1432 (robustHistogram->bounds->data.F32[LQBinNum-1] +1433 robustHistogram->bounds->data.F32[LQBinNum]);1434 x->data.F64[1] = (double) 0.5 *1435 (robustHistogram->bounds->data.F32[LQBinNum] +1436 robustHistogram->bounds->data.F32[LQBinNum+1]);1437 x->data.F64[2] = (double) 0.5 *1438 (robustHistogram->bounds->data.F32[LQBinNum+1] +1439 robustHistogram->bounds->data.F32[LQBinNum+2]);1440 1441 y->data.F64[0] = cumulativeRobustSumsFullRange->data.F32[LQBinNum-1];1442 y->data.F64[1] = cumulativeRobustSumsFullRange->data.F32[LQBinNum];1443 y->data.F64[2] = cumulativeRobustSumsFullRange->data.F32[LQBinNum+1];1444 1445 if (!((y->data.F64[0] <= (countFloat/4.0)) &&1446 ((countFloat/4.0) <= y->data.F64[2]))) {1447 psAbort(__func__, "p_psVectorRobustStats(2): midpoint not within y-range\n");1448 }1449 1450 yErr->data.F64[0] = 1.0;1451 yErr->data.F64[1] = 1.0;1452 yErr->data.F64[2] = 1.0;1453 1454 myPoly = psGetArrayPolynomial(myPoly, x, y, yErr);1455 stats->robustLQ = p_ps1DPolyMedian(myPoly,1456 x->data.F64[0],1457 x->data.F64[2],1458 countFloat/4.0);1459 1460 } else {1461 // If the LQ is the first/last histogram bin, then simply use1462 // the midpoint of that bin.1463 stats->robustLQ = 0.5 * (robustHistogram->bounds->data.F32[LQBinNum+1] +1464 robustHistogram->bounds->data.F32[LQBinNum]);1465 }1466 1467 if ((UQBinNum > 0) && (UQBinNum < (robustHistogram->nums->n-1))) {1468 x->data.F64[0] = (double) 0.5 *1469 (robustHistogram->bounds->data.F32[UQBinNum-1] +1470 robustHistogram->bounds->data.F32[UQBinNum]);1471 x->data.F64[1] = (double) 0.5 *1472 (robustHistogram->bounds->data.F32[UQBinNum] +1473 robustHistogram->bounds->data.F32[UQBinNum+1]);1474 x->data.F64[2] = (double) 0.5 *1475 (robustHistogram->bounds->data.F32[UQBinNum+1] +1476 robustHistogram->bounds->data.F32[UQBinNum+2]);1477 1478 y->data.F64[0] = cumulativeRobustSumsFullRange->data.F32[UQBinNum-1];1479 y->data.F64[1] = cumulativeRobustSumsFullRange->data.F32[UQBinNum];1480 y->data.F64[2] = cumulativeRobustSumsFullRange->data.F32[UQBinNum+1];1481 1482 if (!((y->data.F64[0] <= (3.0 * countFloat/4.0)) &&1483 ((3.0 * countFloat/4.0) <= y->data.F64[2]))) {1484 psAbort(__func__, "p_psVectorRobustStats(3): midpoint not within y-range\n");1485 }1486 1487 yErr->data.F64[0] = 1.0;1488 yErr->data.F64[1] = 1.0;1489 yErr->data.F64[2] = 1.0;1490 1491 myPoly = psGetArrayPolynomial(myPoly, x, y, yErr);1492 stats->robustUQ = p_ps1DPolyMedian(myPoly,1493 x->data.F64[0],1494 x->data.F64[2],1495 3.0*countFloat/4.0);1496 } else {1497 // If the UQ is the first/last histogram bin, then simply use1498 // the midpoint of that bin.1499 stats->robustUQ = 0.5 * (robustHistogram->bounds->data.F32[UQBinNum+1] +1500 robustHistogram->bounds->data.F32[UQBinNum]);1501 }1502 }1427 if ( stats->options & PS_STAT_ROBUST_QUARTILE ) { 1428 countFloat = cumulativeRobustSumsFullRange->data.F32[ robustHistogramVector->n - 1 ]; 1429 1430 if ( ( LQBinNum > 0 ) && ( LQBinNum < ( robustHistogram->nums->n - 1 ) ) ) { 1431 x->data.F64[ 0 ] = ( double ) 0.5 * 1432 ( robustHistogram->bounds->data.F32[ LQBinNum - 1 ] + 1433 robustHistogram->bounds->data.F32[ LQBinNum ] ); 1434 x->data.F64[ 1 ] = ( double ) 0.5 * 1435 ( robustHistogram->bounds->data.F32[ LQBinNum ] + 1436 robustHistogram->bounds->data.F32[ LQBinNum + 1 ] ); 1437 x->data.F64[ 2 ] = ( double ) 0.5 * 1438 ( robustHistogram->bounds->data.F32[ LQBinNum + 1 ] + 1439 robustHistogram->bounds->data.F32[ LQBinNum + 2 ] ); 1440 1441 y->data.F64[ 0 ] = cumulativeRobustSumsFullRange->data.F32[ LQBinNum - 1 ]; 1442 y->data.F64[ 1 ] = cumulativeRobustSumsFullRange->data.F32[ LQBinNum ]; 1443 y->data.F64[ 2 ] = cumulativeRobustSumsFullRange->data.F32[ LQBinNum + 1 ]; 1444 1445 if ( !( ( y->data.F64[ 0 ] <= ( countFloat / 4.0 ) ) && 1446 ( ( countFloat / 4.0 ) <= y->data.F64[ 2 ] ) ) ) { 1447 psAbort( __func__, "p_psVectorRobustStats(2): midpoint not within y-range\n" ); 1448 } 1449 1450 yErr->data.F64[ 0 ] = 1.0; 1451 yErr->data.F64[ 1 ] = 1.0; 1452 yErr->data.F64[ 2 ] = 1.0; 1453 1454 myPoly = psVectorFitPolynomial1D( myPoly, x, y, yErr ); 1455 stats->robustLQ = p_ps1DPolyMedian( myPoly, 1456 x->data.F64[ 0 ], 1457 x->data.F64[ 2 ], 1458 countFloat / 4.0 ); 1459 1460 } else { 1461 // If the LQ is the first/last histogram bin, then simply use 1462 // the midpoint of that bin. 1463 stats->robustLQ = 0.5 * ( robustHistogram->bounds->data.F32[ LQBinNum + 1 ] + 1464 robustHistogram->bounds->data.F32[ LQBinNum ] ); 1465 } 1466 1467 if ( ( UQBinNum > 0 ) && ( UQBinNum < ( robustHistogram->nums->n - 1 ) ) ) { 1468 x->data.F64[ 0 ] = ( double ) 0.5 * 1469 ( robustHistogram->bounds->data.F32[ UQBinNum - 1 ] + 1470 robustHistogram->bounds->data.F32[ UQBinNum ] ); 1471 x->data.F64[ 1 ] = ( double ) 0.5 * 1472 ( robustHistogram->bounds->data.F32[ UQBinNum ] + 1473 robustHistogram->bounds->data.F32[ UQBinNum + 1 ] ); 1474 x->data.F64[ 2 ] = ( double ) 0.5 * 1475 ( robustHistogram->bounds->data.F32[ UQBinNum + 1 ] + 1476 robustHistogram->bounds->data.F32[ UQBinNum + 2 ] ); 1477 1478 y->data.F64[ 0 ] = cumulativeRobustSumsFullRange->data.F32[ UQBinNum - 1 ]; 1479 y->data.F64[ 1 ] = cumulativeRobustSumsFullRange->data.F32[ UQBinNum ]; 1480 y->data.F64[ 2 ] = cumulativeRobustSumsFullRange->data.F32[ UQBinNum + 1 ]; 1481 1482 if ( !( ( y->data.F64[ 0 ] <= ( 3.0 * countFloat / 4.0 ) ) && 1483 ( ( 3.0 * countFloat / 4.0 ) <= y->data.F64[ 2 ] ) ) ) { 1484 psAbort( __func__, "p_psVectorRobustStats(3): midpoint not within y-range\n" ); 1485 } 1486 1487 yErr->data.F64[ 0 ] = 1.0; 1488 yErr->data.F64[ 1 ] = 1.0; 1489 yErr->data.F64[ 2 ] = 1.0; 1490 1491 myPoly = psVectorFitPolynomial1D( myPoly, x, y, yErr ); 1492 stats->robustUQ = p_ps1DPolyMedian( myPoly, 1493 x->data.F64[ 0 ], 1494 x->data.F64[ 2 ], 1495 3.0 * countFloat / 4.0 ); 1496 } else { 1497 // If the UQ is the first/last histogram bin, then simply use 1498 // the midpoint of that bin. 1499 stats->robustUQ = 0.5 * ( robustHistogram->bounds->data.F32[ UQBinNum + 1 ] + 1500 robustHistogram->bounds->data.F32[ UQBinNum ] ); 1501 } 1502 } 1503 1503 stats->robustNfit = sumNfit; 1504 1504 stats->robustN50 = sumN50; 1505 1506 psFree( x);1507 psFree( y);1508 psFree( yErr);1509 psFree( tmpStats);1510 psFree( robustHistogram);1511 psFree( myPoly);1512 psFree( cumulativeRobustSumsFullRange);1513 psFree( cumulativeRobustSumsDlRange);1505 1506 psFree( x ); 1507 psFree( y ); 1508 psFree( yErr ); 1509 psFree( tmpStats ); 1510 psFree( robustHistogram ); 1511 psFree( myPoly ); 1512 psFree( cumulativeRobustSumsFullRange ); 1513 psFree( cumulativeRobustSumsDlRange ); 1514 1514 } 1515 1515 … … 1568 1568 /*****************************************************************************/ 1569 1569 1570 static void histogramFree( psHistogram *myHist);1570 static void histogramFree( psHistogram *myHist ); 1571 1571 1572 1572 /****************************************************************************** 1573 1573 psStatsAlloc(): This routine must create a new psStats data structure. 1574 1574 *****************************************************************************/ 1575 psStats *psStatsAlloc( psStatsOptions options)1576 { 1577 psStats * newStruct = NULL;1578 1579 newStruct = ( psStats *) psAlloc(sizeof(psStats));1575 psStats *psStatsAlloc( psStatsOptions options ) 1576 { 1577 psStats * newStruct = NULL; 1578 1579 newStruct = ( psStats * ) psAlloc( sizeof( psStats ) ); 1580 1580 newStruct->sampleMean = NAN; 1581 1581 newStruct->sampleMedian = NAN; … … 1600 1600 newStruct->binsize = NAN; 1601 1601 newStruct->options = options; 1602 1603 return (newStruct);1602 1603 return ( newStruct ); 1604 1604 } 1605 1605 … … 1616 1616 The histogram structure 1617 1617 *****************************************************************************/ 1618 psHistogram *psHistogramAlloc( float lower,1619 float upper,1620 int n)1618 psHistogram *psHistogramAlloc( float lower, 1619 float upper, 1620 int n ) 1621 1621 { 1622 1622 int i = 0; // Loop index variable 1623 1623 psHistogram *newHist = NULL; // The new histogram structure 1624 1624 float binSize = 0.0; // The histogram bin size 1625 1625 1626 1626 // NOTE: Verify that this is the correct action. 1627 if ( n == 0) {1628 return(NULL);1629 }1630 if ( n < 0) {1631 psAbort(__func__, "psHistogramAlloc() called with bin size %d.\n", n);1632 }1633 1627 if ( n == 0 ) { 1628 return ( NULL ); 1629 } 1630 if ( n < 0 ) { 1631 psAbort( __func__, "psHistogramAlloc() called with bin size %d.\n", n ); 1632 } 1633 1634 1634 // NOTE: Verify that this is the correct action. 1635 if ( lower > upper) {1636 return(NULL);1637 }1638 1635 if ( lower > upper ) { 1636 return ( NULL ); 1637 } 1638 1639 1639 // Allocate memory for the new histogram structure. If there are N 1640 1640 // bins, then there are N+1 bounds to those bins. 1641 newHist = ( psHistogram *) psAlloc(sizeof(psHistogram));1642 p_psMemSetDeallocator( newHist,(psFreeFcn)histogramFree);1643 newHist->bounds = psVectorAlloc( n+1, PS_TYPE_F32);1641 newHist = ( psHistogram * ) psAlloc( sizeof( psHistogram ) ); 1642 p_psMemSetDeallocator( newHist, ( psFreeFcn ) histogramFree ); 1643 newHist->bounds = psVectorAlloc( n + 1, PS_TYPE_F32 ); 1644 1644 newHist->bounds->n = newHist->bounds->nalloc; 1645 1645 1646 1646 // Calculate the bounds for each bin. 1647 binSize = ( upper - lower) / (float) n;1647 binSize = ( upper - lower ) / ( float ) n; 1648 1648 // NOTE: Is the following necessary? It prevents the max data point 1649 1649 // from being in a non-existant bin. 1650 binSize += FLT_EPSILON;1651 for ( i=0;i<n+1;i++) {1652 newHist->bounds->data.F32[i] = lower + (binSize * (float) i);1653 }1654 1650 binSize += FLT_EPSILON; 1651 for ( i = 0;i < n + 1;i++ ) { 1652 newHist->bounds->data.F32[ i ] = lower + ( binSize * ( float ) i ); 1653 } 1654 1655 1655 // Allocate the bins, and initialize them to zero. 1656 newHist->nums = psVectorAlloc(n, PS_TYPE_U32);1656 newHist->nums = psVectorAlloc( n, PS_TYPE_U32 ); 1657 1657 newHist->nums->n = newHist->nums->nalloc; 1658 for ( i=0;i<newHist->nums->n;i++) {1659 newHist->nums->data.U32[i] = 0;1660 }1661 1658 for ( i = 0;i < newHist->nums->n;i++ ) { 1659 newHist->nums->data.U32[ i ] = 0; 1660 } 1661 1662 1662 // Initialize the other members. 1663 1663 newHist->minNum = 0; 1664 1664 newHist->maxNum = 0; 1665 1665 newHist->uniform = true; 1666 1667 return (newHist);1666 1667 return ( newHist ); 1668 1668 } 1669 1669 … … 1677 1677 The histogram structure 1678 1678 *****************************************************************************/ 1679 psHistogram *psHistogramAllocGeneric( const psVector *restrict bounds)1680 { 1681 psHistogram * newHist = NULL; // The new histogram structure1679 psHistogram *psHistogramAllocGeneric( const psVector *restrict bounds ) 1680 { 1681 psHistogram * newHist = NULL; // The new histogram structure 1682 1682 int i; // Loop index variable 1683 1683 1684 1684 // NOTE: Verify that this is the correct action. 1685 if ( bounds == NULL) {1686 // psAbort(__func__, "psHistogram requested with NULL bounds");1687 return(NULL);1688 }1689 1685 if ( bounds == NULL ) { 1686 // psAbort(__func__, "psHistogram requested with NULL bounds"); 1687 return ( NULL ); 1688 } 1689 1690 1690 // NOTE: Verify that this is the correct action. 1691 if ( bounds->n <= 1) {1692 // psAbort(__func__, "psHistogram requested with NULL bounds");1693 return(NULL);1694 }1695 1696 if ( bounds->type.type != PS_TYPE_F32) {1697 // psAbort(__func__, "psHistogram request a bound which is not type F32");1698 return(NULL);1699 }1700 1691 if ( bounds->n <= 1 ) { 1692 // psAbort(__func__, "psHistogram requested with NULL bounds"); 1693 return ( NULL ); 1694 } 1695 1696 if ( bounds->type.type != PS_TYPE_F32 ) { 1697 // psAbort(__func__, "psHistogram request a bound which is not type F32"); 1698 return ( NULL ); 1699 } 1700 1701 1701 // Allocate memory for the new histogram structure. 1702 newHist = ( psHistogram *) psAlloc(sizeof(psHistogram));1703 p_psMemSetDeallocator( newHist,(psFreeFcn)histogramFree);1704 newHist->bounds = psVectorAlloc( bounds->n, PS_TYPE_F32);1702 newHist = ( psHistogram * ) psAlloc( sizeof( psHistogram ) ); 1703 p_psMemSetDeallocator( newHist, ( psFreeFcn ) histogramFree ); 1704 newHist->bounds = psVectorAlloc( bounds->n, PS_TYPE_F32 ); 1705 1705 newHist->bounds->n = newHist->bounds->nalloc; 1706 for ( i=0;i<bounds->n;i++) {1707 newHist->bounds->data.F32[i] = bounds->data.F32[i];1708 }1709 1706 for ( i = 0;i < bounds->n;i++ ) { 1707 newHist->bounds->data.F32[ i ] = bounds->data.F32[ i ]; 1708 } 1709 1710 1710 // Allocate the bins, and initialize them to zero. If there are N bounds, 1711 1711 // then there are N-1 bins. 1712 newHist->nums = psVectorAlloc( (bounds->n)-1, PS_TYPE_U32);1712 newHist->nums = psVectorAlloc( ( bounds->n ) - 1, PS_TYPE_U32 ); 1713 1713 newHist->nums->n = newHist->nums->nalloc; 1714 for ( i=0;i<newHist->nums->n;i++) {1715 newHist->nums->data.U32[i] = 0;1716 }1717 1714 for ( i = 0;i < newHist->nums->n;i++ ) { 1715 newHist->nums->data.U32[ i ] = 0; 1716 } 1717 1718 1718 // Initialize the other members. 1719 1719 newHist->minNum = 0; 1720 1720 newHist->maxNum = 0; 1721 1721 newHist->uniform = false; 1722 1723 return (newHist);1724 } 1725 1726 static void histogramFree( psHistogram *myHist)1727 { 1728 psFree( myHist->bounds);1729 psFree( myHist->nums);1722 1723 return ( newHist ); 1724 } 1725 1726 static void histogramFree( psHistogram *myHist ) 1727 { 1728 psFree( myHist->bounds ); 1729 psFree( myHist->nums ); 1730 1730 } 1731 1731 … … 1745 1745 The histogram structure "out". 1746 1746 *****************************************************************************/ 1747 psHistogram *psVectorHistogram( psHistogram *out,1748 const psVector *restrict in,1749 const psVector *restrict mask,1750 unsigned int maskVal)1747 psHistogram *psVectorHistogram( psHistogram *out, 1748 const psVector *restrict in, 1749 const psVector *restrict mask, 1750 unsigned int maskVal ) 1751 1751 { 1752 1752 int i = 0; // Loop index variable … … 1755 1755 int binNum = 0; // A temporary bin number 1756 1756 int numBins = 0; // The total number of bins 1757 1757 1758 1758 // NOTE: Verify that this is the correct action. 1759 if ( out == NULL) {1760 return(NULL);1761 }1762 1759 if ( out == NULL ) { 1760 return ( NULL ); 1761 } 1762 1763 1763 // Check the specified output histogram for type psF32 1764 if ( out->bounds->type.type != PS_TYPE_F32) {1765 psAbort(__func__,1766 "Only data type PS_TYPE_F32 for the output.bounds member.");1767 }1768 1769 if ( out->nums->type.type != PS_TYPE_U32) {1770 psAbort(__func__,1771 "Only data type PS_TYPE_U32 for output.nums member.");1772 }1773 1764 if ( out->bounds->type.type != PS_TYPE_F32 ) { 1765 psAbort( __func__, 1766 "Only data type PS_TYPE_F32 for the output.bounds member." ); 1767 } 1768 1769 if ( out->nums->type.type != PS_TYPE_U32 ) { 1770 psAbort( __func__, 1771 "Only data type PS_TYPE_U32 for output.nums member." ); 1772 } 1773 1774 1774 // NOTE: Verify that this is the correct action. 1775 if ( in == NULL) {1776 return(out);1777 }1778 1779 if ( in->type.type != PS_TYPE_F32) {1780 psAbort(__func__,1781 "Only data type PS_TYPE_F32 is currently supported (0x%x).",1782 in->type.type);1783 }1784 1785 if ( mask != NULL) {1786 if (in->n != mask->n) {1787 psAbort(__func__,1788 "Vector data and vector mask are of different sizes.");1789 }1790 if (mask->type.type != PS_TYPE_U8) {1791 psAbort(__func__, "Vector mask must be type PS_TYPE_U8");1792 }1793 }1775 if ( in == NULL ) { 1776 return ( out ); 1777 } 1778 1779 if ( in->type.type != PS_TYPE_F32 ) { 1780 psAbort( __func__, 1781 "Only data type PS_TYPE_F32 is currently supported (0x%x).", 1782 in->type.type ); 1783 } 1784 1785 if ( mask != NULL ) { 1786 if ( in->n != mask->n ) { 1787 psAbort( __func__, 1788 "Vector data and vector mask are of different sizes." ); 1789 } 1790 if ( mask->type.type != PS_TYPE_U8 ) { 1791 psAbort( __func__, "Vector mask must be type PS_TYPE_U8" ); 1792 } 1793 } 1794 1794 // NOTE: determine the correct action for a variety of other cases: 1795 1795 // in vector has 0 elements, and histogram structure has zero bins. 1796 1796 1797 1797 numBins = out->nums->n; 1798 for ( i=0;i<in->n;i++) {1799 // Check if this pixel is masked, and if so, skip it.1800 if ((mask == NULL) ||1801 ((mask != NULL) && (!(mask->data.U8[i] & maskVal)))) {1802 // Check if this pixel is below the minimum value, and if so1803 // count it, then skip it.1804 if (in->data.F32[i] < out->bounds->data.F32[0]) {1805 out->minNum++;1806 // Check if this pixel is above the maximum value, and if so1807 // count it, then skip it.1808 } else if (in->data.F32[i] > out->bounds->data.F32[numBins]) {1809 out->maxNum++;1810 } else {1811 // If this is a uniform histogram, determining the correct1812 // number is trivial.1813 if (out->uniform == true) {1814 binSize = out->bounds->data.F32[1] - out->bounds->data.F32[0];1815 binNum = (int) ((in->data.F32[i] - out->bounds->data.F32[0]) /1816 binSize);1817 1818 // NOTE: This next if-statement really shouldn't be necessary.1819 // However, do to numerical lack of precision, we occasionally1820 // produce a binNum outside the range of bins.1821 if (binNum >= out->nums->n) {1822 binNum = out->nums->n-1;1823 }1824 1825 (out->nums->data.S32[binNum])++;1826 1827 // If this is a non-uniform histogram, determining the correct1828 // bin number requires a bit more work.1829 } else {1830 // NOTE: This is slow. Put a smarter algorithm here to1831 // find the correct bin number (bin search, probably)1832 for (j=0;j<(out->bounds->n)-1;j++) {1833 if ((out->bounds->data.S32[j] <= in->data.F32[i]) &&1834 (in->data.F32[i] <= out->bounds->data.S32[j+1])) {1835 (out->nums->data.S32[j])++;1836 }1837 }1838 }1839 }1840 }1841 }1842 return (out);1798 for ( i = 0;i < in->n;i++ ) { 1799 // Check if this pixel is masked, and if so, skip it. 1800 if ( ( mask == NULL ) || 1801 ( ( mask != NULL ) && ( !( mask->data.U8[ i ] & maskVal ) ) ) ) { 1802 // Check if this pixel is below the minimum value, and if so 1803 // count it, then skip it. 1804 if ( in->data.F32[ i ] < out->bounds->data.F32[ 0 ] ) { 1805 out->minNum++; 1806 // Check if this pixel is above the maximum value, and if so 1807 // count it, then skip it. 1808 } else if ( in->data.F32[ i ] > out->bounds->data.F32[ numBins ] ) { 1809 out->maxNum++; 1810 } else { 1811 // If this is a uniform histogram, determining the correct 1812 // number is trivial. 1813 if ( out->uniform == true ) { 1814 binSize = out->bounds->data.F32[ 1 ] - out->bounds->data.F32[ 0 ]; 1815 binNum = ( int ) ( ( in->data.F32[ i ] - out->bounds->data.F32[ 0 ] ) / 1816 binSize ); 1817 1818 // NOTE: This next if-statement really shouldn't be necessary. 1819 // However, do to numerical lack of precision, we occasionally 1820 // produce a binNum outside the range of bins. 1821 if ( binNum >= out->nums->n ) { 1822 binNum = out->nums->n - 1; 1823 } 1824 1825 ( out->nums->data.S32[ binNum ] ) ++; 1826 1827 // If this is a non-uniform histogram, determining the correct 1828 // bin number requires a bit more work. 1829 } else { 1830 // NOTE: This is slow. Put a smarter algorithm here to 1831 // find the correct bin number (bin search, probably) 1832 for ( j = 0;j < ( out->bounds->n ) - 1;j++ ) { 1833 if ( ( out->bounds->data.S32[ j ] <= in->data.F32[ i ] ) && 1834 ( in->data.F32[ i ] <= out->bounds->data.S32[ j + 1 ] ) ) { 1835 ( out->nums->data.S32[ j ] ) ++; 1836 } 1837 } 1838 } 1839 } 1840 } 1841 } 1842 return ( out ); 1843 1843 } 1844 1844 … … 1852 1852 the various stat functions. 1853 1853 *****************************************************************************/ 1854 psVector *p_psConvertToF32( psStats *stats,1855 psVector *in,1856 psVector *mask,1857 unsigned int maskVal)1854 psVector *p_psConvertToF32( psStats *stats, 1855 psVector *in, 1856 psVector *mask, 1857 unsigned int maskVal ) 1858 1858 { 1859 1859 int i = 0; 1860 1860 psVector *tmp = NULL; 1861 1862 if ( in->type.type == PS_TYPE_S32) {1863 tmp = psVectorAlloc(in->n, PS_TYPE_F32);1864 for (i=0;i<in->n;i++) {1865 tmp->data.F32[i] = (float) in->data.S32[i];1866 }1867 } else if (in->type.type == PS_TYPE_U32) {1868 tmp = psVectorAlloc(in->n, PS_TYPE_F32);1869 for (i=0;i<in->n;i++) {1870 tmp->data.F32[i] = (float) in->data.U32[i];1871 }1872 } else if (in->type.type == PS_TYPE_F64) {1873 tmp = psVectorAlloc(in->n, PS_TYPE_F32);1874 for (i=0;i<in->n;i++) {1875 tmp->data.F32[i] = (float) in->data.F64[i];1876 }1877 } else if (in->type.type == PS_TYPE_F32) {1878 // do nothing1879 } else {1880 psAbort(__func__, "unsupported vector type 0x%x\n", in->type.type);1881 }1882 return (tmp);1861 1862 if ( in->type.type == PS_TYPE_S32 ) { 1863 tmp = psVectorAlloc( in->n, PS_TYPE_F32 ); 1864 for ( i = 0;i < in->n;i++ ) { 1865 tmp->data.F32[ i ] = ( float ) in->data.S32[ i ]; 1866 } 1867 } else if ( in->type.type == PS_TYPE_U32 ) { 1868 tmp = psVectorAlloc( in->n, PS_TYPE_F32 ); 1869 for ( i = 0;i < in->n;i++ ) { 1870 tmp->data.F32[ i ] = ( float ) in->data.U32[ i ]; 1871 } 1872 } else if ( in->type.type == PS_TYPE_F64 ) { 1873 tmp = psVectorAlloc( in->n, PS_TYPE_F32 ); 1874 for ( i = 0;i < in->n;i++ ) { 1875 tmp->data.F32[ i ] = ( float ) in->data.F64[ i ]; 1876 } 1877 } else if ( in->type.type == PS_TYPE_F32 ) { 1878 // do nothing 1879 } else { 1880 psAbort( __func__, "unsupported vector type 0x%x\n", in->type.type ); 1881 } 1882 return ( tmp ); 1883 1883 } 1884 1884 … … 1901 1901 macro-ize everything and add PS_TYPE_U16 and PS_TYPE_F64. 1902 1902 *****************************************************************************/ 1903 psStats *psVectorStats( psStats *stats,1904 psVector *in,1905 psVector *mask,1906 unsigned int maskVal)1907 { 1908 psVector * inF32;1903 psStats *psVectorStats( psStats *stats, 1904 psVector *in, 1905 psVector *mask, 1906 unsigned int maskVal ) 1907 { 1908 psVector * inF32; 1909 1909 int mustFreeTmp = 1; 1910 1910 1911 1911 // NOTE: Verify that this is the correct action. 1912 if ( in == NULL) {1913 return(stats);1914 }1915 if ( stats == NULL) {1916 return(NULL);1917 }1918 1919 inF32 = p_psConvertToF32( stats, in, mask, maskVal);1920 if ( inF32 == NULL) {1921 inF32 = in;1922 mustFreeTmp = 0;1923 }1924 1912 if ( in == NULL ) { 1913 return ( stats ); 1914 } 1915 if ( stats == NULL ) { 1916 return ( NULL ); 1917 } 1918 1919 inF32 = p_psConvertToF32( stats, in, mask, maskVal ); 1920 if ( inF32 == NULL ) { 1921 inF32 = in; 1922 mustFreeTmp = 0; 1923 } 1924 1925 1925 // XXX: Should we abort if (stats->min == stats->max)? 1926 if ( (stats->options & PS_STAT_USE_RANGE) &&1927 ( stats->min >= stats->max)) {1928 psAbort(__func__, "psVectorStats() called with range: %f to %f\n",1929 stats->min, stats->max);1930 }1931 1926 if ( ( stats->options & PS_STAT_USE_RANGE ) && 1927 ( stats->min >= stats->max ) ) { 1928 psAbort( __func__, "psVectorStats() called with range: %f to %f\n", 1929 stats->min, stats->max ); 1930 } 1931 1932 1932 // PS_CHECK_VECTOR_TYPE(in, PS_TYPE_F32); 1933 if ( mask != NULL) {1934 PS_CHECK_NULL_VECTOR(mask);1935 PS_CHECK_EMPTY_VECTOR(mask);1936 PS_CHECK_VECTOR_SIZE_EQUAL(mask, in);1937 PS_CHECK_VECTOR_TYPE(mask, PS_TYPE_U8);1938 }1939 1933 if ( mask != NULL ) { 1934 PS_CHECK_NULL_VECTOR( mask ); 1935 PS_CHECK_EMPTY_VECTOR( mask ); 1936 PS_CHECK_VECTOR_SIZE_EQUAL( mask, in ); 1937 PS_CHECK_VECTOR_TYPE( mask, PS_TYPE_U8 ); 1938 } 1939 1940 1940 // ************************************************************************ 1941 if ( stats->options & PS_STAT_SAMPLE_MEAN) {1942 p_psVectorSampleMean(in, mask, maskVal, stats);1943 }1944 1941 if ( stats->options & PS_STAT_SAMPLE_MEAN ) { 1942 p_psVectorSampleMean( in, mask, maskVal, stats ); 1943 } 1944 1945 1945 // ************************************************************************ 1946 if ( stats->options & PS_STAT_SAMPLE_MEDIAN) {1947 p_psVectorSampleMedian(in, mask, maskVal, stats);1948 }1949 1946 if ( stats->options & PS_STAT_SAMPLE_MEDIAN ) { 1947 p_psVectorSampleMedian( in, mask, maskVal, stats ); 1948 } 1949 1950 1950 // ************************************************************************ 1951 1951 // NOTE: The Stdev calculation requires the mean. Should we assume the 1952 1952 // mean has already been calculated? Or should we always calculate it? 1953 if ( stats->options & PS_STAT_SAMPLE_STDEV) {1954 p_psVectorSampleMean(in, mask, maskVal, stats);1955 p_psVectorSampleStdev(in, mask, maskVal, stats);1956 }1957 1953 if ( stats->options & PS_STAT_SAMPLE_STDEV ) { 1954 p_psVectorSampleMean( in, mask, maskVal, stats ); 1955 p_psVectorSampleStdev( in, mask, maskVal, stats ); 1956 } 1957 1958 1958 // ************************************************************************ 1959 if ( stats->options & PS_STAT_SAMPLE_QUARTILE) {1960 p_psVectorSampleQuartiles(in, mask, maskVal, stats);1961 }1962 1959 if ( stats->options & PS_STAT_SAMPLE_QUARTILE ) { 1960 p_psVectorSampleQuartiles( in, mask, maskVal, stats ); 1961 } 1962 1963 1963 // Since the various robust stats quantities share much computation, they 1964 1964 // are grouped together in a single private function: 1965 1965 // p_psVectorRobustStats() 1966 if ( (stats->options & PS_STAT_ROBUST_MEAN) ||1967 ( stats->options & PS_STAT_ROBUST_MEDIAN) ||1968 ( stats->options & PS_STAT_ROBUST_MODE) ||1969 ( stats->options & PS_STAT_ROBUST_STDEV) ||1970 ( stats->options & PS_STAT_ROBUST_QUARTILE)) {1971 p_psVectorRobustStats(in, mask, maskVal, stats);1972 }1973 1974 if ( (stats->options & PS_STAT_CLIPPED_MEAN) ||1975 ( stats->options & PS_STAT_CLIPPED_STDEV)) {1976 p_psVectorClippedStats(in, mask, maskVal, stats);1977 }1978 1966 if ( ( stats->options & PS_STAT_ROBUST_MEAN ) || 1967 ( stats->options & PS_STAT_ROBUST_MEDIAN ) || 1968 ( stats->options & PS_STAT_ROBUST_MODE ) || 1969 ( stats->options & PS_STAT_ROBUST_STDEV ) || 1970 ( stats->options & PS_STAT_ROBUST_QUARTILE ) ) { 1971 p_psVectorRobustStats( in, mask, maskVal, stats ); 1972 } 1973 1974 if ( ( stats->options & PS_STAT_CLIPPED_MEAN ) || 1975 ( stats->options & PS_STAT_CLIPPED_STDEV ) ) { 1976 p_psVectorClippedStats( in, mask, maskVal, stats ); 1977 } 1978 1979 1979 // ************************************************************************ 1980 if ( stats->options & PS_STAT_MAX) {1981 p_psVectorMax(in, mask, maskVal, stats);1982 }1983 1980 if ( stats->options & PS_STAT_MAX ) { 1981 p_psVectorMax( in, mask, maskVal, stats ); 1982 } 1983 1984 1984 // ************************************************************************ 1985 if ( stats->options & PS_STAT_MIN) {1986 p_psVectorMin(in, mask, maskVal, stats);1987 }1988 1989 if ( mustFreeTmp == 1) {1990 psFree(inF32);1991 }1992 return (stats);1993 } 1985 if ( stats->options & PS_STAT_MIN ) { 1986 p_psVectorMin( in, mask, maskVal, stats ); 1987 } 1988 1989 if ( mustFreeTmp == 1 ) { 1990 psFree( inF32 ); 1991 } 1992 return ( stats ); 1993 }
Note:
See TracChangeset
for help on using the changeset viewer.
