Subversion Repositories f9daq

Rev

Rev 197 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /********************************************************************\
  2.  
  3.   Name:         averager.cpp
  4.   Created by:   Stefan Ritt
  5.  
  6.   Contents:     Robust averager
  7.  
  8.   $Id: averager.cpp 21210 2013-12-12 11:36:59Z ritt $
  9.  
  10. \********************************************************************/
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <math.h>
  16. #include <assert.h>
  17.  
  18. #include "averager.h"
  19.  
  20. /*----------------------------------------------------------------*/
  21.  
  22. Averager::Averager(int nx, int ny, int nz, int dim)
  23. {
  24.    fNx = nx;
  25.    fNy = ny;
  26.    fNz = nz;
  27.    fDim = dim;
  28.    
  29.    int size = sizeof(float)*nx*ny*nz * dim;
  30.    fArray = (float *)malloc(size);
  31.    assert(fArray);
  32.    memset(fArray, 0, size);
  33.    size = sizeof(float)*nx*ny*nz;
  34.    fN = (unsigned short *)malloc(size);
  35.    assert(fN);
  36.    memset(fN, 0, size);
  37. }
  38.  
  39. /*----------------------------------------------------------------*/
  40.  
  41. Averager::~Averager()
  42. {
  43.    if (fN)
  44.       free(fN);
  45.    if (fArray)
  46.       free(fArray);
  47.    fN = NULL;
  48.    fArray = NULL;
  49. }
  50.  
  51. /*----------------------------------------------------------------*/
  52.  
  53. void Averager::Add(int x, int y, int z, float value)
  54. {
  55.    assert(x < fNx);
  56.    assert(y < fNy);
  57.    assert(z < fNz);
  58.    
  59.    int nIndex = (x*fNy + y)*fNz + z;
  60.    if (fN[nIndex] == fDim - 1) // check if array full
  61.       return;
  62.    
  63.    int aIndex = ((x*fNy + y)*fNz + z) * fDim + fN[nIndex];
  64.    fN[nIndex]++;
  65.    fArray[aIndex] = value;
  66. }
  67.  
  68. /*----------------------------------------------------------------*/
  69.  
  70. void Averager::Reset()
  71. {
  72.    int size = sizeof(float)*fNx*fNy*fNz * fDim;
  73.    memset(fArray, 0, size);
  74.    size = sizeof(float)*fNx*fNy*fNz;
  75.    memset(fN, 0, size);
  76. }
  77.  
  78. /*----------------------------------------------------------------*/
  79.  
  80. int compar(const void *a, const void *b);
  81.  
  82. int compar(const void *a, const void *b)
  83. {
  84.    if (*((float *)a) == *((float *)b))
  85.       return 0;
  86.    
  87.    return (*((float *)a) < *((float *)b)) ? -1 : 1;
  88. }
  89.            
  90. double Averager::Average(int x, int y, int z)
  91. {
  92.    assert(x < fNx);
  93.    assert(y < fNy);
  94.    assert(z < fNz);
  95.  
  96.    double a = 0;
  97.    
  98.    int nIndex = (x*fNy + y)*fNz + z;
  99.    int aIndex = ((x*fNy + y)*fNz + z) * fDim;
  100.  
  101.    for (int i=0 ; i<fN[nIndex] ; i++)
  102.       a += fArray[aIndex + i];
  103.    
  104.    if (fN[nIndex] > 0)
  105.       a /= fN[nIndex];
  106.    
  107.    return a;
  108. }
  109.  
  110. /*----------------------------------------------------------------*/
  111.  
  112. double Averager::Median(int x, int y, int z)
  113. {
  114.    assert(x < fNx);
  115.    assert(y < fNy);
  116.    assert(z < fNz);
  117.    
  118.    double m = 0;
  119.    
  120.    int nIndex = (x*fNy + y)*fNz + z;
  121.    int aIndex = ((x*fNy + y)*fNz + z) * fDim;
  122.    
  123.    qsort(&fArray[aIndex], fN[nIndex], sizeof(float), compar);
  124.    m = fArray[aIndex + fN[nIndex]/2];
  125.    
  126.    return m;
  127. }
  128.  
  129. /*----------------------------------------------------------------*/
  130.  
  131. double Averager::RobustAverage(double range, int x, int y, int z)
  132. {
  133.    assert(x < fNx);
  134.    assert(y < fNy);
  135.    assert(z < fNz);
  136.    
  137.    double ra = 0;
  138.    int n = 0;
  139.    double m = Median(x, y, z);
  140.    
  141.    int nIndex = (x*fNy + y)*fNz + z;
  142.    int aIndex = ((x*fNy + y)*fNz + z) * fDim;
  143.    
  144.    for (int i=0 ; i<fN[nIndex] ; i++) {
  145.       if (fArray[aIndex + i] > m - range && fArray[aIndex + i] < m + range) {
  146.          ra += fArray[aIndex + i];
  147.          n++;
  148.       }
  149.    }
  150.    
  151.    if (n > 0)
  152.       ra /= n;
  153.  
  154.    //if (y == 0 && z == 7 && fN[nIndex] > 10)
  155.    //   printf("%d %lf %lf %lf\n", fN[nIndex], a, m, ra);
  156.    
  157.    return ra;
  158. }
  159.  
  160. /*----------------------------------------------------------------*/
  161.  
  162. int Averager::SaveNormalizedDistribution(const char *filename, int x, float range)
  163. {
  164.    assert(x < fNx);
  165.    FILE *f = fopen(filename, "wt");
  166.    
  167.    if (!f)
  168.       return 0;
  169.    
  170.    fprintf(f, "X, Y, Z, Min, Max, Ave, Sigma\n");
  171.    
  172.    for (int y=0 ; y<fNy ; y++)
  173.       for (int z=0 ; z<fNz ; z++) {
  174.          
  175.          int nIndex = (x*fNy + y)*fNz + z;
  176.          int aIndex = ((x*fNy + y)*fNz + z) * fDim;
  177.          
  178.          if (fN[nIndex] > 1) {
  179.             fprintf(f, "%d,%d, %d, ", x, y, z);
  180.            
  181.             double s = 0;
  182.             double s2 = 0;
  183.             double min = 0;
  184.             double max = 0;
  185.             int n = fN[nIndex];
  186.             double m = Median(x, y, z);
  187.            
  188.             for (int i=0 ; i<n ; i++) {
  189.                double v = fArray[aIndex + i] - m;
  190.                s += v;
  191.                s2 += v*v;
  192.                if (v < min)
  193.                   min = v;
  194.                if (v > max)
  195.                   max = v;
  196.             }
  197.             double sigma = sqrt((n * s2 - s * s) / (n * (n-1)));
  198.             double average = s / n;
  199.            
  200.             fprintf(f, "%3.1lf, %3.1lf, %3.1lf, %3.3lf, ", min, max, average, sigma);
  201.            
  202.             if (min < -range || max > range) {
  203.                for (int i=0 ; i<n ; i++)
  204.                   fprintf(f, "%3.1lf,", fArray[aIndex + i] - m);
  205.             }
  206.            
  207.             fprintf(f, "\n");
  208.          }
  209.       }
  210.    
  211.    fclose(f);
  212.    return 1;
  213. }
  214.  
  215.