CMS 3D CMS Logo

CTPPSCommonDQMSource.cc
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * This is a part of TotemDQM and TOTEM offline software.
4  * Authors:
5  * Jan Kašpar (jan.kaspar@gmail.com)
6  *
7  ****************************************************************************/
8 
15 
18 
23 
24 #include <string>
25 
26 //----------------------------------------------------------------------------------------------------
27 
28 class CTPPSCommonDQMSource : public DQMOneEDAnalyzer<edm::LuminosityBlockCache<std::vector<int>>> {
29 public:
31  ~CTPPSCommonDQMSource() override;
32 
33 protected:
34  void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override;
35  void analyze(edm::Event const &e, edm::EventSetup const &eSetup) override;
36  std::shared_ptr<std::vector<int>> globalBeginLuminosityBlock(const edm::LuminosityBlock &iLumi,
37  const edm::EventSetup &c) const override;
39 
43 
44 private:
45  const unsigned int verbosity;
46  constexpr static int MAX_LUMIS = 6000;
47  constexpr static int MAX_VBINS = 20;
48 
52 
54  bool perLSsaving_; //to avoid nanoDQMIO crashing, driven by DQMServices/Core/python/DQMStore_cfi.py
55 
56  int currentLS;
57  int endLS;
58 
59  std::vector<int> rpstate;
60 
62  struct GlobalPlots {
63  MonitorElement *RPState = nullptr;
66 
67  void Init(DQMStore::IBooker &ibooker);
68  };
69 
71 
73  struct ArmPlots {
74  int id;
75 
78 
79  MonitorElement *h_proton_xi = nullptr, *h_proton_th_x = nullptr, *h_proton_th_y = nullptr, *h_proton_t = nullptr,
80  *h_proton_time = nullptr;
81 
82  struct TrackingRPPlots {
84  };
85 
86  std::map<unsigned int, TrackingRPPlots> trackingRPPlots;
87 
88  struct TimingRPPlots {
90  };
91 
92  std::map<unsigned int, TimingRPPlots> timingRPPlots;
93 
94  ArmPlots() {}
95 
96  ArmPlots(DQMStore::IBooker &ibooker, int _id, bool makeProtonRecoPlots);
97  };
98 
99  std::map<unsigned int, ArmPlots> armPlots;
100 };
101 
102 //----------------------------------------------------------------------------------------------------
103 //----------------------------------------------------------------------------------------------------
104 
105 using namespace std;
106 using namespace edm;
107 
110 
111 //----------------------------------------------------------------------------------------------------
112 
114  ibooker.setCurrentFolder("CTPPS/common");
115 
116  events_per_bx = ibooker.book1D("events per BX", "rp;Event.BX", 4002, -1.5, 4000. + 0.5);
117  events_per_bx_short = ibooker.book1D("events per BX (short)", "rp;Event.BX", 102, -1.5, 100. + 0.5);
118 
119  /*
120  RP State (HV & LV & Insertion):
121  0 -> not used
122  1 -> bad
123  2 -> warning
124  3 -> ok
125  */
126  RPState = ibooker.book2D("rpstate per LS",
127  "RP State per Lumisection;Luminosity Section;",
128  MAX_LUMIS,
129  0,
130  MAX_LUMIS,
131  MAX_VBINS,
132  0.,
133  MAX_VBINS);
134  {
135  TH2F *hist = RPState->getTH2F();
136  hist->SetCanExtend(TH1::kAllAxes);
137  TAxis *ya = hist->GetYaxis();
138  ya->SetBinLabel(1, "45, 210, FR-BT");
139  ya->SetBinLabel(2, "45, 210, FR-HR");
140  ya->SetBinLabel(3, "45, 210, FR-TP");
141  ya->SetBinLabel(4, "45, 220, C1");
142  ya->SetBinLabel(5, "45, 220, FR-BT");
143  ya->SetBinLabel(6, "45, 220, FR-HR");
144  ya->SetBinLabel(7, "45, 220, FR-TP");
145  ya->SetBinLabel(8, "45, 220, NR-BT");
146  ya->SetBinLabel(9, "45, 220, NR-HR");
147  ya->SetBinLabel(10, "45, 220, NR-TP");
148  ya->SetBinLabel(11, "56, 210, FR-BT");
149  ya->SetBinLabel(12, "56, 210, FR-HR");
150  ya->SetBinLabel(13, "56, 210, FR-TP");
151  ya->SetBinLabel(14, "56, 220, C1");
152  ya->SetBinLabel(15, "56, 220, FR-BT");
153  ya->SetBinLabel(16, "56, 220, FR-HR");
154  ya->SetBinLabel(17, "56, 220, FR-TP");
155  ya->SetBinLabel(18, "56, 220, NR-BT");
156  ya->SetBinLabel(19, "56, 220, NR-HR");
157  ya->SetBinLabel(20, "56, 220, NR-TP");
158  }
159 
160  h_trackCorr_hor = ibooker.book2D("track correlation hor", "ctpps_common_rp_hor", 8, -0.5, 7.5, 8, -0.5, 7.5);
161  {
162  TH2F *hist = h_trackCorr_hor->getTH2F();
163  TAxis *xa = hist->GetXaxis(), *ya = hist->GetYaxis();
164  xa->SetBinLabel(1, "45, 210, FR");
165  ya->SetBinLabel(1, "45, 210, FR");
166  xa->SetBinLabel(2, "45, 220, NR");
167  ya->SetBinLabel(2, "45, 220, NR");
168  xa->SetBinLabel(3, "45, 220, C1");
169  ya->SetBinLabel(3, "45, 220, C1");
170  xa->SetBinLabel(4, "45, 220, FR");
171  ya->SetBinLabel(4, "45, 220, FR");
172 
173  xa->SetBinLabel(5, "56, 210, FR");
174  ya->SetBinLabel(5, "56, 210, FR");
175  xa->SetBinLabel(6, "56, 220, NR");
176  ya->SetBinLabel(6, "56, 220, NR");
177  xa->SetBinLabel(7, "56, 220, C1");
178  ya->SetBinLabel(7, "56, 220, C1");
179  xa->SetBinLabel(8, "56, 220, FR");
180  ya->SetBinLabel(8, "56, 220, FR");
181  }
182 
183  h_trackCorr_vert = ibooker.book2D("track correlation vert", "ctpps_common_rp_vert", 8, -0.5, 7.5, 8, -0.5, 7.5);
184  {
185  TH2F *hist = h_trackCorr_vert->getTH2F();
186  TAxis *xa = hist->GetXaxis(), *ya = hist->GetYaxis();
187  xa->SetBinLabel(1, "45, 210, FR-TP");
188  ya->SetBinLabel(1, "45, 210, FR-TP");
189  xa->SetBinLabel(2, "45, 210, FR-BT");
190  ya->SetBinLabel(2, "45, 210, FR-BT");
191  xa->SetBinLabel(3, "45, 220, FR-TP");
192  ya->SetBinLabel(3, "45, 220, FR-TP");
193  xa->SetBinLabel(4, "45, 220, FR-BT");
194  ya->SetBinLabel(4, "45, 220, FR-BT");
195  xa->SetBinLabel(5, "56, 210, FR-TP");
196  ya->SetBinLabel(5, "56, 210, FR-TP");
197  xa->SetBinLabel(6, "56, 210, FR-BT");
198  ya->SetBinLabel(6, "56, 210, FR-BT");
199  xa->SetBinLabel(7, "56, 220, FR-TP");
200  ya->SetBinLabel(7, "56, 220, FR-TP");
201  xa->SetBinLabel(8, "56, 220, FR-BT");
202  ya->SetBinLabel(8, "56, 220, FR-BT");
203  }
204 }
205 
206 //----------------------------------------------------------------------------------------------------
207 
209  string name;
211 
212  ibooker.setCurrentFolder("CTPPS/common/sector " + name);
213 
214  string title = "ctpps_common_sector_" + name;
215 
217  ibooker.book1D("number of top RPs with tracks", title + ";number of top RPs with tracks", 5, -0.5, 4.5);
219  ibooker.book1D("number of hor RPs with tracks", title + ";number of hor RPs with tracks", 5, -0.5, 4.5);
221  ibooker.book1D("number of bot RPs with tracks", title + ";number of bot RPs with tracks", 5, -0.5, 4.5);
222 
223  h_trackCorr = ibooker.book2D("track correlation", title, 8, -0.5, 7.5, 8, -0.5, 7.5);
224  TH2F *h_trackCorr_h = h_trackCorr->getTH2F();
225  TAxis *xa = h_trackCorr_h->GetXaxis(), *ya = h_trackCorr_h->GetYaxis();
226  xa->SetBinLabel(1, "210, FR-HR");
227  ya->SetBinLabel(1, "210, FR-HR");
228  xa->SetBinLabel(2, "210, FR-TP");
229  ya->SetBinLabel(2, "210, FR-TP");
230  xa->SetBinLabel(3, "210, FR-BT");
231  ya->SetBinLabel(3, "210, FR-BT");
232  xa->SetBinLabel(4, "220, NR-HR");
233  ya->SetBinLabel(4, "220, NR-HR");
234  xa->SetBinLabel(5, "220, C1");
235  ya->SetBinLabel(5, "220, C1");
236  xa->SetBinLabel(6, "220, FR-HR");
237  ya->SetBinLabel(6, "220, FR-HR");
238  xa->SetBinLabel(7, "220, FR-TP");
239  ya->SetBinLabel(7, "220, FR-TP");
240  xa->SetBinLabel(8, "220, FR-BT");
241  ya->SetBinLabel(8, "220, FR-BT");
242 
243  h_trackCorr_overlap = ibooker.book2D("track correlation hor-vert overlaps", title, 8, -0.5, 7.5, 8, -0.5, 7.5);
244  h_trackCorr_h = h_trackCorr_overlap->getTH2F();
245  xa = h_trackCorr_h->GetXaxis();
246  ya = h_trackCorr_h->GetYaxis();
247  xa->SetBinLabel(1, "210, FR-HR");
248  ya->SetBinLabel(1, "210, FR-HR");
249  xa->SetBinLabel(2, "210, FR-TP");
250  ya->SetBinLabel(2, "210, FR-TP");
251  xa->SetBinLabel(3, "210, FR-BT");
252  ya->SetBinLabel(3, "210, FR-BT");
253  xa->SetBinLabel(4, "220, NR-HR");
254  ya->SetBinLabel(4, "220, NR-HR");
255  xa->SetBinLabel(5, "220, C1");
256  ya->SetBinLabel(5, "220, C1");
257  xa->SetBinLabel(6, "220, FR-HR");
258  ya->SetBinLabel(6, "220, FR-HR");
259  xa->SetBinLabel(7, "220, FR-TP");
260  ya->SetBinLabel(7, "220, FR-TP");
261  xa->SetBinLabel(8, "220, FR-BT");
262  ya->SetBinLabel(8, "220, FR-BT");
263 
264  if (makeProtonRecoPlots) {
265  h_proton_xi = ibooker.book1D("proton xi", title + ";xi", 100, 0., 0.3);
266  h_proton_th_x = ibooker.book1D("proton theta st x", ";#theta^{*}_{x} (rad)", 250, -500E-6, +500E-6);
267  h_proton_th_y = ibooker.book1D("proton theta st y", ";#theta^{*}_{y} (rad)", 250, -500E-6, +500E-6);
268  h_proton_t = ibooker.book1D("proton t", title + ";|t| GeV^{2}", 100, 0., 5.);
269  h_proton_time = ibooker.book1D("proton time", title + ";time (ns)", 100, -1., 1.);
270  }
271 
272  for (const unsigned int rpDecId : {3, 22, 16, 23}) {
273  unsigned int st = rpDecId / 10, rp = rpDecId % 10, rpFullDecId = id * 100 + rpDecId;
275  string stName, rpName;
276  rpId.stationName(stName, CTPPSDetId::nShort);
277  rpId.rpName(rpName, CTPPSDetId::nShort);
278  rpName = stName + "_" + rpName;
279 
280  const bool timingRP = (rpDecId == 22 || rpDecId == 16);
281 
282  if (timingRP) {
283  timingRPPlots[rpFullDecId] = {
284  ibooker.book1D(rpName + " - track x histogram", title + "/" + rpName + ";track x (mm)", 200, 0., 40.),
285  ibooker.book1D(
286  rpName + " - track time histogram", title + "/" + rpName + ";track time (ns)", 100, -25., +50.)};
287  } else {
288  trackingRPPlots[rpFullDecId] = {
289  ibooker.book1D(rpName + " - track x histogram", title + "/" + rpName + ";track x (mm)", 200, 0., 40.),
290  ibooker.book1D(rpName + " - track y histogram", title + "/" + rpName + ";track y (mm)", 200, -20., +20.)};
291  }
292  }
293 }
294 
295 //----------------------------------------------------------------------------------------------------
296 //----------------------------------------------------------------------------------------------------
297 
299  : verbosity(ps.getUntrackedParameter<unsigned int>("verbosity", 0)),
300  ctppsRecordToken(consumes<CTPPSRecord>(ps.getUntrackedParameter<edm::InputTag>("ctppsmetadata"))),
302  consumes<vector<CTPPSLocalTrackLite>>(ps.getUntrackedParameter<edm::InputTag>("tagLocalTrackLite"))),
304  consumes<std::vector<reco::ForwardProton>>(ps.getUntrackedParameter<InputTag>("tagRecoProtons"))),
305  makeProtonRecoPlots_(ps.getParameter<bool>("makeProtonRecoPlots")),
306  perLSsaving_(ps.getUntrackedParameter<bool>("perLSsaving", false)) {
307  currentLS = 0;
308  endLS = 0;
309  rpstate.clear();
310 }
311 
312 //----------------------------------------------------------------------------------------------------
313 
315 
316 //----------------------------------------------------------------------------------------------------
317 
319  // global plots
320  globalPlots.Init(ibooker);
321 
322  // loop over arms
323  for (unsigned int arm = 0; arm < 2; arm++) {
325  }
326 }
327 
328 //----------------------------------------------------------------------------------------------------
329 
333 
336 }
337 
338 //----------------------------------------------------------------------------------------------------
339 
341  Handle<CTPPSRecord> hCTPPSRecord;
342  event.getByToken(ctppsRecordToken, hCTPPSRecord);
343 
344  if (!hCTPPSRecord.isValid()) {
345  if (verbosity)
346  LogProblem("CTPPSCommonDQMSource") << "ERROR in CTPPSCommonDQMSource::analyzeCTPPSRecord > input not available.";
347 
348  return;
349  }
350 
351  auto &rpstate = *luminosityBlockCache(event.getLuminosityBlock().index());
352  if (rpstate.empty()) {
353  rpstate.reserve(CTPPSRecord::RomanPot::Last);
354  for (uint8_t i = 0; i < CTPPSRecord::RomanPot::Last; ++i)
355  rpstate.push_back(hCTPPSRecord->status(i));
356  }
357 }
358 
359 //----------------------------------------------------------------------------------------------------
360 
362  // get event data
364  event.getByToken(tokenLocalTrackLite, hTracks);
365 
366  // check validity
367  if (!hTracks.isValid()) {
368  if (verbosity)
369  LogProblem("CTPPSCommonDQMSource") << "ERROR in CTPPSCommonDQMSource::analyzeTracks > input not available.";
370 
371  return;
372  }
373 
374  //------------------------------
375  // collect indeces of RP with tracks, for each correlation plot
376  set<signed int> s_rp_idx_global_hor, s_rp_idx_global_vert;
377  map<unsigned int, set<signed int>> ms_rp_idx_arm;
378 
379  for (auto &tr : *hTracks) {
380  const CTPPSDetId rpId(tr.rpId());
381  const unsigned int arm = rpId.arm();
382  const unsigned int stNum = rpId.station();
383  const unsigned int rpNum = rpId.rp();
384  const unsigned int stRPNum = stNum * 10 + rpNum;
385 
386  {
387  signed int idx = -1;
388  if (stRPNum == 3)
389  idx = 0;
390  if (stRPNum == 22)
391  idx = 1;
392  if (stRPNum == 16)
393  idx = 2;
394  if (stRPNum == 23)
395  idx = 3;
396 
397  if (idx >= 0)
398  s_rp_idx_global_hor.insert(4 * arm + idx);
399  }
400 
401  {
402  signed int idx = -1;
403  if (stRPNum == 4)
404  idx = 0;
405  if (stRPNum == 5)
406  idx = 1;
407  if (stRPNum == 24)
408  idx = 2;
409  if (stRPNum == 25)
410  idx = 3;
411 
412  if (idx >= 0)
413  s_rp_idx_global_vert.insert(4 * arm + idx);
414  }
415 
416  {
417  signed int idx = -1;
418  if (stRPNum == 3)
419  idx = 0;
420  if (stRPNum == 4)
421  idx = 1;
422  if (stRPNum == 5)
423  idx = 2;
424  if (stRPNum == 22)
425  idx = 3;
426  if (stRPNum == 16)
427  idx = 4;
428  if (stRPNum == 23)
429  idx = 5;
430  if (stRPNum == 24)
431  idx = 6;
432  if (stRPNum == 25)
433  idx = 7;
434 
435  const signed int hor = ((rpNum == 2) || (rpNum == 3) || (rpNum == 6)) ? 1 : 0;
436 
437  if (idx >= 0)
438  ms_rp_idx_arm[arm].insert(idx * 10 + hor);
439  }
440  }
441 
442  //------------------------------
443  // Global Plots
444 
445  globalPlots.events_per_bx->Fill(event.bunchCrossing());
446  globalPlots.events_per_bx_short->Fill(event.bunchCrossing());
447 
448  for (const auto &idx1 : s_rp_idx_global_hor)
449  for (const auto &idx2 : s_rp_idx_global_hor)
450  globalPlots.h_trackCorr_hor->Fill(idx1, idx2);
451 
452  for (const auto &idx1 : s_rp_idx_global_vert)
453  for (const auto &idx2 : s_rp_idx_global_vert)
454  globalPlots.h_trackCorr_vert->Fill(idx1, idx2);
455 
456  //------------------------------
457  // Arm Plots
458 
459  map<unsigned int, set<unsigned int>> mTop, mHor, mBot;
460 
461  for (auto &tr : *hTracks) {
462  CTPPSDetId rpId(tr.rpId());
463  const unsigned int rpNum = rpId.rp();
464  const unsigned int armIdx = rpId.arm();
465 
466  if (rpNum == 0 || rpNum == 4)
467  mTop[armIdx].insert(rpId);
468  if (rpNum == 2 || rpNum == 3 || rpNum == 6)
469  mHor[armIdx].insert(rpId);
470  if (rpNum == 1 || rpNum == 5)
471  mBot[armIdx].insert(rpId);
472 
473  auto &ap = armPlots[rpId.arm()];
474  unsigned int rpDecId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
475 
476  // fill in reference tracking-RP plots
477  {
478  auto it = ap.trackingRPPlots.find(rpDecId);
479  if (it != ap.trackingRPPlots.end()) {
480  it->second.h_x->Fill(tr.x());
481  it->second.h_y->Fill(tr.y());
482  }
483  }
484 
485  // fill in reference timing-RP plots
486  {
487  auto it = ap.timingRPPlots.find(rpDecId);
488  if (it != ap.timingRPPlots.end()) {
489  it->second.h_x->Fill(tr.x());
490  it->second.h_time->Fill(tr.time());
491  }
492  }
493  }
494 
495  for (auto &p : armPlots) {
496  p.second.h_numRPWithTrack_top->Fill(mTop[p.first].size());
497  p.second.h_numRPWithTrack_hor->Fill(mHor[p.first].size());
498  p.second.h_numRPWithTrack_bot->Fill(mBot[p.first].size());
499  }
500 
501  //------------------------------
502  // Correlation plots
503 
504  for (const auto &ap : ms_rp_idx_arm) {
505  auto &plots = armPlots[ap.first];
506 
507  for (const auto &idx1 : ap.second) {
508  for (const auto &idx2 : ap.second) {
509  plots.h_trackCorr->Fill(idx1 / 10, idx2 / 10);
510 
511  if ((idx1 % 10) != (idx2 % 10))
512  plots.h_trackCorr_overlap->Fill(idx1 / 10, idx2 / 10);
513  }
514  }
515  }
516 }
517 
518 //----------------------------------------------------------------------------------------------------
519 
521  // get event data
523  event.getByToken(tokenRecoProtons, hRecoProtons);
524 
525  // check validity
526  if (!hRecoProtons.isValid()) {
527  if (verbosity)
528  LogProblem("CTPPSCommonDQMSource") << "ERROR in CTPPSCommonDQMSource::analyzeProtons > input not available.";
529 
530  return;
531  }
532 
533  // loop over protons
534  for (auto &p : *hRecoProtons) {
535  if (!p.validFit())
536  continue;
537 
538  signed int armIndex = -1;
539  if (p.lhcSector() == reco::ForwardProton::LHCSector::sector45)
540  armIndex = 0;
541  if (p.lhcSector() == reco::ForwardProton::LHCSector::sector56)
542  armIndex = 1;
543  if (armIndex < 0)
544  continue;
545 
546  auto &plots = armPlots[armIndex];
547 
548  plots.h_proton_xi->Fill(p.xi());
549  plots.h_proton_th_x->Fill(p.thetaX());
550  plots.h_proton_th_y->Fill(p.thetaY());
551  plots.h_proton_t->Fill(fabs(p.t()));
552  plots.h_proton_time->Fill(p.time());
553  }
554 }
555 
556 //----------------------------------------------------------------------------------------------------
557 
559  const edm::EventSetup &) const {
560  return std::make_shared<std::vector<int>>();
561 }
562 
563 //----------------------------------------------------------------------------------------------------
564 
566  auto const &rpstate = *luminosityBlockCache(iLumi.index());
567  auto currentLS = iLumi.id().luminosityBlock();
568  if (!perLSsaving_) {
569  for (std::vector<int>::size_type i = 0; i < rpstate.size(); i++)
571  }
572 }
573 
574 //----------------------------------------------------------------------------------------------------
575 
std::shared_ptr< std::vector< int > > globalBeginLuminosityBlock(const edm::LuminosityBlock &iLumi, const edm::EventSetup &c) const override
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &) override
std::map< unsigned int, TimingRPPlots > timingRPPlots
Local (=single RP) track with essential information only.
const unsigned int verbosity
uint16_t size_type
void globalEndLuminosityBlock(const edm::LuminosityBlock &iLumi, const edm::EventSetup &c) override
CTPPSCommonDQMSource(const edm::ParameterSet &ps)
std::vector< int > rpstate
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
std::map< unsigned int, ArmPlots > armPlots
void Fill(long long x)
void Init(DQMStore::IBooker &ibooker)
static constexpr int MAX_VBINS
const edm::EDGetTokenT< std::vector< reco::ForwardProton > > tokenRecoProtons
void analyzeTracks(edm::Event const &event, edm::EventSetup const &eventSetup)
void armName(std::string &name, NameFlag flag=nFull) const
Definition: CTPPSDetId.h:98
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
plots related to the whole system
std::map< unsigned int, TrackingRPPlots > trackingRPPlots
virtual void setBinContent(int binx, double content)
set content of bin (1-D)
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:221
bool isValid() const
Definition: HandleBase.h:70
Base class for CTPPS detector IDs.
Definition: CTPPSDetId.h:32
const edm::EDGetTokenT< std::vector< CTPPSLocalTrackLite > > tokenLocalTrackLite
void analyzeProtons(edm::Event const &event, edm::EventSetup const &eventSetup)
Class to contain CTPPS information from soft FED 1022.
Definition: CTPPSRecord.h:20
fixed size matrix
HLT enums.
void analyzeCTPPSRecord(edm::Event const &event, edm::EventSetup const &eventSetup)
void analyze(edm::Event const &e, edm::EventSetup const &eSetup) override
const edm::EDGetTokenT< CTPPSRecord > ctppsRecordToken
Status status(const uint8_t rp) const
Return the status of the given roman pot.
Definition: CTPPSRecord.h:63
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
static constexpr int MAX_LUMIS
Definition: event.py:1
Definition: Run.h:45
Log< level::Error, true > LogProblem