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