Belle II Software development
SpacePointHelperFunctions.h
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#pragma once
10
11#include <vector>
12
13#include <svd/calibration/SVDHitTimeSelection.h>
14#include <svd/calibration/SVDNoiseCalibrations.h>
15#include <svd/dataobjects/SVDCluster.h>
16#include <svd/dataobjects/SVDShaperDigit.h>
17#include <svd/dbobjects/SVDSpacePointSNRFractionSelector.h>
18#include <svd/reconstruction/SVDMaxSumAlgorithm.h>
19
20#include <framework/datastore/StoreArray.h>
21#include <framework/datastore/StoreObjPtr.h>
22#include <framework/database/DBObjPtr.h>
23#include <framework/utilities/MathHelpers.h>
24#include <mdst/dataobjects/EventLevelTrackingInfo.h>
25
26#include <vxd/dataobjects/VxdID.h>
27
28#include <unordered_map>
29
30#include <TH2.h>
31#include <math.h>
32#include <TFile.h>
33
34namespace Belle2 {
39
40
46
47 public:
48
50 inline void addCluster(const SVDCluster* entry)
51 {
52 vxdID = entry->getSensorID();
53 if (entry->isUCluster() == true) { clustersU.push_back(entry); return; }
54 clustersV.push_back(entry);
55 }
56
59
64 std::vector<const SVDCluster*> clustersU;
65
70 std::vector<const SVDCluster*> clustersV;
71
72 };
73
79 template <class SpacePointType> void provideSVDClusterSingles(const StoreArray<SVDCluster>& svdClusters,
80 StoreArray<SpacePointType>& spacePoints)
81 {
82 for (unsigned int i = 0; i < uint(svdClusters.getEntries()); ++i) {
83 const SVDCluster* currentCluster = svdClusters[i];
84 std::vector<const SVDCluster*> currentClusterCombi = { currentCluster };
85 SpacePointType* newSP = spacePoints.appendNew(currentClusterCombi);
86 newSP->addRelationTo(currentCluster);
87 }
88 }
89
90
91
94 std::vector<float>& inputVector,
95 const SVDNoiseCalibrations& noiseCal)
96 {
97 inputVector.clear();
98 inputVector.resize(3, 0.0);
99
100 auto shaperDigits = cls->getRelationsTo<SVDShaperDigit>();
101 float noise = 0;
102 for (auto iSD : shaperDigits) {
103 auto samples = iSD.getSamples();
104 std::vector<float> selectedSamples;
105 if (samples.size() == 6) {
106 Belle2::SVD::SVDMaxSumAlgorithm maxSum(samples);
107 auto maxSamples = maxSum.getSelectedSamples();
108 selectedSamples.assign(maxSamples.begin(), maxSamples.end());
109 } else {
110 selectedSamples.assign(samples.begin(), samples.end());
111 }
112 if (selectedSamples.size() < 3) continue;
113
114 inputVector[0] += selectedSamples[0];
115 inputVector[1] += selectedSamples[1];
116 inputVector[2] += selectedSamples[2];
117
118 VxdID thisSensorID = iSD.getSensorID();
119 bool thisSide = iSD.isUStrip();
120 int thisCellID = iSD.getCellID();
121 float thisNoise = noiseCal.getNoise(thisSensorID, thisSide, thisCellID);
122 noise += thisNoise * thisNoise;
123 }
124 noise = sqrt(noise);
125 inputVector[0] = inputVector[0] / noise;
126 inputVector[1] = inputVector[1] / noise;
127 inputVector[2] = inputVector[2] / noise;
128 }
129
139 std::vector< std::vector<const SVDCluster*> >& foundCombinations, const SVDHitTimeSelection& hitTimeCut,
140 const bool& useSVDGroupInfo, const int& numberOfSignalGroups, const bool& formSingleSignalGroup,
141 const SVDNoiseCalibrations& noiseCal, const DBObjPtr<SVDSpacePointSNRFractionSelector>& svdSpacePointSelectionFunction,
142 bool useSVDSpacePointSNRFractionSelector)
143 {
144
145 for (const SVDCluster* uCluster : aSensor.clustersU) {
146 if (! hitTimeCut.isClusterInTime(uCluster->getSensorID(), 1, uCluster->getClsTime())) {
147 B2DEBUG(29, "Cluster rejected due to timing cut. Cluster time: " << uCluster->getClsTime());
148 continue;
149 }
150 for (const SVDCluster* vCluster : aSensor.clustersV) {
151 if (! hitTimeCut.isClusterInTime(vCluster->getSensorID(), 0, vCluster->getClsTime())) {
152 B2DEBUG(29, "Cluster rejected due to timing cut. Cluster time: " << vCluster->getClsTime());
153 continue;
154 }
155
156 if (! hitTimeCut.areClusterTimesCompatible(vCluster->getSensorID(), uCluster->getClsTime(), vCluster->getClsTime())) {
157 B2DEBUG(29, "Cluster combination rejected due to timing cut. Cluster time U (" << uCluster->getClsTime() <<
158 ") is incompatible with Cluster time V (" << vCluster->getClsTime() << ")");
159 continue;
160 }
161
162 if (useSVDGroupInfo) {
163 const std::vector<int>& uTimeGroupId = uCluster->getTimeGroupId();
164 const std::vector<int>& vTimeGroupId = vCluster->getTimeGroupId();
165
166 if (int(uTimeGroupId.size()) && int(vTimeGroupId.size())) { // indirect check if the clusterizer module is disabled
167 bool isContinue = true;
168 for (auto& uitem : uTimeGroupId) {
169 if (uitem < 0 || uitem >= numberOfSignalGroups) continue;
170 for (auto& vitem : vTimeGroupId) {
171 if (vitem < 0 || vitem >= numberOfSignalGroups) continue;
172 if ((uitem == vitem) || formSingleSignalGroup) { isContinue = false; break; }
173 }
174 if (!isContinue) break;
175 }
176
177 if (isContinue) {
178 B2DEBUG(29, "Cluster combination rejected due to different time-group Id.");
179 continue;
180 }
181 }
182 }
183
184 if (useSVDSpacePointSNRFractionSelector) {
185 std::vector<float> inputU;
186 std::vector<float> inputV;
187
188 storeInputVectorFromSingleCluster(uCluster, inputU, noiseCal);
189 storeInputVectorFromSingleCluster(vCluster, inputV, noiseCal);
190
191 bool pass = svdSpacePointSelectionFunction->passSNRFractionSelection(inputU, inputV);
192 if (!pass) {
193 B2DEBUG(29, "Cluster combination rejected due to SVDSpacePointSNRFractionSelector");
194 continue;
195 }
196 }
197
198 foundCombinations.push_back({uCluster, vCluster});
199
200
201 }
202 }
203
204
205
206
207 }
208
213
214 inline void spPDFName(const VxdID& sensor, int uSize, int vSize, int maxClusterSize, std::string& PDFName,
215 std::string& errorPDFName, bool useLegacyNaming)
216 {
217 if (useLegacyNaming == true) {
218
219 if (uSize > maxClusterSize) uSize = maxClusterSize;
220 if (vSize > maxClusterSize) vSize = maxClusterSize;
221
222 std::string sensorName;
223
224 if (sensor.getLayerNumber() == 3) sensorName = "l3";
225 if (sensor.getLayerNumber() > 3 && sensor.getSensorNumber() == 1) sensorName = "trap";
226 if (sensor.getLayerNumber() > 3 && sensor.getSensorNumber() > 1) sensorName = "large";
227
228 PDFName = sensorName + std::to_string(uSize) + std::to_string(vSize);
229 errorPDFName = "error" + PDFName;
230 } else {
231
232 if (uSize > maxClusterSize) uSize = maxClusterSize;
233 if (vSize > maxClusterSize) vSize = maxClusterSize;
234
235 int layer = sensor.getLayerNumber();
236 int ladder = sensor.getLadderNumber();
237 int sens = sensor.getSensorNumber();
238
239 PDFName = std::to_string(layer) + "." + std::to_string(ladder) + "." + std::to_string(sens) + "." + std::to_string(
240 uSize) + "." + std::to_string(vSize);
241 errorPDFName = PDFName + "_Error";
242 }
243
244
245
246 }
247
248
254
255
256 inline void calculatePairingProb(TFile* pdfFile, std::vector<const SVDCluster*>& clusters, double& prob, double& error,
257 bool useLegacyNaming)
258 {
259
260 int maxSize;
261 int pdfEntries = pdfFile->GetListOfKeys()->GetSize();
262 if (useLegacyNaming == true) {
263 maxSize = floor(sqrt((pdfEntries - 4) / 6)); //4(time+size)+3(sensors)*2(prob/error)*size^2(u/v combo.)
264 } else {
265 maxSize = floor(sqrt((pdfEntries - 4) / 344)); //4(time+size)+172(sensorType)*2(prob/error)*size^2(u/v combo.)
266 }
267 std::string chargeProbInput;
268 std::string chargeErrorInput;
269
270 spPDFName(clusters[0]->getSensorID(), clusters[0]->getSize(), clusters[1]->getSize(), maxSize,
271 chargeProbInput, chargeErrorInput, useLegacyNaming);
272 std::string timeProbInput = "timeProb";
273 std::string timeErrorInput = "timeError";
274 std::string sizeProbInput = "sizeProb";
275 std::string sizeErrorInput = "sizeError";
276
277
278 TH2F* chargePDF = nullptr;
279 TH2F* chargeError = nullptr;
280 TH2F* timePDF = nullptr;
281 TH2F* timeError = nullptr;
282 TH2F* sizePDF = nullptr;
283 TH2F* sizeError = nullptr;
284
285 pdfFile->GetObject(chargeProbInput.c_str(), chargePDF);
286 pdfFile->GetObject(chargeErrorInput.c_str(), chargeError);
287 pdfFile->GetObject(timeProbInput.c_str(), timePDF);
288 pdfFile->GetObject(timeErrorInput.c_str(), timeError);
289 pdfFile->GetObject(sizeProbInput.c_str(), sizePDF);
290 pdfFile->GetObject(sizeErrorInput.c_str(), sizeError);
291
292 int xChargeBin = chargePDF->GetXaxis()->FindFixBin(clusters[0]->getCharge());
293 int yChargeBin = chargePDF->GetYaxis()->FindFixBin(clusters[1]->getCharge());
294
295 int xTimeBin = timePDF->GetXaxis()->FindFixBin(clusters[0]->getClsTime());
296 int yTimeBin = timePDF->GetYaxis()->FindFixBin(clusters[1]->getClsTime());
297
298
299 int xSizeBin = sizePDF->GetXaxis()->FindFixBin(clusters[0]->getSize());
300 int ySizeBin = sizePDF->GetYaxis()->FindFixBin(clusters[1]->getSize());
301
302 double chargeProb = chargePDF->GetBinContent(xChargeBin, yChargeBin);
303 double timeProb = timePDF->GetBinContent(xTimeBin, yTimeBin);
304 double sizeProb = sizePDF->GetBinContent(xSizeBin, ySizeBin);
305 double chargeProbError = chargePDF->GetBinContent(xChargeBin, yChargeBin);
306 double timeProbError = timePDF->GetBinContent(xTimeBin, yTimeBin);
307 double sizeProbError = sizePDF->GetBinContent(xSizeBin, ySizeBin);
308
309
310 if (chargeProbError == 0) {
311 B2DEBUG(21, "svdClusterProbabilityEstimator has not been run, spacePoint QI will return zero!");
312 }
313
314 prob = chargeProb * timeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQuality();
315 error = prob * sqrt(square(timeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQuality() * chargeProbError) +
316 square(chargeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQuality() * timeProbError) +
317 square(chargeProb * timeProb * clusters[0]->getQuality() * clusters[1]->getQuality() * sizeProbError) +
318 square(chargeProb * timeProb * sizeProb * clusters[1]->getQuality() * clusters[0]->getQualityError()) +
319 square(chargeProb * timeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQualityError()));
320 }
321
329 template <class SpacePointType> void provideSVDClusterCombinations(const StoreArray<SVDCluster>& svdClusters,
330 StoreArray<SpacePointType>& spacePoints, SVDHitTimeSelection& hitTimeCut, bool useQualityEstimator, TFile* pdfFile,
331 bool useLegacyNaming, unsigned int numMaxSpacePoints, std::string m_eventLevelTrackingInfoName, const bool& useSVDGroupInfo,
332 const int& numberOfSignalGroups, const bool& formSingleSignalGroup,
333 const SVDNoiseCalibrations& noiseCal, const DBObjPtr<SVDSpacePointSNRFractionSelector>& svdSpacePointSelectionFunction,
334 bool useSVDSpacePointSNRFractionSelector)
335 {
336 std::unordered_map<VxdID::baseType, ClustersOnSensor>
337 activatedSensors; // collects one entry per sensor, each entry will contain all Clusters on it TODO: better to use a sorted vector/list?
338 std::vector<std::vector<const SVDCluster*> >
339 foundCombinations; // collects all combinations of Clusters which were possible (condition: 1u+1v-Cluster on the same sensor)
340
341 // sort Clusters by sensor. After the loop, each entry of activatedSensors contains all U and V-type clusters on that sensor
342 for (unsigned int i = 0; i < uint(svdClusters.getEntries()); ++i) {
343 SVDCluster* currentCluster = svdClusters[i];
344
345 activatedSensors[currentCluster->getSensorID().getID()].addCluster(currentCluster);
346 }
347
348
349 for (auto& aSensor : activatedSensors)
350 findPossibleCombinations(aSensor.second, foundCombinations, hitTimeCut, useSVDGroupInfo, numberOfSignalGroups,
351 formSingleSignalGroup,
352 noiseCal, svdSpacePointSelectionFunction, useSVDSpacePointSNRFractionSelector);
353
354 // Do not make space-points if their number would be too large to be considered by tracking
355 if (foundCombinations.size() > numMaxSpacePoints) {
356 StoreObjPtr<EventLevelTrackingInfo> m_eventLevelTrackingInfo(m_eventLevelTrackingInfoName);
357 if (m_eventLevelTrackingInfo.isValid()) {
358 m_eventLevelTrackingInfo->setSVDSpacePointCreatorAbortionFlag();
359 }
360 return;
361 }
362
363 for (auto& clusterCombi : foundCombinations) {
364 SpacePointType* newSP = spacePoints.appendNew(clusterCombi);
365 if (useQualityEstimator == true) {
366 double probability;
367 double error;
368 calculatePairingProb(pdfFile, clusterCombi, probability, error, useLegacyNaming);
369 newSP->setQualityEstimation(probability);
370 newSP->setQualityEstimationError(error);
371 }
372 for (auto* cluster : clusterCombi) {
373 newSP->addRelationTo(cluster, cluster->isUCluster() ? 1. : -1.);
374 }
375 }
376 }
377
378
380} //Belle2 namespace
Class for accessing objects in the database.
Definition DBObjPtr.h:21
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
The SVD Cluster class This class stores all information about reconstructed SVD clusters.
Definition SVDCluster.h:29
float getClsTime() const
Get average of waveform maximum times of cluster strip signals.
Definition SVDCluster.h:134
VxdID getSensorID() const
Get the sensor ID.
Definition SVDCluster.h:102
bool isUCluster() const
Get the direction of strips.
Definition SVDCluster.h:110
const std::vector< int > & getTimeGroupId() const
Get ID of the time-group.
Definition SVDCluster.h:184
This class defines the dbobject and the methods to access the calibration of the cluster reconstructi...
bool isClusterInTime(const Belle2::VxdID &sensorID, const bool &isU, const double &svdTime, const double &svdTimeError=0, const double &t0=0, const double &t0Error=0) const
Return whether the cluster is estimated to be in time with the event or off-time.
bool areClusterTimesCompatible(const Belle2::VxdID &sensorID, const double &uTime, const double &vTime=0) const
Return whether the cluster is estimated to be in time with the event or off-time.
This class defines the dbobject and the method to access SVD calibrations from the noise local runs.
float getNoise(const VxdID &sensorID, const bool &isU, const unsigned short &strip) const
This is the method for getting the noise.
The SVD ShaperDigit class.
Class implementing the MaxSum algorithm.
std::vector< float > getSelectedSamples()
Accessor to arrays stored in the data store.
Definition StoreArray.h:113
T * appendNew()
Construct a new T object at the end of the array.
Definition StoreArray.h:246
int getEntries() const
Get the number of objects in the array.
Definition StoreArray.h:216
Type-safe access to single objects in the data store.
Definition StoreObjPtr.h:96
bool isValid() const
Check whether the object was created.
Class to uniquely identify a any structure of the PXD and SVD.
Definition VxdID.h:32
baseType getID() const
Get the unique id.
Definition VxdID.h:93
constexpr T square(const T &x)
Calculate the square of the input.
Definition MathHelpers.h:21
double sqrt(double a)
sqrt for double
Definition beamHelpers.h:28
void calculatePairingProb(TFile *pdfFile, std::vector< const SVDCluster * > &clusters, double &prob, double &error, bool useLegacyNaming)
Function to extract probability of correct (pair from signal hit) cluster pairing from preconfigured ...
void provideSVDClusterSingles(const StoreArray< SVDCluster > &svdClusters, StoreArray< SpacePointType > &spacePoints)
simply store one spacePoint for each existing SVDCluster.
void storeInputVectorFromSingleCluster(const SVDCluster *cls, std::vector< float > &inputVector, const SVDNoiseCalibrations &noiseCal)
Store the input values for SVDSpacePoint selection from the given SVDCluster.
void findPossibleCombinations(const Belle2::ClustersOnSensor &aSensor, std::vector< std::vector< const SVDCluster * > > &foundCombinations, const SVDHitTimeSelection &hitTimeCut, const bool &useSVDGroupInfo, const int &numberOfSignalGroups, const bool &formSingleSignalGroup, const SVDNoiseCalibrations &noiseCal, const DBObjPtr< SVDSpacePointSNRFractionSelector > &svdSpacePointSelectionFunction, bool useSVDSpacePointSNRFractionSelector)
stores all possible 2-Cluster-combinations.
void provideSVDClusterCombinations(const StoreArray< SVDCluster > &svdClusters, StoreArray< SpacePointType > &spacePoints, SVDHitTimeSelection &hitTimeCut, bool useQualityEstimator, TFile *pdfFile, bool useLegacyNaming, unsigned int numMaxSpacePoints, std::string m_eventLevelTrackingInfoName, const bool &useSVDGroupInfo, const int &numberOfSignalGroups, const bool &formSingleSignalGroup, const SVDNoiseCalibrations &noiseCal, const DBObjPtr< SVDSpacePointSNRFractionSelector > &svdSpacePointSelectionFunction, bool useSVDSpacePointSNRFractionSelector)
finds all possible combinations of U and V Clusters for SVDClusters.
void spPDFName(const VxdID &sensor, int uSize, int vSize, int maxClusterSize, std::string &PDFName, std::string &errorPDFName, bool useLegacyNaming)
Function to set name of PDF for spacePoint quality estimation.
Abstract base class for different kinds of events.
small struct for storing all clusters of the same sensor in one container.
std::vector< const SVDCluster * > clustersU
stores all SVDclusters of U type.
std::vector< const SVDCluster * > clustersV
stores all SVDclusters of V type.
VxdID vxdID
Id of sensor, TODO can be removed if struct is used in a map.
void addCluster(const SVDCluster *entry)
member function to automatically add the cluster to its corresponding entry