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 <mdst/dataobjects/EventLevelTrackingInfo.h>
24
25#include <vxd/dataobjects/VxdID.h>
26
27#include <unordered_map>
28
29#include <TH2.h>
30#include <math.h>
31#include <TFile.h>
32
33namespace Belle2 {
38
39
45
46 public:
47
49 inline void addCluster(const SVDCluster* entry)
50 {
51 vxdID = entry->getSensorID();
52 if (entry->isUCluster() == true) { clustersU.push_back(entry); return; }
53 clustersV.push_back(entry);
54 }
55
58
63 std::vector<const SVDCluster*> clustersU;
64
69 std::vector<const SVDCluster*> clustersV;
70
71 };
72
78 template <class SpacePointType> void provideSVDClusterSingles(const StoreArray<SVDCluster>& svdClusters,
79 StoreArray<SpacePointType>& spacePoints)
80 {
81 for (unsigned int i = 0; i < uint(svdClusters.getEntries()); ++i) {
82 const SVDCluster* currentCluster = svdClusters[i];
83 std::vector<const SVDCluster*> currentClusterCombi = { currentCluster };
84 SpacePointType* newSP = spacePoints.appendNew(currentClusterCombi);
85 newSP->addRelationTo(currentCluster);
86 }
87 }
88
89
90
93 std::vector<float>& inputVector,
94 const SVDNoiseCalibrations& noiseCal)
95 {
96 inputVector.clear();
97 inputVector.resize(3, 0.0);
98
99 auto shaperDigits = cls->getRelationsTo<SVDShaperDigit>();
100 float noise = 0;
101 for (auto iSD : shaperDigits) {
102 auto samples = iSD.getSamples();
103 std::vector<float> selectedSamples;
104 if (samples.size() == 6) {
105 Belle2::SVD::SVDMaxSumAlgorithm maxSum(samples);
106 auto maxSamples = maxSum.getSelectedSamples();
107 selectedSamples.assign(maxSamples.begin(), maxSamples.end());
108 } else {
109 selectedSamples.assign(samples.begin(), samples.end());
110 }
111 if (selectedSamples.size() < 3) continue;
112
113 inputVector[0] += selectedSamples[0];
114 inputVector[1] += selectedSamples[1];
115 inputVector[2] += selectedSamples[2];
116
117 VxdID thisSensorID = iSD.getSensorID();
118 bool thisSide = iSD.isUStrip();
119 int thisCellID = iSD.getCellID();
120 float thisNoise = noiseCal.getNoise(thisSensorID, thisSide, thisCellID);
121 noise += thisNoise * thisNoise;
122 }
123 noise = sqrt(noise);
124 inputVector[0] = inputVector[0] / noise;
125 inputVector[1] = inputVector[1] / noise;
126 inputVector[2] = inputVector[2] / noise;
127 }
128
138 std::vector< std::vector<const SVDCluster*> >& foundCombinations, const SVDHitTimeSelection& hitTimeCut,
139 const bool& useSVDGroupInfo, const int& numberOfSignalGroups, const bool& formSingleSignalGroup,
140 const SVDNoiseCalibrations& noiseCal, const DBObjPtr<SVDSpacePointSNRFractionSelector>& svdSpacePointSelectionFunction,
141 bool useSVDSpacePointSNRFractionSelector)
142 {
143
144 for (const SVDCluster* uCluster : aSensor.clustersU) {
145 if (! hitTimeCut.isClusterInTime(uCluster->getSensorID(), 1, uCluster->getClsTime())) {
146 B2DEBUG(29, "Cluster rejected due to timing cut. Cluster time: " << uCluster->getClsTime());
147 continue;
148 }
149 for (const SVDCluster* vCluster : aSensor.clustersV) {
150 if (! hitTimeCut.isClusterInTime(vCluster->getSensorID(), 0, vCluster->getClsTime())) {
151 B2DEBUG(29, "Cluster rejected due to timing cut. Cluster time: " << vCluster->getClsTime());
152 continue;
153 }
154
155 if (! hitTimeCut.areClusterTimesCompatible(vCluster->getSensorID(), uCluster->getClsTime(), vCluster->getClsTime())) {
156 B2DEBUG(29, "Cluster combination rejected due to timing cut. Cluster time U (" << uCluster->getClsTime() <<
157 ") is incompatible with Cluster time V (" << vCluster->getClsTime() << ")");
158 continue;
159 }
160
161 if (useSVDGroupInfo) {
162 const std::vector<int>& uTimeGroupId = uCluster->getTimeGroupId();
163 const std::vector<int>& vTimeGroupId = vCluster->getTimeGroupId();
164
165 if (int(uTimeGroupId.size()) && int(vTimeGroupId.size())) { // indirect check if the clusterizer module is disabled
166 bool isContinue = true;
167 for (auto& uitem : uTimeGroupId) {
168 if (uitem < 0 || uitem >= numberOfSignalGroups) continue;
169 for (auto& vitem : vTimeGroupId) {
170 if (vitem < 0 || vitem >= numberOfSignalGroups) continue;
171 if ((uitem == vitem) || formSingleSignalGroup) { isContinue = false; break; }
172 }
173 if (!isContinue) break;
174 }
175
176 if (isContinue) {
177 B2DEBUG(29, "Cluster combination rejected due to different time-group Id.");
178 continue;
179 }
180 }
181 }
182
183 if (useSVDSpacePointSNRFractionSelector) {
184 std::vector<float> inputU;
185 std::vector<float> inputV;
186
187 storeInputVectorFromSingleCluster(uCluster, inputU, noiseCal);
188 storeInputVectorFromSingleCluster(vCluster, inputV, noiseCal);
189
190 bool pass = svdSpacePointSelectionFunction->passSNRFractionSelection(inputU, inputV);
191 if (!pass) {
192 B2DEBUG(29, "Cluster combination rejected due to SVDSpacePointSNRFractionSelector");
193 continue;
194 }
195 }
196
197 foundCombinations.push_back({uCluster, vCluster});
198
199
200 }
201 }
202
203
204
205
206 }
207
212
213 inline void spPDFName(const VxdID& sensor, int uSize, int vSize, int maxClusterSize, std::string& PDFName,
214 std::string& errorPDFName, bool useLegacyNaming)
215 {
216 if (useLegacyNaming == true) {
217
218 if (uSize > maxClusterSize) uSize = maxClusterSize;
219 if (vSize > maxClusterSize) vSize = maxClusterSize;
220
221 std::string sensorName;
222
223 if (sensor.getLayerNumber() == 3) sensorName = "l3";
224 if (sensor.getLayerNumber() > 3 && sensor.getSensorNumber() == 1) sensorName = "trap";
225 if (sensor.getLayerNumber() > 3 && sensor.getSensorNumber() > 1) sensorName = "large";
226
227 PDFName = sensorName + std::to_string(uSize) + std::to_string(vSize);
228 errorPDFName = "error" + PDFName;
229 } else {
230
231 if (uSize > maxClusterSize) uSize = maxClusterSize;
232 if (vSize > maxClusterSize) vSize = maxClusterSize;
233
234 int layer = sensor.getLayerNumber();
235 int ladder = sensor.getLadderNumber();
236 int sens = sensor.getSensorNumber();
237
238 PDFName = std::to_string(layer) + "." + std::to_string(ladder) + "." + std::to_string(sens) + "." + std::to_string(
239 uSize) + "." + std::to_string(vSize);
240 errorPDFName = PDFName + "_Error";
241 }
242
243
244
245 }
246
247
253
254
255 inline void calculatePairingProb(TFile* pdfFile, std::vector<const SVDCluster*>& clusters, double& prob, double& error,
256 bool useLegacyNaming)
257 {
258
259 int maxSize;
260 int pdfEntries = pdfFile->GetListOfKeys()->GetSize();
261 if (useLegacyNaming == true) {
262 maxSize = floor(sqrt((pdfEntries - 4) / 6)); //4(time+size)+3(sensors)*2(prob/error)*size^2(u/v combo.)
263 } else {
264 maxSize = floor(sqrt((pdfEntries - 4) / 344)); //4(time+size)+172(sensorType)*2(prob/error)*size^2(u/v combo.)
265 }
266 std::string chargeProbInput;
267 std::string chargeErrorInput;
268
269 spPDFName(clusters[0]->getSensorID(), clusters[0]->getSize(), clusters[1]->getSize(), maxSize,
270 chargeProbInput, chargeErrorInput, useLegacyNaming);
271 std::string timeProbInput = "timeProb";
272 std::string timeErrorInput = "timeError";
273 std::string sizeProbInput = "sizeProb";
274 std::string sizeErrorInput = "sizeError";
275
276
277 TH2F* chargePDF = nullptr;
278 TH2F* chargeError = nullptr;
279 TH2F* timePDF = nullptr;
280 TH2F* timeError = nullptr;
281 TH2F* sizePDF = nullptr;
282 TH2F* sizeError = nullptr;
283
284 pdfFile->GetObject(chargeProbInput.c_str(), chargePDF);
285 pdfFile->GetObject(chargeErrorInput.c_str(), chargeError);
286 pdfFile->GetObject(timeProbInput.c_str(), timePDF);
287 pdfFile->GetObject(timeErrorInput.c_str(), timeError);
288 pdfFile->GetObject(sizeProbInput.c_str(), sizePDF);
289 pdfFile->GetObject(sizeErrorInput.c_str(), sizeError);
290
291 int xChargeBin = chargePDF->GetXaxis()->FindFixBin(clusters[0]->getCharge());
292 int yChargeBin = chargePDF->GetYaxis()->FindFixBin(clusters[1]->getCharge());
293
294 int xTimeBin = timePDF->GetXaxis()->FindFixBin(clusters[0]->getClsTime());
295 int yTimeBin = timePDF->GetYaxis()->FindFixBin(clusters[1]->getClsTime());
296
297
298 int xSizeBin = sizePDF->GetXaxis()->FindFixBin(clusters[0]->getSize());
299 int ySizeBin = sizePDF->GetYaxis()->FindFixBin(clusters[1]->getSize());
300
301 double chargeProb = chargePDF->GetBinContent(xChargeBin, yChargeBin);
302 double timeProb = timePDF->GetBinContent(xTimeBin, yTimeBin);
303 double sizeProb = sizePDF->GetBinContent(xSizeBin, ySizeBin);
304 double chargeProbError = chargePDF->GetBinContent(xChargeBin, yChargeBin);
305 double timeProbError = timePDF->GetBinContent(xTimeBin, yTimeBin);
306 double sizeProbError = sizePDF->GetBinContent(xSizeBin, ySizeBin);
307
308
309 if (chargeProbError == 0) {
310 B2DEBUG(21, "svdClusterProbabilityEstimator has not been run, spacePoint QI will return zero!");
311 }
312
313 prob = chargeProb * timeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQuality();
314 error = prob * sqrt(pow(timeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQuality() * chargeProbError, 2) +
315 pow(chargeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQuality() * timeProbError, 2) +
316 pow(chargeProb * timeProb * clusters[0]->getQuality() * clusters[1]->getQuality() * sizeProbError, 2) +
317 pow(chargeProb * timeProb * sizeProb * clusters[1]->getQuality() * clusters[0]->getQualityError(), 2) +
318 pow(chargeProb * timeProb * sizeProb * clusters[0]->getQuality() * clusters[1]->getQualityError(), 2));
319 }
320
328 template <class SpacePointType> void provideSVDClusterCombinations(const StoreArray<SVDCluster>& svdClusters,
329 StoreArray<SpacePointType>& spacePoints, SVDHitTimeSelection& hitTimeCut, bool useQualityEstimator, TFile* pdfFile,
330 bool useLegacyNaming, unsigned int numMaxSpacePoints, std::string m_eventLevelTrackingInfoName, const bool& useSVDGroupInfo,
331 const int& numberOfSignalGroups, const bool& formSingleSignalGroup,
332 const SVDNoiseCalibrations& noiseCal, const DBObjPtr<SVDSpacePointSNRFractionSelector>& svdSpacePointSelectionFunction,
333 bool useSVDSpacePointSNRFractionSelector)
334 {
335 std::unordered_map<VxdID::baseType, ClustersOnSensor>
336 activatedSensors; // collects one entry per sensor, each entry will contain all Clusters on it TODO: better to use a sorted vector/list?
337 std::vector<std::vector<const SVDCluster*> >
338 foundCombinations; // collects all combinations of Clusters which were possible (condition: 1u+1v-Cluster on the same sensor)
339
340 // sort Clusters by sensor. After the loop, each entry of activatedSensors contains all U and V-type clusters on that sensor
341 for (unsigned int i = 0; i < uint(svdClusters.getEntries()); ++i) {
342 SVDCluster* currentCluster = svdClusters[i];
343
344 activatedSensors[currentCluster->getSensorID().getID()].addCluster(currentCluster);
345 }
346
347
348 for (auto& aSensor : activatedSensors)
349 findPossibleCombinations(aSensor.second, foundCombinations, hitTimeCut, useSVDGroupInfo, numberOfSignalGroups,
350 formSingleSignalGroup,
351 noiseCal, svdSpacePointSelectionFunction, useSVDSpacePointSNRFractionSelector);
352
353 // Do not make space-points if their number would be too large to be considered by tracking
354 if (foundCombinations.size() > numMaxSpacePoints) {
355 StoreObjPtr<EventLevelTrackingInfo> m_eventLevelTrackingInfo(m_eventLevelTrackingInfoName);
356 if (m_eventLevelTrackingInfo.isValid()) {
357 m_eventLevelTrackingInfo->setSVDSpacePointCreatorAbortionFlag();
358 }
359 return;
360 }
361
362 for (auto& clusterCombi : foundCombinations) {
363 SpacePointType* newSP = spacePoints.appendNew(clusterCombi);
364 if (useQualityEstimator == true) {
365 double probability;
366 double error;
367 calculatePairingProb(pdfFile, clusterCombi, probability, error, useLegacyNaming);
368 newSP->setQualityEstimation(probability);
369 newSP->setQualityEstimationError(error);
370 }
371 for (auto* cluster : clusterCombi) {
372 newSP->addRelationTo(cluster, cluster->isUCluster() ? 1. : -1.);
373 }
374 }
375 }
376
377
379} //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
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