Belle II Software  release-05-02-19
SVDDQMDoseModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2021 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Ludovico Massaccesi *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <svd/modules/svdDQM/SVDDQMDoseModule.h>
12 // Includes for the forward declarations
13 #include <rawdata/dataobjects/RawFTSW.h>
14 #include <svd/dataobjects/SVDShaperDigit.h>
15 #include <mdst/dataobjects/TRGSummary.h>
16 #include <vxd/dataobjects/VxdID.h>
17 // #include <svd/calibration/SVDFADCMaskedStrips.h>
18 // Other includes
19 #include <vxd/geometry/GeoCache.h>
20 #include <svd/geometry/SensorInfo.h>
21 #include <TDirectory.h>
22 #include <TString.h>
23 #include <TMath.h>
24 #include <cmath>
25 
26 using namespace std;
27 using namespace Belle2;
28 using namespace Belle2::SVD;
29 
30 REG_MODULE(SVDDQMDose)
31 
33 {
34  setDescription("The SVD dose-monitoring DQM module. Fills histograms of the SVD's instantaneous occupancy and "
35  "of SVD occupancy vs time since last injection and time in beam revolution cycle.");
36  setPropertyFlags(c_ParallelProcessingCertified);
37  addParam("eventTypeFilter", m_eventFilter,
38  "Types of events to include in the plots (1 = less than noInjectionTimeout after HER injection, "
39  "2 = less than noInjectionTimeout after LER injection, 4 = more than noInjectionTimeout after any "
40  "injection; bitwise or combinations are possible; see SVDDQMDoseModule::EEventType).", 7U);
41  addParam("histogramDirectoryName", m_histogramDirectoryName,
42  "Name of the directory where histograms will be placed in the ROOT file.",
43  std::string("SVDDose"));
44  addParam("offlineZSShaperDigits", m_SVDShaperDigitsName,
45  "Name of the SVDShaperDigits to use for computing occupancy (default is SVDShaperDigitsZS5).",
46  std::string("SVDShaperDigitsZS5"));
47  addParam("noInjectionTimeout", m_noInjectionTime,
48  "Time (microseconds) since last injection after which an event is considered \"No Injection\". "
49  "Also the limit for the x axis of the 2D histograms.",
50  30e3);
51  m_trgTypes.push_back(TRGSummary::TTYP_POIS);
52  addParam("trgTypes", m_trgTypes,
53  "Trigger types for event selection. Empty to select everything. "
54  "Default is only Poisson w/o inj. veto.",
55  m_trgTypes);
56 }
57 
58 void SVDDQMDoseModule::defineHisto()
59 {
60  TDirectory* oldDir = gDirectory;
61  if (m_histogramDirectoryName != "") {
62  oldDir->mkdir(m_histogramDirectoryName.c_str());
63  oldDir->cd(m_histogramDirectoryName.c_str());
64  }
65 
66  // Round noInjectionTimeout to the nearest multiple of the revolution cycle
67  m_noInjectionTime = round(m_noInjectionTime / c_revolutionTime) * c_revolutionTime;
68 
69  h_nEvtsVsTime = new TH2F(
70  "SVDEvtsVsTime",
71  "SVD Events;Time since last injection [#mus];Time in beam cycle [#mus];Events / bin",
72  500, 0, m_noInjectionTime, 100, 0, c_revolutionTime);
73 
74  m_groupOccupanciesU.reserve(c_sensorGroups.size()); // Allocate memory only once
75  TString name = "SVDInstOccu_";
76  TString title = "SVD Instantaneous Occupancy ";
77  TString axisTitle = ";Occupancy [%];Count / bin";
78  for (const SensorGroup& group : c_sensorGroups) {
79  m_groupOccupanciesU.push_back(
80  new TH1F(name + group.nameSuffix + "U",
81  title + group.titleSuffix + " U-side" + axisTitle,
82  group.nBins, group.xMin, group.xMax));
83  }
84 
85  m_groupNHitsU.reserve(c_sensorGroups.size()); // Allocate memory only once
86  name = "SVDHitsVsTime_";
87  title = "SVD Hits ";
88  axisTitle = ";Time since last injection [#mus];Time in beam cycle[#mus];Hits / bin";
89  for (const SensorGroup& group : c_sensorGroups) {
90  m_groupNHitsU.push_back(
91  new TH2F(name + group.nameSuffix + "U",
92  title + group.titleSuffix + " U-side" + axisTitle,
93  500, 0, m_noInjectionTime, 100, 0, c_revolutionTime));
94  }
95 
96  // Nbins for 1D histos such that bin width = beam_revolution_time / 2
97  int nb1 = TMath::Nint(m_noInjectionTime * 2.0 / c_revolutionTime);
98  h_nEvtsVsTime1 = new TH1F(
99  "SVDEvtsVsTime1", "SVD Events;Time since last injection [#mus];Events / bin",
100  nb1, 0, m_noInjectionTime);
101 
102  m_groupNHits1U.reserve(c_sensorGroups.size()); // Allocate memory only once
103  name = "SVDHitsVsTime1_";
104  title = "SVD Hits ";
105  axisTitle = ";Time since last injection [#mus];Hits / bin";
106  for (const SensorGroup& group : c_sensorGroups) {
107  m_groupNHits1U.push_back(
108  new TH1F(name + group.nameSuffix + "U",
109  title + group.titleSuffix + " U-side" + axisTitle,
110  nb1, 0, m_noInjectionTime));
111  }
112 
113  // Include directory name in title: this histogram's canvas is made automatically,
114  // so no analysis modules changes its title to show the event selection used.
115  title = "SVDBunchNumVSNStrips - ";
116  title += m_histogramDirectoryName;
117  title += ";Bunch No.;Number of fired strips;Events / bin";
118  h_bunchNumVsNHits = new TH2F("SVDBunchNumVSNStrips", title, 1280, 0, 1280, 10, 0, 10000);
119 
120  oldDir->cd();
121 }
122 
123 void SVDDQMDoseModule::initialize()
124 {
125  REG_HISTOGRAM
126 
127  // Parameters
128  m_rawTTD.isOptional();
129  m_digits.isOptional(m_SVDShaperDigitsName);
130  m_trgSummary.isOptional();
131 
132  // Total number of strips per group
133  static bool nStripsComputed = false; // Compute only once
134  if (nStripsComputed)
135  return;
136  nStripsComputed = true;
137  VXD::GeoCache& geo = VXD::GeoCache::getInstance();
138  for (const auto& layer : geo.getLayers(VXD::SensorInfoBase::SVD)) {
139  for (const auto& ladder : geo.getLadders(layer)) {
140  for (const auto& sensor : geo.getSensors(ladder)) {
141  const auto& sInfo = VXD::GeoCache::get(sensor);
142  for (const SensorGroup& group : c_sensorGroups) {
143  if (group.contains(sensor)) {
144  // TODO exclude strips that are masked on FADC? It shouldn't matter much...
145  group.nStripsU += sInfo.getUCells();
146  }
147  }
148  }
149  }
150  }
151 }
152 
153 void SVDDQMDoseModule::beginRun()
154 {
155  h_nEvtsVsTime->Reset();
156  h_nEvtsVsTime1->Reset();
157  for (const auto& histPtr : m_groupOccupanciesU)
158  histPtr->Reset();
159  for (const auto& histPtr : m_groupNHitsU)
160  histPtr->Reset();
161  for (const auto& histPtr : m_groupNHits1U)
162  histPtr->Reset();
163  h_bunchNumVsNHits->Reset();
164 }
165 
166 void SVDDQMDoseModule::event()
167 {
168  // Allocate only once, especially good for the vectors
169  // static VXD::GeoCache& geo = VXD::GeoCache::getInstance();
170  static vector<int> groupHitsU(c_sensorGroups.size(), 0);
171 
172  if (m_trgTypes.size()) { // If not trg types are given, take everything
173  if (!m_trgSummary.isValid()) {
174  B2WARNING("Missing TRGSummary, SVDDQMDose is skipped.");
175  return;
176  }
177  auto ttyp = m_trgSummary->getTimType();
178  bool discardEvent = true;
179  for (const auto& ttyp2 : m_trgTypes) {
180  if (ttyp == ttyp2) {
181  discardEvent = false;
182  break;
183  }
184  }
185  if (discardEvent)
186  return;
187  }
188 
189  if (!m_rawTTD.isValid()) {
190  B2WARNING("Missing RawFTSW, SVDDQMDose is skipped.");
191  return;
192  }
193  if (!m_digits.isValid()) {
194  B2WARNING("Missing SVDShaperDigit " << m_SVDShaperDigitsName
195  << ", SVDDQMDose is skipped.");
196  return;
197  }
198 
199  if (m_rawTTD.getEntries() == 0)
200  return;
201  RawFTSW* theTTD = m_rawTTD[0];
202  const double timeSinceInj = theTTD->GetTimeSinceLastInjection(0) / c_globalClock;
203  const bool isHER = theTTD->GetIsHER(0);
204  const EEventType eventType = timeSinceInj > m_noInjectionTime ? c_NoInjection : (isHER ? c_HERInjection : c_LERInjection);
205  if (((unsigned int)eventType & m_eventFilter) == 0U)
206  return;
207  const double timeInCycle = timeSinceInj - (int)(timeSinceInj / c_revolutionTime) * c_revolutionTime;
208 
209  // Reset counters
210  for (int& count : groupHitsU) count = 0;
211 
212  // Count hits
213  for (const SVDShaperDigit& hit : m_digits) {
214  const VxdID& sensorID = hit.getSensorID();
215  if (hit.isUStrip()) {
216  for (unsigned int i = 0; i < c_sensorGroups.size(); i++) {
217  if (c_sensorGroups[i].contains(sensorID)) {
218  groupHitsU[i]++; // For instantaneous occupancy
219  m_groupNHitsU[i]->Fill(timeSinceInj, timeInCycle);
220  m_groupNHits1U[i]->Fill(timeSinceInj);
221  }
222  }
223  }
224  }
225 
226  // Count events
227  h_nEvtsVsTime->Fill(timeSinceInj, timeInCycle);
228  h_nEvtsVsTime1->Fill(timeSinceInj);
229 
230  // Compute instantaneous occupancy
231  for (unsigned int i = 0; i < c_sensorGroups.size(); i++)
232  m_groupOccupanciesU[i]->Fill(groupHitsU[i] * 100.0 / c_sensorGroups[i].nStripsU);
233 
234  // Bunch num vs fired strips
235  h_bunchNumVsNHits->Fill(theTTD->GetBunchNumber(0), m_digits.getEntries());
236 }
237 
238 const std::vector<SVDDQMDoseModule::SensorGroup> SVDDQMDoseModule::c_sensorGroups = {
239  {"L3XX", "L3", c_defaultNBins, c_defaultOccuMin, c_defaultOccuMax, [](const VxdID & s) { return s.getLayerNumber() == 3; }},
240  {"L4XX", "L4", c_defaultNBins, c_defaultOccuMin, c_defaultOccuMax, [](const VxdID & s) { return s.getLayerNumber() == 4; }},
241  {"L5XX", "L5", c_defaultNBins, c_defaultOccuMin, c_defaultOccuMax, [](const VxdID & s) { return s.getLayerNumber() == 5; }},
242  {"L6XX", "L6", c_defaultNBins, c_defaultOccuMin, c_defaultOccuMax, [](const VxdID & s) { return s.getLayerNumber() == 6; }},
243  {"L31X", "L3.1", c_defaultNBins, c_defaultOccuMin, c_defaultOccuMax, [](const VxdID & s) { return s.getLayerNumber() == 3 && s.getLadderNumber() == 1; }},
244  {"L32X", "L3.2", c_defaultNBins, c_defaultOccuMin, c_defaultOccuMax, [](const VxdID & s) { return s.getLayerNumber() == 3 && s.getLadderNumber() == 2; }}
245 };
Belle2::VxdID
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:43
Belle2::SVD::SVDDQMDoseModule::EEventType
EEventType
Bits definition for the bitmask that selects the events to put in the histograms.
Definition: SVDDQMDoseModule.h:57
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::VXD::GeoCache::getLayers
const std::set< Belle2::VxdID > getLayers(SensorInfoBase::SensorType sensortype=SensorInfoBase::VXD)
Return a set of all known Layers.
Definition: GeoCache.cc:177
Belle2::SVD::SVDDQMDoseModule::SensorGroup
A struct to define non-trivial histograms in a human-readable way.
Definition: SVDDQMDoseModule.h:72
Belle2::SVDShaperDigit
The SVD ShaperDigit class.
Definition: SVDShaperDigit.h:46
Belle2::VXD::GeoCache::getSensors
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:205
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::SVD
Namespace to encapsulate code needed for simulation and reconstrucion of the SVD.
Definition: GeoSVDCreator.h:35
Belle2::RawFTSW::GetIsHER
int GetIsHER(int n)
HER injection = 1 or LER injection = 0.
Definition: RawFTSW.h:172
Belle2::RawFTSW::GetBunchNumber
unsigned int GetBunchNumber(int n)
Get a bunch number.
Definition: RawFTSW.h:193
Belle2::VXD::GeoCache
Class to faciliate easy access to sensor information of the VXD like coordinate transformations or pi...
Definition: GeoCache.h:41
Belle2::VXD::GeoCache::getLadders
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:194
Belle2::RawFTSW::GetTimeSinceLastInjection
unsigned int GetTimeSinceLastInjection(int n)
Get time since the last injection.
Definition: RawFTSW.h:179
Belle2::HistoModule
HistoModule.h is supposed to be used instead of Module.h for the modules with histogram definitions t...
Definition: HistoModule.h:29
Belle2::SVD::SVDDQMDoseModule
The SVD dose-monitoring DQM module.
Definition: SVDDQMDoseModule.h:54
Belle2::RawFTSW
The Raw FTSW class.
Definition: RawFTSW.h:30