* This routine searches the cluster tree for all leaf nodes * which are samples in the specified cluster. It computes * a full covariance matrix for these samples as well as * keeping track of the ranges (min and max) for each * dimension. A special data structure is allocated to * return this information to the caller. An incremental * algorithm for computing statistics is not used becau
| 1415 | * @note History: 6/2/89, DSJ, Created. |
| 1416 | */ |
| 1417 | STATISTICS * |
| 1418 | ComputeStatistics (inT16 N, PARAM_DESC ParamDesc[], CLUSTER * Cluster) { |
| 1419 | STATISTICS *Statistics; |
| 1420 | int i, j; |
| 1421 | FLOAT32 *CoVariance; |
| 1422 | FLOAT32 *Distance; |
| 1423 | LIST SearchState; |
| 1424 | SAMPLE *Sample; |
| 1425 | uinT32 SampleCountAdjustedForBias; |
| 1426 | |
| 1427 | // allocate memory to hold the statistics results |
| 1428 | Statistics = (STATISTICS *) Emalloc (sizeof (STATISTICS)); |
| 1429 | Statistics->CoVariance = (FLOAT32 *) Emalloc (N * N * sizeof (FLOAT32)); |
| 1430 | Statistics->Min = (FLOAT32 *) Emalloc (N * sizeof (FLOAT32)); |
| 1431 | Statistics->Max = (FLOAT32 *) Emalloc (N * sizeof (FLOAT32)); |
| 1432 | |
| 1433 | // allocate temporary memory to hold the sample to mean distances |
| 1434 | Distance = (FLOAT32 *) Emalloc (N * sizeof (FLOAT32)); |
| 1435 | |
| 1436 | // initialize the statistics |
| 1437 | Statistics->AvgVariance = 1.0; |
| 1438 | CoVariance = Statistics->CoVariance; |
| 1439 | for (i = 0; i < N; i++) { |
| 1440 | Statistics->Min[i] = 0.0; |
| 1441 | Statistics->Max[i] = 0.0; |
| 1442 | for (j = 0; j < N; j++, CoVariance++) |
| 1443 | *CoVariance = 0; |
| 1444 | } |
| 1445 | // find each sample in the cluster and merge it into the statistics |
| 1446 | InitSampleSearch(SearchState, Cluster); |
| 1447 | while ((Sample = NextSample (&SearchState)) != NULL) { |
| 1448 | for (i = 0; i < N; i++) { |
| 1449 | Distance[i] = Sample->Mean[i] - Cluster->Mean[i]; |
| 1450 | if (ParamDesc[i].Circular) { |
| 1451 | if (Distance[i] > ParamDesc[i].HalfRange) |
| 1452 | Distance[i] -= ParamDesc[i].Range; |
| 1453 | if (Distance[i] < -ParamDesc[i].HalfRange) |
| 1454 | Distance[i] += ParamDesc[i].Range; |
| 1455 | } |
| 1456 | if (Distance[i] < Statistics->Min[i]) |
| 1457 | Statistics->Min[i] = Distance[i]; |
| 1458 | if (Distance[i] > Statistics->Max[i]) |
| 1459 | Statistics->Max[i] = Distance[i]; |
| 1460 | } |
| 1461 | CoVariance = Statistics->CoVariance; |
| 1462 | for (i = 0; i < N; i++) |
| 1463 | for (j = 0; j < N; j++, CoVariance++) |
| 1464 | *CoVariance += Distance[i] * Distance[j]; |
| 1465 | } |
| 1466 | // normalize the variances by the total number of samples |
| 1467 | // use SampleCount-1 instead of SampleCount to get an unbiased estimate |
| 1468 | // also compute the geometic mean of the diagonal variances |
| 1469 | // ensure that clusters with only 1 sample are handled correctly |
| 1470 | if (Cluster->SampleCount > 1) |
| 1471 | SampleCountAdjustedForBias = Cluster->SampleCount - 1; |
| 1472 | else |
| 1473 | SampleCountAdjustedForBias = 1; |
| 1474 | CoVariance = Statistics->CoVariance; |
no test coverage detected