9#include <pxd/calibration/PXDClusterPositionCalibrationAlgorithm.h>
10#include <pxd/dbobjects/PXDClusterShapeIndexPar.h>
11#include <pxd/dbobjects/PXDClusterPositionEstimatorPar.h>
12#include <framework/utilities/MathHelpers.h>
17#include <TMatrixDSym.h>
19#include <TMatrixDSymEigen.h>
21#include <boost/format.hpp>
36 " -------------------------- PXDClusterPositionCalibrationAlgorithm ----------------------\n"
38 " Algorithm for estimating cluster position offsets and shape likelyhoods. \n"
39 " ----------------------------------------------------------------------------------------\n"
49 pitchtree->SetBranchAddress(
"PitchV", &
m_pitchV);
52 for (
int i = 0; i < pitchtree->GetEntries(); ++i) {
53 pitchtree->GetEntry(i);
59 typedef tuple<int, int, int> bufferkey_t;
60 typedef pair<PXDClusterShapeIndexPar, PXDClusterShapeClassifierPar> buffervalue_t;
61 map<bufferkey_t, buffervalue_t> localCalibrationMap;
65 B2INFO(
"Start calibration of clusterkind=" << clusterKind <<
" ...");
67 string gridname = str(format(
"GridKind_%1%") % clusterKind);
70 for (
auto uBin = 1; uBin <= grid->GetXaxis()->GetNbins(); uBin++) {
71 for (
auto vBin = 1; vBin <= grid->GetYaxis()->GetNbins(); vBin++) {
74 auto thetaU = grid->GetXaxis()->GetBinCenter(uBin);
75 auto thetaV = grid->GetYaxis()->GetBinCenter(vBin);
78 B2INFO(
"Skip training estimator on thetaU=" << thetaU <<
", thetaV=" << thetaV);
81 B2INFO(
"Start training estimator on thetaU=" << thetaU <<
", thetaV=" << thetaV);
84 string treename = str(format(
"tree_%1%_%2%_%3%") % clusterKind % uBin % vBin);
90 bufferkey_t key = std::make_tuple(clusterKind, uBin, vBin);
91 localCalibrationMap[key] = buffervalue_t(localShapeIndexer, localShapeClassifier);
99 int globalShapeIndex = 0;
101 shapeIndexer->
addShape(*it, globalShapeIndex);
105 B2INFO(
"Number of cluster shapes is " << globalShapeIndex);
115 string gridname = str(format(
"GridKind_%1%") % clusterKind);
118 positionEstimator->
addGrid(clusterKind, *grid);
120 for (
auto uBin = 1; uBin <= grid->GetXaxis()->GetNbins(); uBin++) {
121 for (
auto vBin = 1; vBin <= grid->GetYaxis()->GetNbins(); vBin++) {
124 auto thetaU = grid->GetXaxis()->GetBinCenter(uBin);
125 auto thetaV = grid->GetYaxis()->GetBinCenter(vBin);
133 auto iter = localCalibrationMap.find(std::make_tuple(clusterKind, uBin, vBin));
134 auto localShapeIndexer = iter->second.first;
135 auto localShapeClassifer = iter->second.second;
138 auto shapeClassifier =
localToGlobal(&localShapeClassifer, &localShapeIndexer, shapeIndexer);
141 auto mirror_vBin = grid->GetYaxis()->FindBin(-thetaV);
145 B2INFO(
"Add shape classifier for angles thetaU=" << thetaU <<
", thetaV=" << thetaV <<
", clusterkind=" << clusterKind);
147 B2INFO(
"Add mirrored shape classifier for angles thetaU=" << thetaU <<
", thetaV=" << -thetaV <<
", clusterkind=" << clusterKind);
148 positionEstimator->
setShapeClassifier(mirroredClassifier, uBin, mirror_vBin, clusterKind);
156 B2INFO(
"PXDClusterPosition Calibration Successful");
169 for (
auto indexAndValue : shapeLikelyhoodMap) {
171 auto shapeIndex = indexAndValue.first;
172 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
174 auto mirroredIndex = shapeIndexer->
getShapeIndex(mirroredName);
176 mirroredShapeClassifier.addShapeLikelyhood(mirroredIndex, indexAndValue.second);
183 for (
auto indexAndValue : offsetMap) {
185 auto shapeIndex = indexAndValue.first;
186 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
188 auto mirroredIndex = shapeIndexer->
getShapeIndex(mirroredName);
190 mirroredShapeClassifier.addShape(mirroredIndex);
193 for (
auto offset : indexAndValue.second) {
195 auto percentile = percentileMap[shapeIndex][etaBin];
196 mirroredShapeClassifier.addEtaPercentile(mirroredIndex, percentile);
198 auto likelyhood = likelyhoodMap[shapeIndex][etaBin];
199 mirroredShapeClassifier.addEtaLikelyhood(mirroredIndex, likelyhood);
202 auto mirroredOffset =
PXDClusterOffsetPar(offset.getU(), shift - offset.getV(), offset.getUSigma2(), offset.getVSigma2(),
203 -offset.getUVCovariance());
204 mirroredShapeClassifier.addEtaOffset(mirroredIndex, mirroredOffset);
209 return mirroredShapeClassifier;
220 for (
auto indexAndValue : shapeLikelyhoodMap) {
222 auto shapeIndex = indexAndValue.first;
223 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
224 auto globalIndex = globalShapeIndexer->
getShapeIndex(shapeName);
226 globalShapeClassifier.addShapeLikelyhood(globalIndex, indexAndValue.second);
233 for (
auto indexAndValue : offsetMap) {
235 auto shapeIndex = indexAndValue.first;
236 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
237 auto globalIndex = globalShapeIndexer->
getShapeIndex(shapeName);
239 globalShapeClassifier.addShape(globalIndex);
242 for (
auto offset : indexAndValue.second) {
244 auto percentile = percentileMap[shapeIndex][etaBin];
245 globalShapeClassifier.addEtaPercentile(globalIndex, percentile);
247 auto likelyhood = likelyhoodMap[shapeIndex][etaBin];
248 globalShapeClassifier.addEtaLikelyhood(globalIndex, likelyhood);
250 globalShapeClassifier.addEtaOffset(globalIndex, offset);
254 return globalShapeClassifier;
263 const auto nEntries = tree->GetEntries();
264 B2INFO(
"Number of clusters is " << nEntries);
269 tree->SetBranchAddress(
"ShapeName", &shapeNamePtr);
270 tree->SetBranchAddress(
"MirroredShapeName", &mirroredShapeNamePtr);
274 tree->SetBranchAddress(
"SizeV", &
m_sizeV);
278 vector< pair<string, float> > shapeList;
280 for (
int i = 0; i < nEntries; ++i) {
285 auto it = std::find_if(shapeList.begin(), shapeList.end(),
286 [&](
const pair<string, float>& element) { return element.first == shapeName;});
289 if (it != shapeList.end()) {
296 shapeList.push_back(pair<string, int>(shapeName, 1));
308 vector< pair<string, TH1D> > etaHistos;
314 double coverage = 0.0;
316 for (
auto iter : shapeList) {
317 auto name = iter.first;
318 auto counter = iter.second;
320 double likelyhood = counter / nEntries;
324 shapeIndexer->
addShape(name, tmpIndex);
336 coverage += likelyhood;
337 string etaname = str(format(
"eta_%1%") % name);
340 if (name ==
"SD0.0") {
341 TH1D etaHisto(etaname.c_str(), etaname.c_str(), 255, 0, 255);
342 etaHisto.SetDirectory(0);
343 etaHistos.push_back(pair<string, TH1D>(name, etaHisto));
347 TH1D etaHisto(etaname.c_str(), etaname.c_str(), 301, 0, 1);
348 etaHisto.SetDirectory(0);
349 etaHistos.push_back(pair<string, TH1D>(name, etaHisto));
354 B2INFO(
"Offset coverage is " << 100 * coverage <<
"%");
359 for (
int i = 0; i < nEntries; ++i) {
363 auto it = std::find_if(etaHistos.begin(), etaHistos.end(),
364 [&](
const pair<string, TH1D>& element) { return element.first == shapeName;});
366 if (it != etaHistos.end()) {
373 vector< pair< string, vector<TH2D> > > offsetHistosVec;
375 for (
auto iter : etaHistos) {
376 auto name = iter.first;
377 auto& histo = iter.second;
378 int nClusters = histo.GetEntries();
382 shapeClassifier->
addShape(shapeIndex);
390 vector< TH2D > offsetHistos;
392 for (
int i = 0; i < nEtaBins; i++) {
394 double xq = double(i) / nEtaBins;
397 histo.GetQuantiles(1, &yq, &xq);
401 string offsetname = str(format(
"offset_%1%_%2%") % name % i);
402 TH2D offsetHisto(offsetname.c_str(), offsetname.c_str(), 1, 0, 1, 1, 0, 1);
403 offsetHisto.SetDirectory(0);
404 offsetHisto.StatOverflows();
405 offsetHistos.push_back(offsetHisto);
408 offsetHistosVec.push_back(pair<
string, vector<TH2D> >(name, offsetHistos));
413 for (
int i = 0; i < nEntries; ++i) {
417 auto it = std::find_if(offsetHistosVec.begin(), offsetHistosVec.end(),
418 [&](
const pair<
string, vector<TH2D>>& element) { return element.first == shapeName;});
420 if (it != offsetHistosVec.end()) {
430 for (
auto iter : offsetHistosVec) {
431 auto name = iter.first;
432 auto& histovec = iter.second;
437 for (
auto& histo : histovec) {
439 double etaLikelyhood = double(histo.GetEntries()) / nEntries;
440 double offsetU = histo.GetMean(1);
441 double offsetV = histo.GetMean(2);
442 double covUV = histo.GetCovariance();
443 double covU =
square(histo.GetRMS(1));
444 double covV =
square(histo.GetRMS(2));
446 B2INFO(
"Name " << name <<
", posU=" << offsetU <<
", posV=" << offsetV <<
", covU=" << covU <<
", covV=" << covV <<
", covUV=" <<
449 TMatrixDSym HitCov(2);
451 HitCov(1, 0) = covUV;
452 HitCov(0, 1) = covUV;
455 TMatrixDSymEigen HitCovE(HitCov);
456 TVectorD eigenval = HitCovE.GetEigenValues();
457 if (eigenval(0) <= 0 || eigenval(1) <= 0) {
458 B2ERROR(
"Estimated covariance matrix not positive definite.");
467 B2INFO(
"Added shape classifier with coverage " << 100 * coverage <<
"% on training data sample.");
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
EResult
The result of calibration.
@ c_OK
Finished successfully =0 in Python.
CalibrationAlgorithm(const std::string &collectorModuleName)
Constructor - sets the prefix for collected objects (won't be accesses until execute(....
The class for PXD cluster position offset payload.
float m_clusterEta
Eta value of cluster.
void createShapeClassifier(std::string treename, PXDClusterShapeClassifierPar *shapeClassifier, PXDClusterShapeIndexPar *shapeIndexer)
Returns a new classifier and index trained on cluster tree.
float m_positionOffsetU
Position offset u of cluster.
std::string m_mirroredShapeName
Name of mirrored cluster shape.
std::vector< int > clusterKinds
Vector of clusterkinds to calibrate.
std::string m_shapeName
Branches for tree.
PXDClusterShapeClassifierPar mirrorShapeClassifier(PXDClusterShapeClassifierPar *shapeClassifier, PXDClusterShapeIndexPar *shapeIndexer, int clusterKind)
Returns a mirrored version of shape classifier.
PXDClusterShapeClassifierPar localToGlobal(PXDClusterShapeClassifierPar *localShapeClassifier, PXDClusterShapeIndexPar *localShapeIndexer, PXDClusterShapeIndexPar *globalShapeIndexer)
Returns a shape classifier using global shape indices instead of local ones.
float m_pitchV
Branches for pitchtree.
std::map< std::string, int > m_sizeMap
Helper needed to map the name of a shape to the V size of the cluster.
float m_positionOffsetV
Position offset v of cluster.
int m_clusterKind
Pitch in V.
int maxEtaBins
Maximum number of eta bins for estimating cluster position offsets.
int minClusterForPositionOffset
Minimum number of collected clusters for estimating cluster position offsets.
int minClusterForShapeLikelyhood
Minimum number of collected clusters for estimating shape likelyhood.
PXDClusterPositionCalibrationAlgorithm()
Constructor set the prefix to PXDClusterPositionCalibrationAlgorithm.
virtual EResult calibrate() override
Run algo on data.
std::map< int, float > m_pitchMap
Helper needed to map the clusterkind to the V pitch of the sensor.
std::set< std::string > m_shapeSet
Set of unique shape names.
std::map< std::string, std::string > m_mirrorMap
Helper needed to map the name of a shape to the name of the mirrored shape.
The class for PXD cluster position lookup table payload.
void setShapeClassifier(const PXDClusterShapeClassifierPar &classifier, int uBin, int vBin, int clusterkind)
Set shape classifier.
void addGrid(int clusterkind, const TH2F &grid)
Add grid for clusterkind.
The class for PXD cluster shape classifier payload.
void addShapeLikelyhood(int shape_index, float likelyhood)
Add shape likelihood.
const std::map< int, std::vector< PXDClusterOffsetPar > > & getOffsetMap() const
Return offset map for position correction.
void addEtaLikelyhood(int shape_index, float likelyhood)
Add eta likelyhood to shape for position correction.
const std::map< int, std::vector< float > > & getPercentilesMap() const
Return percentiles map for position correction.
void addEtaPercentile(int shape_index, float percentile)
Add eta percentile to shape for position correction.
const std::map< int, std::vector< float > > & getLikelyhoodMap() const
Return likelyhood map for position correction.
unsigned int getEtaIndex(int shape_index, float eta) const
Get eta index for position correction.
void addShape(int shape_index)
Add shape for position correction.
const std::map< int, float > & getShapeLikelyhoodMap() const
Return shape likelyhood map.
void addEtaOffset(int shape_index, PXDClusterOffsetPar &offset)
Add offset to shape for position correction.
The class for PXD cluster shape index payload.
int getShapeIndex(const std::string &name) const
Returns shape index from name.
const std::string & getShapeName(int index) const
Returns shape name from index.
void addShape(const std::string &name, int index)
Add shape with name and index.
std::shared_ptr< T > getObjectPtr(const std::string &name, const std::vector< Calibration::ExpRun > &requestedRuns)
Get calibration data object by name and list of runs, the Merge function will be called to generate t...
constexpr T square(const T &x)
Calculate the square of the input.
Abstract base class for different kinds of events.