Belle II Software  release-08-01-10
SVDCrossTalkFinderModule.cc
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 #include <svd/modules/svdCrossTalkFinder/SVDCrossTalkFinderModule.h>
10 #include <svd/modules/svdCrossTalkFinder/SVDCrossTalkFinderHelperFunctions.h>
11 
12 #include <vxd/geometry/GeoCache.h>
13 
14 using namespace std;
15 using namespace Belle2;
16 
17 REG_MODULE(SVDCrossTalkFinder);
18 
19 SVDCrossTalkFinderModule::SVDCrossTalkFinderModule() : Module()
20 
21 {
22  setDescription("Detect SVDRecoDigits created from cross-talk present in the origami sensors");
23 
24  setPropertyFlags(c_ParallelProcessingCertified);
25 
26  addParam("SVDRecoDigits", m_svdRecoDigitsName,
27  "SVDRecoDigit collection name", string(""));
28 
29  addParam("createCalibrationPayload", m_createCalibrationPayload,
30  "Create cross-talk strip channel payload", true);
31 
32  addParam("outputFilename", m_outputFilename,
33  "Filename of root file for calibration payload", std::string("crossTalkStripsCalibration.root"));
34 
35  addParam("uSideOccupancyFactor", m_uSideOccupancyFactor,
36  "Multiple of the average occupancy for high occupancy strip classification", 2);
37 
38  addParam("vSideOccupancyFactor", m_vSideOccupancyFactor,
39  "Multiple of the average occupancy for high occupancy strip classification", 2);
40 
41  addParam("nAPVFactor", m_nAPVFactor,
42  "Number of APV chips with at least one high occupancy strips in event required for cross talk flag", 30);
43 
44 }
45 
46 
47 void SVDCrossTalkFinderModule::initialize()
48 {
49 
51  std::string sensorName;
52  TH1F* sensorHist;
53  //Prepare histograms for payload.
55  for (auto& layers : geo.getLayers(VXD::SensorInfoBase::SVD)) {
56  for (auto& ladders : geo.getLadders(layers)) {
57  for (auto& sensors : geo.getSensors(ladders)) {
58  for (int side = 0; side <= 1; side++) {
59  occupancyPDFName(sensors, side, sensorName);
60  if (m_sensorHistograms.count(sensorName) == 0) {
61  if (layers.getLayerNumber() == 3 or side == 1) {
62  sensorHist = new TH1F(sensorName.c_str(), "", 768, 0, 768);
63  } else {
64  sensorHist = new TH1F(sensorName.c_str(), "", 512, 0, 512);
65  }
66  m_sensorHistograms[sensorName] = sensorHist;
67 
68  }
69 
70  }
71  }
72  }
73  }
74  }
75 
76  // prepare storeArray
78  m_svdEventInfo.isRequired();
79 
80 }
81 
83 {
84 
85  vector<std::string> highOccChips_uSide ;
86  vector<std::string> highOccChips_vSide ;
87  vector<std::string> highOccChipsStripNum_uSide ;
88  vector<std::string> highOccChipsStripNum_vSide ;
89  vector<std::string> clusterStrips_uSide ;
90  vector<std::string> clusterStrips_vSide ;
91  vector<std::string> clusterChips_uSide ;
92  vector<int> strips_uSide;
93  vector<int> strips_vSide;
94 
95  for (auto& svdRecoDigit : m_svdRecoDigits) {
96  //Remove L3 and +fw sensors, not affected by cross-talk
97  if (svdRecoDigit.getSensorID().getLayerNumber() == 3 or svdRecoDigit.getSensorID().getSensorNumber() == 1) {
98  continue;
99  }
100 
101  int side = svdRecoDigit.isUStrip();
102  std::string sensorName;
103  occupancyPDFName(svdRecoDigit.getSensorID(), side, sensorName);
104 
105  double sensorAverage = 0.;
106  calculateAverage(svdRecoDigit.getSensorID(), sensorAverage, side);
107  int stripID = svdRecoDigit.getCellID();
108  std::string sensorStripNum = sensorName + "." + std::to_string(stripID);
109  double stripOccupancy = m_OccupancyCal.getOccupancy(svdRecoDigit.getSensorID(), side, stripID);
110  //Clustering only works assuming digits are ordered.//
111 
112  if (side == 1 && stripOccupancy > (m_uSideOccupancyFactor * sensorAverage)) {
113 
114  int adjacentStrip = 0;
115  if (!strips_uSide.empty()) {
116  adjacentStrip = stripID - strips_uSide.back();
117  }
118  strips_uSide.push_back(stripID);
119  if (!highOccChips_uSide.empty() && sensorName == highOccChips_uSide.back() && adjacentStrip == 1) {
120  clusterChips_uSide.push_back(sensorName);
121  if (clusterStrips_uSide.empty() || clusterStrips_uSide.back() != sensorStripNum) {
122  clusterStrips_uSide.push_back(highOccChipsStripNum_uSide.back());
123  }
124  clusterStrips_uSide.push_back(sensorStripNum);
125  }
126  highOccChipsStripNum_uSide.push_back(sensorStripNum);
127  highOccChips_uSide.push_back(sensorName);
128  }
129 
130  if (side == 0 && stripOccupancy > (m_vSideOccupancyFactor * sensorAverage)) {
131  int adjacentStrip = 0;
132  if (!strips_vSide.empty()) {
133  adjacentStrip = stripID - strips_vSide.back();
134  }
135  strips_vSide.push_back(stripID);
136  if (!highOccChips_vSide.empty() && sensorName == highOccChips_vSide.back() && adjacentStrip == 1) {
137  if (clusterStrips_vSide.empty() || clusterStrips_vSide.back() != sensorStripNum) {
138  clusterStrips_vSide.push_back(highOccChipsStripNum_vSide.back());
139  }
140  clusterStrips_vSide.push_back(sensorStripNum);
141  }
142  highOccChipsStripNum_vSide.push_back(sensorStripNum);
143  highOccChips_vSide.push_back(sensorName);
144  }
145 
146  }
147 
148  std::sort(clusterChips_uSide.begin(), clusterChips_uSide.end());
149  clusterChips_uSide.erase(unique(clusterChips_uSide.begin(), clusterChips_uSide.end()), clusterChips_uSide.end());
150  int numberOfClusterChips = std::distance(clusterChips_uSide.begin(), std::unique(clusterChips_uSide.begin(),
151  clusterChips_uSide.end()));
152 
153 // Crosstalk events flagged using u-side
154  if (numberOfClusterChips > m_nAPVFactor) {
155  m_svdEventInfo->setCrossTalk(true);
156  for (auto& svdRecoDigit : m_svdRecoDigits) {
157  std::string sensorID = svdRecoDigit.getSensorID();
158  std::string digitID = sensorID + "." + std::to_string(svdRecoDigit.isUStrip());
159  std::string stripID = digitID + "." + std::to_string(svdRecoDigit.getCellID());
161  if (std::find(clusterStrips_uSide.begin(), clusterStrips_uSide.end(), stripID) != clusterStrips_uSide.end()) {
162  std::string sensorName;
163  occupancyPDFName(svdRecoDigit.getSensorID(), svdRecoDigit.isUStrip(), sensorName);
164  auto xTalkStrip = m_sensorHistograms.at(sensorName);
165  //Only fill bin once
166  if (xTalkStrip->GetBinContent(svdRecoDigit.getCellID()) < 1.) xTalkStrip->Fill(svdRecoDigit.getCellID(), true);
167  }
168  if (std::find(clusterStrips_vSide.begin(), clusterStrips_vSide.end(), stripID) != clusterStrips_vSide.end()) {
169  std::string sensorName;
170  occupancyPDFName(svdRecoDigit.getSensorID(), svdRecoDigit.isUStrip(), sensorName);
171  auto xTalkStrip = m_sensorHistograms.at(sensorName);
172  if (xTalkStrip->GetBinContent(svdRecoDigit.getCellID()) < 1.) xTalkStrip->Fill(svdRecoDigit.getCellID(), true);
173  }
174 
175  }
176 
177  }//reco digit loop
178  }
179 
180 }
181 
183 {
184  B2INFO("SVDCrossTalkFinderModule::terminate");
185 
187  m_histogramFile = new TFile(m_outputFilename.c_str(), "RECREATE");
188  m_histogramFile->cd();
189  std::string sensorName;
191  for (auto& layers : geo.getLayers(VXD::SensorInfoBase::SVD)) {
192  for (auto& ladders : geo.getLadders(layers)) {
193  for (auto& sensors : geo.getSensors(ladders)) {
194  for (int side = 0; side <= 1; side++) {
195 
196  occupancyPDFName(sensors, side, sensorName);
197  auto sensorOnMap = m_sensorHistograms.at(sensorName);
198  sensorOnMap->Write();
199 
200  }
201  }
202  }
203  }
204  m_histogramFile->Close();
205  }
206 }
207 
208 
209 void SVDCrossTalkFinderModule::calculateAverage(const VxdID& sensorID, double& mean, int side)
210 {
211  double nBins = 0;
212  if (side == 1) nBins = 768; //U-side 768 channels
213  else nBins = 512;
214  double count = 0;
215  for (int i = 0; i < nBins; i++) {
216  count += m_OccupancyCal.getOccupancy(sensorID, side, i);
217  }
218  mean = count / nBins;
219 }
Base class for Modules.
Definition: Module.h:72
StoreArray< SVDRecoDigit > m_svdRecoDigits
The storeArray for svdRecoDigits.
StoreObjPtr< SVDEventInfo > m_svdEventInfo
The storeObject for svdEventInfo.
virtual void event() override
Event.
int m_uSideOccupancyFactor
Parameter to define high occupancy strips (some multiple above sensor average occupancy)
bool m_createCalibrationPayload
If true module will produce and write-out payload for SVDCrossTalkStripsCalibrations.
virtual void terminate() override
Final output.
int m_vSideOccupancyFactor
Parameter to define high occupancy strips (some multiple above sensor average occupancy)
std::string m_outputFilename
Filename of root file containing cross-talk strip calibration payload.
std::string m_svdRecoDigitsName
SVDRecoDigit collection name.
std::map< std::string, TH1F * > m_sensorHistograms
map to store cross-talk strip histograms
void calculateAverage(const VxdID &sensorID, double &mean, int side)
Function to calculate sensor average occupancy.
SVDOccupancyCalibrations m_OccupancyCal
SVDOccupancy calibrations db object.
TFile * m_histogramFile
Pointer to root TFile containing histograms for calibration payload.
int m_nAPVFactor
Parameter to set number of sensors with possible cross-talk clusters required for event flagging.
float getOccupancy(const VxdID &sensorID, const bool &isU, const unsigned short &strip) const
This is the method for getting the occupancy, or the deviation from the average, still to be decided.
Class to faciliate easy access to sensor information of the VXD like coordinate transformations or pi...
Definition: GeoCache.h:39
const std::set< Belle2::VxdID > getLayers(SensorInfoBase::SensorType sensortype=SensorInfoBase::VXD)
Return a set of all known Layers.
Definition: GeoCache.cc:176
const std::set< Belle2::VxdID > & getSensors(Belle2::VxdID ladder) const
Return a set of all sensor IDs belonging to a given ladder.
Definition: GeoCache.cc:204
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
const std::set< Belle2::VxdID > & getLadders(Belle2::VxdID layer) const
Return a set of all ladder IDs belonging to a given layer.
Definition: GeoCache.cc:193
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
void occupancyPDFName(const VxdID &sensor, int side, std::string &PDFName)
Function to maintain common naming convention between calibration occupancy file generation and occup...
Abstract base class for different kinds of events.