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