IcebergDataInterfaceFELIXBufferMarch2021_tool.cc
Go to the documentation of this file.
1 // IcebergDataInterfaceFELIXBufferMarch2021_tool.cc
2 
4 #include "TMath.h"
5 #include "TString.h"
6 #include <iostream>
7 #include <set>
9 
11 
12 // artdaq and dune-raw-data includes
14 
16 {
17  fInputFiles = p.get<std::vector<std::string>>("InputFiles");
18  fNSamples = p.get<size_t>("NSamples",2000);
19  fCompressHuffman = p.get<bool>("CompressHuffman",false);
20  fDesiredStartTimestamp = p.get<ULong64_t>("StartTimestamp",0);
21 
22  fInputFilePointers.clear();
23  for (size_t ifile=0; ifile<fInputFiles.size(); ++ifile)
24  {
25  fInputFilePointers.push_back(fopen(fInputFiles.at(ifile).data(),"r"));
26  }
27  fFirstRead = true;
28 }
29 
30 // return all data for the event. inputLabel is ignored for this as the input files are
31 // separately specified and data in them are unlabeled.
32 
34  std::string inputLabel,
35  std::vector<raw::RawDigit> &raw_digits,
36  std::vector<raw::RDTimeStamp> &rd_timestamps,
37  std::vector<raw::RDStatus> &rdstatuses)
38 {
39 
41 
42  uint32_t framebuf[117];
43  uint16_t databuf[128];
44  uint64_t timestampstart=0;
45  uint64_t timestamp=0;
46 
47  raw_digits.clear();
48  rd_timestamps.clear();
49  rdstatuses.clear();
50 
51  size_t nfiles = fInputFiles.size();
52 
53  // search for the first timestamp on the first read
54  // don't do on subsequent reads so we don't always read in a frame just to see what
55  // the timestamp is.
56 
57  if (fFirstRead)
58  {
59  for (size_t ifile=0; ifile < nfiles; ++ ifile)
60  {
61  do
62  {
63  if (fInputFilePointers.at(ifile) == 0) return 0;
64  fread(framebuf, sizeof(uint32_t), 117, fInputFilePointers.at(ifile));
65  if (feof(fInputFilePointers.at(ifile)))
66  {
67  // close all the input files and return nothing if we hit eof here
68  for (size_t jfile = 0; jfile < nfiles; ++jfile)
69  {
70  fclose(fInputFilePointers.at(jfile));
71  fInputFilePointers.at(jfile) = 0;
72  }
73  return 0;
74  }
75  timestamp= framebuf[3];
76  timestamp <<= 32;
77  timestamp += framebuf[2];
78  }
79  while (timestamp+16 < fDesiredStartTimestamp);
80  }
81  fFirstRead = false;
82  }
83 
84  // align the readin
85 
86  std::vector<std::vector<uint32_t>> fbcache(nfiles);
87  std::vector<uint64_t> tscache;
88  uint64_t latest_timestamp=0;
89 
90  // read one frame in from each file to see what the latest timestamp is
91 
92  for (size_t ifile=0; ifile<nfiles; ++ifile)
93  {
94  fbcache.at(ifile).resize(117);
95  if (fInputFilePointers.at(ifile) == 0) return 0;
96  fread(fbcache.at(ifile).data(), sizeof(uint32_t), 117, fInputFilePointers.at(ifile));
97  if (feof(fInputFilePointers.at(ifile)))
98  {
99  // close all the input files and return nothing if we hit eof here
100  for (size_t jfile = 0; jfile < nfiles; ++jfile)
101  {
102  fclose(fInputFilePointers.at(jfile));
103  fInputFilePointers.at(jfile) = 0;
104  }
105  return 0;
106  }
107  timestamp= fbcache.at(ifile)[3];
108  timestamp <<= 32;
109  timestamp += fbcache.at(ifile)[2];
110  tscache.push_back(timestamp);
111  if (timestamp > latest_timestamp)
112  {
113  latest_timestamp = timestamp;
114  }
115  }
116 
117  // read enough frames from the other files so that we align the frames to +- 16 ticks
118 
119  for (size_t ifile=0; ifile<nfiles; ++ifile)
120  {
121  while (tscache.at(ifile) + 16 < latest_timestamp)
122  {
123  if (fInputFilePointers.at(ifile) == 0) return 0;
124  fread(fbcache.at(ifile).data(), sizeof(uint32_t), 117, fInputFilePointers.at(ifile));
125  if (feof(fInputFilePointers.at(ifile)))
126  {
127  // close all the input files and return nohting if we hit eof here
128  for (size_t jfile = 0; jfile < nfiles; ++jfile)
129  {
130  fclose(fInputFilePointers.at(jfile));
131  fInputFilePointers.at(jfile) = 0;
132  }
133  return 0;
134  }
135  timestamp= fbcache.at(ifile)[3];
136  timestamp <<= 32;
137  timestamp += fbcache.at(ifile)[2];
138  tscache.at(ifile) = timestamp;
139  }
140  }
141 
142  // actually read in the data now -- we already have the first tick read.
143 
144  for (size_t ifile=0; ifile < nfiles; ++ ifile)
145  {
146  if (fInputFilePointers.at(ifile) == 0) break;
147  int slot = 0;
148  int fiber = 0;
149 
150  std::vector<raw::RawDigit::ADCvector_t> adcvv(256);
151  for (size_t itick=0; itick<fNSamples; ++itick)
152  {
153  if (itick == 0) // already read in the first frame
154  {
155  for (size_t i=0; i<117; ++i)
156  {
157  framebuf[i] = fbcache.at(ifile).at(i);
158  }
159  }
160  else
161  {
162  fread(framebuf, sizeof(uint32_t), 117, fInputFilePointers.at(ifile));
163  if (feof(fInputFilePointers.at(ifile)))
164  {
165  // close all the input files and return what we have.
166  for (size_t jfile = 0; jfile < nfiles; ++jfile)
167  {
168  fclose(fInputFilePointers.at(jfile));
169  fInputFilePointers.at(jfile) = 0;
170  }
171  break;
172  }
173  }
174 
175  int curslot = (framebuf[0] & 0x7000) >> 12; // assume these are all the same
176  int curfiber = (framebuf[0] & 0x8000) >> 15;
177  if (itick>0)
178  {
179  if (curslot != slot)
180  {
181  throw cet::exception("IcebergFELXIBufferDecoderMarch2021") <<
182  "Slot mismatch in file: " << curslot << " " << slot;
183  }
184  if (curfiber != fiber)
185  {
186  throw cet::exception("IcebergFELXIBufferDecoderMarch2021") <<
187  "Fiber mismatch in file: " << curfiber << " " << fiber;
188  }
189  }
190  else
191  {
192  slot = curslot;
193  fiber = curfiber;
194  }
195 
196  timestamp= framebuf[3];
197  timestamp <<= 32;
198  timestamp += framebuf[2];
199  //std::cout << std::dec << " Slot: " << slot << " Fiber: " << fiber
200  // << " Timestamp: " << std::dec << timestamp <<std::endl;
201  if (itick == 0)
202  {
203  timestampstart = timestamp;
204  }
205 
206  // do the data-rearrangement transpose
207 
208  unpack14(&(framebuf[4]),databuf);
209  for (size_t ichan=0; ichan<128; ++ichan)
210  {
211  adcvv.at(ichan).push_back(databuf[ichan]);
212  }
213  unpack14(&(framebuf[4+56]),databuf);
214  for (size_t ichan=0; ichan<128; ++ichan)
215  {
216  adcvv.at(ichan+128).push_back(databuf[ichan]);
217  }
218  }
219 
220  for (size_t ichan=0; ichan<256; ++ichan)
221  {
222  float median=0;
223  float sigma=0;
224  computeMedianSigma(adcvv.at(ichan),median,sigma);
225 
226  // handle 256 channels on two fibers -- use the channel map that assumes 128 chans per fiber (=FEMB)
227 
228  unsigned int fiberloc = 0;
229  if (fiber == 0)
230  {
231  fiberloc = 1;
232  }
233  else if (fiber == 1)
234  {
235  fiberloc = 3;
236  }
237 
238  unsigned int chloc = ichan;
239  if (chloc > 127)
240  {
241  chloc -= 128;
242  fiberloc++;
243  }
244  //unsigned int crateloc = crate;
245 
246 
247  // inverted ordering on back side, Run 2c (=Run 3)
248  // note Shekhar's FEMB number is fiber-1, and WIB is slot+1
249 
250  auto slotloc2 = slot;
251  auto fiberloc2 = fiberloc;
252 
253  if (slot == 0 && fiberloc == 4)
254  {
255  slotloc2 = 1;
256  fiberloc2 = 3;
257  }
258  if (slot == 1 && fiberloc == 4)
259  {
260  slotloc2 = 0;
261  fiberloc2 = 3;
262  }
263  if (slot == 1 && fiberloc == 3)
264  {
265  slotloc2 = 0;
266  fiberloc2 = 4;
267  }
268  if (slot == 0 && fiberloc == 3)
269  {
270  slotloc2 = 1;
271  fiberloc2 = 4;
272  }
273 
274  // skip the fake TPC data
275 
276  if ( slotloc2 == 1 && fiberloc2 == 1 )
277  {
278  continue;
279  }
280 
281  if ( slotloc2 == 2 && fiberloc2 == 1 )
282  {
283  continue;
284  }
285 
286  // for iceberg, hardcode the crate number to suppress warnings
287  unsigned int offlineChannel = channelMap->GetOfflineNumberFromDetectorElements(1, slotloc2, fiberloc2, chloc, dune::IcebergChannelMapService::kFELIX);
288 
289  size_t uncompressed_nticks = adcvv.at(0).size();
291  if (fCompressHuffman)
292  {
293  cflag = raw::kHuffman;
294  raw::Compress(adcvv.at(ichan),cflag);
295  }
296 
297  raw::RawDigit raw_digit(offlineChannel, uncompressed_nticks, adcvv.at(ichan), cflag);
298  raw_digit.SetPedestal(median,sigma);
299  raw_digits.push_back(raw_digit);
300 
301  raw::RDTimeStamp rdtimestamp(timestampstart,offlineChannel);
302  rd_timestamps.push_back(rdtimestamp);
303 
304  }
305  }
306  // default all good status
307  unsigned int statword = 0;
308  rdstatuses.emplace_back(false,false,statword);
309  //std::cout << "decoder felix tool nrawdigits: " << raw_digits.size() << std::endl;
310  return 0;
311 }
312 
313 // get data for specified APAs. There's just one APA in ICEBERG so get all the data
314 
316  std::vector<raw::RawDigit> &raw_digits,
317  std::vector<raw::RDTimeStamp> &rd_timestamps,
318  std::vector<raw::RDStatus> &rdstatuses,
319  std::vector<int> &apalist)
320 {
321  // ignore the APA list and also the input label
322  return retrieveData(evt," ",raw_digits,rd_timestamps,rdstatuses);
323 }
324 
325 // get data for a specific label, but only return those raw digits that correspond to APA's on the list
326 // again, just get all the data for this event
327 
329  std::string inputLabel,
330  std::vector<raw::RawDigit> &raw_digits,
331  std::vector<raw::RDTimeStamp> &rd_timestamps,
332  std::vector<raw::RDStatus> &rdstatuses,
333  std::vector<int> &apalist)
334 {
335  return retrieveData(evt,inputLabel,raw_digits,rd_timestamps,rdstatuses);
336 }
337 
338 
339 
340 
341 // compute median and sigma.
342 
344 {
345  size_t asiz = v_adc.size();
346  int imed=0;
347  if (asiz == 0)
348  {
349  median = 0;
350  sigma = 0;
351  }
352  else
353  {
354  // the RMS includes tails from bad samples and signals and may not be the best RMS calc.
355 
356  imed = TMath::Median(asiz,v_adc.data()) + 0.01; // add an offset to make sure the floor gets the right integer
357  median = imed;
358  sigma = TMath::RMS(asiz,v_adc.data());
359 
360  // add in a correction suggested by David Adams, May 6, 2019
361 
362  size_t s1 = 0;
363  size_t sm = 0;
364  for (size_t i=0; i<asiz; ++i)
365  {
366  if (v_adc[i] < imed) s1++;
367  if (v_adc[i] == imed) sm++;
368  }
369  if (sm > 0)
370  {
371  float mcorr = (-0.5 + (0.5*(float) asiz - (float) s1)/ ((float) sm) );
372  //if (std::abs(mcorr)>1.0) std::cout << "mcorr: " << mcorr << std::endl;
373  median += mcorr;
374  }
375  }
376 }
377 
378 void IcebergDataInterfaceFELIXBufferMarch2021::unpack14(const uint32_t *packed, uint16_t *unpacked) {
379  for (size_t i = 0; i < 128; i++) { // i == n'th U,V,X value
380  const size_t low_bit = i*14;
381  const size_t low_word = low_bit / 32;
382  const size_t high_bit = (i+1)*14-1;
383  const size_t high_word = high_bit / 32;
384  //std::cout << "low_word, high_word: " << low_word << " " << high_word << std::endl;
385  //glog.log("word %li :: low %li (%li[%li]) high %li (%li[%li])\n",i,low_bit,low_word,low_bit%32,high_bit,high_word,high_bit%32);
386  if (low_word == high_word) { //all the bits are in the same word
387  unpacked[i] = (packed[low_word] >> (low_bit%32)) & 0x3FFF;
388  } else { //some of the bits are in the next word
389  size_t high_off = high_word*32-low_bit;
390  //glog.log("pre_mask 0x%X post_mask 0x%X\n", (0x3FFF >> (14-high_off)), ((0x3FFF << high_off) & 0x3FFF) );
391  unpacked[i] = (packed[low_word] >> (low_bit%32)) & (0x3FFF >> (14-high_off));
392  unpacked[i] |= (packed[high_word] << high_off) & ((0x3FFF << high_off) & 0x3FFF);
393  }
394  }
395 }
396 
Huffman Encoding.
Definition: RawTypes.h:10
enum raw::_compress Compress_t
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
Collection of charge vs time digitized from a single readout channel.
Definition: RawDigit.h:69
int retrieveData(art::Event &evt, std::string inputlabel, std::vector< raw::RawDigit > &raw_digits, std::vector< raw::RDTimeStamp > &rd_timestamps, std::vector< raw::RDStatus > &rdstatuses)
std::string string
Definition: nybbler.cc:12
std::vector< short > ADCvector_t
Type representing a (compressed) vector of ADC counts.
Definition: RawDigit.h:73
no compression
Definition: RawTypes.h:9
unsigned int GetOfflineNumberFromDetectorElements(unsigned int crate, unsigned int slot, unsigned int fiber, unsigned int fembchannel, FelixOrRCE frswitch)
const double e
T get(std::string const &key) const
Definition: ParameterSet.h:271
p
Definition: test.py:223
int retrieveDataAPAListWithLabels(art::Event &evt, std::string inputlabel, std::vector< raw::RawDigit > &raw_digits, std::vector< raw::RDTimeStamp > &rd_timestamps, std::vector< raw::RDStatus > &rdstatuses, std::vector< int > &apalist)
void unpack14(const uint32_t *packed, uint16_t *unpacked)
void SetPedestal(float ped, float sigma=1.)
Set pedestal and its RMS (the latter is 0 by default)
Definition: RawDigit.cxx:68
void Compress(std::vector< short > &adc, raw::Compress_t compress)
Compresses a raw data buffer.
Definition: raw.cxx:19
int retrieveDataForSpecifiedAPAs(art::Event &evt, std::vector< raw::RawDigit > &raw_digits, std::vector< raw::RDTimeStamp > &rd_timestamps, std::vector< raw::RDStatus > &rdstatuses, std::vector< int > &apalist)
void computeMedianSigma(raw::RawDigit::ADCvector_t &v_adc, float &median, float &sigma)
TCEvent evt
Definition: DataStructs.cxx:7
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
double median(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:26