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