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;
221 for (
auto indexAndValue : shapeLikelyhoodMap) {
223 auto shapeIndex = indexAndValue.first;
224 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
225 auto globalIndex = globalShapeIndexer->
getShapeIndex(shapeName);
227 globalShapeClassifier.addShapeLikelyhood(globalIndex, indexAndValue.second);
234 for (
auto indexAndValue : offsetMap) {
236 auto shapeIndex = indexAndValue.first;
237 auto shapeName = shapeIndexer->
getShapeName(shapeIndex);
238 auto globalIndex = globalShapeIndexer->
getShapeIndex(shapeName);
240 globalShapeClassifier.addShape(globalIndex);
243 for (
auto offset : indexAndValue.second) {
245 auto percentile = percentileMap[shapeIndex][etaBin];
246 globalShapeClassifier.addEtaPercentile(globalIndex, percentile);
248 auto likelyhood = likelyhoodMap[shapeIndex][etaBin];
249 globalShapeClassifier.addEtaLikelyhood(globalIndex, likelyhood);
251 globalShapeClassifier.addEtaOffset(globalIndex, offset);
255 return globalShapeClassifier;
264 const auto nEntries = tree->GetEntries();
265 B2INFO(
"Number of clusters is " << nEntries);
270 tree->SetBranchAddress(
"ShapeName", &shapeNamePtr);
271 tree->SetBranchAddress(
"MirroredShapeName", &mirroredShapeNamePtr);
275 tree->SetBranchAddress(
"SizeV", &
m_sizeV);
279 vector< pair<string, float> > shapeList;
281 for (
int i = 0; i < nEntries; ++i) {
286 auto it = std::find_if(shapeList.begin(), shapeList.end(),
287 [&](
const pair<string, float>& element) { return element.first == shapeName;});
290 if (it != shapeList.end()) {
297 shapeList.push_back(pair<string, int>(shapeName, 1));
309 vector< pair<string, TH1D> > etaHistos;
315 double coverage = 0.0;
317 for (
auto iter : shapeList) {
318 auto name = iter.first;
319 auto counter = iter.second;
321 double likelyhood = counter / nEntries;
325 shapeIndexer->
addShape(name, tmpIndex);
337 coverage += likelyhood;
338 string etaname = str(format(
"eta_%1%") % name);
341 if (name ==
"SD0.0") {
342 TH1D etaHisto(etaname.c_str(), etaname.c_str(), 255, 0, 255);
343 etaHisto.SetDirectory(0);
344 etaHistos.push_back(pair<string, TH1D>(name, etaHisto));
348 TH1D etaHisto(etaname.c_str(), etaname.c_str(), 301, 0, 1);
349 etaHisto.SetDirectory(0);
350 etaHistos.push_back(pair<string, TH1D>(name, etaHisto));
355 B2INFO(
"Offset coverage is " << 100 * coverage <<
"%");
360 for (
int i = 0; i < nEntries; ++i) {
364 auto it = std::find_if(etaHistos.begin(), etaHistos.end(),
365 [&](
const pair<string, TH1D>& element) { return element.first == shapeName;});
367 if (it != etaHistos.end()) {
374 vector< pair< string, vector<TH2D> > > offsetHistosVec;
376 for (
auto iter : etaHistos) {
377 auto name = iter.first;
378 auto& histo = iter.second;
379 int nClusters = histo.GetEntries();
383 shapeClassifier->
addShape(shapeIndex);
391 vector< TH2D > offsetHistos;
393 for (
int i = 0; i < nEtaBins; i++) {
395 double xq = double(i) / nEtaBins;
398 histo.GetQuantiles(1, &yq, &xq);
402 string offsetname = str(format(
"offset_%1%_%2%") % name % i);
403 TH2D offsetHisto(offsetname.c_str(), offsetname.c_str(), 1, 0, 1, 1, 0, 1);
404 offsetHisto.SetDirectory(0);
405 offsetHisto.StatOverflows();
406 offsetHistos.push_back(offsetHisto);
409 offsetHistosVec.push_back(pair<
string, vector<TH2D> >(name, offsetHistos));
414 for (
int i = 0; i < nEntries; ++i) {
418 auto it = std::find_if(offsetHistosVec.begin(), offsetHistosVec.end(),
419 [&](
const pair<
string, vector<TH2D>>& element) { return element.first == shapeName;});
421 if (it != offsetHistosVec.end()) {
431 for (
auto iter : offsetHistosVec) {
432 auto name = iter.first;
433 auto& histovec = iter.second;
438 for (
auto& histo : histovec) {
440 double etaLikelyhood = double(histo.GetEntries()) / nEntries;
441 double offsetU = histo.GetMean(1);
442 double offsetV = histo.GetMean(2);
443 double covUV = histo.GetCovariance();
444 double covU =
square(histo.GetRMS(1));
445 double covV =
square(histo.GetRMS(2));
447 B2INFO(
"Name " << name <<
", posU=" << offsetU <<
", posV=" << offsetV <<
", covU=" << covU <<
", covV=" << covV <<
", covUV=" <<
450 TMatrixDSym HitCov(2);
452 HitCov(1, 0) = covUV;
453 HitCov(0, 1) = covUV;
456 TMatrixDSymEigen HitCovE(HitCov);
457 TVectorD eigenval = HitCovE.GetEigenValues();
458 if (eigenval(0) <= 0 || eigenval(1) <= 0) {
459 B2ERROR(
"Estimated covariance matrix not positive definite.");
468 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.
PXDClusterShapeClassifierPar mirrorShapeClassifier(const PXDClusterShapeClassifierPar *shapeClassifier, const PXDClusterShapeIndexPar *shapeIndexer, int clusterKind)
Returns a mirrored version of shape classifier.
std::string m_shapeName
Branches for tree.
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.
static PXDClusterShapeClassifierPar localToGlobal(const PXDClusterShapeClassifierPar *localShapeClassifier, const PXDClusterShapeIndexPar *localShapeIndexer, const PXDClusterShapeIndexPar *globalShapeIndexer)
Returns a shape classifier using global shape indices instead of local ones.
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.