LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
LArRawInputDriver.cxx
Go to the documentation of this file.
1 
9 
19 #include "cetlib_except/coded_exception.h"
20 
24 
25 #include <algorithm>
26 #include <fstream>
27 #include <memory>
28 #include <ostream>
29 #include <stdlib.h>
30 #include <time.h>
31 
32 extern "C" {
33 #include <dirent.h>
34 }
35 
36 // ======================================================================
37 // ArgoNeuT DAQ480 interface, adapted from code by Rebel/Soderberg:
38 
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  {
140  // Prepare the input file. The sentry is responsible for making the
141  // file stream object, and will *automatically* close it when it
142  // goes out of scope *for any reason*, including normal function
143  // exit or exception throw.
144  EventFileSentry efs(dir + "/" + filename);
145  std::ifstream& infile = efs.infile;
146 
147  if (!infile.is_open()) {
149  << "failed to open input file " << filename << std::endl;
150  }
151 
152  unsigned int wiresPerPlane = 240;
153  unsigned int planes = 2;
154 
155  header h1;
156  channel c1;
157  footer f1;
158 
159  //read in header section of file
160  infile.read((char*)&h1, sizeof h1);
161 
162  time_t mytime = h1.time;
163  mytime = mytime << 32; //Nov. 2, 2010 - "time_t" is a 64-bit word on many 64-bit machines
164  //so we had to change types in header struct to read in the correct
165  //number of bits. Once we have the 32-bit timestamp from the binary
166  //data, shift it up to the upper half of the 64-bit timestamp. - Mitch
167 
168  // std::cout << "Fixed Value (0x0000D480): " << std::hex << h1.fixed << std::endl;
169  // std::cout << "Output Format: " << std::hex << h1.format << std::endl;
170  // std::cout << "Software Version: " << std::hex << h1.software << std::dec << std::endl;
171  // std::cout << "Run " << std::setw(6) << std::left << h1.run
172  // << "Event " << std::setw(8) << std::left << h1.event
173  // << "h1.time " << std::setw(8) << std::left << h1.time;
174  // std::cout << " #Channels = " << h1.nchan << std::endl;
175 
176  daqHeader.SetStatus(1);
177  daqHeader.SetFixedWord(h1.fixed);
178  daqHeader.SetFileFormat(h1.format);
179  daqHeader.SetSoftwareVersion(h1.software);
180  daqHeader.SetRun(h1.run);
181  daqHeader.SetEvent(h1.event);
182  daqHeader.SetTimeStamp(mytime);
183  daqHeader.SetSpareWord(h1.spare);
184  daqHeader.SetNChannels(h1.nchan);
185 
186  //one digit for every wire on each plane
187  digitList.clear();
188  digitList.resize(wiresPerPlane * planes);
189 
190  for (int i = 0; i != h1.nchan; ++i) {
191  infile.read((char*)&c1, sizeof c1);
192  //Create vector for ADC data, with correct number of samples for this event
193  std::vector<short> adclist(c1.samples);
194  infile.read((char*)&adclist[0], sizeof(short) * c1.samples);
195  // std::cout << "Channel = " << c1.ch ;
196  // std::cout << " #Samples = " << c1.samples ;
197  // std::cout << " ADC[0] = " << adclist[0] << " ADC[2047] = " << adclist[2047] << std::endl;
198 
199  digitList[i] =
200  raw::RawDigit((c1.ch - 1), c1.samples, adclist); //subtract one from ch. number...
201  //hence offline channels will always be one lower
202  //than the DAQ480 definition. - mitch 7/8/2009
203  digitList[i].SetPedestal(400.); //carl b assures me this will never change. bjr 4/15/2009
204  }
205  //read in footer section of file...though it's currently empty.
206  infile.read((char*)&f1, sizeof f1);
207 
208  // infile will be closed automatically as EventFileSentry goes out of scope.
209  } // process_LAr_file
210 
211 } // namespace
212 
213 namespace lris {
214  // ======================================================================
215  // class c'tor/d'tor:
216  LArRawInputDriver::LArRawInputDriver(fhicl::ParameterSet const&, // Not used
218  art::SourceHelper const& pm)
219  : principalMaker_(pm)
220  , currentDir_()
221  , inputfiles_()
222  , nextfile_(inputfiles_.begin())
223  , filesdone_(inputfiles_.end())
224  , currentSubRunID_()
225  {
226  helper.reconstitutes<raw::DAQHeader, art::InEvent>("daq");
227  helper.reconstitutes<std::vector<raw::RawDigit>, art::InEvent>("daq");
228  helper.reconstitutes<sumdata::RunData, art::InRun>("daq");
229  }
230 
232  {
233  // Nothing to do (See EventFileSentry).
234  }
235 
236  void LArRawInputDriver::readFile(std::string const& name, art::FileBlock*& fb)
237  {
238  // Get the list of event files for this directory.
239  currentDir_ = name;
240  inputfiles_ = getsortedfiles(currentDir_);
241  nextfile_ = inputfiles_.begin();
242  filesdone_ = inputfiles_.end();
244 
245  // Fill and return a new Fileblock.
246  fb = new art::FileBlock(art::FileFormatVersion(1, "LArRawInput 2011a"), currentDir_);
247  }
248 
250  art::SubRunPrincipal* const& /* inSR */,
251  art::RunPrincipal*& outR,
252  art::SubRunPrincipal*& outSR,
253  art::EventPrincipal*& outE)
254  {
255  if (inputfiles_.empty() || nextfile_ == filesdone_) return false;
256 
257  // Create empty result, then fill it from current filename:
258  std::unique_ptr<std::vector<raw::RawDigit>> rdcol(new std::vector<raw::RawDigit>);
259 
260  raw::DAQHeader daqHeader;
261  bool firstEventInRun = (nextfile_ == inputfiles_.begin());
262 
263  process_LAr_file(currentDir_, *nextfile_++, *rdcol, daqHeader);
264  std::unique_ptr<raw::DAQHeader> daqcol(new raw::DAQHeader(daqHeader));
265 
266  art::RunNumber_t rn = daqHeader.GetRun();
267  art::Timestamp tstamp = daqHeader.GetTimeStamp();
268 
269  if (firstEventInRun) {
270  std::unique_ptr<sumdata::RunData> rundata(new sumdata::RunData("argoneut"));
272  outR = principalMaker_.makeRunPrincipal(rn, tstamp);
274  art::put_product_in_principal(std::move(rundata), *outR, "daq");
275  }
276  else if (rn != currentSubRunID_.run()) {
277  throw cet::exception("InconsistentEventStream")
278  << "Encountered run #" << rn << " while processing events from run #"
279  << currentSubRunID_.run() << "\n";
280  }
281 
283  currentSubRunID_.run(), currentSubRunID_.subRun(), daqHeader.GetEvent(), tstamp);
284 
285  // Put products in the event.
286  art::put_product_in_principal(std::move(rdcol), *outE,
287  "daq"); // Module label
288  art::put_product_in_principal(std::move(daqcol), *outE,
289  "daq"); // Module label
290 
291  return true;
292  }
293 
294 }
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
art::SubRunID currentSubRunID_
SubRunPrincipal * makeSubRunPrincipal(SubRunAuxiliary subRunAux) const
void readFile(std::string const &name, art::FileBlock *&fb)
void SetTimeStamp(time_t t)
Definition: DAQHeader.h:113
stringvec_t::const_iterator nextfile_
EventPrincipal * makeEventPrincipal(EventAuxiliary eventAux) const
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
Source to convert raw binary files to root files.
Float_t f1
stringvec_t::const_iterator filesdone_
void SetNChannels(uint32_t i)
Definition: DAQHeader.h:121
TFile fb("Li6.root")
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.
bool readNext(art::RunPrincipal *const &inR, art::SubRunPrincipal *const &inSR, art::RunPrincipal *&outR, art::SubRunPrincipal *&outSR, art::EventPrincipal *&outE)
void SetFixedWord(int i)
Definition: DAQHeader.h:89
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
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