AdcEventViewer_tool.cc
Go to the documentation of this file.
1 // AdcEventViewer_tool.cc
2 
3 #include "AdcEventViewer.h"
11 #include "TH1.h"
12 #include <iostream>
13 #include <sstream>
14 #include <iomanip>
15 
16 using std::string;
17 using std::to_string;
18 using std::cout;
19 using std::endl;
20 using std::istringstream;
21 using std::ostringstream;
23 using std::setw;
24 using std::fixed;
25 using std::setprecision;
26 
28 
29 //**********************************************************************
30 // Local methods.
31 //**********************************************************************
32 
33 namespace {
34 
35 struct VarInfo {
36  string name;
37  string vname;
38  string label;
39  string unit;
40  VarInfo(string aname, const IndexRange& cr, string clockUnit);
41  bool isValid() const { return vname.size(); }
42 };
43 
44 // Extract variable info from a name.
45 VarInfo::VarInfo(string aname, const IndexRange& cr, string clockUnit) : name(aname) {
46  if ( name.find("nfemb") != string::npos ) {
47  vname = "nfemb";
48  label = "FEMB count";
49  } else if ( name.find("event") != string::npos ) {
50  vname = "event";
51  label = "Event";
52  } else if ( name.find("clock") != string::npos ) {
53  vname = "clock";
54  label = "Timing clock";
55  unit = clockUnit;
56  } else if ( name.find("time") != string::npos ) {
57  vname = "time";
58  label = "Time";
59  unit = "sec";
60  } else if ( name.find("rmPedPower") != string::npos ) {
61  vname = "rmPedPower";
62  label = "Pedestal noise RMS";
63  unit = "ADC counts";
64  } else if ( name.find("meanPed") != string::npos ) {
65  vname = "meanPed";
66  label = "Pedestal mean";
67  unit = "ADC counts";
68  }
69 }
70 
71 string formatValue(float val, string styp) {
72  ostringstream ssval;
73  ssval << val;
74  string sval = ssval.str();
75  if ( styp == "event" ) {
76  while ( sval.size() < 8 ) sval = "0" + sval;
77  }
78  return sval;
79 }
80 
81 } // end unnamed namespace
82 
83 //**********************************************************************
84 // Subclass methods.
85 //**********************************************************************
86 
88  const string myname = "AdcEventViewer::State::runString: ";
89  if ( eventInfo.isValid() ) return eventInfo.runString();
90  if ( runSet.size() == 0 ) return "<no-runs>";
91  if ( runSet.size() > 1 ) {
92  cout << myname << "WARNING: Multiple runs have been processed:";
93  bool first = true;
94  for ( Index irun : runSet ) {
95  if ( first ) first = false;
96  else cout << ", ";
97  cout << irun;
98  }
99  cout << endl;
100  return "<multiple-runs>";
101  }
102  DuneEventInfo evi;
103  evi.run = *runSet.begin();
104  return evi.runString();
105 }
106 
107 //**********************************************************************
108 // Class methods.
109 //**********************************************************************
110 
112 : m_LogLevel(ps.get<int>("LogLevel")),
113  m_EventHists(ps.get<NameVector>("EventHists")),
114  m_EventGraphs(ps.get<NameVector>("EventGraphs")),
115  m_ChannelRanges(ps.get<NameVector>("ChannelRanges")),
116  m_ChannelRangeLabel(ps.get<Name>("ChannelRangeLabel")),
117  m_ClockUnit(ps.get<Name>("ClockUnit")),
118  m_ClockRate(ps.get<double>("ClockRate")),
119  m_state(new AdcEventViewer::State) {
120  const string myname = "AdcEventViewer::ctor: ";
121  // Fetch the channel ranges.
122  bool toolNotFound = false;
123  const IndexRangeTool* pcrt = nullptr;
125  for ( Name crn : m_ChannelRanges.size() ? m_ChannelRanges : NameVector(1, "") ) {
126  if ( crn.size() == 0 || crn == "all" ) {
127  m_crs.emplace_back("all", 0, 0, "All");
128  } else {
129  if ( pcrt == nullptr && !toolNotFound ) {
130  pcrt = ptm->getShared<IndexRangeTool>("channelRanges");
131  if ( pcrt == nullptr ) {
132  cout << myname << "ERROR: IndexRangeTool not found: channelRanges" << endl;
133  }
134  }
135  if ( pcrt != nullptr ) {
136  IndexRange ran = pcrt->get(crn);
137  if ( ran.isValid() ) {
138  m_crs.push_back(ran);
139  } else {
140  cout << myname << "WARNING: Channel range not found: " << crn << endl;
141  }
142  }
143  }
144  }
145  // Display the configuration.
146  if ( m_LogLevel>= 1 ) {
147  cout << myname << " LogLevel: " << m_LogLevel << endl;
148  cout << myname << " EventHists: [" << endl;
149  for ( Index ievh=0; ievh<m_EventHists.size(); ++ievh ) {
150  cout << myname << " " << m_EventHists[ievh] << endl;
151  }
152  cout << myname << " " << "]" << endl;
153  cout << myname << " EventGraphs: [" << endl;
154  for ( Index ievg=0; ievg<m_EventGraphs.size(); ++ievg ) {
155  cout << myname << " " << m_EventGraphs[ievg] << endl;
156  }
157  cout << myname << " " << "]" << endl;
158  cout << myname << " ChannelRanges: [";
159  bool first = true;
160  for ( const IndexRange& ran : m_crs ) {
161  if ( ! first ) cout << ", ";
162  else first = false;
163  cout << ran.name;
164  }
165  cout << "]" << endl;
166  cout << myname << " ChannelRangeLabel: " << m_ChannelRangeLabel << endl;
167  cout << myname << " ClockUnit: " << m_ClockUnit << endl;
168  cout << myname << " ClockRate: " << m_ClockRate << " tick/sec" << endl;
169  }
170  state().firstClock = 0;
171  state().minClock = 0;
172  const string::size_type& npos = string::npos;
173  // Make sure clock unit is valid.
174  if ( m_ClockUnit != "tick" &&
175  m_ClockUnit != "ktick" &&
176  m_ClockUnit != "Mtick" &&
177  m_ClockUnit != "Gtick" ) {
178  cout << myname << "WARNING: invalid clock unit changed to tick" << endl;
179  m_ClockUnit = "tick";
180  }
181  // Loop over channel ranges
182  for ( const IndexRange& cr : m_crs ) {
183  // Create the substate;
184  Name crn = cr.name;
185  if ( state().crstates.find(crn) != state().crstates.end() ) {
186  cout << myname << "WARNING: Skipping duplicate CR name: " << crn << endl;
187  continue;
188  }
190  // Create the histograms.
191  for ( string hspec : m_EventHists ) {
192  string basename;
193  int nbin = 0;
194  float xmin = 0.0;
195  float xmax = 0.0;
196  bool ok = false;
197  string::size_type ipos = 0;
198  string::size_type jpos = 0;
199  istringstream ssin;
200  jpos = hspec.find(":");
201  if ( jpos != npos ) {
202  basename = hspec.substr(ipos, jpos-ipos);
203  ipos = jpos + 1;
204  jpos = hspec.find(":", ipos);
205  if ( jpos != npos && jpos > ipos ) {
206  istringstream ssnbin(hspec.substr(ipos, jpos-ipos));
207  ssnbin >> nbin;
208  ipos = jpos + 1;
209  jpos = hspec.find(":", ipos);
210  if ( jpos != npos && jpos > ipos ) {
211  istringstream ssxmin(hspec.substr(ipos, jpos-ipos));
212  ssxmin >> xmin;
213  ipos = jpos + 1;
214  jpos = hspec.size();
215  istringstream ssxmax(hspec.substr(ipos, jpos-ipos));
216  ssxmax >> xmax;
217  ok = true;
218  }
219  }
220  }
221  if ( ! ok ) {
222  cout << "WARNING: Invalid histogram configuration string: " << hspec << endl;
223  continue;
224  }
225  string hname = basename;
226  if ( crn != "all " ) hname += "_" + crn;
227  string vname;
228  if ( basename.find("nfemb") != string::npos ) {
229  vname = "nfemb";
230  } else if ( basename.find("rmPedPower") != string::npos ) {
231  vname = "rmPedPower";
232  } else if ( basename.find("meanPed") != string::npos ) {
233  vname = "meanPed";
234  } else {
235  cout << myname << "ERROR: No variable for histogram name " << hname << endl;
236  continue;
237  }
238  VarInfo vinfo(vname, cr, m_ClockUnit);
239  string sttl = vinfo.label;
240  sttl += ";" + vinfo.label;
241  Name unit = vinfo.unit;
242  if ( unit.size() ) sttl += " [" + unit + "]";
243  sttl += ";# event";
244  if ( m_LogLevel >= 2 ) {
245  cout << myname << "Creating in histogram " << hname << ", nbin=" << nbin
246  << ", range=(" << xmin << ", " << xmax << ")" << endl;
247  }
248  TH1* ph = new TH1F(hname.c_str(), sttl.c_str(), nbin, xmin, xmax);
249  ph->SetDirectory(nullptr);
250  ph->SetStats(0);
251  ph->SetLineWidth(2);
252  crstate.hists.push_back(ph);
253  if ( m_LogLevel>= 1 ) cout << myname << "Created histogram " << hname << endl;
254  }
255  for ( string gspec : m_EventGraphs ) {
256  if ( m_LogLevel >= 2 ) cout << myname << "Building graph info" << endl;
257  string xname;
258  string yname;
259  float xmin = 0.0;
260  float xmax = 0.0;
261  float xoff = 0.0;
262  float ymin = 0.0;
263  float ymax = 0.0;
264  float yoff = 0.0;
265  string::size_type ipos = 0;
266  string::size_type jpos = 0;
267  istringstream ssin;
268  jpos = gspec.find(":");
269  // x name
270  if ( jpos != npos ) {
271  xname = gspec.substr(ipos, jpos-ipos);
272  ipos = jpos + 1;
273  jpos = gspec.find(":", ipos);
274  if ( m_LogLevel >= 2 ) cout << myname << " xname: " << xname << endl;
275  }
276  // x range
277  if ( jpos != npos && jpos > ipos ) {
278  // Range from job range tool: name:ranName:xoff
279  if ( isalpha(gspec[ipos]) ) {
280  if ( m_LogLevel >= 2 ) cout << myname << " Taking x range from tool." << endl;
281  istringstream ssnran(gspec.substr(ipos, jpos-ipos));
282  Name ranName = gspec.substr(ipos, jpos-ipos);
283  const IndexRangeTool* pcrt = ptm->getShared<IndexRangeTool>("jobRanges");
284  if ( pcrt == nullptr ) {
285  cout << myname << "ERROR: Unable to find index range tool jobRanges" << endl;
286  } else {
287  IndexRange ran = pcrt->get(ranName);
288  if ( ran.isValid() ) {
289  xmin = ran.begin;
290  xmax = ran.end;
291  } else {
292  cout << myname << "ERROR: Unable to find job range " << ranName << endl;
293  }
294  }
295  ipos = jpos + 1;
296  jpos = gspec.find(":", ipos);
297  if ( jpos != npos && jpos > ipos ) {
298  istringstream ssxoff(gspec.substr(ipos, jpos-ipos));
299  ssxoff >> xoff;
300  }
301  // Explicit range
302  } else {
303  if ( m_LogLevel >= 2 ) cout << myname << " Using explicit x range." << endl;
304  istringstream ssxmin(gspec.substr(ipos, jpos-ipos));
305  ssxmin >> xmin;
306  ipos = jpos + 1;
307  jpos = gspec.find(":", ipos);
308  if ( jpos != npos && jpos > ipos ) {
309  istringstream ssxmax(gspec.substr(ipos, jpos-ipos));
310  ssxmax >> xmax;
311  }
312  }
313  }
314  ipos = jpos + 1;
315  jpos = gspec.find(":", ipos);
316  // y name
317  if ( jpos != npos && jpos > ipos ) {
318  yname = gspec.substr(ipos, jpos-ipos);
319  ipos = jpos + 1;
320  jpos = gspec.find(":", ipos);
321  if ( m_LogLevel >= 2 ) cout << myname << " yname: " << yname << endl;
322  }
323  // y range
324  if ( jpos != npos && jpos > ipos ) {
325  // Range from job range tool: name:ranName:yoff
326  if ( isalpha(gspec[ipos]) ) {
327  if ( m_LogLevel >= 2 ) cout << myname << " Taking y range from tool." << endl;
328  istringstream ssnran(gspec.substr(ipos, jpos-ipos));
329  Name ranName = gspec.substr(ipos, jpos-ipos);
330  cout << myname << "Taking y-range from job range " << ranName << endl;
331  const IndexRangeTool* pcrt = ptm->getShared<IndexRangeTool>("jobRanges");
332  if ( pcrt == nullptr ) {
333  cout << myname << "ERROR: Unable to find index range tool jobRanges" << endl;
334  } else {
335  IndexRange ran = pcrt->get(ranName);
336  if ( ran.isValid() ) {
337  ymin = ran.begin;
338  ymax = ran.end;
339  } else {
340  cout << myname << "ERROR: Unable to fund job range " << ranName << endl;
341  }
342  }
343  ipos = jpos + 1;
344  jpos = gspec.find(":", ipos);
345  if ( jpos != npos && jpos > ipos ) {
346  istringstream ssyoff(gspec.substr(ipos, jpos-ipos));
347  ssyoff >> yoff;
348  }
349  // Explicit range
350  } else {
351  if ( m_LogLevel >= 2 ) cout << myname << " Using explicit y range." << endl;
352  istringstream ssymin(gspec.substr(ipos, jpos-ipos));
353  ssymin >> ymin;
354  ipos = jpos + 1;
355  jpos = gspec.find(":", ipos);
356  if ( jpos > ipos ) {
357  istringstream ssymax(gspec.substr(ipos, jpos-ipos));
358  ssymax >> ymax;
359  }
360  }
361  }
362  VarInfo xvin(xname, cr, m_ClockUnit);
363  VarInfo yvin(yname, cr, m_ClockUnit);
364  bool ok = xvin.isValid() && yvin.isValid();
365  if ( ! ok ) {
366  cout << myname << "WARNING: Invalid graph configuration string: " << gspec << endl;
367  continue;
368  }
369  string sttl = yvin.label + " vs. " + xvin.label;
370  if ( m_LogLevel >= 2 ) {
371  cout << myname << "Creating graph of " << yname;
372  if ( ymax > ymin ) cout << " range=(" << ymin - yoff << ", " << ymax + yoff << ")";
373  else if ( ymax >= 0.0 ) cout << " range from data with border " << yoff << endl;
374  cout << " vs. " << xname;
375  if ( xmax > xmin ) cout << " range=(" << xmin << ", " << xmax << ")";
376  else if ( xmax >= 0.0 ) cout << " range from data with border " << xoff << endl;
377  cout << endl;
378  }
379  crstate.graphs.emplace_back(xname, xvin.label, xvin.unit, xmin, xmax, xoff,
380  yname, yvin.label, yvin.unit, ymin, ymax, yoff );
381  if ( m_LogLevel>= 1 ) cout << myname << "Created graph info for " << yname << " vs. " << xname << endl;
382  }
383  } // end loop over channel ranges
384 }
385 
386 //**********************************************************************
387 
389  const string myname = "AdcEventViewer::dtor: ";
390  if ( state().beginEventCount == 0 ) endEventState(state().eventInfo);
391  cout << myname << " Begin event count: " << state().beginEventCount << endl;
392  cout << myname << "Unique event count: " << state().events.size() << endl;
393  displayHists();
394  displayGraphs();
395  cout << myname << "Exiting." << endl;
396 }
397 
398 //**********************************************************************
399 
401  const string myname = "AdcEventViewer::beginEvent: ";
402  DataMap ret;
403  if ( m_LogLevel >= 2 ) {
404  cout << myname << "Begin processing event " << devt.event << " for run " << devt.run;
405  if ( devt.subRun ) cout << "-" << devt.subRun;
406  cout << endl;
407  }
408  if ( state().haveEvent() ) {
409  cout << myname << "WARNING: Begin called wth event " << devt.event
410  << " during processing of event " << state().eventInfo.event
411  << ". Ending current event." << endl;
412  endEvent(state().eventInfo);
413  }
415  beginEventState(devt);
416  return ret;
417 }
418 
419 //**********************************************************************
420 
422  const string myname = "AdcEventViewer::endEvent: ";
423  if ( m_LogLevel >= 2 ) {
424  cout << myname << "End processing event " << devt.event << " for run " << devt.run;
425  if ( devt.subRun ) cout << "-" << devt.subRun;
426  cout << endl;
427  }
428  DataMap ret;
429  endEventState(devt);
430  return ret;
431 }
432 
433 //**********************************************************************
434 
436  const string myname = "AdcEventViewer::view: ";
437  DataMap res;
438  if ( m_LogLevel >= 4 ) cout << myname << "Processing channel " << acd.channel()
439  << " (FEMB " << acd.fembID() << ")"
440  << " in run " << acd.run() << " event " << acd.event() << endl;
441  if ( acd.event() != state().event() || acd.run() != state().run() ) {
442  if ( state().beginEventCount ) {
443  cout << myname << "ERROR: Run:event from data " << acd.run() << ":" << acd.event()
444  << " does not match that from beginEvent "
445  << state().runString() << ":" << state().event() << endl;
446  return res.setStatus(1);
447  }
449  }
450  for ( const IndexRange& cr : m_crs ) {
451  if ( cr.name != "all" && !cr.contains(acd.channel()) ) continue;
453  crstate.fembIDSet.insert(acd.fembID());
454  ++crstate.nchan;
455  crstate.pedSum += acd.pedestal;
456  float pedNoise = acd.pedestalRms;
457  crstate.pedPower += pedNoise*pedNoise;
458  }
459  return res;
460 }
461 
462 //**********************************************************************
463 
465  const string myname = "AdcEventViewer::viewMap: ";
466  if ( m_LogLevel >= 3 ) {
467  Index ncha = acds.size();
468  cout << myname << "Processing " << ncha << " channel" << (ncha == 1 ? "" : "s");
469  if ( ncha > 0 ) {
470  const AdcChannelData& acd = acds.begin()->second;
471  cout << " in run " << acd.run() << " event " << acd.event();
472  cout << ". Count is " << state().beginEventCount << "." << endl;
473  }
474  }
475  DataMap ret;
476  if ( state().beginEventCount == 0 ) {
477  if ( acds.size() == 0 ) {
478  if ( m_LogLevel >=2 ) cout << myname << "Skipping group with no data" << endl;
479  return ret;
480  }
481  const AdcChannelData& acd = acds.begin()->second;
482  if ( acd.event() != state().event() ) beginEventState(acd.getEventInfo());
483  }
484  ++state().ngroup;
485  for ( const AdcChannelDataMap::value_type& iacd : acds ) view(iacd.second);
486  return ret;
487 }
488 
489 //**********************************************************************
490 
492  const string myname = "AdcEventViewer::crstate: ";
493  ChannelRangeStates::iterator icrs = state().crstates.find(crn);
494  if ( icrs == state().crstates.end() ) {
495  cout << myname << "ERROR: There is no substate for channel range " << crn << endl;
496  static ChannelRangeState crsbad;
497  return crsbad;
498  }
499  return icrs->second;
500 }
501 
502 //**********************************************************************
503 
505  const string myname = "AdcEventViewer::beginEventState: ";
506  if ( state().haveEvent() ) {
507  cout << "WARNING: Begin called during event processing. Ending current event." << endl;
508  endEventState(devt);
509  }
510  if ( m_LogLevel >= 4 ) cout << myname << "Starting run" << devt.runString()
511  << " event " << devt.event << endl;
512  if ( state().haveEvent() && state().run() != devt.run ) {
513  cout << myname << "ERROR: change in run number is not (yet) supported." << endl;
514  return;
515  }
516  Index ievt = devt.event;
517  Index irun = devt.run;
518  state().eventInfo = devt;
519  state().events.push_back(ievt);
520  state().eventSet.insert(ievt);
521  state().runSet.insert(irun);
522  LongIndex clk = devt.triggerClock;
523  if ( state().firstClock == 0 ) state().firstClock = clk;
524  if ( clk < state().minClock ) state().minClock = clk;
525  state().ngroup = 0;
526  for ( ChannelRangeStates::iterator icr=state().crstates.begin();
527  icr!=state().crstates.end(); ++icr ) {
528  ChannelRangeState& crstate = icr->second;
529  crstate.fembIDSet.clear();
530  crstate.nchan = 0;
531  crstate.pedSum = 0.0;
532  crstate.pedPower = 0.0;
533  }
534 }
535 
536 //**********************************************************************
537 
539  const string myname = "AdcEventViewer::endEventState: ";
540  if ( ! devt.isValid() ) {
541  cout << myname << "ERROR: End called without an active event." << endl;
542  return;
543  }
544  if ( devt != state().eventInfo ) {
545  cout << myname << "ERROR: End called without incorrect event info." << endl;
546  return;
547  }
548  if ( state().event() == 0 ) return;
549  Index nevt = state().events.size();
550  Index ndup = nevt - state().eventSet.size();
551  const int w = 5;
552  long iclk = state().clock();
553  iclk -= state().firstClock;
554  // Plotted clock has zero 1 sec after the clock for the first event.
555  float xclk = iclk + m_ClockRate;
556  float time = m_ClockRate == 0.0 ? 0.0 : xclk/m_ClockRate;
557  Name clkunit = m_ClockUnit;
558  if ( clkunit == "ktick" ) xclk *= 0.001;
559  else if ( clkunit == "Mtick" ) xclk *= 0.000001;
560  else if ( clkunit == "Gtick" ) xclk *= 0.000000001;
561  if ( m_LogLevel >= 2 ) {
562  cout << myname << " run: " << setw(w) << state().runString() << endl;
563  cout << myname << " event: " << setw(w) << state().event() << endl;
564  cout << myname << " # events: " << setw(w) << state().events.size() << endl;
565  cout << myname << " # duplicate events: " << setw(w) << ndup << endl;
566  cout << myname << " Min clock: " << setw(w) << state().minClock << endl;
567  cout << myname << " clock: " << setw(w+3) << fixed << setprecision(2) << xclk << " " << clkunit << endl;
568  cout << myname << " time: " << setw(w+3) << fixed << setprecision(2) << time << " sec" << endl;
569  cout << myname << " # groups: " << setw(w) << state().ngroup << endl;
570  }
571  for ( const IndexRange& cr : m_crs ) {
573  Index nfmb = crstate.fembIDSet.size();
574  Index nchn = crstate.nchan;
575  float meanPed = nchn > 0 ? crstate.pedSum/nchn : 0.0;
576  float meanPedPower = nchn > 0 ? crstate.pedPower/nchn : 0.0;
577  float rmPedPower = sqrt(meanPedPower);
578  double chanPerFemb = nfmb > 0 ? double(nchn)/nfmb : 0.0;
579  if ( m_LogLevel >= 2 ) {
580  cout << myname << "----- Channel range " << cr.label() << ":" << endl;
581  cout << myname << " # FEMBs: " << setw(w) << nfmb << endl;
582  cout << myname << " # channels: " << setw(w) << nchn << endl;
583  cout << myname << " # channels/FEMB: " << setw(w+5) << fixed << setprecision(4) << chanPerFemb << endl;
584  cout << myname << " Mean pedestal: " << setw(w+3) << fixed << setprecision(2) << meanPed << endl;
585  cout << myname << " RM pedestal power: " << setw(w+3) << fixed << setprecision(2) << rmPedPower << endl;
586  }
587  for ( TH1* ph : crstate.hists ) {
588  string name = ph->GetName();
589  if ( name.find("nfemb") != string::npos ) ph->Fill(nfmb);
590  else if ( name.find("rmPedPower") != string::npos ) ph->Fill(rmPedPower);
591  else if ( name.find("meanPed") != string::npos ) ph->Fill(meanPed);
592  else {
593  cout << myname << "ERROR: No variable for histogram name " << name << endl;
594  }
595  }
596  for ( GraphInfo& gin : crstate.graphs ) {
597  gin.add("event", state().event());
598  gin.add("clock", xclk);
599  gin.add("time", time);
600  gin.add("nfemb", nfmb);
601  gin.add("rmPedPower", rmPedPower);
602  gin.add("meanPed", meanPed);
603  }
604  }
605  state().eventInfo.clear();
606 }
607 
608 //**********************************************************************
609 
611  const string myname = "AdcEventViewer::displayHists: ";
612  string sttlSuf = " for run " + state().runString();
613  Index nevt = state().eventSet.size();
614  if ( nevt == 0 ) sttlSuf += " with no events.";
615  else if ( nevt == 1 ) sttlSuf += " event " + to_string(*state().eventSet.begin());
616  else sttlSuf += " events " + to_string(*state().eventSet.begin()) + "-" + to_string(*state().eventSet.rbegin());
617  string evstring;
618  if ( state().eventSet.size() ) {
619  evstring += "_event" + formatValue(*state().eventSet.cbegin(), "event");
620  if ( state().eventSet.size() > 1 ) {
621  evstring += "-" + formatValue(*state().eventSet.crbegin(), "event");
622  }
623  }
624  for ( const IndexRange& cr : m_crs ) {
626  Index nplt = crstate.hists.size();
627  if ( m_LogLevel >= 1 ) cout << myname << "Creating " << nplt << " plot"
628  << (nplt == 1 ? "" : "s") << sttlSuf
629  << (nplt > 0 ? ":" : "") << endl;
630  for ( TH1* ph : crstate.hists ) {
631  TPadManipulator man;
632  man.add(ph);
633  string sttl = ph->GetTitle() + sttlSuf;
634  string crlab = m_ChannelRangeLabel;
635  StringManipulator smlab(crlab, false);
636  smlab.replace("%CRNAME%", cr.name);
637  smlab.replace("%CRLABEL%", cr.label());
638  smlab.replace("%CRLABEL1%", cr.label(1));
639  smlab.replace("%CRLABEL2%", cr.label(2));
640  if ( crlab.size() ) sttl += " " + crlab;
641  man.setTitle(sttl.c_str());
642 
643  string fname = string("eviewh_") + ph->GetName() + "_run" + state().runString()
644  + evstring + "_" + cr.name + ".{png,tpad}";
645  man.showUnderflow();
646  man.showOverflow();
647  man.addAxis();
648  man.print(fname);
649  if ( m_LogLevel >= 1 ) cout << myname << " " << fname << endl;
650  }
651  }
652 }
653 
654 //**********************************************************************
655 
657  const string myname = "AdcEventViewer::displayGraphs: ";
658  string sttlSufBase = " for run " + state().runString();
659  for ( const IndexRange& cr : m_crs ) {
661  Index nplt = crstate.graphs.size();
662  Index nevt = state().eventSet.size();
663  string sttlSuf = sttlSufBase;
664  if ( nevt == 0 ) sttlSuf += " with no events.";
665  else if ( nevt == 1 ) sttlSuf += " event " + to_string(*state().eventSet.begin());
666  else sttlSuf += " events " + to_string(*state().eventSet.begin()) + "-" + to_string(*state().eventSet.rbegin());
667  if ( m_LogLevel >= 1 ) cout << myname << "Creating " << nplt << " graph"
668  << (nplt == 1 ? "" : "s") << sttlSuf
669  << (nplt > 0 ? ":" : "") << endl;
670  string crlab = m_ChannelRangeLabel;
671  StringManipulator smlab(crlab, false);
672  smlab.replace("%CRNAME%", cr.name);
673  smlab.replace("%CRLABEL%", cr.label());
674  smlab.replace("%CRLABEL1%", cr.label(1));
675  smlab.replace("%CRLABEL2%", cr.label(2));
676  if ( crlab.size() ) sttlSuf += " " + crlab;
677  for ( GraphInfo& gin : crstate.graphs ) {
678  if ( m_LogLevel >= 1 ) cout << myname << "Creating graph of " << gin.vary << " vs. " << gin.varx << endl;
679  Index npt = gin.xvals.size();
680  if ( npt == 0 ) {
681  cout << myname << "Skipping graph with no entries." << endl;
682  continue;
683  }
684  if ( gin.yvals.size() != npt ) {
685  cout << myname << "Skipping graph with inconsistent entries." << endl;
686  continue;
687  }
688  TGraph* pg = new TGraph(npt, &gin.xvals[0], &gin.yvals[0]);
689  pg->GetXaxis()->SetTitle(gin.xAxisLabel().c_str());
690  pg->GetYaxis()->SetTitle(gin.yAxisLabel().c_str());
691  pg->SetMarkerStyle(2);
692  double xmin = gin.xmin;
693  double xmax = gin.xmax;
694  double xoff = gin.xoff;
695  double ymin = gin.ymin;
696  double ymax = gin.ymax;
697  double yoff = gin.yoff;
698  bool setXLimitsFromData = pg->GetN() && xmax == xmin && xmax >= 0.0;
699  bool setYLimitsFromData = pg->GetN() && ymax == ymin && ymax >= 0.0;
700  if ( setXLimitsFromData || setYLimitsFromData ) {
701  double xdmin = 0.0;
702  double xdmax = 0.0;
703  double ydmin = 0.0;
704  double ydmax = 0.0;
705  double xpt, ypt;
706  for ( int ipt=0; ipt<pg->GetN(); ++ipt ) {
707  pg->GetPoint(ipt, xpt, ypt);
708  if ( ipt == 0 ) {
709  xdmin = xpt;
710  xdmax = xpt;
711  ydmin = ypt;
712  ydmax = ypt;
713  } else {
714  if ( xpt < xdmin ) xdmin = xpt;
715  if ( xpt > xdmax ) xdmax = xpt;
716  if ( ypt < ydmin ) ydmin = ypt;
717  if ( ypt > ydmax ) ydmax = ypt;
718  }
719  }
720  if ( setXLimitsFromData ) {
721  xoff = xmax;
722  xmin = xdmin;
723  xmax = xdmax;
724  if ( m_LogLevel >= 2 ) {
725  cout << myname << " Setting graph X range from data (" << xdmin << ", " << xdmax << ") to ("
726  << xmin-xoff << ", " << xmax+xoff << ")" << endl;
727  }
728  }
729  if ( setYLimitsFromData ) {
730  yoff = ymax;
731  ymin = ydmin;
732  ymax = ydmax;
733  if ( m_LogLevel >= 2 ) {
734  cout << myname << " Setting graph Y range from data (" << ydmin << ", " << ydmax << ") to ("
735  << ymin-yoff << ", " << ymax+yoff << ")" << endl;
736  }
737  }
738  }
739  if ( xmax > xmin ) pg->GetXaxis()->SetRangeUser(xmin-xoff, xmax+xoff);
740  if ( ymax > ymin ) pg->GetYaxis()->SetRangeUser(ymin-yoff, ymax+yoff);
741  TPadManipulator man(1400, 500);
742  man.add(pg, "P");
743  string sttl = gin.ylab + " vs. " + gin.xlab + sttlSuf;
744  man.setTitle(sttl.c_str());
745  man.showUnderflow();
746  man.showOverflow();
747  man.addAxis();
748  man.setGridX();
749  man.setGridY();
750  if ( xmax > xmin ) man.setRangeX(xmin-xoff, xmax+xoff);
751  if ( ymax > ymin ) man.setRangeY(ymin-yoff, ymax+yoff);
752  ostringstream ssfname;
753  ssfname << "eviewg_" << gin.varx;
754  if ( gin.xmax > gin.xmin ) ssfname << "-" << formatValue(gin.xmin, gin.varx)
755  << "-" << formatValue(gin.xmax, gin.varx);
756  ssfname << "_" << gin.vary;
757  if ( gin.ymax > gin.ymin ) ssfname << "-" << formatValue(gin.ymin, gin.vary)
758  << "-" << formatValue(gin.ymax, gin.vary);
759  ssfname << "_run" << state().runString();
760  ssfname << "_" << cr.name;
761  ssfname << ".{png,tpad}";
762  Name fname = ssfname.str();
763  man.print(fname);
764  if ( m_LogLevel >= 1 ) cout << myname << " " << fname << endl;
765  }
766  }
767 }
768 
769 //**********************************************************************
770 
static QCString name
Definition: declinfo.cpp:673
intermediate_table::iterator iterator
int setGridY(bool flag=true)
const DuneEventInfo & getEventInfo() const
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
NameVector m_EventHists
void add(Name var, float val)
LongIndex clock() const
int add(unsigned int ipad, TObject *pobj, std::string sopt="", bool replace=false)
unsigned int Index
DataMap & setStatus(int stat)
Definition: DataMap.h:130
std::string string
Definition: nybbler.cc:12
Index begin
Definition: IndexRange.h:34
unsigned long LongIndex
DataMap endEvent(const DuneEventInfo &devt) const override
int replace(std::string substr, const T &xsub)
NameVector m_EventGraphs
unsigned int Index
bool isValid() const
Definition: IndexRange.h:94
int find(char c, int index=0, bool cs=TRUE) const
Definition: qcstring.cpp:41
unsigned int Index
DataMap view(const AdcChannelData &acd) const override
Index end
Definition: IndexRange.h:35
int showOverflow(bool show=true)
Q_EXPORT QTSManip setprecision(int p)
Definition: qtextstream.h:343
void displayGraphs() const
DuneEventInfo eventInfo
DataMap beginEvent(const DuneEventInfo &devt) const override
int setTitle(std::string sttl, float height=-1.0)
Index fembID() const
AdcSignal pedestalRms
AdcEventViewer(fhicl::ParameterSet const &ps)
ChannelRangeStates crstates
int showUnderflow(bool show=true)
AdcIndex run() const
std::string runString() const
int addAxis(bool flag=true)
AdcIndex event() const
State & state() const
static constexpr double ps
Definition: Units.h:99
std::string runString(Index opt=2) const
bool isValid() const
Definition: DuneEventInfo.h:65
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
void beginEventState(const DuneEventInfo &devt) const
Index event() const
Channel channel() const
ChannelRangeState & crstate(Name crn) const
NameVector m_ChannelRanges
AdcSignal pedestal
IndexRangeVector m_crs
void displayHists() const
int setRangeX(double x1, double x2)
void endEventState(const DuneEventInfo &devt) const
~AdcEventViewer() override
std::map< AdcChannel, AdcChannelData > AdcChannelDataMap
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
int setGridX(bool flag=true)
DataMap viewMap(const AdcChannelDataMap &acds) const override
int setRangeY(double y1, double y2)
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
int print(std::string fname, std::string spat="{,}")
static DuneToolManager * instance(std::string fclname="", int dbg=1)
std::string Name
T * getShared(std::string name)
QTextStream & endl(QTextStream &s)
LongIndex triggerClock
Definition: DuneEventInfo.h:27
virtual IndexRange get(Name nam) const =0
std::vector< Name > NameVector