All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sbncode/sbncode/SinglePhotonAnalysis/Libraries/TruncMean.cxx
Go to the documentation of this file.
2 
3 namespace single_photon
4 {
5 
6  double TruncMean::CalcIterativeTruncMean(std::vector<double> v, const size_t& nmin,
7  const size_t& nmax, const size_t& currentiteration,
8  const size_t& lmin,
9  const double& convergencelimit,
10  const double& nsigma, const double& oldmed)
11  {
12 
13  auto const& mean = Mean(v);
14  auto const& med = Median(v);
15  auto const& rms = RMS(v);
16 
17  // if the vector length is below the lower limit -> return
18  if (v.size() < lmin)
19  return mean;
20 
21  // if we have passed the maximum number of iterations -> return
22  if (currentiteration >= nmax)
23  return mean;
24 
25  // if we passed the minimum number of iterations and the mean is close enough to the old value
26  double fracdiff = fabs(med-oldmed) / oldmed;
27  if ( (currentiteration >= nmin) && (fracdiff < convergencelimit) )
28  return mean;
29 
30  // if reached here it means we have to go on for another iteration
31 
32  // cutoff tails of distribution surrounding the mean
33  // use erase-remove : https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
34  // https://stackoverflow.com/questions/17270837/stdvector-removing-elements-which-fulfill-some-conditions
35  v.erase( std::remove_if( v.begin(), v.end(),
36  [med,nsigma,rms](const double& x) { return ( (x < (med-nsigma*rms)) || (x > (med+nsigma*rms)) ); }), // lamdda condition for events to be removed
37  v.end());
38 
39  return CalcIterativeTruncMean(v, nmin, nmax, lmin, currentiteration+1, convergencelimit, nsigma, med);
40  }
41 
42  void TruncMean::CalcTruncMeanProfile(const std::vector<double>& rr_v, const std::vector<double>& dq_v,
43  std::vector<double>& dq_trunc_v, const double& nsigma)
44  {
45 
46  // how many points to sample
47  int Nneighbor = (int)(_rad * 3 * 2);
48 
49  dq_trunc_v.clear();
50  dq_trunc_v.reserve( rr_v.size() );
51 
52  int Nmax = dq_v.size()-1;
53 
54  for (size_t n=0; n < dq_v.size(); n++) { // rr_v and dq_v have the same size
55 
56  // current residual range
57  double rr = rr_v.at(n);
58 
59  int nmin = n - Nneighbor;
60  int nmax = n + Nneighbor;
61 
62  if (nmin < 0) nmin = 0;
63  if (nmax > Nmax) nmax = Nmax;
64 
65  // vector for local dq values
66  std::vector<double> dq_local_v;
67 
68  for (int i=nmin; i < nmax; i++) {
69 
70  double dr = rr - rr_v[i];
71  if (dr < 0) dr *= -1;
72 
73  if (dr > _rad) continue;
74 
75  dq_local_v.push_back( dq_v[i] ); //save for ticks that are close enough
76 
77  }// for all ticks we want to scan
78 
79  if (dq_local_v.size() == 0 ) {
80  dq_trunc_v.push_back( dq_v.at(n) ); // if no neighbours, push back dq of itself
81  continue;
82  }
83 
84  // calculate median and rms
85  double median = Median(dq_local_v);
86  double rms = RMS(dq_local_v);
87 
88  double truncated_dq = 0.;
89  int npts = 0;
90  for (auto const& dq : dq_local_v) {
91  if ( ( dq < (median+rms * nsigma) ) && ( dq > (median-rms * nsigma) ) ){
92  truncated_dq += dq;
93  npts += 1;
94  }
95  }
96 
97  dq_trunc_v.push_back( truncated_dq / npts ); // push back averaged dq for these sitting within nsigma
98 
99  if(dq_trunc_v.back() != dq_trunc_v.back()){
100  std::cout<<"ERROR::TruncMean.cxx || NAN "<<dq_trunc_v.back()<<std::endl;
101  std::cout<<"truncated_dq: "<<truncated_dq<<std::endl;
102  std::cout<<"npts: "<<npts<<std::endl;
103  std::cout<<"median: "<<median<<std::endl;
104  std::cout<<"rms: "<<rms<<std::endl;
105  }
106 
107  }// for all values
108 
109  return;
110  }
111 
112  double TruncMean::Mean(const std::vector<double>& v)
113  {
114 
115  double mean = 0.;
116  for (auto const& n : v) mean += n;
117  mean /= v.size();
118 
119  return mean;
120  }
121 
122  double TruncMean::Median(const std::vector<double>& v)
123  {
124 
125  if (v.size() == 1) return v[0];
126 
127  std::vector<double> vcpy = v;
128 
129  std::sort(vcpy.begin(), vcpy.end()); //sort to ascending order
130 
131  double median = vcpy[ vcpy.size() / 2 ]; // what if v has even # of elements? there is a choice
132 
133  return median;
134  }
135 
136  double TruncMean::RMS(const std::vector<double>& v)
137  {
138 
139  if(v.size()==1) return v.front();
140 
141  double avg = 0.;
142  for (auto const& val : v) avg += val;
143  avg /= v.size();
144  double rms = 0.;
145  for (auto const& val : v) rms += (val-avg)*(val-avg);
146  rms = sqrt( rms / ( v.size() - 1 ) );
147 
148 
149  if(rms!=rms){
150  std::cout<<"ERROR || TruncMean::RMS || is returning nan."<<std::endl;
151  std::cout<<"ERROR || TruncMean::RMS || "<<rms<<std::endl;
152  std::cout<<"ERROR || TruncMean::RMS || Input is of size "<<v.size()<<std::endl;
153  for(auto const &val : v){
154  std::cout<<"ERROR || TruncMean::RMS || "<<val<<std::endl;
155  }
156  std::cout<<"ERROR || TruncMean::RMS || Most likely because your radius is too small! "<<v.size()<<std::endl;
157  }
158 
159  return rms;
160  }
161 
162 }
process_name opflash particleana ie x
void CalcTruncMeanProfile(const std::vector< double > &rr_v, const std::vector< double > &dq_v, std::vector< double > &dq_trunc_v, const double &nsigma=1)
Given residual range and dq vectors return truncated local dq. Input vectors are assumed to be match ...
double CalcIterativeTruncMean(std::vector< double > v, const size_t &nmin, const size_t &nmax, const size_t &currentiteration, const size_t &lmin, const double &convergencelimit, const double &nsigma, const double &oldmed=kINVALID_FLOAT)
Iteratively calculate the truncated mean of a distribution.
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
Definition: UtilFunc.cxx:13
BEGIN_PROLOG could also be cout