Belle II Software development
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
21/* C++ headers. */
22#include <algorithm>
23#include <cmath>
24#include <iostream>
25#include <numeric>
26#include <vector>
27
28
29using namespace Belle2;
30
31REG_MODULE(KLMClusterAna);
32
33
34static double expectation(std::vector<double> vec)
35{
36 //Note that this assumes uniform probability
37 //accumulate from <numeric>
38 return accumulate(vec.begin(), vec.end(), 0.0) / vec.size();
39}
40
41static std::vector<double> addition(std::vector<double> vec1, std::vector<double> vec2)
42{
43 std::vector<double> output(vec1.size());
44 if (vec1.size() != vec2.size()) {
45 B2ERROR("Vector lengths don't match so error. (addition)");
46 for (unsigned int i = 0; i < (unsigned int) vec1.size(); ++i) {
47 output[i] = 0.0;
48 }
49 return output;
50 }
51
52 for (unsigned int i = 0; i < (unsigned int) vec1.size(); ++i) {
53 output[i] = vec1[i] + vec2[i];
54 }
55 return output;
56}
57
58
59
60static std::vector<double> product(std::vector<double> vec1, std::vector<double> vec2)
61{
62 std::vector<double> output(vec1.size());
63 if (vec1.size() != vec2.size()) {
64 B2ERROR("Vector lengths don't match so error. (product)");
65 for (unsigned int i = 0; i < (unsigned int) vec1.size(); ++i) {
66 output[i] = 0.0;
67 }
68 return output;
69 }
70
71 for (unsigned int i = 0; i < (unsigned int) vec1.size(); ++i) {
72 output[i] = vec1[i] * vec2[i];
73 }
74 return output;
75}
76
77
78static std::vector<double> covariance_matrix3x3(std::vector<double> xcoord, std::vector<double> ycoord, std::vector<double> zcoord)
79{
80
81 if (xcoord.size() != ycoord.size() || (ycoord.size() != zcoord.size())) {
82 B2ERROR("Vector lengths don't match so error. (Covariance Matrix)");
83 double array[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
84 std::vector <double>output(std::begin(array), std::end(array));
85 return output;
86 }
87
88 int length = xcoord.size();
89 double xmean = expectation(xcoord); double ymean = expectation(ycoord); double zmean = expectation(zcoord);
90 //minus sign here is purposeful
91 std::vector<double> xmeanV(length, -1 * xmean);
92 std::vector<double> ymeanV(length, -1 * ymean);
93 std::vector<double> zmeanV(length, -1 * zmean);
94
95 std::vector<double> deltax = addition(xcoord, xmeanV);
96 std::vector<double> deltay = addition(ycoord, ymeanV);
97 std::vector<double> deltaz = addition(zcoord, zmeanV);
98
99 double xxterm = expectation(product(deltax, deltax));
100 double xyterm = expectation(product(deltax, deltay));
101 double xzterm = expectation(product(deltax, deltaz));
102 double yyterm = expectation(product(deltay, deltay));
103 double yzterm = expectation(product(deltay, deltaz));
104 double zzterm = expectation(product(deltaz, deltaz));
105
106 double array[] = {xxterm, xyterm, xzterm, xyterm, yyterm, yzterm, xzterm, yzterm, zzterm};
107 std::vector <double>output(std::begin(array), std::end(array));
108
109 return output;
110}
111
112
113static TMatrixT<double> eigenvectors3x3(std::vector<double> matrix)
114{
115 //[rows][columns]
116 TMatrixT<double> output(4, 3);
117 if (matrix.size() != 9) {
118 B2ERROR("Error! For eigenvalue3x3 calc, invalid matrix size");
119 for (int i = 0; i < 3; i++) {
120 for (int j = 0; j < 3; j++) {
121 output[i][j] = 0.0;
122 }
123 output[3][i] = 0.0;
124 }
125 return output;
126 }
127
128 TMatrixDSym covar(3);
129 for (int i = 0; i < 9; i++) {
130 covar[i % 3][i / 3] = matrix[i];
131 }
132 const TMatrixDSymEigen eigen(covar);
133 const TVectorT<double> eigenList = eigen.GetEigenValues();
134 const TMatrixT<double> eigenvecs = eigen.GetEigenVectors();
135
136 for (int i = 0; i < 3; i++) {
137 for (int j = 0; j < 3; j++) {
138 output[i][j] = eigenvecs[i][j];
139 }
140 output[3][i] = eigenList[i];
141 }
142 return output;
143}
144
145
146
147
148static TMatrixT<double> spatialVariances(std::vector<double> xcoord, std::vector<double> ycoord, std::vector<double> zcoord)
149{
155 if (xcoord.size() != ycoord.size() || (ycoord.size() != zcoord.size())) {
156 B2FATAL("Vector lengths don't match so error.");
157 }
158 std::vector<double> covar = covariance_matrix3x3(xcoord, ycoord, zcoord);
159
160 TMatrixT<double> output = eigenvectors3x3(covar);
161 return output;
162}
163
164
165//Code for Module
166
168{
169 setDescription("Module for extracting KLM cluster shape information via PCA.");
170}
171
173{
174}
175
176
178{
179 m_KLMClusterShape.registerInDataStore();
180 m_KLMClusters.isRequired();
181 m_klmHit2ds.isRequired();
182 m_KLMClusters.registerRelationTo(m_KLMClusterShape);
183 m_KLMClusterShape.registerRelationTo(m_klmHit2ds);
184}
185
187{
188}
189
191{
192 for (KLMCluster& klmcluster : m_KLMClusters) {
193 //Obtain KLMHit2D information
194 ROOT::Math::XYZVector hitPosition;
195
196 //Obtain KLMHit2D Information
197 RelationVector<KLMHit2d> hit2ds = klmcluster.getRelationsTo<KLMHit2d>();
198 int nHits = hit2ds.size();
199
200 std::vector<double> xHits(nHits);
201 std::vector<double> yHits(nHits);
202 std::vector<double> zHits(nHits);
203
204 std::vector<KLMHit2d*> klmHit2ds;
205
206 for (int i = 0; i < nHits; i++) {
207 klmHit2ds.push_back(hit2ds[i]);
208 hitPosition = hit2ds[i]->getPosition();
209 xHits[i] = (double) hitPosition.X();
210 yHits[i] = (double) hitPosition.Y();
211 zHits[i] = (double) hitPosition.Z();
212 }
213
214
215 KLMClusterShape* clusterShape = m_KLMClusterShape.appendNew();
216 clusterShape->setNHits(nHits);
217 if (nHits > 1) {
218
219 //Use BKLMHit2D information to obtain relevant cluster information
220 TMatrixT<double> output = spatialVariances(xHits, yHits, zHits);
221 clusterShape->setEigen(output);
222
223 } else {
224 //pass: just initialize and keep empty/default values
225 }
226
227 klmcluster.addRelationTo(clusterShape);
228
229 for (const KLMHit2d* hit2d : klmHit2ds) {
230 clusterShape->addRelationTo(hit2d);
231 }
232
233 }
234
235}
236
237
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).
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.