11 #include <pxd/calibration/PXDClusterPositionCalibrationAlgorithm.h>
16 #include "TMatrixDSym.h"
18 #include "TMatrixDSymEigen.h"
20 #include <boost/format.hpp>
27 PXDClusterPositionCalibrationAlgorithm::PXDClusterPositionCalibrationAlgorithm():
29 minClusterForShapeLikelyhood(500), minClusterForPositionOffset(2000), maxEtaBins(10),
31 m_clusterEta(0), m_positionOffsetU(0), m_positionOffsetV(0), m_sizeV(0),
32 m_pitchV(0), m_clusterKind(0)
35 " -------------------------- PXDClusterPositionCalibrationAlgorithm ----------------------\n"
37 " Algorithm for estimating cluster position offsets and shape likelyhoods. \n"
38 " ----------------------------------------------------------------------------------------\n"
47 auto pitchtree = getObjectPtr<TTree>(
"pitchtree");
48 pitchtree->SetBranchAddress(
"PitchV", &
m_pitchV);
51 for (
int i = 0; i < pitchtree->GetEntries(); ++i) {
52 pitchtree->GetEntry(i);
58 typedef tuple<int, int, int> bufferkey_t;
59 typedef pair<PXDClusterShapeIndexPar, PXDClusterShapeClassifierPar> buffervalue_t;
60 map<bufferkey_t, buffervalue_t> localCalibrationMap;
64 B2INFO(
"Start calibration of clusterkind=" << clusterKind <<
" ...");
66 string gridname = str(format(
"GridKind_%1%") % clusterKind);
67 auto grid = getObjectPtr<TH2F>(gridname);
69 for (
auto uBin = 1; uBin <= grid->GetXaxis()->GetNbins(); uBin++) {
70 for (
auto vBin = 1; vBin <= grid->GetYaxis()->GetNbins(); vBin++) {
73 auto thetaU = grid->GetXaxis()->GetBinCenter(uBin);
74 auto thetaV = grid->GetYaxis()->GetBinCenter(vBin);
77 B2INFO(
"Skip training estimator on thetaU=" << thetaU <<
", thetaV=" << thetaV);
80 B2INFO(
"Start training estimator on thetaU=" << thetaU <<
", thetaV=" << thetaV);
83 string treename = str(format(
"tree_%1%_%2%_%3%") % clusterKind % uBin % vBin);
89 bufferkey_t key = std::make_tuple(clusterKind, uBin, vBin);
90 localCalibrationMap[key] = buffervalue_t(localShapeIndexer , localShapeClassifier);
98 int globalShapeIndex = 0;
100 shapeIndexer->
addShape(*it, globalShapeIndex);
104 B2INFO(
"Number of cluster shapes is " << globalShapeIndex);
114 string gridname = str(format(
"GridKind_%1%") % clusterKind);
115 auto grid = getObjectPtr<TH2F>(gridname);
117 positionEstimator->
addGrid(clusterKind, *grid);
119 for (
auto uBin = 1; uBin <= grid->GetXaxis()->GetNbins(); uBin++) {
120 for (
auto vBin = 1; vBin <= grid->GetYaxis()->GetNbins(); vBin++) {
123 auto thetaU = grid->GetXaxis()->GetBinCenter(uBin);
124 auto thetaV = grid->GetYaxis()->GetBinCenter(vBin);
132 auto iter = localCalibrationMap.find(std::make_tuple(clusterKind, uBin, vBin));
133 auto localShapeIndexer = iter->second.first;
134 auto localShapeClassifer = iter->second.second;
137 auto shapeClassifier =
localToGlobal(&localShapeClassifer, &localShapeIndexer, shapeIndexer);
140 auto mirror_vBin = grid->GetYaxis()->FindBin(-thetaV);
144 B2INFO(
"Add shape classifier for angles thetaU=" << thetaU <<
", thetaV=" << thetaV <<
", clusterkind=" << clusterKind);
146 B2INFO(
"Add mirrored shape classifier for angles thetaU=" << thetaU <<
", thetaV=" << -thetaV <<
", clusterkind=" << clusterKind);
147 positionEstimator->
setShapeClassifier(mirroredClassifier, uBin, mirror_vBin, clusterKind);
155 B2INFO(
"PXDClusterPosition Calibration Successful");
168 for (
auto indexAndValue : shapeLikelyhoodMap) {
170 auto shapeIndex = indexAndValue.first;
171 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
173 auto mirroredIndex = shapeIndexer->
getShapeIndex(mirroredName);
175 mirroredShapeClassifier.addShapeLikelyhood(mirroredIndex, indexAndValue.second);
182 for (
auto indexAndValue : offsetMap) {
184 auto shapeIndex = indexAndValue.first;
185 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
187 auto mirroredIndex = shapeIndexer->
getShapeIndex(mirroredName);
189 mirroredShapeClassifier.addShape(mirroredIndex);
192 for (
auto offset : indexAndValue.second) {
194 auto percentile = percentileMap[shapeIndex][etaBin];
195 mirroredShapeClassifier.addEtaPercentile(mirroredIndex, percentile);
197 auto likelyhood = likelyhoodMap[shapeIndex][etaBin];
198 mirroredShapeClassifier.addEtaLikelyhood(mirroredIndex, likelyhood);
201 auto mirroredOffset =
PXDClusterOffsetPar(offset.getU(), shift - offset.getV(), offset.getUSigma2(), offset.getVSigma2(),
202 -offset.getUVCovariance());
203 mirroredShapeClassifier.addEtaOffset(mirroredIndex, mirroredOffset);
208 return mirroredShapeClassifier;
219 for (
auto indexAndValue : shapeLikelyhoodMap) {
221 auto shapeIndex = indexAndValue.first;
222 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
223 auto globalIndex = globalShapeIndexer->
getShapeIndex(shapeName);
225 globalShapeClassifier.addShapeLikelyhood(globalIndex, indexAndValue.second);
232 for (
auto indexAndValue : offsetMap) {
234 auto shapeIndex = indexAndValue.first;
235 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
236 auto globalIndex = globalShapeIndexer->
getShapeIndex(shapeName);
238 globalShapeClassifier.addShape(globalIndex);
241 for (
auto offset : indexAndValue.second) {
243 auto percentile = percentileMap[shapeIndex][etaBin];
244 globalShapeClassifier.addEtaPercentile(globalIndex, percentile);
246 auto likelyhood = likelyhoodMap[shapeIndex][etaBin];
247 globalShapeClassifier.addEtaLikelyhood(globalIndex, likelyhood);
249 globalShapeClassifier.addEtaOffset(globalIndex, offset);
253 return globalShapeClassifier;
260 auto tree = getObjectPtr<TTree>(treename);
262 const auto nEntries = tree->GetEntries();
263 B2INFO(
"Number of clusters is " << nEntries);
268 tree->SetBranchAddress(
"ShapeName", &shapeNamePtr);
269 tree->SetBranchAddress(
"MirroredShapeName", &mirroredShapeNamePtr);
273 tree->SetBranchAddress(
"SizeV", &
m_sizeV);
277 vector< pair<string, float> > shapeList;
279 for (
int i = 0; i < nEntries; ++i) {
284 auto it = std::find_if(shapeList.begin(), shapeList.end(),
285 [&](
const pair<string, float>& element) { return element.first == shapeName;});
288 if (it != shapeList.end()) {
295 shapeList.push_back(pair<string, int>(shapeName, 1));
307 vector< pair<string, TH1D> > etaHistos;
313 double coverage = 0.0;
315 for (
auto iter : shapeList) {
316 auto name = iter.first;
317 auto counter = iter.second;
319 double likelyhood = counter / nEntries;
323 shapeIndexer->
addShape(name, tmpIndex);
335 coverage += likelyhood;
336 string etaname = str(format(
"eta_%1%") % name);
339 if (name ==
"SD0.0") {
340 TH1D etaHisto(etaname.c_str(), etaname.c_str(), 255, 0, 255);
341 etaHisto.SetDirectory(0);
342 etaHistos.push_back(pair<string, TH1D>(name, etaHisto));
346 TH1D etaHisto(etaname.c_str(), etaname.c_str(), 301, 0, 1);
347 etaHisto.SetDirectory(0);
348 etaHistos.push_back(pair<string, TH1D>(name, etaHisto));
353 B2INFO(
"Offset coverage is " << 100 * coverage <<
"%");
358 for (
int i = 0; i < nEntries; ++i) {
362 auto it = std::find_if(etaHistos.begin(), etaHistos.end(),
363 [&](
const pair<string, TH1D>& element) { return element.first == shapeName;});
365 if (it != etaHistos.end()) {
372 vector< pair< string, vector<TH2D> > > offsetHistosVec;
374 for (
auto iter : etaHistos) {
375 auto name = iter.first;
376 auto& histo = iter.second;
377 int nClusters = histo.GetEntries();
381 shapeClassifier->
addShape(shapeIndex);
389 vector< TH2D > offsetHistos;
391 for (
int i = 0; i < nEtaBins; i++) {
393 double xq = double(i) / nEtaBins;
396 histo.GetQuantiles(1, &yq, &xq);
400 string offsetname = str(format(
"offset_%1%_%2%") % name % i);
401 TH2D offsetHisto(offsetname.c_str(), offsetname.c_str(), 1, 0, 1, 1, 0, 1);
402 offsetHisto.SetDirectory(0);
403 offsetHisto.StatOverflows();
404 offsetHistos.push_back(offsetHisto);
407 offsetHistosVec.push_back(pair<
string, vector<TH2D> >(name, offsetHistos));
412 for (
int i = 0; i < nEntries; ++i) {
416 auto it = std::find_if(offsetHistosVec.begin(), offsetHistosVec.end(),
417 [&](
const pair<
string, vector<TH2D>>& element) { return element.first == shapeName;});
419 if (it != offsetHistosVec.end()) {
429 for (
auto iter : offsetHistosVec) {
430 auto name = iter.first;
431 auto& histovec = iter.second;
436 for (
auto& histo : histovec) {
438 double etaLikelyhood = double(histo.GetEntries()) / nEntries;
439 double offsetU = histo.GetMean(1);
440 double offsetV = histo.GetMean(2);
441 double covUV = histo.GetCovariance();
442 double covU = pow(histo.GetRMS(1), 2);
443 double covV = pow(histo.GetRMS(2), 2);
445 B2INFO(
"Name " << name <<
", posU=" << offsetU <<
", posV=" << offsetV <<
", covU=" << covU <<
", covV=" << covV <<
", covUV=" <<
448 TMatrixDSym HitCov(2);
450 HitCov(1, 0) = covUV;
451 HitCov(0, 1) = covUV;
454 TMatrixDSymEigen HitCovE(HitCov);
455 TVectorD eigenval = HitCovE.GetEigenValues();
456 if (eigenval(0) <= 0 || eigenval(1) <= 0) {
457 B2ERROR(
"Estimated covariance matrix not positive definite.");
466 B2INFO(
"Added shape classifier with coverage " << 100 * coverage <<
"% on training data sample.");