SSPReformatterAlgs.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset: 2; -*-
2 // art includes
3 
6 #include "cetlib/search_path.h"
8 #include <fstream>
9 
10 // lbnecode/daqinput35t includes
11 
12 #include "SSPReformatterAlgs.h"
13 
14 // larsoft includes
15 
17 
18 // lbne-raw-data includes
19 #include "lbne-raw-data/Overlays/SSPFragment.hh"
20 #include "lbne-raw-data/Overlays/anlTypes.hh"
21 
22 
23 
24 //////////////////////////////////////////////////////////////////////////////////////////////////
25 
27  NOvAClockFrequency(pset.get<double>("NOvAClockFrequency")), // in MHz
28  m1(pset.get<int>("SSPm1")),
29  i1(pset.get<int>("SSPi1")),
30  i2(pset.get<int>("SSPi2")),
31  SPESize(pset.get<float>("SPESize"))
32 
33 {
34  BuildOpDetChannelMap(pset.get<std::string>("OpDetChannelMapFile"));
35 }
36 
37 
38 //////////////////////////////////////////////////////////////////////////////////////////////////
39 
40 
41 void DAQToOffline::SSPReformatterAlgs::SSPFragmentToWaveformsAndHits(artdaq::Fragments const& rawFragments,
42  std::vector<raw::OpDetWaveform> &opDetWaveformVector,
43  std::vector<recob::OpHit> &opHitVector)
44 {
45  unsigned int numFragments = rawFragments.size();
46 
47  for (size_t idx = 0; idx < numFragments; ++idx) {
48  const auto& frag(rawFragments[idx]);
49  lbne::SSPFragment sspf(frag);
50 
51  unsigned int nTriggers = CheckAndGetNTriggers(frag, sspf);
52 
53  const unsigned int* dataPointer = sspf.dataBegin();
54 
55 
56  for (unsigned int triggersProcessed = 0;
57  (nTriggers==0 || triggersProcessed < nTriggers) && dataPointer < sspf.dataEnd();
58  ++triggersProcessed) {
59 
60  try {
61  auto daqHeader = GetHeaderAndAdvance(dataPointer);
62  if ( GetWaveformLength(daqHeader) > 0) {
63  // We have a waveform
64  opDetWaveformVector.emplace_back( ConstructWaveformAndAdvance(daqHeader, dataPointer) );
65 
66  }
67  else {
68  // We only have a header
69  opHitVector.emplace_back( ConstructOpHit(daqHeader) );
70  }
71 
72  }
73  catch (cet::exception const&) {
74  continue;
75  }
76  } // End of loop over triggers
77  } // End of loop over fragments (rawFragments)
78 
79 
80 }
81 
82 
83 //////////////////////////////////////////////////////////////////////////////////////////////////
84 
85 std::vector<raw::OpDetWaveform> DAQToOffline::SSPReformatterAlgs::SSPFragmentToOpDetWaveform(artdaq::Fragments const& rawFragments)
86 {
87  std::vector<raw::OpDetWaveform> opDetWaveformVector;
88 
89  unsigned int numFragments = rawFragments.size();
90 
91  for (size_t idx = 0; idx < numFragments; ++idx) {
92  const auto& frag(rawFragments[idx]);
93  lbne::SSPFragment sspf(frag);
94 
95  unsigned int nTriggers = CheckAndGetNTriggers(frag, sspf);
96 
97  const unsigned int* dataPointer = sspf.dataBegin();
98 
99 
100  for (unsigned int triggersProcessed = 0;
101  (nTriggers==0 || triggersProcessed < nTriggers) && dataPointer < sspf.dataEnd();
102  ++triggersProcessed) {
103 
104  try {
105  auto daqHeader = GetHeaderAndAdvance(dataPointer);
106  opDetWaveformVector.emplace_back( ConstructWaveformAndAdvance(daqHeader, dataPointer) );
107  }
108  catch (cet::exception const&) {
109  continue;
110  }
111 
112  } // End of loop over triggers
113  } // End of loop over fragments (rawFragments)
114 
115  return opDetWaveformVector;
116 }
117 
118 //////////////////////////////////////////////////////////////////////////////////////////////////
119 
120 std::vector<recob::OpHit> DAQToOffline::SSPReformatterAlgs::SSPHeaderToOpHit(artdaq::Fragments const& rawFragments)
121 {
122  std::vector<recob::OpHit> opHitVector;
123 
124  unsigned int numFragments = rawFragments.size();
125 
126 
127  for (size_t idx = 0; idx < numFragments; ++idx) {
128  const auto& frag(rawFragments[idx]);
129  lbne::SSPFragment sspf(frag);
130 
131  unsigned int nTriggers = CheckAndGetNTriggers(frag, sspf);
132  const unsigned int* dataPointer = sspf.dataBegin();
133 
134 
135  for (unsigned int triggersProcessed = 0;
136  (nTriggers==0 || triggersProcessed < nTriggers) && dataPointer < sspf.dataEnd();
137  ++triggersProcessed) {
138 
139 
140  try {
141  auto daqHeader = GetHeaderAndAdvance(dataPointer);
142  opHitVector.emplace_back( ConstructOpHit(daqHeader) );
143 
144  // Advance the dataPointer to the next header
145  unsigned int nADC = GetWaveformLength(daqHeader);
146  dataPointer+=nADC/2;
147  }
148  catch (cet::exception const&) {
149  continue;
150  }
151  } // End of loop over triggers
152  } // End of loop over fragments (rawFragments)
153 
154  return opHitVector;
155 }
156 
157 
158 
159 //////////////////////////////////////////////////////////////////////////////////////////////////
160 
161 void DAQToOffline::SSPReformatterAlgs::PrintHeaderInfo(const SSPDAQ::EventHeader *daqHeader)
162 {
163  auto FirstSample = GetGlobalFirstSample(daqHeader);
164  auto InternalSample = GetInternalFirstSample(daqHeader);
165  auto TimeStamp = ((double)FirstSample)/NOvAClockFrequency;
166  auto InternalTimeStamp = ((double)InternalSample)/NOvAClockFrequency;
167 
168  mf::LogDebug("DAQToOffline")
169  << "Header: " << daqHeader->header << "\n"
170  << "Length: " << daqHeader->length << "\n"
171  << "Trigger type: " << ((daqHeader->group1 & 0xFF00) >> 8) << "\n"
172  << "Status flags: " << ((daqHeader->group1 & 0x00F0) >> 4) << "\n"
173  << "Header type: " << ((daqHeader->group1 & 0x000F) >> 0) << "\n"
174  << "Trigger ID: " << daqHeader->triggerID << "\n"
175  << "Module ID: " << ((daqHeader->group2 & 0xFFF0) >> 4) << "\n"
176  << "Channel ID: " << ((daqHeader->group2 & 0x000F) >> 0) << "\n"
177  << "OpChannel: " << GetOpChannel(daqHeader) << "\n"
178  << "External (NOvA) timestamp: " << FirstSample << " ticks" << "\n"
179  << " " << TimeStamp << " microseconds" << "\n"
180  // these first_ ouptuts are a little ill-defined anyway since they are not
181  // reset by run but rather with the job
182  //<< "Since first sample this run: " << FirstSample-first_FirstSample << " ticks" << "\n"
183  //<< " " << TimeStamp-first_TimeStamp << " microseconds" << "\n"
184  << "Peak sum: " << GetPeakSum(daqHeader) << "\n"
185  << "Peak time: " << GetPeakTime(daqHeader) << "\n"
186 
187  << "Baseline Sum (Prerise): " << GetBaselineSum(daqHeader) << "\n"
188  << "Integrated sum: " << GetIntegratedSum(daqHeader) << "\n"
189  << "Baseline: " << daqHeader->baseline << "\n"
190  << "CFD Timestamp interpolation points: " << daqHeader->cfdPoint[0] << " " << daqHeader->cfdPoint[1]
191  << " " << daqHeader->cfdPoint[2] << " " << daqHeader->cfdPoint[3] << "\n"
192  << "Internal interpolation point: " << daqHeader->intTimestamp[0] << "\n"
193  << "Internal timestamp: " << InternalSample << " ticks\n"
194  << " " << InternalTimeStamp << " microseconds" << "\n"
195  //<< "Relative internal timestamp: " << InternalSample-first_InternalSample << " ticks" << "\n"
196  //<< " " << InternalTimeStamp-first_InternalTimeStamp << " microseconds"
197  << "" ;
198 
199 }
200 
201 
202 
203 //////////////////////////////////////////////////////////////////////////////////////////////////
204 
205 
206 unsigned int DAQToOffline::SSPReformatterAlgs::CheckAndGetNTriggers(const artdaq::Fragment& frag, const lbne::SSPFragment sspf)
207 {
208  mf::LogDebug("DAQToOffline") << "\n"
209  << "SSP fragment " << frag.fragmentID()
210  << " has total size: " << sspf.hdr_event_size()
211  << " and run number: " << sspf.hdr_run_number()
212  << " with " << sspf.total_adc_values() << " total ADC values"
213  << "\n"
214  << "\n";
215 
216  const SSPDAQ::MillisliceHeader* meta=0;
217  //get the information from the header
218  if(frag.hasMetadata())
219  {
220  meta = &(frag.metadata<lbne::SSPFragment::Metadata>()->sliceHeader);
221 
222  mf::LogInfo("DAQToOffline")
223  << "===Slice metadata====" << "\n"
224  << " Start time " << meta->startTime << "\n"
225  << " End time " << meta->endTime << "\n"
226  << " Packet length " << meta->length << "\n"
227  << " Number of triggers " << meta->nTriggers << "\n"
228  << "=====================";
229  }
230  else
231  {
232  mf::LogWarning("DAQToOffline") << "SSP fragment has no metadata associated with it.";
233  }
234 
235  // No metadata, no trigger count
236  if (meta == 0) return 0;
237 
238  return meta->nTriggers;
239 }
240 
241 
242 //////////////////////////////////////////////////////////////////////////////////////////////////
243 
244 
246 {
247  theChannelMap.clear();
248 
249  int onlineChannel;
250  int offlineChannel;
251 
252  std::string fullname;
253  cet::search_path sp("FW_SEARCH_PATH");
254  sp.find_file(fChannelMapFile, fullname);
255 
256  if ( fullname.empty() ) {
257  mf::LogWarning("DAQToOffline") << "Input spectrum file "
258  << fChannelMapFile
259  << " not found in FW_SEARCH_PATH, using debugging map!\n";
260  }
261  else {
262  mf::LogVerbatim("DAQToOffline") << "Build Online->Offline channel Map from " << fullname;
263  std::ifstream infile(fullname);
264  while (infile.good()) {
265  infile >> onlineChannel >> offlineChannel;
266  theChannelMap[onlineChannel] = offlineChannel;
267  mf::LogVerbatim("DAQToOffline") << " " << onlineChannel << " -> " << offlineChannel;
268  }
269  }
270 
271 }
272 
273 
274 //////////////////////////////////////////////////////////////////////////////////////////////////
275 
276 const SSPDAQ::EventHeader* DAQToOffline::SSPReformatterAlgs::GetHeaderAndAdvance(const unsigned int* &dataPointer)
277 {
278  // Load the event header, advance the pointer
279  const SSPDAQ::EventHeader* daqHeader=reinterpret_cast<const SSPDAQ::EventHeader*>(dataPointer);
280  dataPointer += sizeof(SSPDAQ::EventHeader)/sizeof(unsigned int);
281  return daqHeader;
282 }
283 
284 
285 
286 //////////////////////////////////////////////////////////////////////////////////////////////////
287 
288 
289 uint32_t DAQToOffline::SSPReformatterAlgs::GetPeakSum(const SSPDAQ::EventHeader* daqHeader)
290 {
291  uint32_t peaksum = ((daqHeader->group3 & 0x00FF) >> 16) + daqHeader->peakSumLow;
292  if(peaksum & 0x00800000) {
293  peaksum |= 0xFF000000;
294  }
295  return peaksum;
296 }
297 
298 
299 
300 //////////////////////////////////////////////////////////////////////////////////////////////////
301 
302 
303 unsigned short DAQToOffline::SSPReformatterAlgs::GetOpChannel(const SSPDAQ::EventHeader* daqHeader)
304 {
305  unsigned short OpChannel = -1;
306 
307  // Extract values we need for the data product
308  if ( theChannelMap.size() == 0) {
309  // No channel map, default to debugging map
310  int HardwareChannel = ((daqHeader->group2 & 0x000F) >> 0); // Channel Number
311  int SSPNumber = ((daqHeader->group2 & 0x00F0) >> 4); // Module Number
312  OpChannel = 100*SSPNumber + HardwareChannel;
313  }
314  else if ( theChannelMap.find(daqHeader->group2) != theChannelMap.end() ) {
315  OpChannel = theChannelMap[daqHeader->group2];
316  }
317  else {
318  int HardwareChannel = ((daqHeader->group2 & 0x000F) >> 0); // Channel Number
319  int SSPNumber = ((daqHeader->group2 & 0x00F0) >> 4); // Module Number
320  mf::LogWarning("DAQToOffline") << "SSP " << SSPNumber << " Channel " << HardwareChannel
321  << "(" << daqHeader->group2 << ") "
322  << " not in the map (OK for uninstrumented channels), skipping." << std::endl;
323  throw cet::exception( "SSP Channel Invalid" );
324  }
325 
326  return OpChannel;
327 }
328 
329 
330 //////////////////////////////////////////////////////////////////////////////////////////////////
331 
332 
333 unsigned long DAQToOffline::SSPReformatterAlgs::GetGlobalFirstSample(const SSPDAQ::EventHeader* daqHeader)
334 {
335  return ( ( (unsigned long)daqHeader->timestamp[3] << 48 )
336  + ( (unsigned long)daqHeader->timestamp[2] << 32 )
337  + ( (unsigned long)daqHeader->timestamp[1] << 16 )
338  + ( (unsigned long)daqHeader->timestamp[0] ) );
339 }
340 
341 
342 //////////////////////////////////////////////////////////////////////////////////////////////////
343 
344 
345 unsigned long DAQToOffline::SSPReformatterAlgs::GetInternalFirstSample(const SSPDAQ::EventHeader *daqHeader)
346 {
347  return ( ((uint64_t)((uint64_t)daqHeader->intTimestamp[3] << 32))
348  + ((uint64_t)((uint64_t)daqHeader->intTimestamp[2]) << 16)
349  + ((uint64_t)((uint64_t)daqHeader->intTimestamp[1])) );
350 }
351 
352 
353 //////////////////////////////////////////////////////////////////////////////////////////////////
354 
355 unsigned long DAQToOffline::SSPReformatterAlgs::GetBaselineSum(const SSPDAQ::EventHeader *daqHeader)
356 {
357  return ((daqHeader->group4 & 0x00FF) << 16) + daqHeader->preriseLow;
358 
359 }
360 
361 //////////////////////////////////////////////////////////////////////////////////////////////////
362 
363 unsigned long DAQToOffline::SSPReformatterAlgs::GetIntegratedSum(const SSPDAQ::EventHeader *daqHeader)
364 {
365  return ((unsigned int)(daqHeader->intSumHigh) << 8) + (((unsigned int)(daqHeader->group4) & 0xFF00) >> 8);
366 }
367 
368 //////////////////////////////////////////////////////////////////////////////////////////////////
369 
370 unsigned int DAQToOffline::SSPReformatterAlgs::GetPeakTime(const SSPDAQ::EventHeader *daqHeader)
371 {
372  return (daqHeader->group3 & 0xFF00) >> 8 ;
373 }
374 
375 
376 //////////////////////////////////////////////////////////////////////////////////////////////////
377 
378 unsigned int DAQToOffline::SSPReformatterAlgs::GetWaveformLength(const SSPDAQ::EventHeader *daqHeader)
379 {
380  unsigned int nADC=(daqHeader->length-sizeof(SSPDAQ::EventHeader)/sizeof(unsigned int))*2;
381  return nADC;
382 }
383 
384 
385 //////////////////////////////////////////////////////////////////////////////////////////////////
386 
388  const unsigned int* &dataPointer)
389 {
390 
391  // Get basic information from the header
392  unsigned short OpChannel = GetOpChannel(daqHeader); ///< Derived Optical channel
393  unsigned long FirstSample = GetGlobalFirstSample(daqHeader); ///< first sample time in ticks
394  double TimeStamp = ((double)FirstSample)/NOvAClockFrequency; ///< first sample time in microseconds
395 
396  // Print some debugging info
397  PrintHeaderInfo(daqHeader);
398 
399  // Get ADC Count, create pointer to adcs
400  unsigned int nADC = GetWaveformLength(daqHeader);
401  const unsigned short* adcPointer = reinterpret_cast<const unsigned short*>(dataPointer);
402 
403  // Initialize the waveform
404  raw::OpDetWaveform Waveform(TimeStamp, OpChannel, nADC);
405 
406  // Build up the waveform
407  for(size_t idata = 0; idata < nADC; idata++) {
408  const unsigned short* adc = adcPointer + idata;
409  Waveform.push_back(*adc);
410  }
411 
412  // Advance the dataPointer to the next header
413  dataPointer+=nADC/2;
414 
415  return Waveform;
416 }
417 
418 
419 //////////////////////////////////////////////////////////////////////////////////////////////////
420 
422 {
423  // Get basic information from the header
424  unsigned short OpChannel = GetOpChannel(daqHeader); ///< Derived Optical channel
425  unsigned long FirstSample = GetGlobalFirstSample(daqHeader);; ///< first sample time in ticks
426  double TimeStamp = ((double)FirstSample)/NOvAClockFrequency; ///< first sample time in microseconds
427 
428  auto const* ts = lar::providerFrom<detinfo::DetectorClocksService>();
429 
430  double peakTime = ((double)GetPeakTime(daqHeader)) * ts->OpticalClock().TickPeriod(); // microseconds
431  double width = ((double)i1) * ts->OpticalClock().TickPeriod(); // microseconds
432 
433  double pedestal = ((double)GetBaselineSum(daqHeader)) / ((double)i1);
434  double area = ((double)GetIntegratedSum(daqHeader)) - pedestal * i2;
435  double peak = ((double)GetPeakSum(daqHeader)) / ((double)m1) - pedestal;
436 
437 
438  recob::OpHit ophit(OpChannel,
439  TimeStamp+peakTime, // Relative Time
440  TimeStamp+peakTime, // Absolute time
441  0, // Frame, not used by DUNE
442  width,
443  area,
444  peak,
445  area / SPESize, // PE
446  0.);
447 
448  return ophit;
449 }
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
recob::OpHit ConstructOpHit(const SSPDAQ::EventHeader *daqHeader)
Construct an OpHit object from the daqHeader.
uint32_t GetPeakSum(const SSPDAQ::EventHeader *daqHeader)
unsigned int GetPeakTime(const SSPDAQ::EventHeader *daqHeader)
void SSPFragmentToWaveformsAndHits(artdaq::Fragments const &rawFragments, std::vector< raw::OpDetWaveform > &opDetWaveformVector, std::vector< recob::OpHit > &opHitVector)
SSPReformatterAlgs(fhicl::ParameterSet const &pset)
raw::OpDetWaveform ConstructWaveformAndAdvance(const SSPDAQ::EventHeader *daqHeader, const unsigned int *&dataPointer)
Construct a waveform from the adc vector, advance the data pointer when done.
std::vector< T > Waveform
Definition: IWaveformTool.h:21
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
unsigned int CheckAndGetNTriggers(const artdaq::Fragment &frag, const lbne::SSPFragment sspf)
Load the milislice.
unsigned long GetInternalFirstSample(const SSPDAQ::EventHeader *daqHeader)
unsigned int GetWaveformLength(const SSPDAQ::EventHeader *daqHeader)
const SSPDAQ::EventHeader * GetHeaderAndAdvance(const unsigned int *&dataPointer)
Load the header.
unsigned long GetBaselineSum(const SSPDAQ::EventHeader *daqHeader)
string infile
unsigned int uint32_t
Definition: stdint.h:126
unsigned long GetIntegratedSum(const SSPDAQ::EventHeader *daqHeader)
unsigned long GetGlobalFirstSample(const SSPDAQ::EventHeader *daqHeader)
T get(std::string const &key) const
Definition: ParameterSet.h:231
unsigned __int64 uint64_t
Definition: stdint.h:136
std::vector< recob::OpHit > SSPHeaderToOpHit(artdaq::Fragments const &raw)
unsigned short GetOpChannel(const SSPDAQ::EventHeader *daqHeader)
void BuildOpDetChannelMap(std::string fChannelMapFile)
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::string find_file(std::string const &filename) const
Definition: search_path.cc:94
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
void PrintHeaderInfo(const SSPDAQ::EventHeader *daqHeader)
Print out header information.
std::vector< raw::OpDetWaveform > SSPFragmentToOpDetWaveform(artdaq::Fragments const &raw)
Construct a waveform from each trigger.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)