9 #include <dqm/analysis/modules/DQMHistAnalysisSVDDose.h>
10 #include <framework/utilities/Utils.h>
18 inline double getClockSeconds() {
return Utils::getClock() / 1e9; }
22 DQMHistAnalysisSVDDoseModule::DQMHistAnalysisSVDDoseModule()
24 setDescription(
"Monitoring of SVD Dose with events from Poisson trigger w/o inj. veto. See also SVDDQMDoseModule.");
26 addParam(
"pvPrefix", m_pvPrefix,
"Prefix for EPICS PVs.", std::string(
"DQM:SVD:"));
27 addParam(
"useEpics", m_useEpics,
"Whether to update EPICS PVs.",
true);
28 addParam(
"epicsUpdateSeconds", m_epicsUpdateSeconds,
29 "Minimum interval between two successive PV updates (in seconds).", 1000.0);
30 addParam(
"pvSuffix", m_pvSuffix,
"Suffix for EPICS PVs.", std::string(
":Occ:Pois:Avg"));
31 addParam(
"deltaTPVSuffix", m_deltaTPVSuffix,
"Suffix for the PV that monitors the update interval of the PVs.",
32 std::string(
"Occ:Pois:UpdateInterval"));
33 addParam(
"statePVSuffix", m_statePVSuffix,
"Suffix for the PV with the state of the monitoring.",
34 std::string(
"Occ:Pois:State"));
37 DQMHistAnalysisSVDDoseModule::~DQMHistAnalysisSVDDoseModule()
40 if (m_useEpics && ca_current_context()) ca_context_destroy();
44 void DQMHistAnalysisSVDDoseModule::initialize()
46 B2DEBUG(18,
"DQMHistAnalysisSVDDose: initialize");
50 m_monObj = getMonitoringObject(
"svd");
52 m_c_instOccu.reserve(c_sensorGroups.size());
53 m_c_occuLER.reserve(c_sensorGroups.size());
54 m_c_occuHER.reserve(c_sensorGroups.size());
55 m_c_occuLER1.reserve(c_sensorGroups.size());
56 m_c_occuHER1.reserve(c_sensorGroups.size());
57 m_c_instOccuAll.reserve(c_sensorGroups.size());
58 m_c_occuLERAll.reserve(c_sensorGroups.size());
59 m_c_occuHERAll.reserve(c_sensorGroups.size());
60 m_c_occuLER1All.reserve(c_sensorGroups.size());
61 m_c_occuHER1All.reserve(c_sensorGroups.size());
62 for (
const auto& group : c_sensorGroups) {
63 TCanvas* c =
new TCanvas(
"SVDDOSE/c_svd_instOccupancy_" + group.nameSuffix +
"_pois",
64 "Instantaneous occupancy (Pois. trig.) " + group.titleSuffix);
65 m_c_instOccu.push_back(c);
66 c =
new TCanvas(
"SVDDOSE/c_svd_occuLER_" + group.nameSuffix +
"_pois",
67 "Occupancy vs time since LER inj. (Pois. trig.) " + group.titleSuffix);
68 m_c_occuLER.push_back(c);
69 c =
new TCanvas(
"SVDDOSE/c_svd_occuHER_" + group.nameSuffix +
"_pois",
70 "Occupancy vs time since HER inj. (Pois. trig.) " + group.titleSuffix);
71 m_c_occuHER.push_back(c);
72 c =
new TCanvas(
"SVDDOSE/c_svd_1DoccuLER_" + group.nameSuffix +
"_pois",
73 "Occupancy vs time since LER inj. (Pois. trig.) " + group.titleSuffix);
74 m_c_occuLER1.push_back(c);
75 c =
new TCanvas(
"SVDDOSE/c_svd_1DoccuHER_" + group.nameSuffix +
"_pois",
76 "Occupancy vs time since HER inj. (Pois. trig.) " + group.titleSuffix);
77 m_c_occuHER1.push_back(c);
79 c =
new TCanvas(
"SVDDOSE/c_svd_instOccupancy_" + group.nameSuffix +
"_all",
80 "Instantaneous occupancy (all events) " + group.titleSuffix);
81 m_c_instOccuAll.push_back(c);
82 c =
new TCanvas(
"SVDDOSE/c_svd_occuLER_" + group.nameSuffix +
"_all",
83 "Occupancy vs time since LER inj. (all events) " + group.titleSuffix);
84 m_c_occuLERAll.push_back(c);
85 c =
new TCanvas(
"SVDDOSE/c_svd_occuHER_" + group.nameSuffix +
"_all",
86 "Occupancy vs time since HER inj. (all events) " + group.titleSuffix);
87 m_c_occuHERAll.push_back(c);
88 c =
new TCanvas(
"SVDDOSE/c_svd_1DoccuLER_" + group.nameSuffix +
"_all",
89 "Occupancy vs time since LER inj. (all events) " + group.titleSuffix);
90 m_c_occuLER1All.push_back(c);
91 c =
new TCanvas(
"SVDDOSE/c_svd_1DoccuHER_" + group.nameSuffix +
"_all",
92 "Occupancy vs time since HER inj. (all events) " + group.titleSuffix);
93 m_c_occuHER1All.push_back(c);
97 m_legend =
new TPaveText(0.53, 0.73, 0.68, 0.88,
"brNDC");
98 m_legend->AddText(
"LER inj."); ((TText*)m_legend->GetListOfLines()->Last())->SetTextColor(kRed);
99 m_legend->AddText(
"HER inj."); ((TText*)m_legend->GetListOfLines()->Last())->SetTextColor(kAzure);
100 m_legend->AddText(
"No inj."); ((TText*)m_legend->GetListOfLines()->Last())->SetTextColor(kBlack);
104 if (!ca_current_context())
105 SEVCHK(ca_context_create(ca_disable_preemptive_callback),
"ca_context_create");
107 m_myPVs.resize(c_sensorGroups.size());
108 for (
unsigned int g = 0; g < c_sensorGroups.size(); g++)
109 SEVCHK(ca_create_channel((m_pvPrefix + c_sensorGroups[g].pvMiddle + m_pvSuffix).data(),
110 NULL, NULL, 10, &m_myPVs[g].mychid),
"ca_create_channel");
112 SEVCHK(ca_create_channel((m_pvPrefix + m_deltaTPVSuffix).data(),
113 NULL, NULL, 10, &m_timeSinceLastPVUpdateChan),
"ca_create_channel");
114 SEVCHK(ca_create_channel((m_pvPrefix + m_statePVSuffix).data(),
115 NULL, NULL, 10, &m_stateChan),
"ca_create_channel");
117 SEVCHK(ca_pend_io(2.0),
"ca_pend_io");
120 SEVCHK(ca_get(DBR_CTRL_ENUM, m_stateChan, &m_stateCtrl),
"ca_get");
121 B2DEBUG(19,
"State PV initialized (ca_get)" <<
LogVar(
"value", m_stateCtrl.value));
122 SEVCHK(ca_pend_io(2.0),
"ca_pend_io");
124 B2DEBUG(18,
"State PV failed to initialize, will retry in beginRun(), event() and endRun().");
127 m_lastPVUpdate = getClockSeconds();
132 void DQMHistAnalysisSVDDoseModule::beginRun()
137 B2DEBUG(19,
"beginRun: setting state PV to RUNNING");
138 m_stateCtrl.value = 1;
140 SEVCHK(ca_put(DBR_ENUM, m_stateChan, &m_stateCtrl.value),
"ca_put");
142 SEVCHK(ca_create_channel((m_pvPrefix + m_statePVSuffix).data(),
143 NULL, NULL, 10, &m_stateChan),
"ca_create_channel (reconnection)");
145 SEVCHK(ca_pend_io(2.0),
"ca_pend_io");
147 m_lastPVUpdate = getClockSeconds();
152 void DQMHistAnalysisSVDDoseModule::event()
156 double timeSinceLastPVUpdate = getClockSeconds() - m_lastPVUpdate;
157 if (m_useEpics && timeSinceLastPVUpdate >= m_epicsUpdateSeconds) {
160 SEVCHK(ca_get(DBR_CTRL_ENUM, m_stateChan, &m_stateCtrl),
"ca_get");
162 SEVCHK(ca_create_channel((m_pvPrefix + m_statePVSuffix).data(),
163 NULL, NULL, 10, &m_stateChan),
"ca_create_channel (reconnection)");
165 SEVCHK(ca_pend_io(2.0),
"ca_pend_io");
168 if (m_timeSinceLastPVUpdateChan) {
169 SEVCHK(ca_put(DBR_DOUBLE, m_timeSinceLastPVUpdateChan, (
void*)&timeSinceLastPVUpdate),
"ca_put");
171 SEVCHK(ca_create_channel((m_pvPrefix + m_deltaTPVSuffix).data(), NULL, NULL, 10, &m_timeSinceLastPVUpdateChan),
172 "ca_create_channel (reconnection)");
174 m_stateCtrl.value = 1;
176 SEVCHK(ca_put(DBR_ENUM, m_stateChan, &m_stateCtrl.value),
"ca_put");
178 SEVCHK(ca_create_channel((m_pvPrefix + m_statePVSuffix).data(),
179 NULL, NULL, 10, &m_stateChan),
"ca_create_channel (reconnection)");
182 for (
unsigned int g = 0; g < c_sensorGroups.size(); g++) {
183 const auto& group = c_sensorGroups[g];
184 double nHits = 0.0, nEvts = 0.0;
185 for (TString dir : {
"SVDDoseLERInjPois",
"SVDDoseHERInjPois",
"SVDDoseNoInjPois"}) {
186 auto hHits = findHistT<TH2F>(dir +
"/SVDHitsVsTime_" + group.nameSuffix);
187 auto hEvts = findHistT<TH2F>(dir +
"/SVDEvtsVsTime");
188 if (!hHits || !hEvts) {
189 B2WARNING(
"Histograms needed for Average Poisson Occupancy U-side not found.");
193 nHits += hHits->GetEntries();
194 nEvts += hEvts->GetEntries();
197 B2DEBUG(19,
"DQMHistAnalysisSVDDose: PV write"
198 <<
LogVar(
"group", group.nameSuffix.Data())
201 auto& pv = m_myPVs[g];
202 double delta_nHits = nHits - pv.lastNHits;
203 double delta_nEvts = nEvts - pv.lastNEvts;
204 double occ = delta_nEvts > 0.0 ? (delta_nHits / delta_nEvts * 100.0 / group.nStrips) : -1.0;
206 SEVCHK(ca_put(DBR_DOUBLE, pv.mychid, (
void*)&occ),
"ca_put");
208 SEVCHK(ca_create_channel((m_pvPrefix + c_sensorGroups[g].pvMiddle + m_pvSuffix).data(),
209 NULL, NULL, 10, &m_myPVs[g].mychid),
"ca_create_channel (reconnection)");
211 pv.lastNEvts = nEvts;
212 pv.lastNHits = nHits;
216 SEVCHK(ca_pend_io(2.0),
"ca_pend_io");
217 m_lastPVUpdate = getClockSeconds();
224 void DQMHistAnalysisSVDDoseModule::endRun()
226 B2DEBUG(18,
"DQMHistAnalysisSVDDose: endRun");
231 B2DEBUG(19,
"endRun: setting state PV to NOT RUNNING");
232 m_stateCtrl.value = 0;
234 SEVCHK(ca_put(DBR_ENUM, m_stateChan, &m_stateCtrl.value),
"ca_put");
236 SEVCHK(ca_create_channel((m_pvPrefix + m_statePVSuffix).data(),
237 NULL, NULL, 10, &m_stateChan),
"ca_create_channel (reconnection)");
239 SEVCHK(ca_pend_io(2.0),
"ca_pend_io");
241 for (
auto& pv : m_myPVs)
242 pv.lastNEvts = pv.lastNHits = 0.0;
247 for (
unsigned int g = 0; g < c_sensorGroups.size(); g++) {
248 const auto& group = c_sensorGroups[g];
249 double nHits = 0.0, nEvts = 0.0;
250 for (TString dir : {
"SVDDoseLERInjPois",
"SVDDoseHERInjPois",
"SVDDoseNoInjPois"}) {
251 auto hHits = findHistT<TH2F>(dir +
"/SVDHitsVsTime_" + group.nameSuffix);
252 auto hEvts = findHistT<TH2F>(dir +
"/SVDEvtsVsTime");
253 if (!hHits || !hEvts) {
254 B2WARNING(
"Histograms needed for Average Poisson Occupancy U-side not found.");
258 nHits += hHits->GetEntries();
259 nEvts += hEvts->GetEntries();
262 B2DEBUG(19,
"DQMHistAnalysisSVDDose: MonObj write"
263 <<
LogVar(
"group", group.nameSuffix.Data())
266 double occ = nEvts ? (nHits / nEvts * 100.0 / group.nStrips) : -1.0;
267 TString vName = group.nameSuffix +
"OccPoisAvg";
268 m_monObj->setVariable(vName.Data(), occ);
274 void DQMHistAnalysisSVDDoseModule::updateCanvases()
276 B2DEBUG(18,
"DQMHistAnalysisSVDDose: updating canvases");
278 for (
unsigned int g = 0; g < c_sensorGroups.size(); g++) {
279 const auto& group = c_sensorGroups[g];
281 auto c = m_c_instOccu[g];
282 auto hLER = findHistT<TH1F>(
"SVDDoseLERInjPois/SVDInstOccu_" + group.nameSuffix);
283 auto hHER = findHistT<TH1F>(
"SVDDoseHERInjPois/SVDInstOccu_" + group.nameSuffix);
284 auto hNo = findHistT<TH1F>(
"SVDDoseNoInjPois/SVDInstOccu_" + group.nameSuffix);
285 if (hLER && hHER && hNo) {
286 hLER->SetLineColor(kRed);
287 hHER->SetLineColor(kAzure);
288 hNo->SetLineColor(kBlack);
289 carryOverflowOver(hLER);
290 carryOverflowOver(hHER);
291 carryOverflowOver(hNo);
294 hNo->SetTitle(
"SVD instantaneous occu. " + group.titleSuffix +
" U-side Pois. trig.");
296 hLER->Draw(
"hist same");
297 hHER->Draw(
"hist same");
303 auto hHits = findHistT<TH2F>(
"SVDDoseLERInjPois/SVDHitsVsTime_" + group.nameSuffix);
304 auto hEvts = findHistT<TH2F>(
"SVDDoseLERInjPois/SVDEvtsVsTime");
305 if (hHits && hEvts) {
306 auto hOccu = divide(hHits, hEvts, 100.0f / group.nStrips);
307 hOccu->SetTitle(
"SVD Occupancy " + group.titleSuffix +
" - LER inj. Pois. trig."
308 ";Time since last injection [#mus];Time in beam cycle [#mus]"
310 hOccu->SetMinimum(1e-3);
311 hOccu->SetMaximum(10);
314 c->SetRightMargin(0.16);
320 auto hpEvts = findHistT<TH1F>(
"SVDDoseLERInjPois/SVDEvtsVsTime1");
321 auto hpHits = findHistT<TH1F>(
"SVDDoseLERInjPois/SVDHitsVsTime1_" + group.nameSuffix);
322 if (hpHits && hpEvts) {
323 auto hpOccu = divide(hpHits, hpEvts, 100.0f / group.nStrips);
324 hpOccu->SetTitle(
"SVD Occupancy " + group.titleSuffix +
" - LER inj. Pois. trig."
325 ";Time since last injection [#mus];Occupancy [%]");
326 hpOccu->SetMinimum(1e-3);
327 hpOccu->SetMaximum(10);
330 hpOccu->SetMarkerStyle(7);
331 hpOccu->Draw(
"hist P");
336 hHits = findHistT<TH2F>(
"SVDDoseHERInjPois/SVDHitsVsTime_" + group.nameSuffix);
337 hEvts = findHistT<TH2F>(
"SVDDoseHERInjPois/SVDEvtsVsTime");
338 if (hHits && hEvts) {
339 auto hOccu = divide(hHits, hEvts, 100.0f / group.nStrips);
340 hOccu->SetTitle(
"SVD Occupancy " + group.titleSuffix +
" - HER inj. Pois. trig."
341 ";Time since last injection [#mus];Time in beam cycle [#mus]"
343 hOccu->SetMinimum(1e-3);
344 hOccu->SetMaximum(10);
347 c->SetRightMargin(0.16);
353 hpEvts = findHistT<TH1F>(
"SVDDoseHERInjPois/SVDEvtsVsTime1");
354 hpHits = findHistT<TH1F>(
"SVDDoseHERInjPois/SVDHitsVsTime1_" + group.nameSuffix);
355 if (hpHits && hpEvts) {
356 auto hpOccu = divide(hpHits, hpEvts, 100.0f / group.nStrips);
357 hpOccu->SetTitle(
"SVD Occupancy " + group.titleSuffix +
" - HER inj. Pois. trig."
358 ";Time since last injection [#mus];Occupancy [%]");
359 hpOccu->SetMinimum(1e-3);
360 hpOccu->SetMaximum(10);
363 hpOccu->SetMarkerStyle(7);
364 hpOccu->Draw(
"hist P");
369 c = m_c_instOccuAll[g];
370 hLER = findHistT<TH1F>(
"SVDDoseLERInjAll/SVDInstOccu_" + group.nameSuffix);
371 hHER = findHistT<TH1F>(
"SVDDoseHERInjAll/SVDInstOccu_" + group.nameSuffix);
372 hNo = findHistT<TH1F>(
"SVDDoseNoInjAll/SVDInstOccu_" + group.nameSuffix);
373 if (hLER && hHER && hNo) {
374 hLER->SetLineColor(kRed);
375 hHER->SetLineColor(kAzure);
376 hNo->SetLineColor(kBlack);
377 carryOverflowOver(hLER);
378 carryOverflowOver(hHER);
379 carryOverflowOver(hNo);
382 hNo->SetTitle(
"SVD instantaneous occu. " + group.titleSuffix +
" U-side all events");
384 hLER->Draw(
"hist same");
385 hHER->Draw(
"hist same");
390 c = m_c_occuLERAll[g];
391 hHits = findHistT<TH2F>(
"SVDDoseLERInjAll/SVDHitsVsTime_" + group.nameSuffix);
392 hEvts = findHistT<TH2F>(
"SVDDoseLERInjAll/SVDEvtsVsTime");
393 if (hHits && hEvts) {
394 auto hOccu = divide(hHits, hEvts, 100.0f / group.nStrips);
395 hOccu->SetTitle(
"SVD Occupancy " + group.titleSuffix +
" - LER inj. all events"
396 ";Time since last injection [#mus];Time in beam cycle [#mus]"
398 hOccu->SetMinimum(1e-3);
399 hOccu->SetMaximum(10);
402 c->SetRightMargin(0.16);
407 c = m_c_occuLER1All[g];
408 hpEvts = findHistT<TH1F>(
"SVDDoseLERInjAll/SVDEvtsVsTime1");
409 hpHits = findHistT<TH1F>(
"SVDDoseLERInjAll/SVDHitsVsTime1_" + group.nameSuffix);
410 if (hpHits && hpEvts) {
411 auto hpOccu = divide(hpHits, hpEvts, 100.0f / group.nStrips);
412 hpOccu->SetTitle(
"SVD Occupancy " + group.titleSuffix +
" - LER inj. all events"
413 ";Time since last injection [#mus];Occupancy [%]");
414 hpOccu->SetMinimum(1e-3);
415 hpOccu->SetMaximum(10);
418 hpOccu->SetMarkerStyle(7);
419 hpOccu->Draw(
"hist P");
423 c = m_c_occuHERAll[g];
424 hHits = findHistT<TH2F>(
"SVDDoseHERInjAll/SVDHitsVsTime_" + group.nameSuffix);
425 hEvts = findHistT<TH2F>(
"SVDDoseHERInjAll/SVDEvtsVsTime");
426 if (hHits && hEvts) {
427 auto hOccu = divide(hHits, hEvts, 100.0f / group.nStrips);
428 hOccu->SetTitle(
"SVD Occupancy " + group.titleSuffix +
" - HER inj. all events"
429 ";Time since last injection [#mus];Time in beam cycle [#mus]"
431 hOccu->SetMinimum(1e-3);
432 hOccu->SetMaximum(10);
435 c->SetRightMargin(0.16);
440 c = m_c_occuHER1All[g];
441 hpEvts = findHistT<TH1F>(
"SVDDoseHERInjAll/SVDEvtsVsTime1");
442 hpHits = findHistT<TH1F>(
"SVDDoseHERInjAll/SVDHitsVsTime1_" + group.nameSuffix);
443 if (hpHits && hpEvts) {
444 auto hpOccu = divide(hpHits, hpEvts, 100.0f / group.nStrips);
445 hpOccu->SetTitle(
"SVD Occupancy " + group.titleSuffix +
" - HER inj. all events"
446 ";Time since last injection [#mus];Occupancy [%]");
447 hpOccu->SetMinimum(1e-3);
448 hpOccu->SetMaximum(10);
451 hpOccu->SetMarkerStyle(7);
452 hpOccu->Draw(
"hist P");
458 void DQMHistAnalysisSVDDoseModule::carryOverflowOver(TH1F* h)
460 int i = h->GetNbinsX();
461 float t = h->GetBinContent(i) + h->GetBinContent(i + 1);
462 h->SetBinContent(i, t);
463 h->SetBinContent(i + 1, 0);
466 const vector<DQMHistAnalysisSVDDoseModule::SensorGroup> DQMHistAnalysisSVDDoseModule::c_sensorGroups = {
467 {
"L31XU",
"L3.1",
"L3:1", 768 * 2},
468 {
"L32XU",
"L3.2",
"L3:2", 768 * 2},
469 {
"L3XXU",
"L3 avg.",
"L3", 768 * 14},
470 {
"L4XXU",
"L4 avg.",
"L4", 768 * 30},
471 {
"L5XXU",
"L5 avg.",
"L5", 768 * 48},
472 {
"L6XXU",
"L6 avg.",
"L6", 768 * 80}
Class to store variables with their name which were sent to the logging service.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.