11 #include <svd/modules/svdDQM/SVDDQMDoseModule.h>
13 #include <rawdata/dataobjects/RawFTSW.h>
14 #include <svd/dataobjects/SVDShaperDigit.h>
15 #include <mdst/dataobjects/TRGSummary.h>
16 #include <vxd/dataobjects/VxdID.h>
19 #include <vxd/geometry/GeoCache.h>
20 #include <svd/geometry/SensorInfo.h>
21 #include <TDirectory.h>
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.",
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.",
58 void SVDDQMDoseModule::defineHisto()
60 TDirectory* oldDir = gDirectory;
61 if (m_histogramDirectoryName !=
"") {
62 oldDir->mkdir(m_histogramDirectoryName.c_str());
63 oldDir->cd(m_histogramDirectoryName.c_str());
67 m_noInjectionTime = round(m_noInjectionTime / c_revolutionTime) * c_revolutionTime;
69 h_nEvtsVsTime =
new TH2F(
71 "SVD Events;Time since last injection [#mus];Time in beam cycle [#mus];Events / bin",
72 500, 0, m_noInjectionTime, 100, 0, c_revolutionTime);
74 m_groupOccupanciesU.reserve(c_sensorGroups.size());
75 TString name =
"SVDInstOccu_";
76 TString title =
"SVD Instantaneous Occupancy ";
77 TString axisTitle =
";Occupancy [%];Count / bin";
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));
85 m_groupNHitsU.reserve(c_sensorGroups.size());
86 name =
"SVDHitsVsTime_";
88 axisTitle =
";Time since last injection [#mus];Time in beam cycle[#mus];Hits / bin";
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));
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);
102 m_groupNHits1U.reserve(c_sensorGroups.size());
103 name =
"SVDHitsVsTime1_";
105 axisTitle =
";Time since last injection [#mus];Hits / bin";
107 m_groupNHits1U.push_back(
108 new TH1F(name + group.nameSuffix +
"U",
109 title + group.titleSuffix +
" U-side" + axisTitle,
110 nb1, 0, m_noInjectionTime));
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);
123 void SVDDQMDoseModule::initialize()
128 m_rawTTD.isOptional();
129 m_digits.isOptional(m_SVDShaperDigitsName);
130 m_trgSummary.isOptional();
133 static bool nStripsComputed =
false;
136 nStripsComputed =
true;
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);
143 if (group.contains(sensor)) {
145 group.nStripsU += sInfo.getUCells();
153 void SVDDQMDoseModule::beginRun()
155 h_nEvtsVsTime->Reset();
156 h_nEvtsVsTime1->Reset();
157 for (
const auto& histPtr : m_groupOccupanciesU)
159 for (
const auto& histPtr : m_groupNHitsU)
161 for (
const auto& histPtr : m_groupNHits1U)
163 h_bunchNumVsNHits->Reset();
166 void SVDDQMDoseModule::event()
170 static vector<int> groupHitsU(c_sensorGroups.size(), 0);
172 if (m_trgTypes.size()) {
173 if (!m_trgSummary.isValid()) {
174 B2WARNING(
"Missing TRGSummary, SVDDQMDose is skipped.");
177 auto ttyp = m_trgSummary->getTimType();
178 bool discardEvent =
true;
179 for (
const auto& ttyp2 : m_trgTypes) {
181 discardEvent =
false;
189 if (!m_rawTTD.isValid()) {
190 B2WARNING(
"Missing RawFTSW, SVDDQMDose is skipped.");
193 if (!m_digits.isValid()) {
194 B2WARNING(
"Missing SVDShaperDigit " << m_SVDShaperDigitsName
195 <<
", SVDDQMDose is skipped.");
199 if (m_rawTTD.getEntries() == 0)
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)
207 const double timeInCycle = timeSinceInj - (int)(timeSinceInj / c_revolutionTime) * c_revolutionTime;
210 for (
int& count : groupHitsU) count = 0;
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)) {
219 m_groupNHitsU[i]->Fill(timeSinceInj, timeInCycle);
220 m_groupNHits1U[i]->Fill(timeSinceInj);
227 h_nEvtsVsTime->Fill(timeSinceInj, timeInCycle);
228 h_nEvtsVsTime1->Fill(timeSinceInj);
231 for (
unsigned int i = 0; i < c_sensorGroups.size(); i++)
232 m_groupOccupanciesU[i]->Fill(groupHitsU[i] * 100.0 / c_sensorGroups[i].nStripsU);
235 h_bunchNumVsNHits->Fill(theTTD->
GetBunchNumber(0), m_digits.getEntries());
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; }}