Belle II Software  release-08-01-10
KLMClusterAnaModule.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 /* Own header. */
10 #include <klm/modules/KLMClusterAna/KLMClusterAnaModule.h>
11 
12 /* Basf2 headers. */
13 #include <framework/dataobjects/EventMetaData.h>
14 #include <framework/datastore/StoreObjPtr.h>
15 
16 /* ROOT headers. */
17 #include <TMatrixT.h>
18 #include <TMatrixDSymEigen.h>
19 #include <TVectorT.h>
20 #include <TVector3.h>
21 
22 /* C++ headers. */
23 #include <algorithm>
24 #include <cmath>
25 #include <iostream>
26 #include <numeric>
27 #include <vector>
28 
29 
30 using namespace Belle2;
31 
32 REG_MODULE(KLMClusterAna);
33 
34 
35 static double expectation(std::vector<double> vec)
36 {
37  //Note that this assumes uniform probability
38  //accumulate from <numeric>
39  return accumulate(vec.begin(), vec.end(), 0.0) / vec.size();
40 }
41 
42 static std::vector<double> addition(std::vector<double> vec1, std::vector<double> vec2)
43 {
44  std::vector<double> output(vec1.size());
45  if (vec1.size() != vec2.size()) {
46  B2ERROR("Vector lengths don't match so error. (addition)");
47  for (unsigned int i = 0; i < (unsigned int) vec1.size(); ++i) {
48  output[i] = 0.0;
49  }
50  return output;
51  }
52 
53  for (unsigned int i = 0; i < (unsigned int) vec1.size(); ++i) {
54  output[i] = vec1[i] + vec2[i];
55  }
56  return output;
57 }
58 
59 
60 
61 static std::vector<double> product(std::vector<double> vec1, std::vector<double> vec2)
62 {
63  std::vector<double> output(vec1.size());
64  if (vec1.size() != vec2.size()) {
65  B2ERROR("Vector lengths don't match so error. (product)");
66  for (unsigned int i = 0; i < (unsigned int) vec1.size(); ++i) {
67  output[i] = 0.0;
68  }
69  return output;
70  }
71 
72  for (unsigned int i = 0; i < (unsigned int) vec1.size(); ++i) {
73  output[i] = vec1[i] * vec2[i];
74  }
75  return output;
76 }
77 
78 
79 static std::vector<double> covariance_matrix3x3(std::vector<double> xcoord, std::vector<double> ycoord, std::vector<double> zcoord)
80 {
81 
82  if (xcoord.size() != ycoord.size() || (ycoord.size() != zcoord.size())) {
83  B2ERROR("Vector lengths don't match so error. (Covariance Matrix)");
84  double array[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
85  std::vector <double>output(std::begin(array), std::end(array));
86  return output;
87  }
88 
89  int length = xcoord.size();
90  double xmean = expectation(xcoord); double ymean = expectation(ycoord); double zmean = expectation(zcoord);
91  //minus sign here is purposeful
92  std::vector<double> xmeanV(length, -1 * xmean);
93  std::vector<double> ymeanV(length, -1 * ymean);
94  std::vector<double> zmeanV(length, -1 * zmean);
95 
96  std::vector<double> deltax = addition(xcoord, xmeanV);
97  std::vector<double> deltay = addition(ycoord, ymeanV);
98  std::vector<double> deltaz = addition(zcoord, zmeanV);
99 
100  double xxterm = expectation(product(deltax, deltax));
101  double xyterm = expectation(product(deltax, deltay));
102  double xzterm = expectation(product(deltax, deltaz));
103  double yyterm = expectation(product(deltay, deltay));
104  double yzterm = expectation(product(deltay, deltaz));
105  double zzterm = expectation(product(deltaz, deltaz));
106 
107  double array[] = {xxterm, xyterm, xzterm, xyterm, yyterm, yzterm, xzterm, yzterm, zzterm};
108  std::vector <double>output(std::begin(array), std::end(array));
109 
110  return output;
111 }
112 
113 
114 static TMatrixT<double> eigenvectors3x3(std::vector<double> matrix)
115 {
116  //[rows][columns]
117  TMatrixT<double> output(4, 3);
118  if (matrix.size() != 9) {
119  B2ERROR("Error! For eigenvalue3x3 calc, invalid matrix size");
120  for (int i = 0; i < 3; i++) {
121  for (int j = 0; j < 3; j++) {
122  output[i][j] = 0.0;
123  }
124  output[3][i] = 0.0;
125  }
126  return output;
127  }
128 
129  TMatrixDSym covar(3);
130  for (int i = 0; i < 9; i++) {
131  covar[i % 3][i / 3] = matrix[i];
132  }
133  const TMatrixDSymEigen eigen(covar);
134  const TVectorT<double> eigenList = eigen.GetEigenValues();
135  const TMatrixT<double> eigenvecs = eigen.GetEigenVectors();
136 
137  for (int i = 0; i < 3; i++) {
138  for (int j = 0; j < 3; j++) {
139  output[i][j] = eigenvecs[i][j];
140  }
141  output[3][i] = eigenList[i];
142  }
143  return output;
144 }
145 
146 
147 
148 
149 static TMatrixT<double> spatialVariances(std::vector<double> xcoord, std::vector<double> ycoord, std::vector<double> zcoord)
150 {
156  if (xcoord.size() != ycoord.size() || (ycoord.size() != zcoord.size())) {
157  B2FATAL("Vector lengths don't match so error.");
158  }
159  std::vector<double> covar = covariance_matrix3x3(xcoord, ycoord, zcoord);
160 
161  TMatrixT<double> output = eigenvectors3x3(covar);
162  return output;
163 }
164 
165 
166 //Code for Module
167 
169 {
170  setDescription("Module for extracting KLM cluster shape information via PCA.");
171 }
172 
174 {
175 }
176 
177 
179 {
180  m_KLMClusterShape.registerInDataStore();
181  m_KLMClusters.isRequired();
182  m_klmHit2ds.isRequired();
183  m_KLMClusters.registerRelationTo(m_KLMClusterShape);
184  m_KLMClusterShape.registerRelationTo(m_klmHit2ds);
185 }
186 
188 {
189 }
190 
192 {
193  for (KLMCluster& klmcluster : m_KLMClusters) {
194  //Obtain KLMHit2D information
195  ROOT::Math::XYZVector hitPosition;
196 
197  //Obtain KLMHit2D Information
198  RelationVector<KLMHit2d> hit2ds = klmcluster.getRelationsTo<KLMHit2d>();
199  int nHits = hit2ds.size();
200 
201  std::vector<double> xHits(nHits);
202  std::vector<double> yHits(nHits);
203  std::vector<double> zHits(nHits);
204 
205  std::vector<KLMHit2d*> klmHit2ds;
206  std::vector<KLMHit2d*>::iterator it;
207 
208  for (int i = 0; i < nHits; i++) {
209  klmHit2ds.push_back(hit2ds[i]);
210  hitPosition = hit2ds[i]->getPosition();
211  xHits[i] = (double) hitPosition.X();
212  yHits[i] = (double) hitPosition.Y();
213  zHits[i] = (double) hitPosition.Z();
214  }
215 
216 
217  KLMClusterShape* clusterShape = m_KLMClusterShape.appendNew();
218  clusterShape->setNHits(nHits);
219  if (nHits > 1) {
220 
221  //Use BKLMHit2D information to obtain relevant cluster information
222  TMatrixT<double> output = spatialVariances(xHits, yHits, zHits);
223  clusterShape->setEigen(output);
224 
225  } else {
226  //pass: just initialize and keep empty/default values
227  }
228 
229  klmcluster.addRelationTo(clusterShape);
230 
231  for (it = klmHit2ds.begin(); it != klmHit2ds.end(); ++it) {
232  clusterShape->addRelationTo(*it);
233  }
234 
235  }
236 
237 }
238 
239 
void initialize() override
Initializer.
void event() override
This method is called for each event.
StoreArray< KLMClusterShape > m_KLMClusterShape
Output per cluster.
void beginRun() override
Called when entering a new run.
StoreArray< KLMHit2d > m_klmHit2ds
Two-dimensional hits.
StoreArray< KLMCluster > m_KLMClusters
KLM clusters.
Variable for KLM cluster shape analysis.
void setEigen(TMatrixT< double > eigenList)
Set eigenvectors and eigenvalues.
void setNHits(int nHits)
Set number of hits.
KLM cluster data.
Definition: KLMCluster.h:28
KLM 2d hit.
Definition: KLMHit2d.h:33
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
REG_MODULE(arichBtest)
Register the Module.
Abstract base class for different kinds of events.