AdcMultiChannelPlotter.cc
Go to the documentation of this file.
1 // AdcMultiChannelPlotter_t.cc
2 
10 #include <iostream>
11 #include <sstream>
12 
13 using std::cout;
14 using std::endl;
15 using std::ostringstream;
16 
17 //**********************************************************************
18 
20 : m_LogLevel(ps.get<Index>("LogLevel")),
21  m_PlotChannelRanges(ps.get<NameVector>(prefix + "ChannelRanges")),
22  m_PlotChannelGroups(ps.get<NameVector>(prefix + "ChannelGroups")),
23  m_PlotOverlayGroups(ps.get<Index>(prefix + "OverlayGroups")),
24  m_PlotDataView(ps.get<Name>(prefix + "DataView")),
25  m_PlotName(ps.get<Name>(prefix + "Name")),
26  m_PlotSummaryNames(ps.get<NameVector>(prefix + "SummaryNames")),
27  m_PlotSizeX(ps.get<Index>(prefix + "SizeX")),
28  m_PlotSizeY(ps.get<Index>(prefix + "SizeY")),
29  m_PlotSplitX(ps.get<Index>(prefix + "SplitX")),
30  m_PlotSplitY(ps.get<Index>(prefix + "SplitY")) {
31  const Name myname = "AdcMultiChannelPlotter::ctor: ";
32  if ( m_LogLevel >= 1 ) {
33  cout << myname << " LogLevel: " << m_LogLevel << endl;
34  bool first = true;
35  cout << myname << " " << prefix + "ChannelRanges: [";
36  for ( Name crn : m_PlotChannelRanges ) {
37  if ( first ) first = false;
38  else cout << ", ";
39  cout << crn;
40  }
41  cout << "]" << endl;
42  cout << myname << " " << prefix + "ChannelGroups: [";
43  first = true;
44  for ( Name cgn : m_PlotChannelGroups ) {
45  if ( first ) first = false;
46  else cout << ", ";
47  cout << cgn;
48  }
49  cout << "]" << endl;
50  cout << myname << " " << prefix << "OverlayGroups: " << m_PlotOverlayGroups << endl;
51  cout << myname << " " << prefix << "DataView: " << m_PlotDataView << endl;
52  cout << myname << " " << prefix << "Name: " << m_PlotName << endl;
53  cout << myname << " " << prefix << "SummaryNames: [";
54  first = true;
55  for ( Name name : m_PlotSummaryNames ) {
56  if ( first ) first = false;
57  else cout << ", ";
58  cout << name;
59  }
60  cout << "]" << endl;
61  cout << myname << " " << prefix << "SizeX: " << m_PlotSizeX << endl;
62  cout << myname << " " << prefix << "SizeY: " << m_PlotSizeY << endl;
63  cout << myname << " " << prefix << "SplitX: " << m_PlotSplitX << endl;
64  cout << myname << " " << prefix << "SplitY: " << m_PlotSplitY << endl;
65  }
66  Name stringBuilder = "adcStringBuilder";
68  if ( ptm == nullptr ) {
69  cout << myname << "ERROR: Tool manager not found." << endl;
70  } else {
71  // Fetch the string builder.
72  m_adcStringBuilder = ptm->getShared<AdcChannelStringTool>(stringBuilder);
73  if ( m_adcStringBuilder == nullptr ) {
74  cout << myname << "WARNING: AdcChannelStringTool not found: " << stringBuilder << endl;
75  }
76  // Build pad descriptions from groups.
77  if ( haveChannelGroups() && ptm != nullptr ) {
78  const IndexRangeGroupTool* pcgt = ptm->getShared<IndexRangeGroupTool>("channelGroups");
79  if ( pcgt == nullptr ) {
80  cout << myname << "ERROR: IndexRangeGroupTool not found: channelGroups" << endl;
81  } else {
82  for ( Name cgn : m_PlotChannelGroups ) {
83  IndexRangeGroup grp = pcgt->get(cgn);
84  if ( ! grp.isValid() ) {
85  cout << myname << "WARNING: Skipping invalid group " << cgn << endl;
86  continue;
87  }
88  m_cgmap[cgn] = grp;
89  Pad* ppad = nullptr;
90  for ( const IndexRange& ran : grp.ranges ) {
91  Name crn = ran.name;
92  if ( ! ran.isValid() ) {
93  cout << myname << "WARNING: Skipping invalid range " << crn << " in group " << cgn << endl;
94  continue;
95  }
96  if ( ppad == nullptr ) {
97  m_pads.emplace_back(cgn);
98  ppad = &m_pads.back();
99  }
100  if ( ppad->crmap.find(crn) != ppad->crmap.end() ) {
101  cout << myname << "WARNING: Ignoring duplicate channel range group " << cgn << endl;
102  continue;
103  }
104  ppad->crnames.push_back(crn);
105  ppad->crmap[crn] = ran;
106  if ( ! overlayGroups() ) ppad = nullptr;
107  } // end loop over ranges in group
108  } // end loop over groups
109  }
110  }
111  // Build pad descriptions from ranges.
112  if ( haveChannelRanges() && ptm != nullptr ) {
113  const IndexRangeTool* pcrt = ptm->getShared<IndexRangeTool>("channelRanges");
114  if ( pcrt == nullptr ) {
115  cout << myname << "ERROR: IndexRangeTool not found: channelRanges" << endl;
116  } else {
117  for ( Name crn : m_PlotChannelRanges ) {
118  IndexRange ran = pcrt->get(crn);
119  if ( ! ran.isValid() ) {
120  cout << myname << "WARNING: Skipping invalid range " << crn << endl;
121  continue;
122  }
123  m_pads.emplace_back(crn); // Use range name as group name
124  Pad& pad = m_pads.back();
125  pad.crnames.push_back(crn);
126  pad.crmap[crn] = ran;
127  } // end loop over ranges
128  }
129  }
130  }
131  if ( m_LogLevel >= 1 ) cout << myname << "Drawing pad count is " << m_pads.size() << endl;
132 }
133 
134 //**********************************************************************
135 
137  // viewSummary(); // Can't call this here b/c it uses virtual calls.
138 }
139 
140 //**********************************************************************
141 
143  const Name myname = "AdcMultiChannelPlotter::viewMap: ";
144  DataMap ret;
145  if ( acds.size() == 0 ) return ret;
146  if ( ! getBaseState().hasRun() ) {
147  getBaseState().setRun(acds.begin()->second.run());
148  }
149  getBaseState().event = acds.begin()->second.event();
150  Index npadx = 0;
151  Index npady = 0;
152  Index npadOnPage = 0;
153  if ( getPlotName().size() && m_PlotSplitX > 0 ) {
154  npadx = m_PlotSplitX;
156  npadOnPage = npadx*npady;
157  }
158  if ( getLogLevel() >= 2 ) {
159  cout << myname << "Per page pad count is " << npadOnPage << " (" << npady << " x " << npadx << ")" << endl;
160  }
161  Name plotName;
162  Name cgrn;
163  TPadManipulator* pmantop = nullptr;
164  bool doRanges = haveChannelRanges() || haveChannelGroups();
165  PadVector localPads;
166  // Build pad vector for single channels.
167  if ( ! doRanges ) {
168  for ( AdcChannelDataMap::value_type iacd : acds ) {
169  const AdcChannelData& acd = iacd.second;
170  Index icha = acd.channel();
171  getBaseState().channels.insert(icha);
172  ostringstream sscha;
173  sscha << icha;
174  Name scha = sscha.str();
175  while ( scha.size() < 6 ) scha = "0" + scha;
176  scha = "chan" + scha;
177  localPads.emplace_back(scha);
178  Pad& pad = localPads.back();
179  pad.crnames.push_back(scha);
180  pad.crmap[scha] = IndexRange(icha, icha+1);
181  }
182  }
183  const PadVector& pads = doRanges ? m_pads : localPads;
184  Index npad = pads.size();
185  if ( getLogLevel() >= 4 ) cout << myname << "Pad count is " << npad << endl;
186  Index ncha = 0;
187  Index nplt = 0;
188  Index ipadOnPage = 0;
189  for ( Index ipad=0; ipad<npad; ++ipad ) {
190  const Pad& pad = pads[ipad];
191  Name cgn = pad.cgname;
192  if ( getLogLevel() >= 4 ) {
193  cout << myname << " Processing pad " << ipad << " for channel group " << cgn << endl;
194  }
195  Index ncr = pad.crnames.size();
196  for ( Index icr=0; icr<ncr; ++icr ) {
197  Name crn = pad.crnames[icr];
198  const IndexRange& ran = pad.crmap.at(crn);
199  if ( ! ran.isValid() ) {
200  cout << "ERROR: Range " << crn << " in pad group " << cgn << " is invalid. Aborting." << endl;
201  abort();
202  }
203  if ( getLogLevel() >= 5 ) {
204  cout << myname << " Processing range " << ran << endl;
205  }
206  AdcChannelDataMap::const_iterator iacd1 = acds.lower_bound(ran.first());
207  if ( iacd1 == acds.end() ) {
208  if ( getLogLevel() >= 5 ) cout << myname << " Skipping range above data." << endl;
209  continue;
210  }
211  AdcChannelDataMap::const_iterator iacd2 = acds.upper_bound(ran.last());
212  if ( iacd2 == iacd1 ) {
213  if ( getLogLevel() >= 5 ) cout << myname << " Skipping range below data." << endl;
214  continue;
215  }
216  AcdVector acdvec;
217  Index ncha = 0;
218  for ( AdcChannelDataMap::const_iterator iacd=iacd1; iacd!=iacd2; ++iacd ) {
219  const AdcChannelData& acd = iacd->second;
220  Index icha = iacd->first;
221  if ( ! acd.hasView(getDataView()) ) {
222  cout << myname << "WARNING: View " << getDataView() << " is missing for channel "
223  << icha << "." << endl;
224  }
225  Index ndve = acd.viewSize(getDataView());
226  for ( Index idve=0; idve<ndve; ++idve ) {
227  acdvec.push_back(acd.viewEntry(getDataView(), idve));
228  }
229  ++ncha;
230  }
231  if ( getLogLevel() >= 4 ) {
232  Index nacd = acdvec.size();
233  cout << myname << " Processing channel range " << crn << " with " << nacd
234  << " entr" << (nacd == 1 ? "y" : "ies" ) << " in " << ncha << " channel"
235  << (ncha == 1 ? "" : "s") << "." << endl;
236  }
237  // If needed, create a new canvas.
238  AdcChannelData acdTmp; // Temporary channel data to hold event and (someday?) channel info.
239  acdTmp.setEventInfo(acds.begin()->second.getEventInfoPtr());
240  if ( pmantop == nullptr ) {
241  pmantop = new TPadManipulator;
243  if ( npadOnPage > 1 ) pmantop->split(npadx, npady);
244  }
245  // Assign group/range name using the first plot on the canvas.
246  if ( cgrn.size() == 0 ) {
247  cgrn = overlayGroups() ? cgn : crn;
248  }
249  // Assign plot name using the first plot with data on the canvas.
250  // Thepreviously-assigned group/range name is used.
251  if ( plotName.size() == 0 && acdvec.size() ) {
252  const AdcChannelData& acdFirst = *acdvec[0];
254  StringManipulator sman(plotName, false);
255  sman.replace("%CGNAME%", cgn);
256  sman.replace("%CRNAME%", crn);
257  sman.replace("%CGRNAME%", cgrn);
258  sman.replace("%VIEW%", getDataView());
259  plotName = sman.str();
260  if ( getLogLevel() >= 4 ) {
261  if ( plotName.size() ) cout << myname << " Created pad with plot name " << plotName << endl;
262  else cout << myname << " Created pad with no plot name." << endl;
263  }
264  if ( getLogLevel() >= 3 ) {
265  cout << myname << " Run " << acdFirst.run() << ", event " << acdFirst.event()
266  << " group/range " << cgrn << " ==> plot name " << plotName << endl;
267  }
268  }
269  // View this channel range.
270  TPadManipulator* ppadPage = pmantop->man(ipadOnPage);
271  if ( ppadPage == nullptr ) {
272  cout << myname << "ERROR: View pad " << ipadOnPage << " not found for pad " << ipad
273  << ", channel range " << crn << "." << endl;
274  } else {
275  viewMapChannels(crn, acdvec, *ppadPage, ncr, icr);
276  ncha += acds.size();
277  }
278  }
279  // Handle the end of a plot file.
280  ++ipadOnPage;
281  bool lastpad = (npadOnPage == 0) || (ipadOnPage == npadOnPage) || (ipad+1 == npad);
282  if ( lastpad && pmantop != nullptr ) {
283  if ( plotName.size() ) {
284  if ( getLogLevel() >= 3 ) cout << myname << " Printing canvas to " << plotName << endl;
285  pmantop->print(plotName);
286  } else {
287  if ( getLogLevel() >= 3 ) cout << myname << " Not printing canvas for channel group/range "
288  << cgrn << "." << endl;
289  }
290  delete pmantop;
291  pmantop = nullptr;
292  plotName = "";
293  cgrn = "";
294  ipadOnPage = 0;
295  ++nplt;
296  }
297  }
298  delete pmantop;
299  ret.setInt("multiChannelNChannel", ncha);
300  ret.setInt("multiChannelNPlot", nplt);
301  return ret;
302 }
303 
304 //**********************************************************************
305 
307  const Name myname = "AdcMultiChannelPlotter::viewSummary: ";
308  if ( getPlotSummaryName(ilev).size() == 0 ) {
309  if ( getLogLevel() >= 3 ) cout << myname << "Summmary plots not named for level " << ilev << endl;
310  return;
311  }
312  if ( getLogLevel() >= 3 ) cout << myname << "Creating summmary plots for level " << ilev << endl;
313  Index npadx = 0;
314  Index npady = 0;
315  Index npadOnPage = 1;
316  if ( m_PlotSplitX > 0 ) {
317  npadx = m_PlotSplitX;
319  npadOnPage = npadx*npady;
320  }
321  if ( getLogLevel() >= 2 ) {
322  cout << myname << "Pad count/page is " << npadOnPage << " (" << npady << " x " << npadx << ")" << endl;
323  }
324  TPadManipulator* pmantop = nullptr;
325  PadVector localPads;
326  // Build pad vector for single channels.
327  bool doRanges = haveChannelRanges() || haveChannelGroups();
328  if ( ! doRanges ) {
329  for ( Index icha : getBaseState().channels ) {
330  ostringstream sscha;
331  sscha << icha;
332  Name scha = sscha.str();
333  while ( scha.size() < 6 ) scha = "0" + scha;
334  scha = "chan" + scha;
335  localPads.emplace_back(scha);
336  Pad& pad = localPads.back();
337  pad.crnames.push_back(scha);
338  pad.crmap[scha] = IndexRange(icha, icha+1);
339  }
340  }
341  const PadVector& pads = doRanges ? m_pads : localPads;
342  Index npad = pads.size();
343  Name plotName;
344  Name cgrn;
345  AdcChannelData acdPrint;
348  if ( getLogLevel() >= 3 ) cout << myname << "Pad count is " << npad << endl;
349  for ( Index ipad =0; ipad<npad; ++ipad ) {
350  const Pad& pad = pads[ipad];
351  Name cgn = pad.cgname;
352  Index ipadOnPage = npad == 0 ? 0 : ipad % npadOnPage;
353  if ( getLogLevel() >= 4 ) cout << myname << " Channel group " << cgn
354  << " channel range count is " << pad.crnames.size() << endl;
355  Index ncrn = pad.crnames.size();
356  // # CRNs included in plot.
357  for ( Index icrn=0; icrn<ncrn; ++icrn ) {
358  Name crn = pad.crnames[icrn];
359  if ( getLogLevel() >= 4 ) {
360  cout << myname << " Processing group/range " << cgn << "/" << crn << endl;
361  }
362  // Assign group/range name for the canvas.
363  if ( cgrn.size() == 0 ) {
364  cgrn = overlayGroups() ? cgn : crn;
365  }
366  // If needed, create a new canvas and a name.
367  acdPrint.setChannelInfo(pad.crmap.at(crn).begin);
368  if ( pmantop == nullptr ) {
369  if ( getLogLevel() >= 3 ) cout << myname << " Creating canvas for run " << acdPrint.run()
370  << ", event " << acdPrint.event() << "." << endl;
371  pmantop = new TPadManipulator;
373  if ( npadOnPage > 1 ) pmantop->split(npadx, npady);
374  DataMap dmPrint;
375  //dmPrint.setInt("CHAN1", ran.first());
376  //dmPrint.setInt("CHAN2", ran.last());
377  plotName = AdcChannelStringTool::build(m_adcStringBuilder, acdPrint, dmPrint, getPlotSummaryName(ilev));
378  StringManipulator sman(plotName, false);
379  sman.replace("%CRNAME%", crn);
380  sman.replace("%CGNAME%", cgn);
381  sman.replace("%CGRNAME%", cgrn);
382  sman.replace("%VIEW%", getDataView());
383  }
384  // View this channel range.
385  int rstat = viewMapSummary(ilev, cgn, crn, *pmantop->man(ipadOnPage), ncrn, icrn);
386  if ( rstat >= 1 ) cout << myname << "WARNING: viewMapSummary returned error code " << rstat << endl;
387  if ( getLogLevel() >= 5 ) cout << myname << " Pad " << ipadOnPage << " extra object count: "
388  << pmantop->man(ipadOnPage)->objects().size() << endl;
389  }
390  // Handle the end of a plot file.
391  bool lastpad = (npadOnPage == 0) || (ipadOnPage+1 == npadOnPage) || (ipad+1 == npad);
392  if ( lastpad && pmantop != nullptr ) {
393  if ( getLogLevel() >= 3 ) cout << myname << " Printing summary canvas to " << plotName << endl;
394  pmantop->print(plotName);
395  delete pmantop;
396  pmantop = nullptr;
397  plotName = "";
398  cgrn = "";
399  }
400  }
401 }
402 
403 //**********************************************************************
404 
406  const Name myname = "AdcMultiChannelPlotter::getChannelGroup: ";
407  ChannelGroupMap::const_iterator icgr = m_cgmap.find(cgn);
408  if ( icgr == m_cgmap.end() ) {
409  // Not an error -- we may index by range or channel name instead of group name.
410  //cout << myname << "ERROR: Group not found: " << cgn << endl;
411  static const IndexRangeGroup badcgr;
412  return badcgr;
413  }
414  return icgr->second;
415 }
416 
417 //**********************************************************************
static QCString name
Definition: declinfo.cpp:673
std::vector< Name > NameVector
Name getPlotSummaryName(Index ilev) const
unsigned int Index
BaseState & getBaseState() const
int replace(std::string substr, const T &xsub)
int setCanvasSize(int wx, int wy)
int split(Index nx, Index ny)
intermediate_table::const_iterator const_iterator
bool isValid() const
Definition: IndexRange.h:94
const std::string & str() const
Name name
Definition: IndexRange.h:32
void viewSummary(Index ilev) const
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
Index last() const
Definition: IndexRange.h:96
void setChannelInfo(ChannelInfoPtr pchi)
AdcMultiChannelPlotter(const fhicl::ParameterSet &ps, Name prefix="Plot")
const IndexRangeGroup & getChannelGroup(Name cgn) const
static std::string build(const AdcChannelStringTool *ptool, const AdcChannelData &acd, const DataMap &dm, std::string spat)
DataMap viewMap(const AdcChannelDataMap &acds) const override
Framework includes.
AdcIndex run() const
void setEventInfo(EventInfoPtr pevi)
void setInt(Name name, int val)
Definition: DataMap.h:131
virtual int viewMapSummary(Index ilev, Name cgn, Name crn, TPadManipulator &man, Index ncr, Index icr) const =0
AdcIndex event() const
static constexpr double ps
Definition: Units.h:99
TPadManipulator * man(unsigned int ipad=0)
virtual IndexRangeGroup get(Name nam) const =0
std::vector< Pad > PadVector
Channel channel() const
RangeVector ranges
Index first() const
Definition: IndexRange.h:95
virtual int viewMapChannels(Name crn, const AcdVector &acds, TPadManipulator &man, Index ncr, Index icr) const =0
const AdcChannelData * viewEntry(Name vpnam, AdcIndex ient) const
size_t viewSize() const
std::map< AdcChannel, AdcChannelData > AdcChannelDataMap
const TObjVector & objects() const
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
bool hasView(Name vnam) const
const AdcChannelStringTool * m_adcStringBuilder
bool isValid() const
int print(std::string fname, std::string spat="{,}")
static DuneToolManager * instance(std::string fclname="", int dbg=1)
DuneEventInfo EventInfo
std::vector< const AdcChannelData * > AcdVector
T * getShared(std::string name)
QTextStream & endl(QTextStream &s)
Event finding and building.
virtual IndexRange get(Name nam) const =0