AdcRoiViewer_tool.cc
Go to the documentation of this file.
1 // AdcRoiViewer_tool.cc
2 
3 #include "AdcRoiViewer.h"
17 #include <iostream>
18 #include <fstream>
19 #include <sstream>
20 #include <iomanip>
21 #include <algorithm>
22 #include "TH1F.h"
23 #include "TH2F.h"
24 #include "TDirectory.h"
25 #include "TFile.h"
26 #include "TF1.h"
27 #include "TTimeStamp.h"
28 
29 using std::string;
30 using std::to_string;
31 using std::cout;
32 using std::endl;
33 using std::ostringstream;
34 using std::istringstream;
36 
39 using NameVector = std::vector<Name>;
40 using ParameterSetVector = std::vector<ParameterSet>;
41 using FloatVector = std::vector<float>;
42 using IntVector = std::vector<int>;
43 using ManVector = std::vector<TPadManipulator*>;
44 using ManVectorMap = std::vector<Name, ManVector>;
45 
46 namespace {
47 string timeString(int itim) {
48  TTimeStamp ts(itim);
49  string stim = ts.AsString("s");
50  stim += " UTC";
51  return stim;
52 }
53 } // end unnamed namespace
54 
55 //**********************************************************************
56 // Subclass methods.
57 //**********************************************************************
58 
60  for ( HistInfoMap::value_type ihin : sumHistTemplates ) {
61  TH1*& ph = ihin.second.ph;
62  delete ph;
63  ph = nullptr;
64  }
65  for ( HistMap::value_type ihst : sumHists ) {
66  TH1*& ph = ihst.second;
67  delete ph;
68  ph = nullptr;
69  }
70  for ( HistMap::value_type ihst : chanSumHists ) {
71  TH1*& ph = ihst.second;
72  delete ph;
73  ph = nullptr;
74  }
75 }
76 
77 //**********************************************************************
78 
80  HistMap::iterator ihst = sumHists.find(hname);
81  if ( ihst == sumHists.end() ) return nullptr;
82  return ihst->second;
83 }
84 
85 //**********************************************************************
86 
88  NameMap::const_iterator ifit = sumFitNames.find(hnam);
89  if ( ifit == sumFitNames.end() ) return "";
90  return ifit->second;
91 }
92 
93 //**********************************************************************
94 
96  NameMap::const_iterator iplt = sumPlotNames.find(hnam);
97  if ( iplt == sumPlotNames.end() ) return "";
98  return iplt->second;
99 }
100 
101 //**********************************************************************
102 
104  FloatMap::const_iterator iplt = sumPlotWidths.find(hnam);
105  if ( iplt == sumPlotWidths.end() ) return 0.0;
106  return iplt->second;
107 }
108 
109 //**********************************************************************
110 
113  if ( ihst == chanSumHistTemplateNames.end() ) return nullptr;
114  return ihst->second;
115 }
116 
117 //**********************************************************************
118 
121  if ( ihst == chanSumHistVariableTypes.end() ) return nullptr;
122  return ihst->second;
123 }
124 
125 //**********************************************************************
126 
129  if ( ihst == chanSumHistErrorTypes.end() ) return nullptr;
130  return ihst->second;
131 }
132 
133 //**********************************************************************
134 
136  NameMap::const_iterator ihst = chanSumPlotNames.find(hnam);
137  if ( ihst == chanSumPlotNames.end() ) return nullptr;
138  return ihst->second;
139 }
140 
141 //**********************************************************************
142 
144  const Name myname = "AdcRoiViewer::State::getChannelStatus: ";
146  if ( ichs == channelStatuses.end() ) {
147  cout << myname << "WARNING: Status not found for channel " << icha << endl;
148  return 0;
149  }
150  return ichs->second;
151 }
152 
153 //**********************************************************************
154 
156  const Name myname = "AdcRoiViewer::State::getChannelStatus: ";
158  if ( ichc == sumHistChannels.end() ) {
159  cout << myname << "WARNING: Channel not found for chansum histogram " << hnam << endl;
160  return 0;
161  }
162  return getChannelStatus(ichc->second);
163 }
164 
165 //**********************************************************************
166 // Class methods.
167 //**********************************************************************
168 
170 : m_LogLevel(ps.get<int>("LogLevel")),
171  m_SigThresh(ps.get<float>("SigThresh")),
172  m_TickBorder(ps.get<Index>("TickBorder")),
173  m_RoiHistOpt(ps.get<int>("RoiHistOpt")),
174  m_FitOpt(ps.get<int>("FitOpt")),
175  m_RoiPlotOpt(ps.get<Index>("RoiPlotOpt")),
176  m_MaxRoiPlots(ps.get<int>("MaxRoiPlots")),
177  m_RoiPlotPadX(ps.get<Index>("RoiPlotPadX")),
178  m_RoiPlotPadY(ps.get<Index>("RoiPlotPadY")),
179  m_StartTime(ps.get<time_t>("StartTime")),
180  m_PulserStepCharge(ps.get<float>("PulserStepCharge")),
181  m_PulserDacOffset(ps.get<float>("PulserDacOffset")),
182  m_PulserChargeUnit(ps.get<string>("PulserChargeUnit")),
183  m_SumNegate(ps.get<bool>("SumNegate")),
184  m_SumPlotPadX(ps.get<Index>("SumPlotPadX")),
185  m_SumPlotPadY(ps.get<Index>("SumPlotPadY")),
186  m_ChannelLineModulus(ps.get<Index>("ChannelLineModulus")),
187  m_ChannelLinePattern(ps.get<IndexVector>("ChannelLinePattern")),
188  m_RunDataTool(ps.get<string>("RunDataTool")),
189  m_TickOffsetTool(ps.get<string>("TickOffsetTool")),
190  m_RoiRootFileName(ps.get<string>("RoiRootFileName")),
191  m_SumRootFileName(ps.get<string>("SumRootFileName")),
192  m_ChanSumRootFileName(ps.get<string>("ChanSumRootFileName")),
193  m_ChannelRanges(ps.get<NameVector>("ChannelRanges")),
194  m_PlotLabels(ps.get<NameVector>("PlotLabels")),
196 {
197  const string myname = "AdcRoiViewer::ctor: ";
198  if ( m_LogLevel >=2 ) cout << myname << "Begin constructing tool." << endl;
199  string stringBuilder = "adcStringBuilder";
201  m_adcStringBuilder = ptm->getShared<AdcChannelStringTool>(stringBuilder);
202  if ( m_adcStringBuilder == nullptr ) {
203  cout << myname << "WARNING: AdcChannelStringTool not found: " << stringBuilder << endl;
204  }
205  if ( m_RunDataTool.size() ) {
207  if ( m_pRunDataTool == nullptr ) {
208  cout << myname << "WARNING: RunDataTool not found: " << m_RunDataTool << endl;
209  } else {
210  cout << myname << "Found run data tool." << endl;
211  }
212  }
213  if ( m_TickOffsetTool.size() ) {
215  if ( m_pTickOffsetTool == nullptr ) {
216  cout << myname << "WARNING: Tick offset tool not found: " << m_TickOffsetTool << endl;
217  } else {
218  cout << myname << "Found tick offset tool." << endl;
219  }
220  }
221  if ( m_ChannelRangeTool.size() ) {
223  if ( m_pChannelRangeTool == nullptr ) {
224  cout << myname << "WARNING: Index range tool not found: " << m_ChannelRangeTool << endl;
225  } else {
226  cout << myname << "Found channel range tool." << endl;
227  }
228  }
229  // Build the label substitutions.
230  for ( Index ilab=0; ilab<m_PlotLabels.size(); ++ilab ) {
231  Name stxt = "%LAB" + to_string(ilab) + "%";
232  m_plotLabelSubs[stxt] = m_PlotLabels[ilab];
233  }
234  // Build the summary template histograms.
235  // The summary histogram for each channel is created the first time it is encountered in th data.
236  ParameterSetVector pshists = ps.get<ParameterSetVector>("SumHists");
237  string stimepre = "Time since " + timeString(m_StartTime) + " ";
238  for ( const ParameterSet& psh : pshists ) {
239  Name hvarx = psh.get<Name>("var");
240  Name hvary;
241  if ( hvarx == "timingPhase_fitToffPulserMod10" ) {
242  hvarx = "fitToffPulserMod10";
243  hvary = "timingPhase";
244  }
245  if ( hvarx == "event_fitToffPulser" ) {
246  hvarx = "fitToffPulser";
247  hvary = "event";
248  }
249  Name hnam = psh.get<Name>("name");
250  setPlotLabels(hnam);
251  Name httl = psh.get<Name>("title");
252  setPlotLabels(httl);
253  if ( getState().sumHistTemplates.find(hnam) != getState().sumHistTemplates.end() ) {
254  cout << myname << "ERROR: Duplicate summary template name: " << hnam << endl;
255  continue;
256  }
257  int nbin = psh.get<int>("nbin");
258  float xmin = psh.get<float>("xmin");
259  float xmax = psh.get<float>("xmax");
260  Name sfit;
261  psh.get_if_present("fit", sfit);
262  Name plotName;
263  psh.get_if_present("plot", plotName);
264  float plotWidth = 0.0;
265  psh.get_if_present("pwid", plotWidth);
266  Name xlab = hvarx;
267  if ( hvarx == "fitHeight" ) xlab = "Fit height% [SUNIT]%";
268  else if ( hvarx == "fitHeightNeg" ) xlab = "-(Fit height)% [SUNIT]%";
269  else if ( hvarx == "fitHeightGain" ) {
270  xlab = "Fit height gain% [SUNIT]%";
271  Name sden = m_PulserChargeUnit;
272  if ( sden.size() ) {
273  if ( sden.find(" ") != string::npos ) sden = "(" + sden + ")";
274  xlab = "Fit height gain [%((SUNIT))%/" + sden + "]";
275  }
276  }
277  else if ( hvarx == "fitWidth" ) xlab = "Fit width [Tick]";
278  else if ( hvarx == "fitPos" ) xlab = "Fit position [Tick]";
279  else if ( hvarx == "fitPosRem" ) xlab = "Fit position tick remainder [Tick]";
280  else if ( hvarx == "fitPosPulser" )
281  xlab = "Fit position wrt pulser [Tick]";
282  else if ( hvarx == "fitToffPulser" )
283  xlab = "Offset fit position wrt pulser [Tick]";
284  else if ( hvarx == "fitToffPulserMod10" )
285  xlab = "mod_{10}(offset fit position wrt pulser) [Tick]";
286  else if ( hvarx == "fitChiSquare" ) xlab = "Fit #chi^{2}";
287  else if ( hvarx == "fitChiSquareDof" ) xlab = "Fit #chi^{2}/DOF";
288  else if ( hvarx == "fitCSNorm" ) xlab = "Normalized fit #chi^{2}";
289  else if ( hvarx == "fitCSNormDof" ) xlab = "Normalized fit #chi^{2}/DOF";
290  else if ( hvarx == "sigArea" ) xlab = "Area [%ASUNIT%]";
291  else if ( hvarx == "sigAreaNeg" ) xlab = "-Area [%ASUNIT%]";
292  else if ( hvarx == "sigWidth" ) xlab = "Width [Tick]";
293  else if ( hvarx == "timeSec" || hvarx == "procTimeSec" ) xlab = stimepre + " [sec]";
294  else if ( hvarx == "timeHour" || hvarx == "procTimeHour") xlab = stimepre + " [hour]";
295  else if ( hvarx == "timeDay" || hvarx == "procTimeDay" ) xlab = stimepre + " [day]";
296  else {
297  cout << myname << "WARNING: Unknown summary variable: " << hvarx << endl;
298  }
299  Name ylab;
300  if ( hvary.size() ) {
301  if ( hvary == "timingPhase" ) ylab = "Timing phase [Tick]";
302  if ( hvary == "event" ) ylab = "Event";
303  }
304  TH1* ph = nullptr;
305  if ( hvary == "" ) {
306  ph = new TH1F(hnam.c_str(), httl.c_str(), nbin, xmin, xmax);
307  ph->GetYaxis()->SetTitle("# ROI");
308  ph->Sumw2(); // Needed for likelihood fit
309  } else {
310  int nbiny = psh.get<int>("nbiny");
311  float ymin = psh.get<float>("ymin");
312  float ymax = psh.get<float>("ymax");
313  ph = new TH2F(hnam.c_str(), httl.c_str(), nbin, xmin, xmax, nbiny, ymin, ymax);
314  ph->GetYaxis()->SetTitle(ylab.c_str());
315  }
316  ph->SetDirectory(nullptr);
317  ph->SetLineWidth(2);
318  ph->GetXaxis()->SetTitle(xlab.c_str());
319  // Add fit to template so it will be used for each child histogram.
320  //if ( sfit.size() ) {
321  // if ( m_LogLevel >= 1 ) cout << myname << "Adding fitter " << sfit
322  // << " to hist template " << hnam << endl;
323  // TF1* pf = new TF1(sfit.c_str(), sfit.c_str());
324  // ph->GetListOfFunctions()->AddLast(pf);
325  // ph->GetListOfFunctions()->SetOwner(kTRUE);
326  //}
327  HistInfo& hin = getState().sumHistTemplates[hnam];
328  hin.ph = ph;
329  hin.varx = hvarx;
330  hin.vary = hvary;
331  hin.plotName = plotName;
332  hin.plotWidth = plotWidth;
333  hin.fitName = sfit;
334  }
335  // Build the channel summary histograms.
336  ParameterSetVector pcshists = ps.get<ParameterSetVector>("ChanSumHists");
337  for ( const ParameterSet& psh : pcshists ) {
338  Name hnam0 = psh.get<Name>("name"); // Name for this histogram
339  Name httl0 = psh.get<Name>("title"); // Title for this histogram
340  Name vhnam = psh.get<Name>("valHist"); // Name of the template for the histogram used to fill
341  Name valType = psh.get<Name>("valType"); // Type of variable extracted from histogram
342  Name etype = psh.get<Name>("errType"); // Type of variable extracted from histogram
343  Name crname0 = psh.get<Name>("cr"); // Name of the channel range for this histogram
344  Name plname = psh.get<Name>("plot"); // Name of the plot file for this histogram
345  Name spran = psh.get<Name>("pran"); // Plot range with format "ymin:ymax"
346  Index nbins = psh.get<Index>("nbins"); // # bins for #ROI vs var plot. 0 means var vs chan plot.;
347  if ( hnam0.size() == 0 ) {
348  cout << myname << "ERROR: Channel summary histogram name is missing." << endl;
349  continue;
350  }
351  if ( m_pChannelRangeTool == nullptr ) {
352  cout << myname << "ERROR: Channel range tool not found." << endl;
353  continue;
354  }
356  if ( ivh == getState().sumHistTemplates.end() || ivh->second.ph == nullptr ) {
357  cout << myname << "ERROR: Channel summary histogram value histogram not found: " << vhnam << endl;
358  continue;
359  }
360  const NameVector valTypes = {"entries", "count", "mean", "peak", "rms", "sum", "fitMean", "fitSigma"};
361  if ( std::find(valTypes.begin(), valTypes.end(), valType) == valTypes.end() ) {
362  cout << myname << "ERROR: Channel summary histogram has invalid variable type: " << valType << endl;
363  continue;
364  }
365  const NameVector errTypes = {"none", "zero", "rms", "meanError", "rmsError", "fitSigma"};
366  if ( std::find(errTypes.begin(), errTypes.end(), etype) == errTypes.end() ) {
367  cout << myname << "ERROR: Channel summary histogram has invalid error type: \"" << etype << '"' << endl;
368  continue;
369  }
370  TH1* phval = ivh->second.ph;
371  Name valLabel = phval->GetXaxis()->GetTitle();
372  Name yttl = "Unknown";
373  if ( valType == "mean" ) {
374  yttl = "Mean of " + valLabel;
375  } else if ( valType == "peak" ) {
376  yttl = "Peak of " + valLabel;
377  } else if ( valType == "rms" ) {
378  yttl = "Sum of " + valLabel;
379  } else if ( valType == "rms" ) {
380  yttl = "RMS of " + valLabel;
381  } else if ( valType == "fitMean" ) {
382  yttl = "Fit mean of " + valLabel;
383  } else if ( valType == "fitSigma" ) {
384  yttl = "Fit sigma of " + valLabel;
385  } else if ( valType == "entries" ) {
386  yttl = "# ROI";
387  } else if ( valType == "count" ) {
388  yttl = "# ROI";
389  }
390  // Find y-range for plot.
391  bool havePlotYMin = false;
392  bool havePlotYMax = false;
393  float plotYMin = 0;
394  float plotYMax = 0;
395  Name plotYOpt;
396  if ( spran.size() ) {
397  Name::size_type ipos = spran.find(":");
398  if ( ipos == Name::npos ) {
399  cout << myname << "WARNING: Channel summary range specifcation must include \":\"" << endl;
400  } else {
401  Name::size_type jpos = spran.find(":", ipos+1);
402  Name spmin = spran.substr(0, ipos);
403  if ( spmin.size() ) {
404  istringstream ssin(spmin);
405  ssin >> plotYMin;
406  havePlotYMin = true;
407  }
408  Name spmax = spran.substr(ipos+1, jpos-ipos);
409  if ( spmax.size() ) {
410  istringstream ssin(spmax);
411  ssin >> plotYMax;
412  havePlotYMax = true;
413  }
414  if ( jpos != Name::npos ) {
415  plotYOpt = spran.substr(jpos+1);
416  }
417  }
418  }
419  // Loop over channel ranges. Value "list" means all; otherwise just the one given.
420  NameVector crns;
421  if ( crname0 == "list" ) crns = m_ChannelRanges;
422  else crns.push_back(crname0);
423  if ( crns.size() == 0 ) crns.push_back("all");
424  for ( Name crname : crns ) {
425  if ( m_LogLevel >= 2 ) cout << myname << "Creating channel summary histograms for channel range "
426  << crname << endl;
428  if ( ! cr.isValid() ) {
429  cout << myname << "ERROR: Channel range " << crname << " not found." << endl;
430  continue;
431  }
432  StringManipulator smhnam(hnam0, false);
433  smhnam.replace("%CRNAME%", cr.name);
434  smhnam.replace("%CRLABEL%", cr.label());
435  smhnam.replace("%CRLABEL1%", cr.label(1));
436  smhnam.replace("%CRLABEL2%", cr.label(2));
437  Name hnam = smhnam.str();
438  if ( getState().chanSumHists.find(hnam) != getState().chanSumHists.end() ) {
439  cout << myname << "ERROR: Duplicate channel summary histogram name: " << hnam << endl;
440  continue;
441  }
442  setPlotLabels(hnam);
443  StringManipulator smttl(httl0, false);
444  smttl.replace("%CRNAME%", cr.name);
445  smttl.replace("%CRLABEL%", cr.label());
446  smttl.replace("%CRLABEL1%", cr.label(1));
447  smttl.replace("%CRLABEL2%", cr.label(2));
448  Name httl = smttl.str();
449  setPlotLabels(httl);
450  TH1* phf = nullptr;
451  if ( nbins == 0 ) {
452  phf = new TH1F(hnam.c_str(), httl.c_str(), cr.size(), cr.begin, cr.end);
453  phf->GetXaxis()->SetTitle("Channel");
454  phf->GetYaxis()->SetTitle(yttl.c_str());
455  } else {
456  phf = new TH1F(hnam.c_str(), httl.c_str(), nbins, plotYMin, plotYMax);
457  phf->GetXaxis()->SetTitle(yttl.c_str());
458  phf->GetYaxis()->SetTitle("# channels");
459  phf->SetLineWidth(2);
460  }
461  phf->SetDirectory(nullptr);
462  phf->SetStats(0);
463  if ( cr.size() < 400 ) phf->SetLineWidth(2);
464  if ( etype == "none" ) phf->SetMarkerStyle(2);
465  else phf->SetMarkerStyle(0); // Draw error bars instead of markers
466  StringManipulator smplt(plname, false);
467  smplt.replace("%HNAME%", hnam0);
468  smplt.replace("%CRNAME%", cr.name);
469  smplt.replace("%CRLABEL%", cr.label());
470  smplt.replace("%CRLABEL1%", cr.label(1));
471  smplt.replace("%CRLABEL2%", cr.label(2));
472  plname = smplt.str();
473  setPlotLabels(plname);
474  getState().chanSumHists[hnam] = phf;
475  getState().chanSumHistTemplateNames[hnam] = vhnam;
476  getState().chanSumHistTypes[hnam] = nbins > 0;
477  getState().chanSumHistVariableTypes[hnam] = valType;
478  getState().chanSumHistErrorTypes[hnam] = etype;
479  getState().chanSumPlotNames[hnam] = plname;
480  if ( havePlotYMin ) getState().chanSumPlotYMins[hnam] = plotYMin;
481  if ( havePlotYMax ) getState().chanSumPlotYMaxs[hnam] = plotYMax;
482  if ( havePlotYMin || havePlotYMax ) getState().chanSumPlotYOpts[hnam] = plotYOpt;
483  getState().chanSumChaBegin[hnam] = cr.begin;
484  getState().chanSumChaEnd[hnam] = cr.end;
485  if ( m_LogLevel >= 3 ) {
486  cout << myname << " Histogram name: " << hnam << endl;
487  cout << myname << " Value type: " << valType << endl;
488  cout << myname << " Error type: " << etype << endl;
489  cout << myname << " Histogram name: " << hnam << endl;
490  cout << myname << " Histogram name: " << hnam << endl;
491  cout << myname << " Plot name: " << plname << endl;
492  cout << myname << " Plot ymin: ";
493  if ( havePlotYMin ) cout << plotYMin;
494  cout << endl;
495  cout << myname << " Plot ymax: ";
496  if ( havePlotYMax ) cout << plotYMax;
497  cout << endl;
498  cout << " Plot yopt: " << plotYOpt << endl;
499  }
500  } // End loop over channel ranges
501  } // End loop over channel summmary histogram configurations
502  // Display the configuration.
503  if ( m_LogLevel>= 1 ) {
504  cout << myname << " LogLevel: " << m_LogLevel << endl;
505  cout << myname << " RoiHistOpt: " << m_RoiHistOpt << endl;
506  cout << myname << " SigThresh: " << m_SigThresh << endl;
507  cout << myname << " TickBorder: " << m_TickBorder << endl;
508  cout << myname << " FitOpt: " << m_FitOpt << endl;
509  cout << myname << " StartTime: " << m_StartTime
510  << " (" << timeString(m_StartTime) << ")" << endl;
511  cout << myname << " PulserStepCharge: " << m_PulserStepCharge << endl;
512  cout << myname << " PulserDacOffset: " << m_PulserDacOffset << endl;
513  cout << myname << " PulserChargeUnit: " << m_PulserChargeUnit << endl;
514  cout << myname << " RoiPlotOpt: " << m_RoiPlotOpt << endl;
515  cout << myname << " MaxRoiPlots: " << m_MaxRoiPlots << endl;
516  cout << myname << " RoiPlotPadX: " << m_RoiPlotPadX << endl;
517  cout << myname << " RoiPlotPadY: " << m_RoiPlotPadY << endl;
518  cout << myname << " SumNegate: " << (m_SumNegate ? "true" : "false") << endl;
519  cout << myname << " SumPlotPadX: " << m_SumPlotPadX << endl;
520  cout << myname << " SumPlotPadY: " << m_SumPlotPadY << endl;
521  cout << myname << " ChannelRanges: [";
522  bool first = true;
523  for ( string crn : m_ChannelRanges ) {
524  if ( first ) first = false;
525  else cout << ", ";
526  cout << crn;
527  }
528  cout << "]" << endl;
529  cout << myname << " ChannelLineModulus: " << m_ChannelLineModulus << endl;
530  cout << myname << " ChannelLinePattern: {";
531  first = true;
532  for ( Index icha : m_ChannelLinePattern ) {
533  if ( ! first ) cout << ", ";
534  first = false;
535  cout << icha;
536  }
537  cout << "}" << endl;
538  cout << myname << " RoiRootFileName: " << m_RoiRootFileName << endl;
539  cout << myname << " SumRootFileName: " << m_SumRootFileName << endl;
540  cout << myname << " ChanSumRootFileName: " << m_ChanSumRootFileName << endl;
541  if ( getState().sumHistTemplates.size() == 0 ) {
542  cout << myname << " No summary histograms" << endl;
543  } else {
544  cout << myname << " SumHists:" << endl;
545  for ( const HistInfoMap::value_type& ish : getState().sumHistTemplates ) {
546  const HistInfo& hin = ish.second;
547  cout << myname << " ";
548  cout << hin.ph->GetName() << "(" << hin.varx;
549  if ( hin.vary.size() ) cout << "," << hin.vary;
550  cout << ")";
551  if ( hin.fitName.size() ) cout << " fit=" << hin.fitName;
552  if ( hin.plotName.size() ) cout << " plot=" << hin.plotName;
553  cout << endl;
554  }
555  }
556  if ( getState().chanSumHists.size() == 0 ) {
557  cout << myname << " No channel summary histograms" << endl;
558  } else {
559  cout << myname << " ChanSumHists:" << endl;
560  for ( HistMap::value_type ihst : getState().chanSumHists ) {
561  TH1* ph = ihst.second;
562  cout << myname << " " << ph->GetName() << endl;
563  }
564  }
565  cout << myname << " PlotLabels: [";
566  first = true;
567  for ( Name slab : m_PlotLabels ) {
568  if ( first ) first = false;
569  else cout << ", ";
570  cout << slab;
571  }
572  cout << "]" << endl;
573  cout << myname << " RunDataTool: \"" << m_RunDataTool << "\" @ "
574  << m_pRunDataTool << endl;
575  cout << myname << " TickOffsetTool: \"" << m_TickOffsetTool << "\" @ "
576  << m_pTickOffsetTool << endl;
577  }
578  if ( m_LogLevel >=2 ) cout << myname << "End constructing tool." << endl;
579 }
580 
581 //**********************************************************************
582 
584  const string myname = "AdcRoiViewer::dtor: ";
585  close(nullptr);
586 }
587 
588 //**********************************************************************
589 
591  DataMap res;
592  doView(acd, m_LogLevel, res);
593  if ( m_RoiRootFileName.size() ) {
595  }
596  return res;
597 }
598 
599 //**********************************************************************
600 
602  const string myname = "AdcRoiViewer::viewMap: ";
603  DataMap ret;
604  Index ncha = 0;
605  Index nroi = 0;
606  Index nfail = 0;
607  DataMap::IntVector failedChannels;
608  bool save = m_RoiRootFileName.size();
609  Index ndm = save ? acds.size() : 1;
610  int dbg = m_LogLevel > 3 ? m_LogLevel - 2 : 0;
611  Index nacd = acds.size();
612  DataMapVector dms; // Cache to hold results from doView
613  dms.reserve(ndm);
614  Index nroiLimit = save ? 1000 : 1000; // Clear cache after we get this many ROIs.
615  Index nroiCached = 0;
616  for ( const AdcChannelDataMap::value_type& iacd : acds ) {
617  const AdcChannelData& acd = iacd.second;
618  if ( m_LogLevel >= 3 ) {
619  cout << myname << "Processing channel " << acd.channel()
620  << " (" << ncha << "/" << nacd << ")" << endl;
621  }
622  dms.emplace_back();
623  DataMap& dm = dms.back();
624  doView(acd, dbg, dm);
625  if ( dm.status() ) {
626  ++nfail;
627  failedChannels.push_back(acd.channel());
628  }
629  ++ncha;
630  nroi += dm.getInt("roiCount");
631  nroiCached += dm.getInt("roiCount");
632  if ( nroiCached > nroiLimit ) {
633  if ( m_LogLevel >= 3 ) cout << myname << " Clearing result cache." << endl;
634  if ( save && dms.size() ) writeRoiHists(dms, dbg);
635  dms.clear();
636  nroiCached = 0;
637  }
638  }
639  if ( save && dms.size() ) writeRoiHists(dms, dbg);
640  ret.setInt("roiChannelCount", ncha);
641  ret.setInt("roiFailedChannelCount", nfail);
642  ret.setIntVector("roiFailedChannels", failedChannels);
643  ret.setInt("roiCount", nroi);
644  return ret;
645 }
646 
647 //**********************************************************************
648 
650  const string myname = "AdcRoiViewer::close: ";
651  DataMap ret;
652  if ( getState().closeCount ) return ret.setStatus(1);
653  ++getState().closeCount;
654  if ( m_LogLevel >= 1 ) {
655  cout << myname << "Closing." << endl;
656  cout << myname << " Event count: " << getState().eventCallCount.size() << endl;
657  cout << myname << " Call count: " << getState().callCount << endl;
658  cout << myname << " Sample unit: " << getState().cachedSampleUnit << endl;
659  }
660  if ( m_RoiPlotOpt == 2 ) {
661  Index ntpm = getState().roiPads.size();
662  if ( m_LogLevel >= 2 ) cout << myname << "Printing " << ntpm << " ROI pad"
663  << (ntpm == 1 ? "" : "s") << endl;
664  for ( TpmMap::value_type& itpm : getState().roiPads ) {
665  Index icha = itpm.first;
666  TpmPtr& pmantop = itpm.second;
667  if ( pmantop ) {
668  Name plotFileName = getState().roiPadNames[icha];
669  if ( m_LogLevel >=3 ) cout << myname << "Writing " << plotFileName << endl;
670  pmantop->print(plotFileName);
671  pmantop.reset(nullptr);
672  }
673  }
674  }
675  if ( getState().sumHists.size() ) {
676  fitSumHists();
677  writeSumHists();
678  writeSumPlots(pdmin);
679  }
680  if ( getState().chanSumHists.size() ) {
684  }
685  return ret;
686 }
687 
688 //**********************************************************************
689 
690 int AdcRoiViewer::doView(const AdcChannelData& acd, int dbg, DataMap& res) const {
691  const string myname = "AdcRoiViewer::doView: ";
692  unsigned int ievt = acd.event();
693  ++getState().callCount;
694  if ( getState().eventCallCount.find(ievt) == getState().eventCallCount.end() ) {
695  getState().eventCallCount[ievt] = 0;
696  } else {
697  ++getState().eventCallCount[ievt];
698  }
699  unsigned int nraw = acd.raw.size();
700  unsigned int nsam = acd.samples.size();
701  unsigned int ntickChannel = nsam > nraw ? nsam : nraw;
702  unsigned int nroiRaw = acd.rois.size();
703  bool doHist = m_RoiHistOpt != 0;
704  bool histRelativeTick = false;
705  int histType = 0;
706  if ( doHist ) {
707  if ( m_RoiHistOpt == 1 ) {
708  histType = 1;
709  } else if ( m_RoiHistOpt == 2 ) {
710  histType = 2;
711  } else if ( m_RoiHistOpt == 11 ) {
712  histType = 1;
713  histRelativeTick = true;
714  } else if ( m_RoiHistOpt == 12 ) {
715  histType = 2;
716  histRelativeTick = true;
717  } else {
718  cout << myname << "Invalid value for RoiHistOpt: " << m_RoiHistOpt << endl;
719  return res.setStatus(1).status();
720  }
721  }
722  if ( dbg >=2 ) cout << myname << "Processing channel " << acd.channel() << "."
723  << " Input ROI count is " << nroiRaw << endl;
724  DataMap::HistVector roiHists;
725  DataMap::FloatVector roiSigMins;
726  DataMap::FloatVector roiSigMaxs;
727  DataMap::FloatVector roiSigAreas;
728  DataMap::FloatVector roiFitHeights;
729  DataMap::FloatVector roiFitWidths;
730  DataMap::FloatVector roiFitPositions;
731  DataMap::FloatVector roiFitChiSquares;
732  DataMap::FloatVector roiFitChiSquareDofs;
733  DataMap::IntVector roiTickMins;
734  DataMap::IntVector roiTickMaxs;
735  DataMap::IntVector roiTimes;
736  DataMap::IntVector roiNUnderflows;
737  DataMap::IntVector roiNOverflows;
738  DataMap::IntVector tick1;
739  DataMap::IntVector ntick;
740  DataMap::IntVector roiFitStats;
741  Index nroi = 0;
742  for ( unsigned int iroiRaw=0; iroiRaw<nroiRaw; ++iroiRaw ) {
743  AdcRoi roi = acd.rois[iroiRaw];
744  if ( dbg >=3 ) cout << myname << " ROI " << nroi << "(raw " << iroiRaw << "): ["
745  << roi.first << ", " << roi.second << "]" << endl;
746  ostringstream sshnam;
747  sshnam << "hroi_run_%0RUN%_evt%0EVENT%_chan%0CHAN%_roi";
748  if ( nroi < 100 ) sshnam << "0";
749  if ( nroi < 10 ) sshnam << "0";
750  sshnam << nroi;
751  string hnam = AdcChannelStringTool::AdcChannelStringTool::build(m_adcStringBuilder, acd, sshnam.str());
752  ostringstream sshttl;
753  sshttl << "Run %RUN% event %EVENT% channel %CHAN% ROI " << nroi;
754  sshttl << " ;Tick ;";
755  if ( histType == 1 ) sshttl << "Signal% [SUNIT]%";
756  if ( histType == 2 ) sshttl << "ADC count";
757  string httl = AdcChannelStringTool::build(m_adcStringBuilder, acd, sshttl.str());
758  unsigned int isam1 = roi.first;
759  unsigned int isam2 = roi.second + 1;
760  // Check position if this a ROI to keep.
761  if ( m_TickBorder > 0 ) {
762  if ( isam1 < m_TickBorder ) continue;
763  if ( isam2 + m_TickBorder > nsam ) continue;
764  }
765  float x1 = histRelativeTick ? 0.0 : isam1;
766  float x2 = histRelativeTick ? isam2 - isam1 : isam2;
767  TH1* ph = new TH1F(hnam.c_str(), httl.c_str(), isam2-isam1, x1, x2);
768  ph->SetDirectory(nullptr);
769  //ph->Sumw2(); // Likelihood fit needs weights.
770  ph->SetStats(0);
771  ph->SetLineWidth(2);
772  unsigned int ibin = 0;
773  float sigmin = 0.0;
774  float sigmax = 0.0;
775  float sigarea = 0.0;
776  int roiTickMin = 0;
777  int roiTickMax = 0;
778  Index nunder = 0;
779  Index nover = 0;
780  for ( unsigned int isam=isam1; isam<isam2; ++isam ) {
781  float sig = 0.0;
782  if ( histType == 1 && isam<nsam ) sig = acd.samples[isam];
783  if ( histType == 2 && isam<nraw ) sig = isam<nraw ? acd.raw[isam] : 0.0;
784  if ( ibin == 0 ) {
785  sigmin = sig;
786  sigmax = sig;
787  } else {
788  if ( sig < sigmin ) {
789  sigmin = sig;
790  roiTickMin = ibin;
791  }
792  if ( sig > sigmax ) {
793  sigmax = sig;
794  roiTickMax = ibin;
795  }
796  }
797  sigarea += sig;
798  ph->SetBinContent(++ibin, sig);
799  AdcFlag flag = acd.flags.size() > isam ? acd.flags[isam] : 0;
800  if ( flag == AdcUnderflow ) ++nunder;
801  if ( flag == AdcOverflow ) ++nover;
802  }
803  // Check height if this a ROI to keep.
804  if ( m_SigThresh < 0.0 && sigmin > m_SigThresh ) continue;
805  if ( m_SigThresh > 0.0 && sigmax < m_SigThresh ) continue;
806  ++nroi;
807  roiHists.push_back(ph);
808  roiTickMins.push_back(roiTickMin);
809  roiNUnderflows.push_back(nunder);
810  roiNOverflows.push_back(nover);
811  roiTickMaxs.push_back(roiTickMax);
812  roiTimes.push_back(int(acd.time()) - int(m_StartTime));
813  roiSigMins.push_back(sigmin);
814  roiSigMaxs.push_back(sigmax);
815  roiSigAreas.push_back(sigarea);
816  tick1.push_back(isam1);
817  ntick.push_back(isam2 - isam1);
818  if ( m_FitOpt == 1 ) {
819  if ( dbg >= 3 ) cout << " Fitting with coldelecResponse" << endl;
820  bool isNeg = fabs(sigmin) > sigmax;
821  double h = isNeg ? sigmin : sigmax;
822  //double shap = 2.5*ph->GetRMS(); // No! Negative entries break RMS calculation.
823  double shap = 0.8*fabs(sigarea)/fabs(h);
824  double t0 = x1 + (isNeg ? roiTickMin : roiTickMax) - shap;
825  TF1* pf = coldelecResponseTF1(h, shap, t0, "coldelec");
826  TF1* pfinit = coldelecResponseTF1(h, shap, t0, "coldelec");
827  // The following was very slow when function was written to a file.
828  //TF1* pfinit = dynamic_cast<TF1*>(pf->Clone("coldelec0"));
829  pfinit->SetLineColor(3);
830  pfinit->SetLineStyle(2);
831  string fopt = "0";
832  fopt = "WWB";
833  //fopt = "LWB"; // Use likelihood fit to include empty bins. Do we want this here?
834  if ( dbg < 3 ) fopt += "Q";
835  // Do shifted fit to avoid numerical issues if t0 is large.
836  double xshift = 0.0;
837  if ( t0 > 500.0 ) {
838  xshift = 500*(long(t0)/500);
839  }
840  int fstat = shiftHistFit(ph, pf, fopt.c_str(), 2, xshift);
841  ph->GetListOfFunctions()->AddLast(pfinit, "0");
842  ph->GetListOfFunctions()->Last()->SetBit(TF1::kNotDraw, true);
843  ph->GetListOfFunctions()->SetOwner(kTRUE); // So the histogram owns pfinit
844  roiFitHeights.push_back(pf->GetParameter(0));
845  roiFitWidths.push_back(pf->GetParameter(1));
846  roiFitPositions.push_back(pf->GetParameter(2));
847  roiFitStats.push_back(fstat);
848  float cs = pf->GetChisquare();
849  int ndf = pf->GetNDF();
850  float csn = ndf > 0 ? cs/float(ndf) : -1.0;
851  roiFitChiSquares.push_back(cs);
852  roiFitChiSquareDofs.push_back(csn);
853  delete pf;
854  //delete pfinit; This give error: list accessing deleted object
855  }
856  }
857  writeRoiPlots(roiHists, acd);
858  res.setInt("roiEvent", acd.event());
859  res.setInt("roiRun", acd.run());
860  res.setInt("roiSubRun", acd.subRun());
861  res.setInt("roiChannel", acd.channel());
862  res.setInt("roiCount", nroi);
863  res.setInt("roiRawCount", nroiRaw);
864  res.setInt("roiNTickChannel", ntickChannel);
865  res.setIntVector("roiTick0s", tick1);
866  res.setIntVector("roiNTicks", ntick);
867  res.setIntVector("roiNUnderflows", roiNUnderflows);
868  res.setIntVector("roiNOverflows", roiNOverflows);
869  res.setIntVector("roiTickMins", roiTickMins);
870  res.setIntVector("roiTickMaxs", roiTickMaxs);
871  res.setIntVector("roiTimes", roiTimes);
872  res.setFloatVector("roiSigMins", roiSigMins);
873  res.setFloatVector("roiSigMaxs", roiSigMaxs);
874  res.setFloatVector("roiSigAreas", roiSigAreas);
875  res.setHistVector("roiHists", roiHists, true);
876  if ( roiFitHeights.size() ) {
877  res.setFloatVector("roiFitHeights", roiFitHeights);
878  res.setFloatVector("roiFitWidths", roiFitWidths);
879  res.setFloatVector("roiFitPositions", roiFitPositions);
880  res.setIntVector("roiFitStats", roiFitStats);
881  res.setFloatVector("roiFitChiSquares", roiFitChiSquares);
882  res.setFloatVector("roiFitChiSquareDofs", roiFitChiSquareDofs);
883  }
884  fillSumHists(acd, res);
885  if ( acd.run() != AdcChannelData::badIndex() ) {
886  if ( getState().cachedRunCount == 0 ) {
887  getState().cachedRun = acd.run();
888  getState().cachedRunCount = 1;
889  } else {
890  if ( acd.run() != getState().cachedRun ) {
891  getState().cachedRun = acd.run();
893  }
894  }
895  }
896  if ( getState().cachedSampleUnit.size() == 0 ) {
898  }
900  return res.status();
901 }
902 
903 //**********************************************************************
904 
905 void AdcRoiViewer::writeRoiHists(const DataMap& dm, int dbg) const {
906  DataMapVector dms(1, dm);
907  writeRoiHists(dms, dbg);
908 }
909 
910 //**********************************************************************
911 
912 void AdcRoiViewer::writeRoiHists(const DataMapVector& dms, int dbg) const {
913  const string myname = "AdcRoiViewer::writeRoiHists: ";
914  if ( m_RoiRootFileName.size() == 0 ) return;
915  TDirectory* savdir = gDirectory;
916  string ofrnameOld = "";
917  TFile* pfile = nullptr;
918  for ( const DataMap& dm : dms ) {
919  AdcChannelData acd;
920  acd.setEventInfo(
921  dm.getInt("roiRun"),
922  dm.getInt("roiEvent"),
923  dm.getInt("roiSubRun")
924  );
925  acd.setChannelInfo(dm.getInt("roiChannel"));
927  if ( ofrname != ofrnameOld ) {
928  if ( pfile != nullptr ) pfile->Close();
929  delete pfile;
930  if ( m_LogLevel >= 2 ) cout << myname << "Writing histograms to " << ofrname << endl;
931  pfile = TFile::Open(ofrname.c_str(), "UPDATE");
932  ofrnameOld = ofrname;
933  }
934  const DataMap::HistVector& roiHists = dm.getHistVector("roiHists");
935  for ( TH1* ph : roiHists ) {
936  TH1* phnew = dynamic_cast<TH1*>(ph->Clone());
937  phnew->GetListOfFunctions()->SetOwner(kTRUE); // So the histogram owns pfinit
938  phnew->Write();
939  if ( dbg >= 3 ) cout << myname << " Wrote " << phnew->GetName() << endl;
940  }
941  }
942  if ( pfile != nullptr ) pfile->Close();
943  delete pfile;
944  savdir->cd();
945 }
946 
947 //**********************************************************************
948 
949 void AdcRoiViewer::writeRoiPlots(const HistVector& hsts, const AdcChannelData& acd) const {
950  const string myname = "AdcRoiViewer::writeRoiPlots: ";
951  if ( m_MaxRoiPlots >=0 && getState().nRoiPlot >= Index(m_MaxRoiPlots) ) return;
952  Index npadx = m_RoiPlotPadX;
953  Index npady = m_RoiPlotPadY;
954  Index npad = npadx*npady;
955  if ( npad == 0 ) return;
956  Index wpadx = 1400;
957  Index wpady = 1000;
958  TpmPtr pmantopLocal;
959  TpmPtr& pmantop = m_RoiPlotOpt == 2 ? getState().roiPads[acd.channel()] : pmantopLocal;
960  Name plotFileName;
961  Index ipad = 0;
962  if ( m_RoiPlotOpt == 2 ) {
963  // Fetch the print name.
964  plotFileName = getState().roiPadNames[acd.channel()];
965  // Find the first empty sub pad.
966  if ( pmantop && npad > 1 ) {
967  for ( ipad=0; ipad<npad; ++ipad ) {
968  if ( pmantop->man(ipad)->hist() == nullptr ) break;
969  }
970  if ( ipad >= npad ) {
971  cout << myname << "FATAL: ROI pad is full." << endl;
972  abort();
973  }
974  }
975  }
976  Index ihst = 0;
977  for ( TH1* ph : hsts ) {
978  if ( ph == nullptr ) continue;
979  Name hnam = ph->GetName();
980  if ( ! pmantop ) {
981  plotFileName = hnam.substr(1) + ".png"; // Strip leading h from histogram name.
982  if ( m_RoiPlotOpt == 2 ) {
983  ostringstream sscha;
984  sscha << acd.channel();
985  string scha = sscha.str();
986  while ( scha.size() < 6 ) scha = "0" + scha;
987  ostringstream sspag;
988  sspag << getState().roiPadCounts[acd.channel()];
989  string spag = sspag.str();
990  while ( spag.size() < 3 ) spag = "0" + spag;
991  plotFileName = "roi_chan" + scha + "_" + spag + ".png";
992  getState().roiPadNames[acd.channel()] = plotFileName;
993  }
994  ipad = 0;
995  pmantop.reset(new TPadManipulator);
996  pmantop->setCanvasSize(wpadx, wpady);
997  if ( npad > 1 ) pmantop->split(npadx, npady);
998  if ( m_LogLevel >= 3 ) cout << myname << " Creating plots for " << plotFileName << endl;
999  if ( m_LogLevel >= 4 ) cout << myname << " Plotting " << ph->GetName() << endl;
1000  }
1001  TPadManipulator* pman = pmantop->man(ipad);
1002  pman->add(ph, "hist", false);
1003  pman->addHistFun(0);
1004  TF1* pfit = ph->GetFunction("coldelec");
1005  if ( true ) {
1006  NameVector labs;
1007  double area = ph->Integral();
1008  ostringstream ssout;
1009  ssout.precision(3);
1010  ssout.setf(std::ios_base::fixed);
1011  ssout << "Area: " << area;
1012  labs.push_back(ssout.str());
1013  if ( pfit != nullptr ) {
1014  double height = pfit->GetParameter("Height");
1015  double shaping = pfit->GetParameter("Shaping");
1016  double t0 = pfit->GetParameter("T0");
1017  ssout.str("");
1018  ssout << "Height: " << height;
1019  labs.push_back(ssout.str());
1020  ssout.str("");
1021  ssout << "Shaping: " << shaping << " tick";
1022  labs.push_back(ssout.str());
1023  ssout.str("");
1024  ssout.precision(2);
1025  ssout << "Position: " << t0 << " tick";
1026  labs.push_back(ssout.str());
1027  ssout.str("");
1028  ssout.precision(1);
1029  ssout << "#chi^{2}: " << pfit->GetChisquare();
1030  labs.push_back(ssout.str());
1031  Index chanStat = acd.channelStatus();
1032  if ( chanStat == AdcChannelStatusBad ) labs.push_back("Bad channel");
1033  if ( chanStat == AdcChannelStatusNoisy ) labs.push_back("Noisy channel");
1034  }
1035  double xlab = 0.70;
1036  double ylab = 0.80;
1037  double dylab = 0.04;
1038  for ( Name lab : labs ) {
1039  TLatex* pptl = nullptr;
1040  pptl = new TLatex(xlab, ylab, lab.c_str());
1041  pptl->SetNDC();
1042  pptl->SetTextFont(42);
1043  pptl->SetTextSize(dylab);
1044  pman->add(pptl);
1045  ylab -= 1.2*dylab;
1046  }
1047  }
1048  pman->addAxis();
1049  pman->addHorizontalLine(0.0);
1050  pman->showUnderflow();
1051  pman->showOverflow();
1052  ++ipad;
1053  if ( ipad >= npad || (++ihst >= hsts.size() && m_RoiPlotOpt != 2) ) {
1054  if ( m_LogLevel >= 3 ) cout << myname << " Writing " << plotFileName << endl;
1055  pmantop->print(plotFileName);
1056  pmantop.reset(nullptr);
1057  ++getState().roiPadCounts[acd.channel()];
1058  ipad = 0;
1059  ++getState().nRoiPlot;
1060  if ( m_MaxRoiPlots >=0 && getState().nRoiPlot >= Index(m_MaxRoiPlots) ) return;
1061  }
1062  }
1063 }
1064 
1065 //**********************************************************************
1066 
1067 void AdcRoiViewer::fillSumHists(const AdcChannelData& acd, const DataMap& dm) const {
1068  const string myname = "AdcRoiViewer::fillSumHists: ";
1069  // Fetch the run data.
1070  RunData rdat;
1071  if ( m_pRunDataTool != nullptr ) {
1072  rdat = m_pRunDataTool->runData(acd.run(), acd.subRun());
1073  RunData& rdatOld = getState().runData;
1074  if ( rdat.isValid() && ! rdatOld.isValid() ) {
1075  if ( m_LogLevel >= 2 ) cout << myname << "Setting run data." << endl;
1076  rdatOld = rdat;
1077  } else if ( rdat.isValid() && rdatOld.isValid() ) {
1078  if ( rdat.run() != rdatOld.run() ) {
1079  cout << myname << "Ignoring unexpected change in run number: " << rdatOld.run()
1080  << " --> " << rdat.run();
1081  }
1082  } else if ( ! rdat.isValid() ) {
1083  if ( m_LogLevel >= 3 ) cout << myname << "Run data not found." << endl;
1084  }
1085  }
1086  float pulserQin = 0.0;
1087  bool havePulserAmplitude = rdat.havePulserAmplitude() && rdat.havePulserSource();
1088  bool havePulserPeriod = rdat.havePulserPeriod();
1089  bool haveQin = false;
1090  if ( havePulserAmplitude ) {
1091  int qfac = rdat.pulserAmplitude();
1092  //if ( rdat.pulserSource() == 2 && qfac > 0 ) --qfac; // Should we do this??
1093  pulserQin = (qfac - m_PulserDacOffset)*m_PulserStepCharge;
1094  haveQin = pulserQin != 0.0;
1095  if ( ! haveQin ) {
1096  cout << myname << "WARNING: Pulser charge evaluates to zero." << endl;
1097  }
1098  }
1099  Index pulserPeriod = 0;
1100  if ( havePulserPeriod ) {
1101  pulserPeriod = rdat.pulserPeriod();
1102  if ( pulserPeriod == 0 ) {
1103  havePulserPeriod = false;
1104  cout << myname << "WARNING: Pulser period is zero." << endl;
1105  }
1106  }
1107  // Fetch the tick offset.
1108  TimeOffsetTool::Data tdat;
1109  bool haveTickOffset = false;
1110  long tickOffset = 0;
1111  bool haveTickOffsetPulserMod = false;
1112  Index tickOffsetPulserMod = 0; // Tick offset modulus the pulser period [0, pulserPeriod).
1113  double timingPhase = 0.0; // Phase of the timing clock (0,1]
1114  if ( m_pTickOffsetTool != nullptr ) {
1115  tdat.run = acd.run();
1116  tdat.subrun = acd.subRun();
1117  tdat.event = acd.event();
1118  tdat.channel = acd.channel();
1119  tdat.fembID = acd.fembID();
1120  tdat.triggerClock = acd.triggerClock();
1122  if ( off.isValid() ) {
1123  haveTickOffset = true;
1124  tickOffset = off.value;
1125  timingPhase = off.rem;
1126  } else {
1127  cout << myname << "Unable to retrieve tick offset for run " << tdat.run << "-" << tdat.subrun
1128  << " event " << tdat.event << " channel " << tdat.channel << endl;
1129  }
1130  if ( haveTickOffset && havePulserPeriod ) {
1131  long toff = tickOffset;
1132  long period = pulserPeriod;
1133  toff = toff % period;
1134  if ( toff < 0 ) toff += period;
1135  tickOffsetPulserMod = toff;
1136  haveTickOffsetPulserMod = true;
1137  }
1138  }
1139  // Loop over summary histogram templates.
1140  Index nhst = 0;
1141  Index nhstGood = 0;
1142  for ( const HistInfoMap::value_type ish : getState().sumHistTemplates ) {
1143  const HistInfo& hin0 = ish.second;
1144  ++nhst;
1145  Name varx = hin0.varx;
1146  if ( m_SumNegate ) {
1147  if ( varx == "fitHeight" ) varx = "fitHeightNeg";
1148  if ( varx == "sigArea" ) varx = "sigAreaNeg";
1149  }
1150  Name vary = hin0.vary;
1151  TH1* ph0 = hin0.ph;
1152  Name fitName = hin0.fitName;
1153  Name plotNameTemplate = hin0.plotName;
1154  FloatVector vals;
1155  IntVector ivals;
1156  if ( varx == "sigArea" ) vals = dm.getFloatVector("roiSigAreas");
1157  else if ( varx == "sigAreaNeg" ) vals = dm.getFloatVector("roiSigAreas");
1158  else if ( varx == "sigWidth" ) ivals = dm.getIntVector("roiNTicks");
1159  else if ( varx == "sigTick0" ) ivals = dm.getIntVector("roiTick0s");
1160  else if ( varx == "sigTick0Pulser" ) ivals = dm.getIntVector("roiTick0s");
1161  else if ( varx == "sigTickMax" ) ivals = dm.getIntVector("roiTickMaxs");
1162  else if ( varx == "sigTickMaxPulser" ) ivals = dm.getIntVector("roiTickMaxs");
1163  else if ( varx == "fitHeight" ) vals = dm.getFloatVector("roiFitHeights");
1164  else if ( varx == "fitHeightNeg" ) vals = dm.getFloatVector("roiFitHeights");
1165  else if ( varx == "fitHeightGain" ) vals = dm.getFloatVector("roiFitHeights");
1166  else if ( varx == "fitWidth" ) vals = dm.getFloatVector("roiFitWidths");
1167  else if ( varx == "fitPos" ) vals = dm.getFloatVector("roiFitPositions");
1168  else if ( varx == "fitPosRem" ) vals = dm.getFloatVector("roiFitPositions");
1169  else if ( varx == "fitPosPulser" ) vals = dm.getFloatVector("roiFitPositions");
1170  else if ( varx == "fitToffPulser" ) vals = dm.getFloatVector("roiFitPositions");
1171  else if ( varx == "fitToffPulserMod10" ) vals = dm.getFloatVector("roiFitPositions");
1172  else if ( varx == "fitStat" ) ivals = dm.getIntVector("roiFitStats");
1173  else if ( varx == "fitChiSquare" ) vals = dm.getFloatVector("roiFitChiSquares");
1174  else if ( varx == "fitChiSquareDof" ) vals = dm.getFloatVector("roiFitChiSquareDofs");
1175  else if ( varx == "fitCSNorm" ) vals = dm.getFloatVector("roiFitChiSquares");
1176  else if ( varx == "fitCSNormDof" ) vals = dm.getFloatVector("roiFitChiSquareDofs");
1177  else if ( varx == "timeSec" ) ivals = dm.getIntVector("roiTimes");
1178  else if ( varx == "timeHour" ) ivals = dm.getIntVector("roiTimes");
1179  else if ( varx == "timeDay" ) ivals = dm.getIntVector("roiTimes");
1180  else if ( varx == "procEvent" ) ivals.push_back(acd.event());
1181  else if ( varx == "procTimeSec" ) ivals.push_back(int(acd.time()) - int(m_StartTime));
1182  else if ( varx == "procTimeHour" ) ivals.push_back(int(acd.time()) - int(m_StartTime));
1183  else if ( varx == "procTimeDay" ) ivals.push_back(int(acd.time()) - int(m_StartTime));
1184  else {
1185  if ( m_LogLevel >= 2 ) {
1186  cout << myname << "ERROR: Invalid variable name: " << varx << endl;
1187  continue;
1188  }
1189  }
1190  Name hnam0 = ph0->GetName();
1192  Name xlab = AdcChannelStringTool::build(m_adcStringBuilder, acd, ph0->GetXaxis()->GetTitle());
1193  Name ylab = ph0->GetYaxis()->GetTitle();
1194  TH1* ph = getState().getSumHist(hnam);
1195  if ( ivals.size() && !vals.size() ) for ( int ival : ivals ) vals.push_back(ival);
1196  if ( varx == "fitPosRem" ) for ( float& val : vals ) val = std::remainder(val,1);
1197  if ( varx == "fitPosPulser" ) {
1198  if ( ! havePulserPeriod ) {
1199  cout << myname << "WARNING: Cannot evaluate " << varx << " without pulser period" << endl;
1200  continue;
1201  }
1202  for ( float& val : vals ) val = fmod(val, pulserPeriod);
1203  }
1204  if ( varx == "fitToffPulser" || varx == "fitToffPulserMod10" ||
1205  varx == "sigTick0Pulser" || varx == "sigTickMaxPulser" ) {
1206  if ( ! haveTickOffsetPulserMod ) {
1207  cout << myname << "WARNING: Cannot evaluate " << varx << " without timing offset and pulser period" << endl;
1208  continue;
1209  }
1210  for ( float& val : vals ) val = fmod(val + pulserPeriod + tickOffsetPulserMod, pulserPeriod);
1211  if ( varx == "fitToffPulserMod10" ) {
1212  for ( float& val : vals ) val = fmod(val, 10.0);
1213  }
1214  }
1215  float varfac = 1.0;
1216  if ( varx == "fitHeightNeg" ) varfac = -1.0;
1217  if ( varx == "sigAreaNeg" ) varfac = -1.0;
1218  if ( varx == "fitCSNorm" || varx == "fitCSNormDof" ) {
1219  float pedrms = acd.pedestalRms;
1220  if ( pedrms > 0.0 ) varfac = 1.0/(pedrms*pedrms);
1221  else varfac = 0.0;
1222  }
1223  if ( varx == "fitHeightGain" ) {
1224  if ( ! haveQin ) {
1225  cout << myname << "WARNING: Cannot evaluate " << varx << " without Qin" << endl;
1226  continue;
1227  }
1228  varfac = 1.0/pulserQin;
1229  }
1230  if ( varx == "timeHour" || varx == "procTimeHour" ) varfac = 1/3600.0;
1231  if ( varx == "timeDay" || varx == "procTimeDay" ) varfac = 1/(24*3600.0);
1232  if ( varfac != 1.0 ) for ( float& val : vals ) val *= varfac;
1233  // Create histogram if it does not yet exist or is empty and we have data here.
1234  //if ( ph == nullptr && vals.size() ) {
1235  //if ( ph == nullptr ) {
1236  if ( (ph == nullptr) || (ph->GetEntries() == 0 && vals.size()) ) {
1237  bool replacingHistogram = ph != nullptr;
1238  // Fetch the vector that lists the summary histograms to be plotted for the current template.
1239  // Find or make a place to record this histogram.
1240  HistVector empty;
1241  bool havePlot = plotNameTemplate.size();
1242  HistVector& plotHists = havePlot ? getState().sumPlotHists[plotNameTemplate] : empty;
1243  HistVector::iterator iplotHist = plotHists.end();
1244  if ( replacingHistogram ) {
1245  if ( havePlot ) {
1246  iplotHist = find(plotHists.begin(), plotHists.end(), ph);
1247  if ( iplotHist == plotHists.end() ) {
1248  cout << myname << "ERROR: Unable to find histogram in plot name list." << endl;
1249  plotHists.clear();
1250  iplotHist = plotHists.end();
1251  }
1252  *iplotHist = nullptr;
1253  }
1254  delete ph;
1255  ph = nullptr;
1256  if ( m_LogLevel >= 2 ) cout << myname << "Replacing histogram " << hnam << endl;
1257  } else {
1258  if ( havePlot ) {
1259  plotHists.push_back(nullptr);
1260  iplotHist = plotHists.end();
1261  --iplotHist;
1262  }
1263  if ( m_LogLevel >= 2 ) cout << myname << "Creating histogram " << hnam << endl;
1264  }
1265  Name httl0 = ph0->GetTitle();
1267  int nbin = ph0->GetNbinsX();
1268  float xmin = ph0->GetXaxis()->GetXmin();
1269  float xmax = ph0->GetXaxis()->GetXmax();
1270  // If xmin > xmax and xmin > 0, then we center histogram on median and use width = xmin.
1271  // If also xmax >0, then we round the first bin edge to that value.
1272  if ( vals.size() && xmin > xmax && xmin > 0.0 ) {
1273  FloatVector tmpvals = vals;
1274  std::sort(tmpvals.begin(), tmpvals.end());
1275  Index nval = tmpvals.size();
1276  if ( m_LogLevel >= 3 ) cout << myname << " Centering histogram on median of "
1277  << nval << " value" << (nval==1 ? "" : "s") << endl;
1278  float xmed = 0.5*(tmpvals[(nval-1)/2] + tmpvals[nval/2]);
1279  float width = xmin;
1280  xmin = xmed - 0.5*width;
1281  bool roundXmin = xmax > 0.0;
1282  if ( roundXmin ) {
1283  //float rexp = log10(width/50.0);
1284  //rexp = rexp > 0 ? int(rexp) : int(rexp-1);
1285  //float rfac = pow(10, rexp);
1286  float rfac = xmax;
1287  xmin = rfac*int(xmin/rfac + (xmin > 0.0 ? 0.5 : -0.5));
1288  }
1289  xmax = xmin + width;
1290  // Make sure we have xmax > xmin so Root won't complain when we plot.
1291  } else if ( xmin >= xmax ) {
1292  if ( xmin > 0.0 ) {
1293  xmax = xmin;
1294  xmin = 0;
1295  } else if ( xmin < 0.0 ) {
1296  xmax = 0.0;
1297  } else {
1298  xmin = 0.0;
1299  xmax = 1.0;
1300  }
1301  }
1302  if ( m_LogLevel >= 3 ) {
1303  cout << myname << " Name: " << hnam << endl;
1304  cout << myname << " Title: " << httl << endl;
1305  cout << myname << " nbin: " << nbin << endl;
1306  cout << myname << " xmin: " << xmin << endl;
1307  cout << myname << " xmax: " << xmax << endl;
1308  cout << myname << " fit: " << fitName << endl;
1309  }
1310  bool isTH2 = dynamic_cast<TH2*>(ph0);
1311  if ( ! isTH2 ) {
1312  ph = new TH1F(hnam.c_str(), httl.c_str(), nbin, xmin, xmax);
1313  } else {
1314  int nbiny = ph0->GetNbinsY();
1315  float ymin = ph0->GetYaxis()->GetXmin();
1316  float ymax = ph0->GetYaxis()->GetXmax();
1317  ph = new TH2F(hnam.c_str(), httl.c_str(), nbin, xmin, xmax, nbiny, ymin, ymax);
1318  }
1319  ph->SetDirectory(nullptr);
1320  ph->SetStats(0);
1321  ph->Sumw2(); // Needed for likelihood fit.
1322  ph->SetLineWidth(2);
1323  ph->GetXaxis()->SetTitle(xlab.c_str());
1324  ph->GetYaxis()->SetTitle(ylab.c_str());
1325  if ( ph0->GetListOfFunctions()->GetEntries() ) {
1326  TF1* pf = dynamic_cast<TF1*>(ph0->GetListOfFunctions()->At(0)->Clone());
1327  ph->GetListOfFunctions()->AddLast(pf);
1328  ph->GetListOfFunctions()->SetOwner(kTRUE);
1329  }
1330  getState().sumHistChannels[hnam] = acd.channel();
1331  getState().sumHists[hnam] = ph;
1332  getState().sumFitNames[hnam] = fitName;
1333  if ( plotNameTemplate.size() ) {
1334  Name plotNameHist = AdcChannelStringTool::build(m_adcStringBuilder, acd, plotNameTemplate);
1335  if ( havePlot ) *iplotHist = ph;
1336  if ( ! replacingHistogram ) {
1337  getState().sumPlotNames[hnam] = plotNameHist;
1338  getState().sumPlotWidths[hnam] = hin0.plotWidth;
1339  }
1340  }
1341  }
1342  if ( m_LogLevel >= 3 ) cout << myname << "Filling summary histogram " << hnam
1343  << ". Fill count is " << vals.size() << endl;
1344  FloatVector csds = dm.getFloatVector("roiFitChiSquareDofs");
1345  IntVector fstats = dm.getIntVector("roiFitStats");
1346  bool checkFit = varx.substr(0,3) == "fit";
1347  if ( csds.size() == 0 || fstats.size() == 0 ) checkFit = false;
1348  double chiSquareDofMax = 0.0; // was 1000; should be config param?
1349  if ( checkFit ) {
1350  if ( csds.size() != vals.size() ) {
1351  cout << "ERROR: Variable and chi-square/DF vectors have different sizes." << endl;
1352  checkFit = false;
1353  }
1354  if ( fstats.size() != vals.size() ) {
1355  cout << "ERROR: Variable and fit status vectors have different sizes: "
1356  << vals.size() << " != " << fstats.size() << endl;
1357  checkFit = false;
1358  }
1359  }
1360  Index nval = 0;
1361  Index nvalSkip = 0;
1362  bool logerr = m_LogLevel >= 3 && nhstGood == 0;
1363  for ( Index ival=0; ival<vals.size(); ++ival ) {
1364  ++nval;
1365  if ( checkFit ) {
1366  int fstat = fstats[ival];
1367  float csd = csds[ival];
1368  if ( fstat ) {
1369  if ( logerr) cout << myname << "WARNING: Skipping entry with fit status " << fstat
1370  << " (chi-square/DOF = " << csd << ")" << endl;
1371  ++nvalSkip;
1372  continue;
1373  } else if ( chiSquareDofMax > 0.0 && csd > chiSquareDofMax ) {
1374  if ( logerr) cout << myname << "WARNING: Skipping entry with chi-square/DOF = " << csd << endl;
1375  ++nvalSkip;
1376  continue;
1377  }
1378  }
1379  float val = vals[ival];
1380  double valy = 0.0;
1381  if ( vary == "timingPhase" ) valy = timingPhase;
1382  if ( vary == "event" ) valy = acd.event();
1383  if ( vary == "" ) {
1384  ph->Fill(val);
1385  } else {
1386  ph->Fill(val, valy);
1387  }
1388  }
1389  // Show skips for the first histogram only.
1390  if ( nvalSkip ) {
1391  cout << myname << "WARNING: Skipped " << nvalSkip << " of " << nval
1392  << " entries due to bad fit for histogram " << hnam << "." << endl;
1393  }
1394  ++nhstGood;
1395  }
1396  if ( nhstGood != nhst ) {
1397  cout << myname << "WARNING: Only filled " << nhstGood << " of " << nhst << " histograms." << endl;
1398  }
1399 }
1400 
1401 //**********************************************************************
1402 
1404  const string myname = "AdcRoiViewer::fitSumHists: ";
1405  if ( getState().sumHists.size() == 0 ) {
1406  cout << myname << "No summary histograms found." << endl;
1407  return;
1408  }
1409  if ( m_LogLevel >= 1 ) cout << myname << "Fitting summary histograms. Count is "
1410  << getState().sumHists.size() << "." << endl;
1411  for ( HistMap::value_type ihst : getState().sumHists ) {
1412  TH1* ph = ihst.second;
1413  string hnam = ph->GetName();
1414  string fitName = getState().getSumFitName(hnam);
1415  bool fitDone = false;
1416  if ( m_LogLevel >= 3 ) cout << myname << "Fitting hist " << ph->GetName() << " with " << fitName << endl;
1417  if ( fitName.size() ) {
1418  TF1* pf = nullptr;
1419  int binMax = ph->GetMaximumBin();
1420  double mean0 = ph->GetBinLowEdge(binMax);
1421  double sigma0 = ph->GetRMS();
1422  double height0 = ph->GetMaximum();
1423  // Use gaus step fit.
1424  if ( fitName.substr(0,5) == "sgaus" ) {
1425  if ( m_LogLevel >= 4 ) cout << myname << " Doing gaus step fit." << endl;
1426  if ( fitName.size() > 5 ) {
1427  istringstream ssin(fitName.substr(5));
1428  ssin >> sigma0;
1429  }
1430  GausStepFitter gsf(mean0, sigma0, height0, fitName, "WWS");
1431  fitDone = gsf.fit(ph) == 0;
1432  // Use gaus from RMS.
1433  } else if ( fitName.substr(0,5) == "rgaus" ) {
1434  if ( m_LogLevel >= 4 ) cout << myname << " Doing fixed rms fit." << endl;
1435  double sigma0 = 0.0;
1436  double nsigma = 4.0;
1437  Name spar1 = fitName.substr(5);
1438  Name spar2;
1439  if ( spar1.size() ) {
1440  if ( spar1[0] == '_' ) spar1 = spar1.substr(1);
1441  string::size_type ipos = spar1.find("_");
1442  if ( ipos != string::npos ) {
1443  spar2 = spar1.substr(ipos+1);
1444  spar1 = spar1.substr(0, ipos);
1445  istringstream ssin2(spar2);
1446  ssin2 >> nsigma;
1447  }
1448  istringstream ssin1(spar1);
1449  ssin1 >> sigma0;
1450  }
1451  GausRmsFitter grf(sigma0, nsigma, fitName);
1452  if ( m_LogLevel >=4 ) grf.setLogLevel(m_LogLevel - 3);
1453  if ( grf.fit(ph, mean0) == 0 ) {
1454  fitDone = true;
1455  } else {
1456  pf = new TF1("mygaus", "gaus");
1457  }
1458  } else {
1459  pf = new TF1(fitName.c_str(), fitName.c_str());
1460  }
1461  if ( m_LogLevel >= 4 && pf != nullptr ) {
1462  cout << myname << " Created function " << pf->GetName() << " at " << std::hex << pf << endl;
1463  }
1464  if ( ! fitDone ) {
1465  if ( m_LogLevel >= 4 ) cout << myname << " Doing unconstrained fit" << endl;
1466  string fopt = "LWWS";
1467  if ( m_LogLevel < 4 ) fopt += "Q";
1468  int fstat = quietHistFit(ph, pf, fopt.c_str());
1469  if ( fstat != 0 ) {
1470  cout << myname << " WARNING: Fit " << pf->GetName() << " of " << ph->GetName() << " returned " << fstat << endl;
1471  ph->GetListOfFunctions()->Clear(); // Otherwise we may get a crash when we try to view saved copy of histo
1472  } else {
1473  if ( m_LogLevel >=4 ) cout << myname << " Fit succeeded." << endl;
1474  }
1475  ph->GetListOfFunctions()->SetOwner(kTRUE); // So the histogram owns pf
1476  }
1477  delete pf;
1478  }
1479  }
1480 }
1481 
1482 //**********************************************************************
1483 
1485  const string myname = "AdcRoiViewer::writeSumHists: ";
1486  bool saveHist = m_SumRootFileName.size();
1487  if ( ! saveHist ) return;
1488  if ( getState().sumHists.size() == 0 ) {
1489  cout << myname << "No summary histograms found." << endl;
1490  return;
1491  }
1492  TDirectory* savdir = gDirectory;
1493  Name ofrname = m_SumRootFileName;
1494  TFile* pfile = TFile::Open(ofrname.c_str(), "UPDATE");
1495  saveHist = pfile != nullptr && pfile->IsOpen();
1496  if ( ! saveHist ) {
1497  cout << myname << "ERROR: Unable to open output file " << ofrname << endl;
1498  return;
1499  }
1500  if ( m_LogLevel >= 1 ) cout << myname << "Writing summary histograms. Count is "
1501  << getState().sumHists.size() << "." << endl;
1502  for ( HistMap::value_type ihst : getState().sumHists ) {
1503  TH1* ph = ihst.second;
1504  TH1* phnew = dynamic_cast<TH1*>(ph->Clone());
1505  if ( saveHist ) phnew->Write();
1506  if ( m_LogLevel >= 2 ) cout << myname << " Wrote " << phnew->GetName() << endl;
1507  }
1508  pfile->Close();
1509  if ( m_LogLevel >= 1 ) cout << myname << "Closed summary histogram file " << ofrname << endl;
1510  savdir->cd();
1511  delete pfile;
1512 }
1513 
1514 //**********************************************************************
1515 
1516 void AdcRoiViewer::writeSumPlots(const DataMap* pdmin) const {
1517  const string myname = "AdcRoiViewer::writeSumPlots: ";
1518  int dbgin = pdmin == nullptr ? 0 : pdmin->getInt("dbg", 0);
1519  Index npad = 0;
1520  Index npadx = m_SumPlotPadX;
1521  Index npady = m_SumPlotPadY;
1522  Index wpadx = 1400;
1523  Index wpady = 1000;
1524  npad = npadx*npady;
1525  Index nvec = getState().sumPlotHists.size();
1526  if ( npad == 0 ) return;
1527  if ( m_LogLevel >= 1 ) cout << myname << "Plotting " << nvec << " set"
1528  << (nvec == 1 ? "" : "s") << " of summary histograms " << endl;
1529  for ( const HistVectorMap::value_type ihv : getState().sumPlotHists ) {
1530  Name plotNameTemplate = ihv.first;
1531  const HistVector& hsts = ihv.second;
1532  TPadManipulator* pmantop = nullptr;
1533  Index ipad = 0;
1534  Name plotFileName;
1535  for ( Index ihst=0; ihst<hsts.size(); ++ihst ) {
1536  TH1* ph = hsts[ihst];
1537  if ( ph == nullptr ) {
1538  cout << myname << "WARNING: Histogram " << ihst << " not found for template " << plotNameTemplate << endl;
1539  } else {
1540  Name hnam = ph->GetName();
1541  bool haveExpectedValue = pdmin != nullptr && pdmin->haveFloat(hnam);
1542  float expValue = haveExpectedValue ? pdmin->getFloat(hnam) : 0.0;
1543  if ( dbgin ) {
1544  cout << myname << " Processing histogram " << hnam << endl;
1545  if ( haveExpectedValue ) cout << myname << " Expected value: " << expValue << endl;
1546  else cout << myname << " No expected value." << endl;
1547  }
1548  if ( pmantop == nullptr ) {
1549  plotFileName = getState().getSumPlotName(hnam);
1550  if ( plotFileName.size() == 0 ) {
1551  cout << myname << "ERROR: Plot file name is not assigned for " << hnam << endl;
1552  break;
1553  }
1554  ipad = 0;
1555  pmantop = new TPadManipulator;
1556  if ( npadx && npady ) pmantop->setCanvasSize(wpadx, wpady);
1557  if ( npad > 1 ) pmantop->split(npadx, npady);
1558  if ( m_LogLevel >= 2 ) cout << myname << " Creating plots for " << plotFileName << endl;
1559  }
1560  if ( m_LogLevel >= 3 ) cout << myname << " Plotting " << ph->GetName() << endl;
1561  TPadManipulator* pman = pmantop->man(ipad);
1562  pman->add(ph, "hist", false);
1563  if ( ph->GetListOfFunctions()->GetEntries() ) {
1564  //dynamic_cast<TF1*>(pman->hist()->GetListOfFunctions()->At(0))->SetNpx(2000);
1565  pman->addHistFun(0);
1566  }
1567  pman->addAxis();
1568  pman->showUnderflow();
1569  pman->showOverflow();
1570  float plotWidth = getState().getSumPlotWidth(hnam);
1571  if ( plotWidth > 0.0 ) {
1572  int binMax = ph->GetMaximumBin();
1573  if ( binMax && binMax <= ph->GetNbinsX() ) {
1574  float xCen = ph->GetBinLowEdge(binMax);
1575  float xmin = xCen - 0.5*plotWidth;
1576  float xmax = xCen + 0.5*plotWidth;
1577  pman->setRangeX(xmin, xmax);
1578  }
1579  }
1580  NameVector labs;
1581  bool showMean = true;
1582  if ( showMean ) {
1583  double mean = ph->GetMean();
1584  double sigm = ph->GetRMS();
1585  float meanDen = haveExpectedValue ? expValue : mean;
1586  ostringstream ssout;
1587  ssout.precision(3);
1588  ssout.setf(std::ios_base::fixed);
1589  ssout.str("");
1590  ssout << "# ROI: " << int(ph->GetEntries() + 0.1);
1591  labs.push_back(ssout.str());
1592  ssout.str("");
1593  ssout << "Hist mean: " << mean;
1594  labs.push_back(ssout.str());
1595  ssout.str("");
1596  ssout << "Hist RMS: " << sigm;
1597  ssout.precision(1);
1598  if ( meanDen != 0.0 ) ssout << " [" << 100*sigm/meanDen << "%]";
1599  ssout.precision(3);
1600  labs.push_back(ssout.str());
1601  if ( haveExpectedValue ) {
1602  ssout.str("");
1603  float bias = mean - expValue;
1604  ssout << "Hist bias: " << bias;
1605  ssout.precision(1);
1606  if ( expValue != 0.0 ) ssout << " [" << 100*bias/expValue << "%]";
1607  ssout.precision(3);
1608  labs.push_back(ssout.str());
1609  }
1610  }
1611  TF1* pffit = dynamic_cast<TF1*>(ph->GetListOfFunctions()->Last());
1612  if ( pffit != nullptr ) {
1613  string fnam = pffit->GetName();
1614  double mean = pffit->GetParameter("Mean");
1615  double sigm = pffit->GetParameter("Sigma");
1616  float meanDen = haveExpectedValue ? expValue : mean;
1617  labs.push_back("Fitter: " + fnam);
1618  ostringstream ssout;
1619  ssout.precision(3);
1620  ssout.setf(std::ios_base::fixed);
1621  ssout << "Fit mean: " << mean;
1622  labs.push_back(ssout.str());
1623  ssout.str("");
1624  ssout << "Fit sigma: " << sigm;
1625  ssout.precision(1);
1626  if ( meanDen != 0.0 ) ssout << " [" << 100*sigm/meanDen << "%]";
1627  ssout.precision(3);
1628  labs.push_back(ssout.str());
1629  if ( haveExpectedValue ) {
1630  ssout.str("");
1631  float bias = mean - expValue;
1632  ssout << "Fit bias: " << bias;
1633  ssout.precision(1);
1634  if ( expValue != 0.0 ) ssout << " [" << 100*bias/expValue << "%]";
1635  ssout.precision(3);
1636  labs.push_back(ssout.str());
1637  }
1638  }
1639  {
1640  ostringstream ssout;
1641  ssout.str("");
1642  Index chanStat = getState().getChannelStatus(ph->GetName());
1643  if ( chanStat == AdcChannelStatusBad ) labs.push_back("Bad channel");
1644  if ( chanStat == AdcChannelStatusNoisy ) labs.push_back("Noisy channel");
1645  }
1646  double xlab = 0.65;
1647  double ylab = 0.80;
1648  double dylab = 0.04;
1649  for ( Name lab : labs ) {
1650  TLatex* pptl = nullptr;
1651  pptl = new TLatex(xlab, ylab, lab.c_str());
1652  pptl->SetNDC();
1653  pptl->SetTextFont(42);
1654  pptl->SetTextSize(dylab);
1655  pman->add(pptl);
1656  ylab -= 1.2*dylab;
1657  }
1658  }
1659  ++ipad;
1660  if ( ipad >= npad || ihst+1 >= hsts.size() ) {
1661  if ( pmantop == nullptr ) {
1662  if ( m_LogLevel >= 2 ) cout << myname << " Not writing empty plot" << endl;
1663  } else {
1664  if ( m_LogLevel >= 2 ) cout << myname << " Writing " << plotFileName << endl;
1665  pmantop->print(plotFileName);
1666  delete pmantop;
1667  pmantop = nullptr;
1668  }
1669  ipad = 0;
1670  }
1671  }
1672  }
1673 }
1674 
1675 //**********************************************************************
1676 
1678  const string myname = "AdcRoiViewer::fillChanSumHists: ";
1679  if ( getState().chanSumHists.size() == 0 ) {
1680  cout << myname << "No channel summary histograms found." << endl;
1681  return;
1682  }
1683  Name ofrname = m_ChanSumRootFileName;
1684  if ( m_LogLevel >= 1 ) cout << myname << "Filling channel summary histograms. Count is "
1685  << getState().chanSumHists.size() << "." << endl;
1686  for ( HistMap::value_type ihst : getState().chanSumHists ) {
1687  TH1* ph = ihst.second;
1688  Name hnam = ph->GetName();
1689  Name hnamTemplate = getState().getChanSumHistTemplateName(hnam);
1690  if ( hnamTemplate.size() == 0 ) {
1691  cout << myname << "ERROR: Summary template histogram name not found for channel summary " << hnam << endl;
1692  continue;
1693  }
1694  Name vartype = getState().getChanSumHistVariableType(hnam);
1695  Name errtype = getState().getChanSumHistErrorType(hnam);
1696  double errmin = 0.0;
1697  if ( errtype.substr(0,3) == "rms" && errtype.size() > 3 ) {
1698  string serrmin = errtype.substr(3);
1699  istringstream ssermin(serrmin);
1700  ssermin >> errmin;
1701  errtype = "rms";
1702  }
1703  bool isDist = getState().chanSumHistTypes[hnam];
1704  if ( vartype.size() == 0 ) {
1705  cout << myname << "ERROR: Variable type name not found for " << hnam << endl;
1706  continue;
1707  }
1708  AdcChannelData acd;
1709  acd.setEventInfo(getState().cachedRun, 0);
1711  Index ncha = 0;
1712  Index nchaGood = 0;
1713  int logthresh = 3;
1714  Index icha1 = getState().chanSumChaBegin[hnam];
1715  Index icha2 = getState().chanSumChaEnd[hnam];
1716  //for ( int ibin=1; ibin<=ph->GetNbinsX(); ++ibin ) {
1717  // Index icha = ph->GetBinCenter(ibin);
1718  for ( Index icha=icha1; icha<icha2; ++icha ) {
1719  Index ichaBin = icha + 1 - icha1;
1720  acd.setChannelInfo(icha);
1721  Name hnam = AdcChannelStringTool::build(m_adcStringBuilder, acd, hnamTemplate);
1722  //Index chanStat = getState().getChannelStatus(hnam);
1723  //if ( chanStat ) continue;
1724  ++ncha;
1725  TH1* phvar = getState().getSumHist(hnam);
1726  if ( phvar == nullptr ) {
1727  if ( m_LogLevel >= logthresh )
1728  cout << myname << "Unable to find sum hist " << hnam << endl;
1729  continue;
1730  }
1731  float val = 0.0;
1732  if ( vartype == "mean" ) {
1733  val = phvar->GetMean();
1734  } else if ( vartype == "peak" ) {
1735  int ibin = phvar->GetMaximumBin();
1736  val = phvar->GetBinCenter(ibin);
1737  } else if ( vartype == "rms" ) {
1738  val = phvar->GetRMS();
1739  } else if ( vartype == "entries" ) {
1740  val = phvar->GetEntries();
1741  } else if ( vartype == "count" ) {
1742  val = phvar->Integral();
1743  } else if ( vartype == "sum" ) {
1744  val = phvar->Integral()*phvar->GetMean();
1745  } else if ( vartype.substr(0,3) == "fit" ) {
1746  Index nfun = phvar->GetListOfFunctions()->GetEntries();
1747  TF1* pf = nfun ? dynamic_cast<TF1*>(phvar->GetListOfFunctions()->At(0)) : nullptr;
1748  if ( pf == nullptr ) {
1749  if ( m_LogLevel >= logthresh )
1750  cout << myname << "Unable to find find fit for sum hist " << hnam << endl;
1751  continue;
1752  }
1753  bool doRat = vartype.substr(3,3) == "rat";
1754  string::size_type ipos = doRat ? 6 : 3;
1755  Name spar = vartype.substr(ipos);
1756  int ipar = pf->GetParNumber(spar.c_str());
1757  if ( ipar < 0 ) {
1758  if ( m_LogLevel >= logthresh )
1759  cout << myname << "ERROR: Invalid fit parameter name: " << spar << endl;
1760  continue;
1761  }
1762  val = pf->GetParameter(ipar);
1763  if ( doRat ) {
1764  double mean = pf->GetParameter("Mean");
1765  val *= (mean == 0.0 ? 0.0 : 1.0/mean);
1766  }
1767  } else {
1768  cout << myname << "Invalid variable type " << vartype << " for " << hnam << endl;
1769  break;
1770  }
1771  float dval = 0.0;
1772  bool haveErr = true;
1773  if ( errtype == "none" ) {
1774  haveErr = false;
1775  } else if ( errtype == "zero" ) {
1776  dval = 0.0;
1777  } else if ( errtype.substr(0,3) == "rms" ) {
1778  dval = phvar->GetRMS();
1779  if ( dval < errmin ) dval = errmin;
1780  } else if ( errtype == "meanError" ) {
1781  dval = phvar->GetMeanError();
1782  if ( dval < errmin ) dval = errmin;
1783  } else if ( errtype == "rmsError" ) {
1784  dval = phvar->GetRMSError();
1785  if ( dval < errmin ) dval = errmin;
1786  } else if ( errtype.substr(0,3) == "fit" ) {
1787  Index nfun = phvar->GetListOfFunctions()->GetEntries();
1788  TF1* pf = nfun ? dynamic_cast<TF1*>(phvar->GetListOfFunctions()->At(0)) : nullptr;
1789  if ( phvar == nullptr ) {
1790  if ( m_LogLevel >= logthresh )
1791  cout << myname << "Unable to find find fit for sum hist " << hnam << endl;
1792  continue;
1793  }
1794  Name spar = errtype.substr(3);
1795  int ipar = pf->GetParNumber(spar.c_str());
1796  if ( ipar < 0 ) {
1797  cout << myname << "ERROR: Invalid fit parameter name: " << spar << endl;
1798  } else {
1799  dval = pf->GetParameter(ipar);
1800  }
1801  } else {
1802  cout << myname << "Invalid error type: " << errtype << endl;
1803  abort();
1804  }
1805  if ( ph->GetEntries() == 0 ) {
1806  TAxis* paxis = isDist ? ph->GetXaxis() : ph->GetYaxis();
1807  Name vlabOld = paxis->GetTitle();
1808  Name vlabNew = AdcChannelStringTool::build(m_adcStringBuilder, acd, vlabOld);
1809  if ( vlabNew != vlabOld ) {
1810  if ( m_LogLevel >= 3 ) cout << myname << "Setting variable label for " << hnam
1811  << " to \"" << vlabNew << "\"." << endl;
1812  paxis->SetTitle(vlabNew.c_str());
1813  }
1814  Name httlOld = ph->GetTitle();
1815  Name httlNew = AdcChannelStringTool::build(m_adcStringBuilder, acd, httlOld);
1816  if ( httlNew != httlOld ) {
1817  if ( m_LogLevel >= 3 ) cout << myname << "Setting title for " << hnam << " to \""
1818  << httlNew << "\"." << endl;
1819  ph->SetTitle(httlNew.c_str());
1820  }
1821  }
1822  if ( isDist ) {
1823  ph->Fill(val);
1824  } else {
1825  ph->SetBinContent(ichaBin, val);
1826  if ( haveErr ) ph->SetBinError(ichaBin, dval);
1827  }
1828  ++nchaGood;
1829  }
1830  if ( nchaGood < ncha ) {
1831  cout << myname << "WARNING: Only filled " << nchaGood << " of " << ncha
1832  << " channels for channel summary histogram " << hnam << endl;
1833  }
1834  }
1835 }
1836 
1837 //**********************************************************************
1838 
1840  const string myname = "AdcRoiViewer::writeChanSumHists: ";
1841  if ( m_ChanSumRootFileName.size() == 0 ) return;
1842  if ( getState().chanSumHists.size() == 0 ) {
1843  cout << myname << "No channel summary histograms found." << endl;
1844  return;
1845  }
1846  Name ofrname = m_ChanSumRootFileName;
1847  TDirectory* savdir = gDirectory;
1848  TFile* pfile = TFile::Open(ofrname.c_str(), "UPDATE");
1849  if ( m_LogLevel >= 1 ) cout << myname << "Writing channel summary histograms. Count is "
1850  << getState().chanSumHists.size() << "." << endl;
1851  for ( HistMap::value_type ihst : getState().chanSumHists ) {
1852  TH1* ph = ihst.second;
1853  TH1* phnew = dynamic_cast<TH1*>(ph->Clone());
1854  phnew->Write();
1855  if ( m_LogLevel >= 2 ) cout << myname << " Wrote " << phnew->GetName() << endl;
1856  }
1857  if ( pfile != nullptr ) pfile->Close();
1858  delete pfile;
1859  if ( m_LogLevel >= 1 ) cout << myname << "Closed summary histogram file " << ofrname << endl;
1860  savdir->cd();
1861 }
1862 
1863 //**********************************************************************
1864 
1866  const string myname = "AdcRoiViewer::writeChanSumPlots: ";
1867  for ( HistMap::value_type ihst : getState().chanSumHists ) {
1868  TH1* ph = ihst.second;
1869  Name hnam = ph->GetName();
1870  Name pnam = getState().getChanSumPlotName(hnam);
1871  if ( pnam.size() == 0 ) continue;
1872  if ( m_LogLevel >= 2 ) cout << myname << "Hist:Plot name: " << hnam << ":" << pnam << endl;
1873  bool isDist = getState().chanSumHistTypes[hnam];
1874  Index wpadx = isDist ? 700 : 1400;
1875  Index wpady = 500;
1876  TPadManipulator* pman = new TPadManipulator(wpadx, wpady);
1877  Name plotOpt = isDist ? "hist" : "p";
1878  pman->add(ph, plotOpt, false);
1879  pman->addAxis();
1880  pman->showUnderflow();
1881  pman->showOverflow();
1882  if ( ! isDist ) {
1883  bool doRange = false;
1884  float ymin = ph->GetMinimum();
1885  float ymax = ph->GetMaximum();
1886  Name yopt;
1887  if ( getState().chanSumPlotYMins.find(hnam) != getState().chanSumPlotYMins.end() ) {
1888  ymin = getState().chanSumPlotYMins[hnam];
1889  doRange = true;
1890  }
1891  if ( getState().chanSumPlotYMaxs.find(hnam) != getState().chanSumPlotYMaxs.end() ) {
1892  ymax = getState().chanSumPlotYMaxs[hnam];
1893  doRange = true;
1894  }
1895  if ( doRange ) {
1896  Name yopt = getState().chanSumPlotYOpts[hnam];
1897  double yfac = 0.0;
1898  if ( yopt == "pamp") {
1899  const RunData& rdat = getState().runData;
1900  if ( rdat.havePulserAmplitude() ) {
1901  yfac = rdat.pulserAmplitude();
1902  } else {
1903  yfac = 10.0;
1904  cout << myname << "WARNING: Scaling option pamp requested without run data." << endl;
1905  }
1906  } else if ( yopt == "pampg14") {
1907  const RunData& rdat = getState().runData;
1908  if ( rdat.havePulserAmplitude() && rdat.haveGain() ) {
1909  yfac = rdat.pulserAmplitude()*rdat.gain()/14.0;
1910  } else {
1911  yfac = 10.0;
1912  cout << myname << "WARNING: Scaling option pampg14 requested without run data." << endl;
1913  }
1914  } else if ( yopt == "nevt") {
1915  yfac = getState().eventCallCount.size();
1916  }
1917  if ( yfac != 0.0 ) {
1918  ymin *= yfac;
1919  ymax *= yfac;
1920  }
1921  // If ymin > ymax and ymin > 0, then we center histogram on median and use width = ymin.
1922  if ( ymin > ymax && ymin > 0.0 ) {
1923  int nval = ph->GetNbinsX();
1924  FloatVector tmpvals(nval);
1925  for ( int ival=0; ival<nval; ++ival ) tmpvals[ival] = ph->GetBinContent(ival+1);
1926  std::sort(tmpvals.begin(), tmpvals.end());
1927  float ymed = 0.5*(tmpvals[(nval-1)/2] + tmpvals[nval/2]);
1928  float width = ymin;
1929  ymin = ymed - 0.5*width;
1930  ymax = ymin + width;
1931  }
1932  if ( ymax > ymin ) {
1933  if ( m_LogLevel >= 2 ) cout << myname << "Setting plot range to (" << ymin << ", " << ymax << ")" << endl;
1934  pman->setRangeY(ymin, ymax);
1935  TH1* php = pman->hist();
1936  double del = 1.e-4*(ymax -ymin);
1937  // Put points on the page.
1938  for ( int ibin=1; ibin<php->GetNbinsX(); ++ibin ) {
1939  if ( php->GetBinContent(ibin) > ymax ) php->SetBinContent(ibin, ymax-del);
1940  if ( php->GetBinContent(ibin) < ymin ) php->SetBinContent(ibin, ymin+del);
1941  }
1942  }
1943  }
1944  }
1945  bool highlightBadChannels = ! isDist;
1946  if ( highlightBadChannels ) {
1947  TH1* php = pman->hist();
1948  LineColors cols;
1949  TGraph* pgb = new TGraph;
1950  TGraph* pgn = new TGraph;
1951  pgb->SetMarkerStyle(4);
1952  pgb->SetMarkerColor(cols.red());
1953  pgn->SetMarkerStyle(4);
1954  pgn->SetMarkerColor(cols.brown());
1955  Index icha0 = php->GetBinLowEdge(1);
1956  Index nbad = 0;
1957  Index nnoi = 0;
1958  for ( int ibin=1; ibin<php->GetNbinsX(); ++ibin ) {
1959  Index icha = icha0 + Index(ibin) - 1;
1960  Index chanStat = getState().getChannelStatus(icha);
1961  if ( chanStat == AdcChannelStatusBad ) {
1962  pgb->SetPoint(nbad++, icha+0.5, php->GetBinContent(ibin));
1963  }
1964  if ( chanStat == AdcChannelStatusNoisy ) {
1965  pgn->SetPoint(nnoi++, icha+0.5, php->GetBinContent(ibin));
1966  }
1967  }
1968  if ( nnoi ) pman->add(pgn, "P");
1969  if ( nbad ) pman->add(pgb, "P");
1970  delete pgb;
1971  delete pgn;
1972  }
1973  if ( m_ChannelLineModulus ) {
1974  for ( Index icha : m_ChannelLinePattern ) {
1976  }
1977  } else {
1978  for ( Index icha : m_ChannelLinePattern ) {
1979  pman->addVerticalLine(icha, 1.0, 3);
1980  }
1981  }
1982  if ( m_LogLevel >= 1 ) cout << myname << "Plotting channel summary " << pnam << endl;
1983  pman->print(pnam);
1984  delete pman;
1985  }
1986 }
1987 
1988 //**********************************************************************
1989 
1991  StringManipulator sman(sttl, false);
1992  for ( NameMap::value_type isub : m_plotLabelSubs ) {
1993  sman.replace(isub.first, isub.second);
1994  }
1995  sttl = sman.str();
1996 }
1997 
1998 //**********************************************************************
1999 
Index m_TickBorder
Definition: AdcRoiViewer.h:330
code to link reconstructed objects back to the MC truth information
Index m_SumPlotPadX
Definition: AdcRoiViewer.h:342
const TimeOffsetTool * m_pTickOffsetTool
Definition: AdcRoiViewer.h:365
intermediate_table::iterator iterator
std::vector< float > FloatVector
Definition: DataMap.h:54
bool havePulserPeriod() const
Definition: RunData.h:59
void writeChanSumPlots() const
const AdcChannelStringTool * m_adcStringBuilder
Definition: AdcRoiViewer.h:363
HistInfoMap sumHistTemplates
Definition: AdcRoiViewer.h:231
Index pulserAmplitude() const
Definition: RunData.h:41
IndexByIndexMap channelStatuses
Definition: AdcRoiViewer.h:268
Index m_ChannelLineModulus
Definition: AdcRoiViewer.h:344
void writeSumPlots(const DataMap *pdmin) const
void writeSumHists() const
bool havePulserSource() const
Definition: RunData.h:58
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
const RunDataTool * m_pRunDataTool
Definition: AdcRoiViewer.h:364
void fitSumHists() const
std::vector< ParameterSet > ParameterSetVector
void writeRoiPlots(const HistVector &hists, const AdcChannelData &acd) const
short AdcFlag
Definition: AdcTypes.h:29
AdcIndex subRun() const
float getSumPlotWidth(Name hnam) const
bool dbg
const AdcIndex AdcChannelStatusNoisy
Definition: AdcTypes.h:48
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
StatePtr m_state
Definition: AdcRoiViewer.h:360
IndexVector m_ChannelLinePattern
Definition: AdcRoiViewer.h:345
Index begin
Definition: IndexRange.h:34
static ColorType red()
Definition: LineColors.h:27
Name m_RoiRootFileName
Definition: AdcRoiViewer.h:349
IndexByNameMap sumHistChannels
Definition: AdcRoiViewer.h:239
IndexByNameMap chanSumChaBegin
Definition: AdcRoiViewer.h:250
ChannelGroupService::Name Name
Index run() const
Definition: RunData.h:33
int replace(std::string substr, const T &xsub)
TpmNameMap roiPadNames
Definition: AdcRoiViewer.h:228
NameVector m_PlotLabels
Definition: AdcRoiViewer.h:353
std::pair< AdcIndex, AdcIndex > AdcRoi
Definition: AdcTypes.h:54
int setCanvasSize(int wx, int wy)
const IntVector & getIntVector(Name name) const
Definition: DataMap.h:219
float m_SigThresh
Definition: AdcRoiViewer.h:329
const AdcFlag AdcUnderflow
Definition: AdcTypes.h:33
int split(Index nx, Index ny)
void fillChanSumHists() const
Index size() const
Definition: IndexRange.h:88
std::vector< Index > IndexVector
Definition: AdcRoiViewer.h:190
FloatMap chanSumPlotYMins
Definition: AdcRoiViewer.h:247
intermediate_table::const_iterator const_iterator
const FloatVector & getFloatVector(Name name) const
Definition: DataMap.h:221
Name m_PulserChargeUnit
Definition: AdcRoiViewer.h:340
TH1 * getSumHist(Name hnam)
void writeRoiHists(const DataMap &res, int dbg) const
QTextStream & hex(QTextStream &s)
std::vector< DataMap > DataMapVector
Definition: AdcRoiViewer.h:292
std::vector< TH1 * > HistVector
Definition: AdcRoiViewer.h:193
int shiftHistFit(TH1 *ph, TF1 *pf, std::string fopt, int ipar, double xshift)
unsigned int Index
bool isValid() const
Definition: IndexRange.h:94
DataMap close(const DataMap *dmin) override
const std::string & str() const
Index end
Definition: IndexRange.h:35
TH1 * hist() const
time_t time() const
NameVector m_ChannelRanges
Definition: AdcRoiViewer.h:352
int showOverflow(bool show=true)
NameMap chanSumHistErrorTypes
Definition: AdcRoiViewer.h:244
Name name
Definition: IndexRange.h:32
DataMap viewMap(const AdcChannelDataMap &acds) const override
bool isValid() const
Definition: RunData.h:48
std::vector< int > IntVector
Definition: DataMap.h:50
std::vector< Name > NameVector
Definition: AdcRoiViewer.h:192
Index fembID() const
int status() const
Definition: DataMap.h:202
void setIntVector(Name name, const IntVector &val)
Definition: DataMap.h:132
float gain() const
Definition: RunData.h:36
int addHorizontalLine(double yoff=0.0, double lenfrac=1.0, int isty=1)
void setChannelInfo(ChannelInfoPtr pchi)
int quietHistFit(TH1 *ph, std::string fname, std::string fopt)
virtual Offset offset(const Data &dat) const =0
AdcSignal pedestalRms
void setHistVector(Name name, const HistVector &hsts, bool own=false)
Definition: DataMap.h:150
const AdcFlag AdcOverflow
Definition: AdcTypes.h:34
Name getSumFitName(Name hnam) const
Index m_RoiPlotOpt
Definition: AdcRoiViewer.h:333
Name m_ChanSumRootFileName
Definition: AdcRoiViewer.h:351
Index pulserPeriod() const
Definition: RunData.h:43
AdcRoiVector rois
static std::string build(const AdcChannelStringTool *ptool, const AdcChannelData &acd, const DataMap &dm, std::string spat)
NameMap chanSumHistTemplateNames
Definition: AdcRoiViewer.h:242
Name getChanSumHistVariableType(Name hnam) const
FloatMap chanSumPlotYMaxs
Definition: AdcRoiViewer.h:248
AdcRoiViewer(fhicl::ParameterSet const &ps)
Index getChannelStatus(Index icha) const
T get(std::string const &key) const
Definition: ParameterSet.h:271
float m_PulserDacOffset
Definition: AdcRoiViewer.h:339
Index m_SumPlotPadY
Definition: AdcRoiViewer.h:343
int showUnderflow(bool show=true)
AdcIndex run() const
void setEventInfo(EventInfoPtr pevi)
int addAxis(bool flag=true)
Name getSumPlotName(Name hnam) const
void setInt(Name name, int val)
Definition: DataMap.h:131
std::vector< TPadManipulator * > ManVector
int doView(const AdcChannelData &acd, int dbg, DataMap &dm) const
virtual RunData runData(Index run, Index subRun=0) const =0
AdcIndex event() const
def save(obj, fname)
Definition: root.py:19
IndexByNameMap chanSumHistTypes
Definition: AdcRoiViewer.h:245
HistVectorMap sumPlotHists
Definition: AdcRoiViewer.h:234
unsigned int Index
Definition: AdcRoiViewer.h:189
static constexpr double ps
Definition: Units.h:99
Name label(Index ilab=0) const
Definition: IndexRange.h:106
AdcCountVector raw
TPadManipulator * man(unsigned int ipad=0)
Name getChanSumHistErrorType(Name hnam) const
IndexByNameMap chanSumChaEnd
Definition: AdcRoiViewer.h:251
int fit(TH1 *ph) const
DataMap view(const AdcChannelData &acd) const override
int addVerticalModLines(double xmod, double xoff=0.0, double lenfrac=1.0, int isty=3)
Index m_RoiPlotPadX
Definition: AdcRoiViewer.h:335
NameMap m_plotLabelSubs
Definition: AdcRoiViewer.h:357
Name getChanSumHistTemplateName(Name hnam) const
Float getFloat(Name name, Float def=0.0) const
Definition: DataMap.h:220
time_t m_StartTime
Definition: AdcRoiViewer.h:337
std::vector< int > IntVector
Definition: fcldump.cxx:26
std::vector< Name, ManVector > ManVectorMap
State & getState() const
Definition: AdcRoiViewer.h:304
void setPlotLabels(Name &sttl) const
Index channelStatus() const
Channel channel() const
int fit(TH1 *ph, double mean0) const
int addHistFun(unsigned int ifun=0)
Name getChanSumPlotName(Name hnam) const
bool haveGain() const
Definition: RunData.h:52
~AdcRoiViewer() override
int getInt(Name name, int def=0) const
Definition: DataMap.h:218
std::vector< string > NameVector
Name m_RunDataTool
Definition: AdcRoiViewer.h:346
std::unique_ptr< TPadManipulator > TpmPtr
Definition: AdcRoiViewer.h:203
bool haveFloat(Name name) const
Definition: DataMap.h:209
TF1 * coldelecResponseTF1(double gainIn, double shapingIn, double t0, std::string fname="ceresp")
NameMap chanSumHistVariableTypes
Definition: AdcRoiViewer.h:243
int setRangeX(double x1, double x2)
Index m_RoiPlotPadY
Definition: AdcRoiViewer.h:336
int addVerticalLine(double xoff=0.0, double lenfrac=1.0, int isty=1)
float m_PulserStepCharge
Definition: AdcRoiViewer.h:338
void writeChanSumHists() const
std::map< AdcChannel, AdcChannelData > AdcChannelDataMap
const AdcIndex AdcChannelStatusBad
Definition: AdcTypes.h:47
Dft::FloatVector FloatVector
const char * cs
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
void fillSumHists(const AdcChannelData &acd, const DataMap &dm) const
void setFloatVector(Name name, const FloatVector &val)
Definition: DataMap.h:134
std::vector< TH1 * > HistVector
Definition: DataMap.h:57
if(!yymsg) yymsg
std::string Name
Definition: AdcRoiViewer.h:191
static Index badIndex()
int bool
Definition: qglobal.h:345
int setRangeY(double y1, double y2)
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:16
IndexByIndexMap eventCallCount
Definition: AdcRoiViewer.h:273
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
const IndexRangeTool * m_pChannelRangeTool
Definition: AdcRoiViewer.h:366
static ColorType brown()
Definition: LineColors.h:29
int print(std::string fname, std::string spat="{,}")
static DuneToolManager * instance(std::string fclname="", int dbg=1)
AdcSignalVector samples
AdcLongIndex triggerClock() const
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
Name m_SumRootFileName
Definition: AdcRoiViewer.h:350
TpmCountMap roiPadCounts
Definition: AdcRoiViewer.h:229
T * getShared(std::string name)
QTextStream & endl(QTextStream &s)
bool havePulserAmplitude() const
Definition: RunData.h:57
Name m_ChannelRangeTool
Definition: AdcRoiViewer.h:348
void setLogLevel(Index lev)
Definition: GausRmsFitter.h:55
AdcFlagVector flags
virtual IndexRange get(Name nam) const =0
Name m_TickOffsetTool
Definition: AdcRoiViewer.h:347