Belle II Software  release-06-02-00
Cluster.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <mdst/dataobjects/Cluster.h>
10 #include <framework/logging/Logger.h>
11 
12 #include <cmath>
13 #include <iostream>
14 #include <iomanip>
15 
16 using namespace std;
17 using namespace Belle2;
18 
19 Cluster::Cluster()
20 {
21  for (unsigned short i = 0; i < Const::ClusterDetectors::c_size; i++) {
22  for (unsigned int k = 0; k < Const::Cluster::c_SetSize; k++) {
23  m_logl[i][k] = 0.0;
24  }
25  }
26 }
27 
28 
29 void Cluster::setLogLikelihood(Const::EDetector det,
30  const Const::Cluster& part,
31  float logl)
32 {
33  int index = Const::ClusterDetectors::set().getIndex(det);
34  if (index < 0) {
35  B2ERROR("ClusterLikelihood::setLogLikelihood: detector is not a cluster device");
36  return;
37  }
38  if (logl != logl or logl == INFINITY) {
39  B2ERROR("ClusterLikelihood::setLogLikelihood: log-likelihood for detector " << det << " is " << logl <<
40  " (i.e. +inf or NaN)! Ignoring this value. (" << Const::ECL << "=ECL, " << Const::KLM << "=KLM");
41 
42  return;
43  }
44  m_detectors += det;
45  m_logl[index][part.getIndex()] = logl;
46 }
47 
48 
49 float Cluster::getLogL(const Const::Cluster& cluster,
50  Const::ClusterDetectorSet set) const
51 {
52  float result = 0;
53  for (unsigned int index = 0; index < Const::ClusterDetectorSet::set().size(); ++index) {
54  if (set.contains(Const::ClusterDetectorSet::set()[index]))
55  result += m_logl[index][cluster.getIndex()];
56  }
57  return result;
58 }
59 
60 
61 Double32_t Cluster::getProbability(const Const::Cluster& c1,
62  const Const::Cluster& c2,
63  double ratio,
64  Const::ClusterDetectorSet set) const
65 {
66  if (ratio < 0) {
67  B2ERROR("Cluster::probability argument 'ratio' is given with negative value");
68  return 0;
69  }
70  if (ratio == 0) return 0;
71 
72  double dlogl = getLogL(c2, set) - getLogL(c1, set);
73  double res;
74  if (dlogl < 0) {
75  double elogl = exp(dlogl);
76  res = ratio / (ratio + elogl);
77  } else {
78  double elogl = exp(-dlogl) * ratio; // to prevent overflow for very large dlogl
79  res = elogl / (1.0 + elogl);
80  }
81  //TODO: only necessary if one wants to use mcprod1405 MC sample. Remove when there's a good replacement.
82  if (std::isfinite(res))
83  return res;
84  return 0.0;
85 }
86 
87 double Cluster::getProbability(const Const::Cluster& cluster,
88  const double* fractions,
89  Const::ClusterDetectorSet detSet) const
90 {
91  double prob[Const::Cluster::c_SetSize];
92  probability(prob, fractions, detSet);
93 
94  int k = cluster.getIndex();
95  if (k < 0) return 0;
96 
97  return prob[k];
98 
99 }
100 
101 Const::Cluster Cluster::getMostLikely(const double* fractions,
102  Const::ClusterDetectorSet detSet) const
103 {
104  const unsigned int n = Const::Cluster::c_SetSize;
105  double prob[n];
106  probability(prob, fractions, detSet);
107 
108  int k = 0;
109  double maxProb = prob[k];
110  for (unsigned i = 0; i < n; ++i) {
111  if (prob[i] > maxProb) {maxProb = prob[i]; k = i;}
112  }
113  return Const::clusterSet.at(k);
114 
115 }
116 
117 
118 void Cluster::probability(double probabilities[],
119  const double* fractions,
120  Const::ClusterDetectorSet detSet) const
121 {
122  const unsigned int n = Const::Cluster::c_SetSize;
123  double frac[n];
124  if (!fractions) {
125  for (unsigned int i = 0; i < n; ++i) frac[i] = 1.0; // normalization not needed
126  fractions = frac;
127  }
128 
129  double logL[n];
130  double logLmax = 0;
131  bool hasMax = false;
132  for (unsigned i = 0; i < n; ++i) {
133  logL[i] = 0;
134  if (fractions[i] > 0) {
135  logL[i] = getLogL(Const::clusterSet.at(i), detSet);
136  if (!hasMax || logL[i] > logLmax) {
137  logLmax = logL[i];
138  hasMax = true;
139  }
140  }
141  }
142 
143  double norm = 0;
144  for (unsigned i = 0; i < n; ++i) {
145  probabilities[i] = 0;
146  if (fractions[i] > 0) probabilities[i] = exp(logL[i] - logLmax) * fractions[i];
147  norm += probabilities[i];
148  }
149  if (norm == 0) return;
150 
151  for (unsigned i = 0; i < n; ++i) {
152  probabilities[i] /= norm;
153  }
154 
155 }
156 
157 
158 void Cluster::printArray() const
159 {
160 
161  string detectorName[Const::ClusterDetectors::c_size] = {"ECL", "KLM"};
162  string hline("-------");
163  for (unsigned i = 0; i < Const::Cluster::c_SetSize; i++)
164  hline += "-----------";
165  string Hline("=======");
166  for (unsigned i = 0; i < Const::Cluster::c_SetSize; i++)
167  Hline += "===========";
168 
169  cout << Hline << endl;
170 
171  cout << "PDGcode";
172  for (unsigned i = 0; i < Const::Cluster::c_SetSize; i++)
173  cout << setw(10) << Const::clusterSet.at(i).getPDGCode() << " ";
174  cout << endl;
175 
176  cout << Hline << endl;
177 
178  float sum_logl[Const::Cluster::c_SetSize];
179  for (unsigned i = 0; i < Const::Cluster::c_SetSize; i++) sum_logl[i] = 0;
180 
181  for (unsigned k = 0; k < Const::ClusterDetectors::c_size; k++) {
182  cout << setw(7) << detectorName[k];
183  for (unsigned i = 0; i < Const::Cluster::c_SetSize; i++) {
184  cout << setw(10) << setprecision(4) << m_logl[k][i] << " ";
185  sum_logl[i] += m_logl[k][i];
186  }
187  cout << endl;
188  }
189 
190  cout << hline << endl;
191 
192  cout << setw(7) << "sum";
193  for (unsigned i = 0; i < Const::Cluster::c_SetSize; i++)
194  cout << setw(10) << setprecision(4) << sum_logl[i] << " ";
195  cout << endl;
196 
197  if (isAvailable(Const::ECL) or isAvailable(Const::KLM)) {
198  unsigned k = 0;
199  for (unsigned i = 0; i < Const::Cluster::c_SetSize; i++)
200  if (sum_logl[i] > sum_logl[k]) k = i;
201  unsigned pos = 11 * (k + 1) + 3;
202  Hline.replace(pos, 1, "^");
203  }
204  cout << Hline << endl;
205 
206 }
207 
208 std::string Cluster::getInfoHTML() const
209 {
210  string detectorName[Const::ClusterDetectors::c_size] = {"ECL", "KLM"};
211 
212  std::stringstream stream;
213  stream << std::setprecision(4);
214  stream << "<b>Likelihoods</b><br>";
215  stream << "<table>";
216  stream << "<tr><th>Cluster / Detector</th>";
217  for (unsigned k = 0; k < Const::ClusterDetectors::c_size; k++)
218  stream << "<th>" << detectorName[k] << "</th>";
219  stream << "</tr>";
220  for (unsigned i = 0; i < Const::Cluster::c_SetSize; i++) {
221  stream << "<tr>";
222  stream << "<td>" << Const::clusterSet.at(i).getPDGCode() << "</td>";
223  for (unsigned k = 0; k < Const::ClusterDetectors::c_size; k++) {
224  stream << "<td>" << m_logl[k][i] << "</td>";
225  }
226  stream << "</tr>";
227  }
228  stream << "</table>";
229  stream << "<br>";
230 
231  return stream.str();
232 }
233 
234 
Provides a type-safe way to pass members of the clusterSet set.
Definition: Const.h:507
bool contains(const DetectorSet &set) const
Check whether this set contains another set.
Definition: Const.h:121
A class for sets of detector IDs whose content is limited to restricted set of valid detector IDs.
Definition: Const.h:177
EDetector
Enum for identifying the detector components (detector and subdetector).
Definition: Const.h:42
Abstract base class for different kinds of events.