Belle II Software development
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
14using namespace std;
15using namespace Belle2;
16
17REG_MODULE(SVDCrossTalkFinder);
18
19SVDCrossTalkFinderModule::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
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
209void 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.
virtual void initialize() override
Init the module.
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.
Class to facilitate easy access to sensor information of the VXD like coordinate transformations or p...
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:649
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.
STL namespace.