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(const std::vector<double>& vec1, const 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(const std::vector<double>& vec1, const 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(const std::vector<double>& xcoord, const std::vector<double>& ycoord,
79 const 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 const 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 const 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
114static TMatrixT<double> eigenvectors3x3(const 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
149static TMatrixT<double> spatialVariances(const std::vector<double>& xcoord, const std::vector<double>& ycoord,
150 const std::vector<double>& zcoord)
151{
156
157 if (xcoord.size() != ycoord.size() || (ycoord.size() != zcoord.size())) {
158 B2FATAL("Vector lengths don't match so error.");
159 }
160 std::vector<double> covar = covariance_matrix3x3(xcoord, ycoord, zcoord);
161
162 TMatrixT<double> output = eigenvectors3x3(covar);
163 return output;
164}
165
166
167//Code for Module
168
170{
171 setDescription("Module for extracting KLM cluster shape information via PCA.");
172
174}
175
179
180
182{
183 m_KLMClusterShape.registerInDataStore();
184 m_KLMClusters.isRequired();
185 m_klmHit2ds.isRequired();
186 m_KLMClusters.registerRelationTo(m_KLMClusterShape);
187 m_KLMClusterShape.registerRelationTo(m_klmHit2ds);
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 // Fill relevant KLMCluster data members
233 if (nHits == 1) {
234 klmcluster.setShapeStdDev1(0);
235 klmcluster.setShapeStdDev2(0);
236 klmcluster.setShapeStdDev3(0);
237 } else {
238 klmcluster.setShapeStdDev1(sqrt(clusterShape->getVariance1()));
239 klmcluster.setShapeStdDev2(sqrt(clusterShape->getVariance2()));
240 klmcluster.setShapeStdDev3(sqrt(clusterShape->getVariance3()));
241 }
242 }
243}
void initialize() override
Initializer.
void event() override
This method is called for each event.
StoreArray< KLMClusterShape > m_KLMClusterShape
Output per cluster.
~KLMClusterAnaModule() override
Destructor.
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.
double getVariance1() const
Get principal axis eigenvector.
double getVariance3() const
Get tertiary axis eigenvector.
double getVariance2() const
Get secondary axis eigenvector.
KLM cluster data.
Definition KLMCluster.h:29
KLM 2d hit.
Definition KLMHit2d.h:33
void setDescription(const std::string &description)
Sets the description of the module.
Definition Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition Module.cc:208
Module()
Constructor.
Definition Module.cc:30
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition Module.h:80
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:649
double sqrt(double a)
sqrt for double
Definition beamHelpers.h:28
Abstract base class for different kinds of events.