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.
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.
STL namespace.