DQMPlotter.cpp
Go to the documentation of this file.
1 //File: DQMPlotter.cpp
2 //Brief: An "algorithm" class for creating online monitoring plots in a way that works
3 // either with or without LArSoft. Should start out by plotting diagnostics from
4 // perl plotting code, then branch out as we identify more pathologies.
5 //Author: Andrew Olivier aolivier@ur.rochester.edu
6 
7 #ifndef CRT_ONLINEPLOTTER_CPP
8 #define CRT_ONLINEPLOTTER_CPP
9 
10 //crt-core includes
12 
13 //crt-alg includes
15 
16 //ROOT includes
17 #include "TDirectory.h"
18 #include "TH1D.h"
19 #include "TGraph.h"
20 
21 //c++ includes
22 #include <map>
23 #include <string>
24 
25 //TODO: Remove me
26 #include <iostream>
27 namespace CRT
28 {
29  template <class TFS>
30  //TFS is an object that defines a function like:
31  //
32  //template <class HIST, class ARGS...> HIST* make(ARGS... args)
33  //
34  //Looks like ART's TFileService.
35  class DQMPlotter
36  {
37  public:
38 
39  DQMPlotter(TFS& tfs, const double timeTickSize, std::unique_ptr<CRT::Geometry>&& geom): fFileService(tfs),
40  fFirstTime(std::numeric_limits<uint64_t>::max()),
41  fTickSize(timeTickSize), fGeom(std::move(geom))
42  {
43  fTimestamps = fFileService->template make<TH1D>("timestamps", "Timestamps for All Modules;Timestamp;Triggers", 300, 6.592522e18, 6.592525e18); //Trigger automatic binning?
44  fTriggerDeltaT = fFileService->template make<TH1D>("triggerDeltaT", "Time Difference Between Two Triggers on Any Channel;"
45  "#Delta T[ns];Triggrs", 1000, -50, 100);
46 
47  fTriggerTime = fFileService->template make<TH1D>("triggerTime", "Time of each Trigger in Run;Time [s];Triggers", 100, 0, 3);
48 
49  fDeltaTSeconds = fFileService->template make<TH1D>("deltaTSeconds", "Difference in Elapsed Time Between Adjacent Triggers;#Delta T [s];"
50  "Triggers", 400, -0.3, 0.3);
51 
52  fEventLength = fFileService->template make<TH1D>("EventLength", "Time Ticks Between Earliest and Latest Triggers;#DeltaT [ticks];Events",
53  100, 0, 100);
54  }
55 
56  virtual ~DQMPlotter() = default; //All pointers kept by this class are owned
57  //by another object.
58 
59 
60  void AnalyzeEvent(const std::vector<CRT::Trigger>& triggers) //Make plots from CRT::Triggers
61  {
62  const auto end = triggers.cend();
63  auto prev = end;
64 
65  //If first timestamp hasn't been set to a suitable value yet, try to set it now to the
66  //earliest timestamp in this event.
68  {
69  for(const auto& trigger: triggers)
70  {
71  if(trigger.Timestamp() > 1e18 && trigger.Timestamp() < fFirstTime)
72  {
73  fFirstTime = trigger.Timestamp();
74  }
75  }
76  }
77 
78  //Map from Trigger to times in frame along each axis. First element is first 2 Triggers (alternates x and y), and second element is
79  //second 2 triggers (alternates y and x). What the "first" element means is different between frames, but it is consistent within a
80  //frame.
81  std::map<CRT::FrameID, std::map<CRT::PlaneID, std::vector<uint64_t>>> moduleToOverlapTimes;
82  uint64_t earliest = std::numeric_limits<uint64_t>::max(), latest = 1e16;
83  for(auto iter = triggers.cbegin(); iter != end; ++iter)
84  {
85  const auto& trigger = *iter;
86 
87  fTimestamps->Fill(trigger.Timestamp());
88  if(prev != end)
89  {
90  fTriggerDeltaT->Fill(trigger.Timestamp()-prev->Timestamp());
91  }
92 
93  //Find the plots for this Module
94  const auto moduleID = fGeom->ModuleID(trigger.Channel());
95  std::cout << "Looking for plots for module " << trigger.Channel() << "\n";
96  auto found = fModules.find(moduleID);
97  if(found == fModules.end())
98  {
99  std::cout << "Adding directory for module " << trigger.Channel() << "\n";
100  found = fModules.emplace(moduleID, ModulePlots<decltype(fFileService->mkdir("test"))>(fFileService->mkdir("module"+std::to_string(trigger.Channel())))).first;
101  }
102  auto& module = found->second;
103 
104  //Keep track of times of overlaps in this event
105  moduleToOverlapTimes[moduleID][moduleID].push_back(trigger.Timestamp());
106 
107  //Keep track of earliest and latest Trigger times in the event
108  if(trigger.Timestamp() > 1e16 && trigger.Timestamp() < earliest) earliest = trigger.Timestamp();
109  if(trigger.Timestamp() > latest) latest = trigger.Timestamp();
110 
111  if(trigger.Timestamp() > 1e16) //TODO: What do the very small timestamps represent? They have UNIX timestamp of 0
112  {
113  //Plot lower 32 timestamp bits versus time since beginning of event.
114  //To get time since beginning of event, I have to extract each part of the timestamp and convert the lower half to seconds.
115  const double elapsed = (trigger.Timestamp() - fFirstTime)*fTickSize; //In seconds.
116  fTriggerTime->Fill(elapsed);
117  fDeltaTSeconds->Fill(elapsed-module.fPrevSeconds);
118  module.fPrevSeconds = elapsed;
119 
120  if(module.fPrevTimestamp < std::numeric_limits<unsigned long long>::max()) //Don't fill fPrevTimestamp if there WAS no
121  //fPrevTimestamp
122  {
123  module.fTriggerDeltaT->Fill(trigger.Timestamp()-module.fPrevTimestamp);
124  }
125  module.fPrevTimestamp = trigger.Timestamp(); //This also sets the first fPrevTimestamp value
126  }
127 
128  const auto& hits = trigger.Hits();
129  module.fHitsPerTrigger->Fill(hits.size());
130  for(const auto& hit: hits)
131  {
132  const auto channel = hit.Channel();
133  module.fHits->Fill(channel);
134 
135  const auto adcFound = module.fChannelToADC.find(channel);
136  if(adcFound == module.fChannelToADC.end())
137  {
138  const auto name = "channel"+std::to_string(channel);
139  module.fChannelToADC[channel] = module.fDir.template make<TH1D>(name.c_str(), ("Hits on Channel "
140  +std::to_string(channel)).c_str(),
141  500, 0, 2000);
142  }
143 
144  module.fChannelToADC[channel]->Fill(hit.ADC());
145  module.fAllADC->Fill(hit.ADC());
146  } //For each Hit
147  prev = iter;
148  } //For each Trigger
149 
150  if(triggers.size() > 1) fEventLength->Fill(latest-earliest);
151 
152  //Fill overlap histograms
153  for(const auto& trigger: triggers)
154  {
155  const auto thisTime = trigger.Timestamp();
156  const auto& id = fGeom->ModuleID(trigger.Channel());
157 
158  //Find the plots for this module if any
159  auto found = fModules.find(id);
160  if(found == fModules.end()) continue;
161  auto& plots = found->second;
162 
163  const auto& frame = moduleToOverlapTimes[id];
164  const auto thisPlane = frame.find(id);
165  for(auto plane = frame.begin(); plane != frame.end(); ++plane)
166  {
167  if(plane != thisPlane) //TODO: I know that there will always be exactly 2 orientations for the CRT,
168  // so maybe I should use some dedicated keyed container with a complement()
169  // function here.
170  {
171  for(const auto& time: plane->second) plots.fDeltaTOverlap->Fill(thisTime-time);
172  } //If this is not the plane of the current Trigger
173  } //For each plane in this Trigger's frame
174  } //For each Trigger in this event
175  }
176 
177  private:
178  TFS fFileService; //Handle to tool for writing out files
179 
180  //Plots that will be filled during the lifetime of this object
181  //Group plots for a module into one object
182  template <class DIRECTORY>
183  struct ModulePlots
184  {
185  ModulePlots(DIRECTORY&& dir): fDir(dir), fPrevTimestamp(std::numeric_limits<decltype(fPrevTimestamp)>::max()), fPrevSeconds(0)
186  {
187  fHits = fDir.template make<TH1D>("Hits", "Hits for Each Channel;Channel;Hits", 65, 0, 64);
188  fTriggerDeltaT = fDir.template make<TH1D>("TriggerDeltaT", "Time Between Triggers;#Delta Timestamp [ticks];Pairs of Triggers",
189  1e3, 0., 1e6);
190  fHitsPerTrigger = fDir.template make<TH1D>("HitsPerTrigger", "Hits in each Trigger;Hits;Triggers", 65, 0, 64);
191 
192  fAllADC = fDir.template make<TH1D>("AllADC", "ADCs for All Channels in this Module;ADC;Hits", 1024, 0, 4096);
193 
194  fDeltaTOverlap = fDir.template make<TH1D>("DeltaTOverlap", "Time Ticks Between Overlapping Modules' Triggers in an Event;"
195  "#DeltaT [ticks];Overlaps", 200, 0, 200);
196  }
197 
198  DIRECTORY fDir; //Directory to which this module's plots will be written
199  TH1D* fHits; //Plot of number of hits in each channel for this module
200  TH1D* fTriggerDeltaT; //Plot time between Triggers on this module
201  TH1D* fHitsPerTrigger; //Number of Hits per Trigger
202  TH1D* fAllADC; //ADC values for all channels in this module
203  TH1D* fDeltaTOverlap; //Time difference between pairs of overlapping modules
204  std::map<size_t, TH1D*> fChannelToADC; //Plot of ADC counts for each channel
205 
206  unsigned long long fPrevTimestamp; //Timestamp of the previous Trigger
207  double fPrevSeconds; //Previous elapsed time in seconds
208  //timing of sync pulses before resetting.
209  };
210 
211  //TODO: It seems like I only need fFileService for this decltype declaration. Otherwise, I could move from a class template to
212  // just a function template for the constructor.
213  std::map<CRT::ModuleID, ModulePlots<decltype(fFileService->mkdir("test"))>> fModules; //A group of plots for each module
214  TH1D* fTimestamps; //Plot of timestampts for all Triggers
215  TH1D* fTriggerDeltaT; //Time difference between any Trigger and its' neighbor within an event.
216  TH1D* fTriggerTime; //Elapsed time before each Trigger was detected
217  TH1D* fDeltaTSeconds; //Difference between elpased time between Trigger and previous Trigger
218  TH1D* fEventLength; //Time between earliest and latest timestamp in each AnalyzeEvent() call in clock ticks
219 
220  //Keep track of elapsed time since earliest Trigger
221  uint64_t fFirstTime; //First timestamp of any Trigger in first event.
222  const double fTickSize; //Size of a time tick in seconds
223  std::unique_ptr<CRT::Geometry> fGeom; //Handle to geometrical description of CRT
224  };
225 }
226 
227 #endif //CRT_ONLINEPLOTTER_CPP
static QCString name
Definition: declinfo.cpp:673
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
DQMPlotter(TFS &tfs, const double timeTickSize, std::unique_ptr< CRT::Geometry > &&geom)
Definition: DQMPlotter.cpp:39
virtual ~DQMPlotter()=default
void AnalyzeEvent(const std::vector< CRT::Trigger > &triggers)
Definition: DQMPlotter.cpp:60
const double fTickSize
Definition: DQMPlotter.cpp:222
unsigned long long fPrevTimestamp
Definition: DQMPlotter.cpp:206
STL namespace.
std::map< CRT::ModuleID, ModulePlots< decltype(fFileService->mkdir("test"))> > fModules
Definition: DQMPlotter.cpp:213
uint8_t channel
Definition: CRTFragment.hh:201
string dir
std::unique_ptr< CRT::Geometry > fGeom
Definition: DQMPlotter.cpp:223
detail::Node< PlaneID, bool > ModuleID
Definition: CRTID.h:132
uint64_t fFirstTime
Definition: DQMPlotter.cpp:221
ModulePlots(DIRECTORY &&dir)
Definition: DQMPlotter.cpp:185
TH1D * fDeltaTSeconds
Definition: DQMPlotter.cpp:217
def move(depos, offset)
Definition: depos.py:107
static int max(int a, int b)
Detector simulation of raw signals on wires.
TH1D * fTriggerDeltaT
Definition: DQMPlotter.cpp:215
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
std::map< size_t, TH1D * > fChannelToADC
Definition: DQMPlotter.cpp:204