Belle II Software prerelease-11-00-00e
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 <utility>
12#include <vector>
13
14#include <svd/calibration/SVDHitTimeSelection.h>
15#include <svd/calibration/SVDNoiseCalibrations.h>
16#include <svd/dataobjects/SVDCluster.h>
17#include <svd/dataobjects/SVDShaperDigit.h>
18#include <svd/dbobjects/SVDSpacePointSNRFractionSelector.h>
19#include <svd/reconstruction/SVDMaxSumAlgorithm.h>
20
21#include <framework/datastore/RelationArray.h>
22#include <framework/datastore/StoreArray.h>
23#include <framework/datastore/StoreObjPtr.h>
24#include <framework/database/DBObjPtr.h>
25#include <mdst/dataobjects/EventLevelTrackingInfo.h>
26
27#include <vxd/dataobjects/VxdID.h>
28
29#include <unordered_map>
30
31#include <TH2.h>
32#include <math.h>
33#include <TFile.h>
34
35namespace Belle2 {
40
41
47
48 public:
49
56 inline void addCluster(const SVDCluster* entry, int index)
57 {
58 vxdID = entry->getSensorID();
59 if (entry->isUCluster() == true) {
60 clustersU.push_back(entry);
61 indicesU.push_back(index);
62 return;
63 }
64 clustersV.push_back(entry);
65 indicesV.push_back(index);
66 }
67
70
75 std::vector<const SVDCluster*> clustersU;
76
81 std::vector<const SVDCluster*> clustersV;
82
84 std::vector<int> indicesU;
85
87 std::vector<int> indicesV;
88
89 };
90
96 template <class SpacePointType> void provideSVDClusterSingles(const StoreArray<SVDCluster>& svdClusters,
97 StoreArray<SpacePointType>& spacePoints)
98 {
99 // RelationArray is much cheaper than addRelationTo
100 RelationArray spacePointsToClusters(spacePoints, svdClusters);
101 for (unsigned int i = 0; i < uint(svdClusters.getEntries()); ++i) {
102 const SVDCluster* currentCluster = svdClusters[i];
103 std::vector<const SVDCluster*> currentClusterCombi = { currentCluster };
104 const int spacePointIndex = spacePoints.getEntries();
105 spacePoints.appendNew(currentClusterCombi);
106 spacePointsToClusters.add(spacePointIndex, i);
107 }
108 }
109
110
111
114 std::vector<float>& inputVector,
115 const SVDNoiseCalibrations& noiseCal)
116 {
117 inputVector.clear();
118 inputVector.resize(3, 0.0);
119
120 auto shaperDigits = cls->getRelationsTo<SVDShaperDigit>();
121 float noise = 0;
122 for (auto iSD : shaperDigits) {
123 auto samples = iSD.getSamples();
124 std::vector<float> selectedSamples;
125 if (samples.size() == 6) {
126 Belle2::SVD::SVDMaxSumAlgorithm maxSum(samples);
127 auto maxSamples = maxSum.getSelectedSamples();
128 selectedSamples.assign(maxSamples.begin(), maxSamples.end());
129 } else {
130 selectedSamples.assign(samples.begin(), samples.end());
131 }
132 if (selectedSamples.size() < 3) continue;
133
134 inputVector[0] += selectedSamples[0];
135 inputVector[1] += selectedSamples[1];
136 inputVector[2] += selectedSamples[2];
137
138 VxdID thisSensorID = iSD.getSensorID();
139 bool thisSide = iSD.isUStrip();
140 int thisCellID = iSD.getCellID();
141 float thisNoise = noiseCal.getNoise(thisSensorID, thisSide, thisCellID);
142 noise += thisNoise * thisNoise;
143 }
144 noise = sqrt(noise);
145 inputVector[0] = inputVector[0] / noise;
146 inputVector[1] = inputVector[1] / noise;
147 inputVector[2] = inputVector[2] / noise;
148 }
149
159 std::vector< std::vector<const SVDCluster*> >& foundCombinations,
160 std::vector< std::pair<int, int> >& foundCombinationIndices, const SVDHitTimeSelection& hitTimeCut,
161 const bool& useSVDGroupInfo, const int& numberOfSignalGroups, const bool& formSingleSignalGroup,
162 const SVDNoiseCalibrations& noiseCal, const DBObjPtr<SVDSpacePointSNRFractionSelector>& svdSpacePointSelectionFunction,
163 bool useSVDSpacePointSNRFractionSelector)
164 {
165
166 for (size_t iU = 0; iU < aSensor.clustersU.size(); ++iU) {
167 const SVDCluster* uCluster = aSensor.clustersU[iU];
168 if (! hitTimeCut.isClusterInTime(uCluster->getSensorID(), 1, uCluster->getClsTime())) {
169 B2DEBUG(29, "Cluster rejected due to timing cut. Cluster time: " << uCluster->getClsTime());
170 continue;
171 }
172 for (size_t iV = 0; iV < aSensor.clustersV.size(); ++iV) {
173 const SVDCluster* vCluster = aSensor.clustersV[iV];
174 if (! hitTimeCut.isClusterInTime(vCluster->getSensorID(), 0, vCluster->getClsTime())) {
175 B2DEBUG(29, "Cluster rejected due to timing cut. Cluster time: " << vCluster->getClsTime());
176 continue;
177 }
178
179 if (! hitTimeCut.areClusterTimesCompatible(vCluster->getSensorID(), uCluster->getClsTime(), vCluster->getClsTime())) {
180 B2DEBUG(29, "Cluster combination rejected due to timing cut. Cluster time U (" << uCluster->getClsTime() <<
181 ") is incompatible with Cluster time V (" << vCluster->getClsTime() << ")");
182 continue;
183 }
184
185 if (useSVDGroupInfo) {
186 const std::vector<int>& uTimeGroupId = uCluster->getTimeGroupId();
187 const std::vector<int>& vTimeGroupId = vCluster->getTimeGroupId();
188
189 if (int(uTimeGroupId.size()) && int(vTimeGroupId.size())) { // indirect check if the clusterizer module is disabled
190 bool isContinue = true;
191 for (auto& uitem : uTimeGroupId) {
192 if (uitem < 0 || uitem >= numberOfSignalGroups) continue;
193 for (auto& vitem : vTimeGroupId) {
194 if (vitem < 0 || vitem >= numberOfSignalGroups) continue;
195 if ((uitem == vitem) || formSingleSignalGroup) { isContinue = false; break; }
196 }
197 if (!isContinue) break;
198 }
199
200 if (isContinue) {
201 B2DEBUG(29, "Cluster combination rejected due to different time-group Id.");
202 continue;
203 }
204 }
205 }
206
207 if (useSVDSpacePointSNRFractionSelector) {
208 std::vector<float> inputU;
209 std::vector<float> inputV;
210
211 storeInputVectorFromSingleCluster(uCluster, inputU, noiseCal);
212 storeInputVectorFromSingleCluster(vCluster, inputV, noiseCal);
213
214 bool pass = svdSpacePointSelectionFunction->passSNRFractionSelection(inputU, inputV);
215 if (!pass) {
216 B2DEBUG(29, "Cluster combination rejected due to SVDSpacePointSNRFractionSelector");
217 continue;
218 }
219 }
220
221 foundCombinations.push_back({uCluster, vCluster});
222 foundCombinationIndices.emplace_back(aSensor.indicesU[iU], aSensor.indicesV[iV]);
223
224
225 }
226 }
227
228
229
230
231 }
232
237
238 inline void spPDFName(const VxdID& sensor, int uSize, int vSize, int maxClusterSize, std::string& PDFName,
239 std::string& errorPDFName, bool useLegacyNaming)
240 {
241 if (useLegacyNaming == true) {
242
243 if (uSize > maxClusterSize) uSize = maxClusterSize;
244 if (vSize > maxClusterSize) vSize = maxClusterSize;
245
246 std::string sensorName;
247
248 if (sensor.getLayerNumber() == 3) sensorName = "l3";
249 if (sensor.getLayerNumber() > 3 && sensor.getSensorNumber() == 1) sensorName = "trap";
250 if (sensor.getLayerNumber() > 3 && sensor.getSensorNumber() > 1) sensorName = "large";
251
252 PDFName = sensorName + std::to_string(uSize) + std::to_string(vSize);
253 errorPDFName = "error" + PDFName;
254 } else {
255
256 if (uSize > maxClusterSize) uSize = maxClusterSize;
257 if (vSize > maxClusterSize) vSize = maxClusterSize;
258
259 int layer = sensor.getLayerNumber();
260 int ladder = sensor.getLadderNumber();
261 int sens = sensor.getSensorNumber();
262
263 PDFName = std::to_string(layer) + "." + std::to_string(ladder) + "." + std::to_string(sens) + "." + std::to_string(
264 uSize) + "." + std::to_string(vSize);
265 errorPDFName = PDFName + "_Error";
266 }
267
268
269
270 }
271
272
278
279
280 inline void calculatePairingProb(TFile* pdfFile, std::vector<const SVDCluster*>& clusters, double& prob, double& error,
281 bool useLegacyNaming)
282 {
283
284 int maxSize;
285 int pdfEntries = pdfFile->GetListOfKeys()->GetSize();
286 if (useLegacyNaming == true) {
287 maxSize = floor(sqrt((pdfEntries - 4) / 6)); //4(time+size)+3(sensors)*2(prob/error)*size^2(u/v combo.)
288 } else {
289 maxSize = floor(sqrt((pdfEntries - 4) / 344)); //4(time+size)+172(sensorType)*2(prob/error)*size^2(u/v combo.)
290 }
291 std::string chargeProbInput;
292 std::string chargeErrorInput;
293
294 spPDFName(clusters[0]->getSensorID(), clusters[0]->getSize(), clusters[1]->getSize(), maxSize,
295 chargeProbInput, chargeErrorInput, useLegacyNaming);
296 std::string timeProbInput = "timeProb";
297 std::string timeErrorInput = "timeError";
298 std::string sizeProbInput = "sizeProb";
299 std::string sizeErrorInput = "sizeError";
300
301
302 TH2F* chargePDF = nullptr;
303 TH2F* chargeError = nullptr;
304 TH2F* timePDF = nullptr;
305 TH2F* timeError = nullptr;
306 TH2F* sizePDF = nullptr;
307 TH2F* sizeError = nullptr;
308
309 pdfFile->GetObject(chargeProbInput.c_str(), chargePDF);
310 pdfFile->GetObject(chargeErrorInput.c_str(), chargeError);
311 pdfFile->GetObject(timeProbInput.c_str(), timePDF);
312 pdfFile->GetObject(timeErrorInput.c_str(), timeError);
313 pdfFile->GetObject(sizeProbInput.c_str(), sizePDF);
314 pdfFile->GetObject(sizeErrorInput.c_str(), sizeError);
315
316 int xChargeBin = chargePDF->GetXaxis()->FindFixBin(clusters[0]->getCharge());
317 int yChargeBin = chargePDF->GetYaxis()->FindFixBin(clusters[1]->getCharge());
318
319 int xTimeBin = timePDF->GetXaxis()->FindFixBin(clusters[0]->getClsTime());
320 int yTimeBin = timePDF->GetYaxis()->FindFixBin(clusters[1]->getClsTime());
321
322
323 int xSizeBin = sizePDF->GetXaxis()->FindFixBin(clusters[0]->getSize());
324 int ySizeBin = sizePDF->GetYaxis()->FindFixBin(clusters[1]->getSize());
325
326 double chargeProb = chargePDF->GetBinContent(xChargeBin, yChargeBin);
327 double timeProb = timePDF->GetBinContent(xTimeBin, yTimeBin);
328 double sizeProb = sizePDF->GetBinContent(xSizeBin, ySizeBin);
329 double chargeProbError = chargePDF->GetBinContent(xChargeBin, yChargeBin);
330 double timeProbError = timePDF->GetBinContent(xTimeBin, yTimeBin);
331 double sizeProbError = sizePDF->GetBinContent(xSizeBin, ySizeBin);
332
333
334 if (chargeProbError == 0) {
335 B2DEBUG(21, "svdClusterProbabilityEstimator has not been run, spacePoint QI will return zero!");
336 }
337
338 prob = chargeProb * timeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQuality();
339 error = prob * sqrt(pow(timeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQuality() * chargeProbError, 2) +
340 pow(chargeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQuality() * timeProbError, 2) +
341 pow(chargeProb * timeProb * clusters[0]->getQuality() * clusters[1]->getQuality() * sizeProbError, 2) +
342 pow(chargeProb * timeProb * sizeProb * clusters[1]->getQuality() * clusters[0]->getQualityError(), 2) +
343 pow(chargeProb * timeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQualityError(), 2));
344 }
345
353 template <class SpacePointType> void provideSVDClusterCombinations(const StoreArray<SVDCluster>& svdClusters,
354 StoreArray<SpacePointType>& spacePoints, SVDHitTimeSelection& hitTimeCut, bool useQualityEstimator, TFile* pdfFile,
355 bool useLegacyNaming, unsigned int numMaxSpacePoints, std::string m_eventLevelTrackingInfoName, const bool& useSVDGroupInfo,
356 const int& numberOfSignalGroups, const bool& formSingleSignalGroup,
357 const SVDNoiseCalibrations& noiseCal, const DBObjPtr<SVDSpacePointSNRFractionSelector>& svdSpacePointSelectionFunction,
358 bool useSVDSpacePointSNRFractionSelector)
359 {
360 std::unordered_map<VxdID::baseType, ClustersOnSensor>
361 activatedSensors; // collects one entry per sensor, each entry will contain all Clusters on it TODO: better to use a sorted vector/list?
362 std::vector<std::vector<const SVDCluster*> >
363 foundCombinations; // collects all combinations of Clusters which were possible (condition: 1u+1v-Cluster on the same sensor)
364 std::vector<std::pair<int, int> >
365 foundCombinationIndices; // StoreArray indices of the (u, v) clusters of each entry of foundCombinations
366
367 // sort Clusters by sensor. After the loop, each entry of activatedSensors contains all U and V-type clusters on that sensor
368 for (unsigned int i = 0; i < uint(svdClusters.getEntries()); ++i) {
369 SVDCluster* currentCluster = svdClusters[i];
370
371 activatedSensors[currentCluster->getSensorID().getID()].addCluster(currentCluster, i);
372 }
373
374 for (auto& aSensor : activatedSensors)
375 findPossibleCombinations(aSensor.second, foundCombinations, foundCombinationIndices, hitTimeCut, useSVDGroupInfo,
376 numberOfSignalGroups, formSingleSignalGroup, noiseCal, svdSpacePointSelectionFunction,
377 useSVDSpacePointSNRFractionSelector);
378
379 // Do not make space-points if their number would be too large to be considered by tracking
380 if (foundCombinations.size() > numMaxSpacePoints) {
381 StoreObjPtr<EventLevelTrackingInfo> m_eventLevelTrackingInfo(m_eventLevelTrackingInfoName);
382 if (m_eventLevelTrackingInfo.isValid()) {
383 m_eventLevelTrackingInfo->setSVDSpacePointCreatorAbortionFlag();
384 }
385 return;
386 }
387
388 // RelationArray is much cheaper than addRelationTo
389 // The relation weight codes the type of the cluster: +1 for u and -1 for v.
390 RelationArray spacePointsToClusters(spacePoints, svdClusters);
391
392 for (size_t iCombi = 0; iCombi < foundCombinations.size(); ++iCombi) {
393 auto& clusterCombi = foundCombinations[iCombi];
394 const int spacePointIndex = spacePoints.getEntries();
395 SpacePointType* newSP = spacePoints.appendNew(clusterCombi);
396 if (useQualityEstimator == true) {
397 double probability;
398 double error;
399 calculatePairingProb(pdfFile, clusterCombi, probability, error, useLegacyNaming);
400 newSP->setQualityEstimation(probability);
401 newSP->setQualityEstimationError(error);
402 }
403 // the first cluster of the combination is always the u one, the second one the v one
404 spacePointsToClusters.add(spacePointIndex, foundCombinationIndices[iCombi].first, 1.);
405 spacePointsToClusters.add(spacePointIndex, foundCombinationIndices[iCombi].second, -1.);
406 }
407 }
408
409
411} //Belle2 namespace
Class for accessing objects in the database.
Definition DBObjPtr.h:21
Low-level class to create/modify relations between StoreArrays.
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
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
double sqrt(double a)
sqrt for double
Definition beamHelpers.h:28
void findPossibleCombinations(const Belle2::ClustersOnSensor &aSensor, std::vector< std::vector< const SVDCluster * > > &foundCombinations, std::vector< std::pair< int, int > > &foundCombinationIndices, 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 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 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.
std::vector< int > indicesV
stores the StoreArray indices of the clusters in clustersV, in the same order
std::vector< int > indicesU
stores the StoreArray indices of the clusters in clustersU, in the same order
void addCluster(const SVDCluster *entry, int index)
member function to automatically add the cluster to its corresponding entry