Belle II Software  release-08-01-10
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 
32 namespace 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.
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 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.
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 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.
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