CRTRawDecoder_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: CRTRawDecoder
3 // Plugin Type: producer (art v2_10_03)
4 // File: CRTRawDecoder_module.cc
5 //
6 // Generated at Wed Jul 4 08:14:43 2018 by Andrew Olivier using cetskelgen
7 // from cetlib version v3_02_00.
8 ////////////////////////////////////////////////////////////////////////
9 
10 //Framework includes
17 #include "art_root_io/TFileService.h"
19 #include "fhiclcpp/ParameterSet.h"
21 
22 //LArSoft includes
25 
26 //dune-artdaq includes
27 #include "artdaq-core/Data/ContainerFragment.hh"
28 
29 //dune-raw-data includes
31 
32 //dunetpc includes
35 
36 //ROOT includes
37 #include "TGraph.h"
38 
39 //c++ includes
40 #include <memory>
41 
42 using namespace CRT;
43 
44 //A CRTRawDecoder takes artdaq::Fragments made from Cosmic Ray Tagger input
45 //and produces a CRT::Trigger for each time a CRT module triggered in this Event.
46 namespace CRT
47 {
49  {
50  public:
51  explicit CRTRawDecoder(fhicl::ParameterSet const & p);
52  // The compiler-generated destructor is fine for non-base
53  // classes without bare pointers or other resource use.
54 
55  // Plugins should not be copied or assigned.
56  CRTRawDecoder(CRTRawDecoder const &) = delete;
57  CRTRawDecoder(CRTRawDecoder &&) = delete;
58  CRTRawDecoder & operator = (CRTRawDecoder const &) = delete;
60 
61  // Required functions.
62  void produce(art::Event & e) override;
63 
64  // Selected optional functions. I might get services that I expect to change here. So far, seems like only service I might need is timing.
65  void beginJob() override;
66  //void beginRun(art::Run & r) override;
67  //void beginSubRun(art::SubRun & sr) override;
68 
69  private:
70 
71  // Configuration data
72  const art::InputTag fFragTag; //Label and product instance name (try eventdump.fcl on your input file) of the module that produced
73  //artdaq::Fragments from CRT data that I will turn into CRT::Triggers. Usually seems to be "daq" from artdaq.
74 
75  const bool fLookForContainer; //Should this module look for "container" artdaq::Fragments instead of "single" artdaq::Fragments?
76  //If you ran the CRT board reader with the "request_mode" FHICL parameter set to "window", you need
77  //to look for "container" Fragments and probably won't get any useful Fragments otherwise. If you
78  //ran the CRT board reader with "request_mode" set to "ignore", then set fLookForContainer to "false"
79  //which is the default.
80  //You probably want this set to "true" because the CRT should be run in "window" request_mode for
81  //production. You might set it to "false" if you took debugging data in which you wanted to ignore
82  //timestamp matching with other detectors.
83  const bool fMatchOfflineMapping; //Should the hardware channel mapping match the order in which AuxDetGeos are sorted in the offline
84  //framework? Default is true. Please set to false for online monitoring so that CRT experts can
85  //understand problems more quickly.
86  std::vector<size_t> fChannelMap; //Simple map from raw data module number to offline module number. Initialization depends on
87  //fMatchOfflineMapping above.
88 
89  // Compartmentalize internal functionality so that I can reuse it with both regular Fragments and "container" Fragments
90  void FragmentToTriggers(const artdaq::Fragment& artFrag, std::unique_ptr<std::vector<CRT::Trigger>>& triggers);
91 
92  // For the first Event of every job, I want to set fEarliestTime to the earliest time in that Event
93  void SetEarliestTime(const artdaq::Fragment& frag);
94 
95  //Sync diagnostic plots
96  struct PerModule
97  {
98  PerModule(art::TFileDirectory& parent, const size_t module): fModuleDir(parent.mkdir("Module"+std::to_string(module)))
99  {
100  fLowerTimeVersusTime = fModuleDir.makeAndRegister<TGraph>("LowerTimeVersusTime", "Raw 32 Bit Timestamp versus Elapsed Time in Seconds;"
101  "Time [s];Raw Timestamp [ticks]");
102  }
103 
104  art::TFileDirectory fModuleDir; //Directory for plots from this module
105  TGraph* fLowerTimeVersusTime; //Graph of lower 32 bits of raw timestamp versus processed timestamp in seconds.
106  };
107 
108  void createSyncPlots();
109 
110  std::vector<PerModule> fSyncPlots; //Mapping from module number to sync diagnostic plots in a directory
111  uint64_t fEarliestTime; //Earliest time in clock ticks
112  };
113 
114 
116  fLookForContainer(p.get<bool>("LookForContainer", false)),
117  fMatchOfflineMapping(p.get<bool>("MatchOfflineMapping", true)),
118  fEarliestTime(std::numeric_limits<decltype(fEarliestTime)>::max())
119  {
120  // Call appropriate produces<>() functions here.
121  produces<std::vector<CRT::Trigger>>();
122  consumes<std::vector<artdaq::Fragment>>(fFragTag);
123 
124  //Register callback to make new plots on every file
126  tfs->registerFileSwitchCallback(this, &CRTRawDecoder::createSyncPlots);
127  }
128 
129  void CRTRawDecoder::FragmentToTriggers(const artdaq::Fragment& artFrag, std::unique_ptr<std::vector<CRT::Trigger>>& triggers)
130  {
131  CRT::Fragment frag(artFrag);
132 
133  MF_LOG_DEBUG("CRTGoodEvent") << "Is this Fragment good? " << ((frag.good_event())?"true":"false") << "\n";
134  /*frag.print_header();
135  frag.print_hits();*/
136 
137  std::vector<CRT::Hit> hits;
138 
139  //Make a CRT::Hit from each non-zero ADC value in this Fragment
140  for(size_t hitNum = 0; hitNum < frag.num_hits(); ++hitNum)
141  {
142  const auto hit = *(frag.hit(hitNum));
143  MF_LOG_DEBUG("CRTRaw") << "Channel: " << (int)(hit.channel) << "\n"
144  << "ADC: " << hit.adc << "\n";
145  //Determine the offline channel number for each strip
146  size_t offline_channel = hit.channel;
147  if (frag.module_num() == 14 ||
148  frag.module_num() == 15 ||
149  frag.module_num() == 8 ||
150  frag.module_num() == 9 ||
151  frag.module_num() == 10 ||
152  frag.module_num() == 11 ||
153  frag.module_num() == 4 ||
154  frag.module_num() == 5 ||
155  frag.module_num() == 30 ||
156  frag.module_num() == 31 ||
157  frag.module_num() == 24 ||
158  frag.module_num() == 25 ||
159  frag.module_num() == 26 ||
160  frag.module_num() == 27 ||
161  frag.module_num() == 20 ||
162  frag.module_num() == 21){ //Strips need to be flipped (TY)
163  if (hit.channel<32){
164  offline_channel = (31-hit.channel)*2;
165  }
166  else{
167  offline_channel = (63-hit.channel)*2+1;
168  }
169  }
170  else{//Strips do not need to be flipped
171  if (hit.channel<32){
172  offline_channel = hit.channel*2;
173  }
174  else{
175  offline_channel = (hit.channel-32)*2+1;
176  }
177  }
178  //Flip the two layers
179  if (offline_channel%2==0) ++offline_channel;
180  else --offline_channel;
181  hits.emplace_back(offline_channel, hit.adc);
182  //MF_LOG_DEBUG("CRT Hits") CRT::operator << hits.back() << "\n"; //TODO: Some function template from the message service interferes with my
183  // function template from namespace CRT. using namespace CRT seems like
184  // it should solve this, but it doesn't seem to.
185  }
186 
187  MF_LOG_DEBUG("CRTFragments") << "Module: " << frag.module_num() << "\n"
188  << "Number of hits: " << frag.num_hits() << "\n"
189  << "Fifty MHz time: " << frag.fifty_mhz_time() << "\n";
190 
191  try
192  {
193  triggers->emplace_back(fChannelMap.at(frag.module_num()), frag.fifty_mhz_time(), std::move(hits));
194  }
195  catch(const std::out_of_range& e)
196  {
197  mf::LogWarning("Bad CRT Channel") << "Got CRT channel number " << frag.module_num() << " that is greater than the number of boards"
198  << " in the channel map: " << fChannelMap.size() << ". Throwing out this Trigger.\n";
199  }
200 
201  //Make diagnostic plots for sync pulses
202  const auto& plots = fSyncPlots[frag.module_num()];
203  const double deltaT = (frag.fifty_mhz_time() - fEarliestTime)*1.6e-8; //TODO: Get size of clock ticks from a service
204  if(deltaT > 0 && deltaT < 1e6) //Ignore time differences less than 1s and greater than 1 day
205  //TODO: Understand why these cases come up
206  {
207  plots.fLowerTimeVersusTime->SetPoint(plots.fLowerTimeVersusTime->GetN(), deltaT, frag.raw_backend_time());
208  }
209  else
210  {
211  mf::LogWarning("SyncPlots") << "Got time difference " << deltaT << " that was not included in sync plots.\n"
212  << "lhs is " << frag.fifty_mhz_time() << ", and rhs is " << fEarliestTime << ".\n"
213  << "Hardware raw time is " << frag.raw_backend_time() << ".\n";
214  }
215  }
216 
217  void CRTRawDecoder::SetEarliestTime(const artdaq::Fragment& frag)
218  {
219  CRT::Fragment crt(frag);
221  }
222 
223  //Read artdaq::Fragments produced by fFragTag, and use CRT::Fragment to convert them to CRT::Triggers.
225  {
226  //Create an empty container of CRT::Triggers. Any Triggers in this container will be put into the
227  //event at the end of produce. I will try to fill this container, but just not produce any CRT::Triggers
228  //if there are no input artdaq::Fragments.
229  auto triggers = std::make_unique<std::vector<CRT::Trigger>>();
230 
231  try
232  {
233  //Try to get artdaq::Fragments produced from CRT data. The following line is the reason for
234  //this try-catch block. I don't expect anything else to throw a cet::Exception.
235  const auto& fragHandle = e.getValidHandle<std::vector<artdaq::Fragment>>(fFragTag);
236 
238  {
239  //If this is the first event, set fEarliestTime
240  if(fEarliestTime == std::numeric_limits<decltype(fEarliestTime)>::max())
241  {
242  for(const auto& frag: *fragHandle)
243  {
244  artdaq::ContainerFragment container(frag);
245  for(size_t pos = 0; pos < container.block_count(); ++pos) SetEarliestTime(*container[pos]);
246  }
247  }
248 
249  for(const auto& artFrag: *fragHandle)
250  {
251  artdaq::ContainerFragment container(artFrag);
252  for(size_t pos = 0; pos < container.block_count(); ++pos) FragmentToTriggers(*container[pos], triggers);
253  }
254  }
255  else
256  {
257  //If this is the first event, set fEarliestTime
258  if(fEarliestTime == std::numeric_limits<decltype(fEarliestTime)>::max())
259  {
260  for(const auto& frag: *fragHandle) SetEarliestTime(frag);
261  }
262 
263  //Convert each fragment into a CRT::Trigger.
264  for(const auto& artFrag: *fragHandle) FragmentToTriggers(artFrag, triggers);
265  }
266  }
267  catch(const cet::exception& exc) //If there are no artdaq::Fragments in this Event, just add an empty container of CRT::Triggers.
268  {
269  mf::LogWarning("MissingData") << "No artdaq::Fragments produced by " << fFragTag << " in this event, so "
270  << "not doing anything.\n";
271  }
272 
273  //Put a vector of CRT::Triggers into this Event for other modules to read.
274  e.put(std::move(triggers));
275  }
276 
278  {
279  createSyncPlots();
280 
281  //Set up channel mapping base on user configuration
283  const auto nModules = geom->NAuxDets();
285  {
286 // std::vector<const geo::AuxDetGeo*> auxDets; //The function to retrieve this vector seems to have been made protected
287 // for(size_t auxDet = 0; auxDet < nModules; ++auxDet) auxDets.push_back(&geom->AuxDet(auxDet));
288 //
289 // fChannelMap = CRTSorter::Mapping(auxDets); //Match whatever the current AuxDet sorter does.
290  //Based on v6 geometry (TY)
291  fChannelMap.push_back(24);
292  fChannelMap.push_back(25);
293  fChannelMap.push_back(30);
294  fChannelMap.push_back(18);
295  fChannelMap.push_back(15);
296  fChannelMap.push_back(7);
297  fChannelMap.push_back(13);
298  fChannelMap.push_back(12);
299  fChannelMap.push_back(11);
300  fChannelMap.push_back(10);
301  fChannelMap.push_back(6);
302  fChannelMap.push_back(14);
303  fChannelMap.push_back(19);
304  fChannelMap.push_back(31);
305  fChannelMap.push_back(26);
306  fChannelMap.push_back(27);
307  fChannelMap.push_back(22);
308  fChannelMap.push_back(23);
309  fChannelMap.push_back(29);
310  fChannelMap.push_back(17);
311  fChannelMap.push_back(8);
312  fChannelMap.push_back(0);
313  fChannelMap.push_back(3);
314  fChannelMap.push_back(2);
315  fChannelMap.push_back(5);
316  fChannelMap.push_back(4);
317  fChannelMap.push_back(1);
318  fChannelMap.push_back(9);
319  fChannelMap.push_back(16);
320  fChannelMap.push_back(28);
321  fChannelMap.push_back(20);
322  fChannelMap.push_back(21);
323  }
324  else
325  {
326  for(size_t module = 0; module < nModules; ++module) fChannelMap.push_back(module); //Map each index to itself
327  }
328  }
329 
331  {
332  const auto nModules = art::ServiceHandle<geo::Geometry>()->NAuxDets();
334  fSyncPlots.clear(); //Clear any previous pointers to histograms. Some TFile owned them.
335  for(size_t module = 0; module < nModules; ++module) fSyncPlots.emplace_back(*tfs, module); //32 modules in the ProtoDUNE-SP CRT
336  }
337 
338  /*void CRT::CRTRawDecoder::beginRun(art::Run & r)
339  {
340  // Implementation of optional member function here.
341  }
342 
343  void CRT::CRTRawDecoder::beginSubRun(art::SubRun & sr)
344  {
345  // Implementation of optional member function here.
346  }*/
347 }
348 
PerModule(art::TFileDirectory &parent, const size_t module)
uint64_t fifty_mhz_time() const
Definition: CRTFragment.cc:29
const art::InputTag fFragTag
def mkdir(path, mode=0o777)
std::string string
Definition: nybbler.cc:12
void produce(art::Event &e) override
uint64_t raw_backend_time() const
Definition: CRTFragment.cc:23
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
STL namespace.
size_t num_hits() const
Definition: CRTFragment.cc:17
CRTRawDecoder(fhicl::ParameterSet const &p)
std::vector< PerModule > fSyncPlots
art framework interface to geometry description
bool good_event() const
Definition: CRTFragment.cc:178
const double e
void SetEarliestTime(const artdaq::Fragment &frag)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
def move(depos, offset)
Definition: depos.py:107
std::vector< size_t > fChannelMap
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
CRTRawDecoder & operator=(CRTRawDecoder const &)=delete
void FragmentToTriggers(const artdaq::Fragment &artFrag, std::unique_ptr< std::vector< CRT::Trigger >> &triggers)
static int max(int a, int b)
Detector simulation of raw signals on wires.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
#define MF_LOG_DEBUG(id)
uint16_t module_num() const
Definition: CRTFragment.cc:11
Access the description of detector geometry.
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
def parent(G, child, parent_type)
Definition: graph.py:67
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
unsigned int NAuxDets() const
Returns the number of auxiliary detectors.
const hit_t * hit(const int i) const
Definition: CRTFragment.cc:192