LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
LArRawInputDriverLongBo.cxx
Go to the documentation of this file.
1 
9 
14 
24 #include "cetlib_except/coded_exception.h"
25 #include "cetlib_except/exception.h"
26 
27 #include <algorithm>
28 #include <fstream>
29 #include <stdlib.h>
30 #include <time.h>
31 
32 extern "C" {
33 #include <dirent.h>
34 }
35 
36 // ======================================================================
37 // LongBo DAQ480 interface, adapted from code by Rebel/Soderberg:
38 // modified M. Stancari Jan 4, 2013
39 namespace {
40 
41  //Define Structures corresponding to Binary data file.
42 
43  // ======================================================================
44  struct header {
45  int fixed; //Fixed 32-bit word with value: 0x0000D480
46  unsigned short format; //File Format Version. 16-bit word. Currently = 0x0001
47  unsigned short software; //DAQ480 Software Version. 16-bit word. Currently 0x0600 (v6.0)
48  unsigned short run; //16-bit word.
49  unsigned short event; //16-bit word.
50  int time; //Event timestamp. Coordinated Universal Time. 32-bit word.
51  short spare; //Spare 16-bit word. Currently 0x0000
52  unsigned short nchan; //Total # of channels in readout. 16-bit word.
53  };
54 
55  // ======================================================================
56  struct channel {
57  unsigned short ch; //Channel #. 16-bit word.
58  unsigned short samples; //# samples for this channel. 16-bit word.
59  };
60 
61  // ======================================================================
62  struct footer {
63  int spare; //Spare 32-bit word. Currently 0x00000000
64  int checksum; //Reserved for checksum. 32-bit word. Currently 0x00000000
65  };
66 
67  // ======================================================================
68  int run(std::string s1)
69  {
70  size_t p1 = s1.find("R");
71  size_t p2 = s1.find("_E");
72 
73  int run = atoi((s1.substr(p1 + 1, p2 - p1 - 1)).c_str());
74  return run;
75  }
76 
77  // ======================================================================
78  int event(std::string s1)
79  {
80  size_t p1 = s1.find("E");
81  size_t p2 = s1.find("_T");
82 
83  int event = atoi((s1.substr(p1 + 1, p2 - p1 - 1)).c_str());
84  return event;
85  }
86 
87  // ======================================================================
88  bool compare(std::string s1, std::string s2)
89  {
90  int r1 = run(s1);
91  int r2 = run(s2);
92  int e1 = event(s1);
93  int e2 = event(s2);
94 
95  return r1 == r2 ? e1 < e2 : r1 < r2;
96  }
97 
98  // ======================================================================
99  std::vector<std::string> getsortedfiles(std::string dir)
100  {
101  if (dir == "")
102  throw art::Exception(art::errors::Configuration) << "Vacuous directory name" << std::endl;
103 
104  std::vector<std::string> files;
105 
106  DIR* dp = NULL;
107  if ((dp = opendir(dir.c_str())) == NULL) {
109  << "Error opening directory " << dir << std::endl;
110  }
111 
112  dirent* dirp = NULL;
113  while ((dirp = readdir(dp)) != NULL) {
114  std::string filename(dirp->d_name);
115  if (filename.find("bin") != std::string::npos) { files.push_back(filename); }
116  }
117  closedir(dp);
118 
119  sort(files.begin(), files.end(), compare);
120 
121  return files;
122  } // getsortedfiles()
123 
124  struct EventFileSentry {
125  // Use RAII (Resource Acquisition Is Initialization)
126  explicit EventFileSentry(std::string const& filepath)
127  : infile(filepath.c_str(), std::ios_base::in | std::ios_base::binary)
128  {}
129  ~EventFileSentry() { infile.close(); }
130 
131  std::ifstream infile;
132  };
133 
134  // ======================================================================
135  void process_LAr_file(std::string dir,
136  std::string const& filename,
137  std::vector<raw::RawDigit>& digitList,
138  raw::DAQHeader& daqHeader,
139  std::vector<raw::ExternalTrigger>& extTrig)
140  {
141  // Prepare the input file. The sentry is responsible for making the
142  // file stream object, and will *automatically* close it when it
143  // goes out of scope *for any reason*, including normal function
144  // exit or exception throw.
145  EventFileSentry efs(dir + "/" + filename);
146  std::ifstream& infile = efs.infile;
147 
148  if (!infile.is_open()) {
150  << "failed to open input file " << filename << std::endl;
151  }
152 
154  unsigned int wiresPerPlane = 48;
155  unsigned int planes = 3;
156  int nwires = wiresPerPlane * planes;
157 
158  header h1;
159  channel c1;
160  // footer f1;
161 
162  //read in header section of file
163  infile.read((char*)&h1, sizeof h1);
164 
165  time_t mytime = h1.time;
166  mytime = mytime << 32; //Nov. 2, 2010 - "time_t" is a 64-bit word on many 64-bit machines
167  //so we had to change types in header struct to read in the correct
168  //number of bits. Once we have the 32-bit timestamp from the binary
169  //data, shift it up to the upper half of the 64-bit timestamp. - Mitch
170 
171  // std::cout << "Fixed Value (0x0000D480): " << std::hex << h1.fixed << std::endl;
172  // std::cout << "Output Format: " << std::hex << h1.format << std::endl;
173  // std::cout << "Software Version: " << std::hex << h1.software << std::dec << std::endl;
174  // std::cout << "Run " << std::setw(6) << std::left << h1.run
175  // << "Event " << std::setw(8) << std::left << h1.event
176  // << "h1.time " << std::setw(8) << std::left << h1.time;
177  // std::cout << " #Channels = " << h1.nchan << std::endl;
178 
179  daqHeader.SetStatus(1);
180  daqHeader.SetFixedWord(h1.fixed);
181  daqHeader.SetFileFormat(h1.format);
182  daqHeader.SetSoftwareVersion(h1.software);
183  daqHeader.SetRun(h1.run);
184  daqHeader.SetEvent(h1.event);
185  daqHeader.SetTimeStamp(mytime);
186  daqHeader.SetSpareWord(h1.spare);
187  daqHeader.SetNChannels(h1.nchan);
188 
189  //one digit for every wire on each plane
190  digitList.clear();
191  digitList.resize(wiresPerPlane * planes);
192 
193  //16 external trigger inputs
194  extTrig.clear();
195  extTrig.resize(16);
196 
197  for (int i = 0; i != nwires; ++i) {
198  infile.read((char*)&c1, sizeof c1);
199  //Create vector for ADC data, with correct number of samples for this event
200  std::vector<short> adclist(c1.samples);
201  infile.read((char*)&adclist[0], sizeof(short) * c1.samples);
202  // std::cout << "Channel = " << c1.ch ;
203  // std::cout << " #Samples = " << c1.samples ;
204  // std::cout << " ADC[0] = " << adclist[0] << " ADC[2047] = " << adclist[2047] << std::endl;
205 
206  // set signal to be 400 if it is 0 (bad pedestal)
207  for (int ijk = 0; ijk < c1.samples; ++ijk) {
208  if (std::abs(adclist[ijk]) < 1e-5) adclist[ijk] += 400;
209  }
210 
211  // invert the signals from the BNL ASIC
212  if (i > 63 && i < 80) {
213  for (int ijk = 0; ijk < c1.samples; ++ijk) {
214  int mysig = adclist[ijk] - 400;
215  adclist[ijk] = 400 - mysig;
216  }
217  }
218 
219  if (i < 96) {
220  // digitList[i] = raw::RawDigit((c1.ch-1), c1.samples, adclist);//subtract one from ch. number...
221  digitList[i] = raw::RawDigit(i, c1.samples, adclist); //subtract one from ch. number...
222  //hence offline channels will always be one lower
223  //than the DAQ480 definition. - mitch 7/8/2009
224  digitList[i].SetPedestal(400.); //carl b assures me this will never change. bjr 4/15/2009
225  }
226  else { //flip collection wires to be consistent with offline geometry. TYang 12/23/2013
227  digitList[239 - i] = raw::RawDigit(239 - i, c1.samples, adclist);
228  digitList[239 - i].SetPedestal(
229  400.); //carl b assures me this will never change. bjr 4/15/2009
230  }
231  }
232 
233  //
234  // MStancari, TYang - Apr 4 2013
235  //
236  // Add trigger information to the record
237 
238  unsigned int ichan;
239  for (int i = 0; i < 16; ++i) {
240  unsigned int utrigtime = 0;
241  infile.read((char*)&c1, sizeof c1);
242  //Create vector for ADC data, with correct number of samples for this event
243  std::vector<short> adclist(c1.samples);
244  infile.read((char*)&adclist[0], sizeof(short) * c1.samples);
245 
246  int j = 0;
247  while (j < c1.samples) {
248  float test = 400.0 - adclist[j];
249  if (test > 10 && j > 0) {
250  utrigtime = j;
251  break;
252  }
253  j++;
254  }
255  ichan = i + 144;
256  extTrig[i] = raw::ExternalTrigger(ichan, utrigtime);
257  }
258 
259  // infile will be closed automatically as EventFileSentry goes out of scope.
260  } // process_LAr_file
261 
262 } // namespace
263 
264 namespace lris {
265  // ======================================================================
266  // class c'tor/d'tor:
267  LArRawInputDriverLongBo::LArRawInputDriverLongBo(fhicl::ParameterSet const&, // Not used
269  art::SourceHelper const& pm)
270  : principalMaker_(pm)
271  , currentDir_()
272  , inputfiles_()
273  , nextfile_(inputfiles_.begin())
274  , filesdone_(inputfiles_.end())
275  , currentSubRunID_()
276  {
277  helper.reconstitutes<raw::DAQHeader, art::InEvent>("daq");
278  helper.reconstitutes<std::vector<raw::RawDigit>, art::InEvent>("daq");
279  helper.reconstitutes<std::vector<raw::ExternalTrigger>, art::InEvent>("daq");
280  helper.reconstitutes<sumdata::RunData, art::InRun>("daq");
281  }
282 
284  {
285  // Nothing to do (See EventFileSentry).
286  }
287 
288  void LArRawInputDriverLongBo::readFile(std::string const& name, art::FileBlock*& fb)
289  {
290  // Get the list of event files for this directory.
291  currentDir_ = name;
292  inputfiles_ = getsortedfiles(currentDir_);
293  nextfile_ = inputfiles_.begin();
294  filesdone_ = inputfiles_.end();
296 
297  // Fill and return a new Fileblock.
298  fb = new art::FileBlock(art::FileFormatVersion(1, "LArRawInput 2011a"), currentDir_);
299  }
300 
302  art::SubRunPrincipal* const& /* inSR */,
303  art::RunPrincipal*& outR,
304  art::SubRunPrincipal*& outSR,
305  art::EventPrincipal*& outE)
306  {
307  if (inputfiles_.empty() || nextfile_ == filesdone_) return false;
308 
309  // Create empty result, then fill it from current filename:
310  std::unique_ptr<std::vector<raw::RawDigit>> rdcollb(new std::vector<raw::RawDigit>);
311  std::unique_ptr<std::vector<raw::ExternalTrigger>> etcollb(
312  new std::vector<raw::ExternalTrigger>);
313 
314  raw::DAQHeader daqHeader;
315  bool firstEventInRun = (nextfile_ == inputfiles_.begin());
316 
317  process_LAr_file(currentDir_, *nextfile_++, *rdcollb, daqHeader, *etcollb);
318  std::unique_ptr<raw::DAQHeader> daqcollb(new raw::DAQHeader(daqHeader));
319 
320  art::RunNumber_t rn = daqHeader.GetRun();
321  art::Timestamp tstamp = daqHeader.GetTimeStamp();
322 
323  if (firstEventInRun) {
324  std::unique_ptr<sumdata::RunData> rundata(new sumdata::RunData("bo"));
326  outR = principalMaker_.makeRunPrincipal(rn, tstamp);
328  art::put_product_in_principal(std::move(rundata), *outR, "daq");
329  }
330  else if (rn != currentSubRunID_.run()) {
331  throw cet::exception("InconsistentEventStream")
332  << "Encountered run #" << rn << " while processing events from run #"
333  << currentSubRunID_.run() << "\n";
334  }
335 
337  currentSubRunID_.run(), currentSubRunID_.subRun(), daqHeader.GetEvent(), tstamp);
338 
339  // Put products in the event.
340  art::put_product_in_principal(std::move(etcollb), *outE,
341  "daq"); // Module label
342  art::put_product_in_principal(std::move(rdcollb), *outE,
343  "daq"); // Module label
344  art::put_product_in_principal(std::move(daqcollb), *outE,
345  "daq"); // Module label
346 
347  return true;
348  }
349 
350 }
void SetSpareWord(short s)
Definition: DAQHeader.h:117
Collection of charge vs time digitized from a single readout channel.
Definition: RawDigit.h:68
void SetRun(unsigned short i)
Definition: DAQHeader.h:101
SubRunPrincipal * makeSubRunPrincipal(SubRunAuxiliary subRunAux) const
void SetTimeStamp(time_t t)
Definition: DAQHeader.h:113
EventPrincipal * makeEventPrincipal(EventAuxiliary eventAux) const
constexpr auto abs(T v)
Returns the absolute value of the argument.
stringvec_t::const_iterator nextfile_
STL namespace.
Definition of basic raw digits.
art::SourceHelper const & principalMaker_
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
TypeLabel const & reconstitutes(std::string const &modLabel, std::string const &instanceName={})
TCanvas * c1
Definition: plotHisto.C:7
RunNumber_t run() const
Definition: SubRunID.h:85
void SetNChannels(uint32_t i)
Definition: DAQHeader.h:121
TFile fb("Li6.root")
void readFile(std::string const &name, art::FileBlock *&fb)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
ifstream in
Definition: comparison.C:7
RunPrincipal * makeRunPrincipal(RunAuxiliary runAux) const
Definition: SourceHelper.cc:89
std::enable_if_t<!detail::range_sets_supported(P::branch_type)> put_product_in_principal(std::unique_ptr< T > &&product, P &principal, std::string const &module_label, std::string const &instance_name={})
TDirectory * dir
Definition: macro.C:5
Conversion of binary data to root files.
void SetFixedWord(int i)
Definition: DAQHeader.h:89
bool readNext(art::RunPrincipal *const &inR, art::SubRunPrincipal *const &inSR, art::RunPrincipal *&outR, art::SubRunPrincipal *&outSR, art::EventPrincipal *&outE)
unsigned short GetRun() const
Definition: DAQHeader.h:141
TH1F * h1
Definition: plot.C:41
unsigned short GetEvent() const
Definition: DAQHeader.h:149
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
SubRunNumber_t subRun() const
Definition: SubRunID.h:91
stringvec_t::const_iterator filesdone_
Float_t e
Definition: plot.C:35
void SetSoftwareVersion(unsigned short i)
Definition: DAQHeader.h:97
void SetEvent(unsigned short i)
Definition: DAQHeader.h:109
void SetStatus(unsigned int i)
Definition: DAQHeader.h:85
void SetFileFormat(unsigned short i)
Definition: DAQHeader.h:93
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
time_t GetTimeStamp() const
Definition: DAQHeader.h:153
Event finding and building.
IDNumber_t< Level::Run > RunNumber_t
Definition: IDNumber.h:120