10#include <klm/modules/KLMClusterAna/KLMClusterAnaModule.h>
13#include <framework/dataobjects/EventMetaData.h>
14#include <framework/datastore/StoreObjPtr.h>
18#include <TMatrixDSymEigen.h>
34static double expectation(std::vector<double> vec)
38 return accumulate(vec.begin(), vec.end(), 0.0) / vec.size();
41static std::vector<double> addition(
const std::vector<double>& vec1,
const std::vector<double>& vec2)
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) {
52 for (
unsigned int i = 0; i < (
unsigned int) vec1.size(); ++i) {
53 output[i] = vec1[i] + vec2[i];
60static std::vector<double> product(
const std::vector<double>& vec1,
const std::vector<double>& vec2)
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) {
71 for (
unsigned int i = 0; i < (
unsigned int) vec1.size(); ++i) {
72 output[i] = vec1[i] * vec2[i];
78static std::vector<double> covariance_matrix3x3(
const std::vector<double>& xcoord,
const std::vector<double>& ycoord,
79 const std::vector<double>& zcoord)
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));
89 int length = xcoord.size();
90 double xmean = expectation(xcoord);
double ymean = expectation(ycoord);
double zmean = expectation(zcoord);
92 std::vector<double> xmeanV(length, -1 * xmean);
93 std::vector<double> ymeanV(length, -1 * ymean);
94 std::vector<double> zmeanV(length, -1 * zmean);
96 std::vector<double> deltax = addition(xcoord, xmeanV);
97 std::vector<double> deltay = addition(ycoord, ymeanV);
98 std::vector<double> deltaz = addition(zcoord, zmeanV);
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));
107 const double array[] = {xxterm, xyterm, xzterm, xyterm, yyterm, yzterm, xzterm, yzterm, zzterm};
108 std::vector <double>output(std::begin(array), std::end(array));
114static TMatrixT<double> eigenvectors3x3(
const std::vector<double>& matrix)
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++) {
129 TMatrixDSym covar(3);
130 for (
int i = 0; i < 9; i++) {
131 covar[i % 3][i / 3] = matrix[i];
133 const TMatrixDSymEigen eigen(covar);
134 const TVectorT<double> eigenList = eigen.GetEigenValues();
135 const TMatrixT<double> eigenvecs = eigen.GetEigenVectors();
137 for (
int i = 0; i < 3; i++) {
138 for (
int j = 0; j < 3; j++) {
139 output[i][j] = eigenvecs[i][j];
141 output[3][i] = eigenList[i];
149static TMatrixT<double> spatialVariances(
const std::vector<double>& xcoord,
const std::vector<double>& ycoord,
150 const std::vector<double>& zcoord)
157 if (xcoord.size() != ycoord.size() || (ycoord.size() != zcoord.size())) {
158 B2FATAL(
"Vector lengths don't match so error.");
160 std::vector<double> covar = covariance_matrix3x3(xcoord, ycoord, zcoord);
162 TMatrixT<double> output = eigenvectors3x3(covar);
171 setDescription(
"Module for extracting KLM cluster shape information via PCA.");
194 ROOT::Math::XYZVector hitPosition;
198 int nHits = hit2ds.
size();
200 std::vector<double> xHits(nHits);
201 std::vector<double> yHits(nHits);
202 std::vector<double> zHits(nHits);
204 std::vector<KLMHit2d*> klmHit2ds;
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();
220 TMatrixT<double> output = spatialVariances(xHits, yHits, zHits);
227 klmcluster.addRelationTo(clusterShape);
229 for (
const KLMHit2d* hit2d : klmHit2ds) {
234 klmcluster.setShapeStdDev1(0);
235 klmcluster.setShapeStdDev2(0);
236 klmcluster.setShapeStdDev3(0);
void initialize() override
Initializer.
void event() override
This method is called for each event.
KLMClusterAnaModule()
Constructor.
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.
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
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.
double sqrt(double a)
sqrt for double
Abstract base class for different kinds of events.