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{
154
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
172}
173
177
178
180{
181 m_KLMClusterShape.registerInDataStore();
182 m_KLMClusters.isRequired();
183 m_klmHit2ds.isRequired();
184 m_KLMClusters.registerRelationTo(m_KLMClusterShape);
185 m_KLMClusterShape.registerRelationTo(m_klmHit2ds);
186}
187
191
193{
194 for (KLMCluster& klmcluster : m_KLMClusters) {
195 //Obtain KLMHit2D information
196 ROOT::Math::XYZVector hitPosition;
197
198 //Obtain KLMHit2D Information
199 RelationVector<KLMHit2d> hit2ds = klmcluster.getRelationsTo<KLMHit2d>();
200 int nHits = hit2ds.size();
201
202 std::vector<double> xHits(nHits);
203 std::vector<double> yHits(nHits);
204 std::vector<double> zHits(nHits);
205
206 std::vector<KLMHit2d*> klmHit2ds;
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 (const KLMHit2d* hit2d : klmHit2ds) {
232 clusterShape->addRelationTo(hit2d);
233 }
234 // Fill relevant KLMCluster data members
235 if (nHits == 1) {
236 klmcluster.setShapeStdDev1(0);
237 klmcluster.setShapeStdDev2(0);
238 klmcluster.setShapeStdDev3(0);
239 } else {
240 klmcluster.setShapeStdDev1(sqrt(clusterShape->getVariance1()));
241 klmcluster.setShapeStdDev2(sqrt(clusterShape->getVariance2()));
242 klmcluster.setShapeStdDev3(sqrt(clusterShape->getVariance3()));
243 }
244 }
245}
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.
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).
STL class.
#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.