REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestRawUSTCToSignalProcess.cxx
1 /*************************************************************************
2  * This file is part of the REST software framework. *
3  * *
4  * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5  * For more information see http://gifna.unizar.es/trex *
6  * *
7  * REST is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * REST is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have a copy of the GNU General Public License along with *
18  * REST in $REST_PATH/LICENSE. *
19  * If not, see http://www.gnu.org/licenses/. *
20  * For the list of contributors see $REST_PATH/CREDITS. *
21  *************************************************************************/
22 
59 
60 // int counter = 0;
61 
62 #include "TRestRawUSTCToSignalProcess.h"
63 
64 using namespace std;
65 
66 #include <bitset>
67 
68 #include "TTimeStamp.h"
69 
71 
72 TRestRawUSTCToSignalProcess::TRestRawUSTCToSignalProcess() { Initialize(); }
73 
74 TRestRawUSTCToSignalProcess::TRestRawUSTCToSignalProcess(const char* configFilename) { Initialize(); }
75 
76 TRestRawUSTCToSignalProcess::~TRestRawUSTCToSignalProcess() {
77  // TRestRawUSTCToSignalProcess destructor
78 }
79 
82 
83  SetSectionName(this->ClassName());
84  SetLibraryVersion(LIBRARY_VERSION);
85 }
86 
88  fEventBuffer.clear();
89  errorevents.clear();
90  unknownerrors = 0;
91  fLastBufferedId = 0;
92 
93 #ifndef Incoherent_Event_Generation
94  nBufferedEvent = StringToInteger(GetParameter("BufferNumber", "2"));
95  if (nBufferedEvent < 1) nBufferedEvent = 1;
96 #else
97  nBufferedEvent = 2;
98 #endif // !Incoherent_Readout
99 
100  for (int n = 0; n < nBufferedEvent + 1; n++) {
101  fEventBuffer.push_back(vector<USTCDataFrame>());
102  }
103 
104  fRunOrigin = fRunInfo->GetRunNumber();
105  fCurrentFile = 0;
106  fCurrentBuffer = 0;
107  totalBytesReaded = 0;
108 
109  USTCDataFrame frame;
110  if ((!GetNextFrame(frame)) || (!ReadFrameData(frame))) {
111  FixToNextFrame(fInputFiles[fCurrentFile]);
112  if ((!GetNextFrame(frame)) || (!ReadFrameData(frame))) {
113  RESTError << "TRestRawUSTCToSignalProcess: Failed to read the first data "
114  "frame in file, may be wrong "
115  "input?"
116  << RESTendl;
117  exit(1);
118  }
119  }
120 
121  fCurrentEvent = frame.evId;
122  AddBuffer(frame);
123 
124  if (fCurrentEvent != 0) {
125  RESTWarning << "TRestRawUSTCToSignalProcess : first event is not with id 0 !" << RESTendl;
126  RESTWarning << "The first Id is " << fCurrentEvent << ". May be input file not the first file?"
127  << RESTendl;
128  }
129 }
130 
132  while (1) {
133  if (EndReading()) {
134  return nullptr;
135  }
136  if (!FillBuffer()) {
137  fSignalEvent->SetOK(false);
138  }
139  if (fEventBuffer[fCurrentBuffer].size() == 0) {
140  RESTDebug << "Blank event " << fCurrentEvent << " !" << RESTendl;
141  fCurrentEvent++;
142  ClearBuffer();
143  } else {
144  break;
145  }
146  }
147 
148  fSignalEvent->Initialize();
149  fSignalEvent->SetID(fCurrentEvent);
150 
151  RESTDebug << "------------------------------------" << RESTendl;
152  RESTDebug << "Generating event with ID: " << fCurrentEvent << RESTendl;
153 
154  // some event level operation
155  USTCDataFrame* frame0 = &fEventBuffer[fCurrentBuffer][0];
156  TTimeStamp tSt = 0;
157  Long64_t evtTime = frame0->eventTime;
158  tSt.SetNanoSec((fTimeOffset + evtTime) % ((Long64_t)1e9));
159  tSt.SetSec((fTimeOffset + evtTime) / ((Long64_t)1e9));
160 
161  // some signal level operation
162  for (unsigned int i = 0; i < fEventBuffer[fCurrentBuffer].size(); i++) {
163  USTCDataFrame* frame = &fEventBuffer[fCurrentBuffer][i];
164  if (frame->evId == fCurrentEvent && frame->eventTime == evtTime) {
165  sgnl.Initialize();
166  sgnl.SetSignalID(frame->signalId);
167  for (int j = 0; j < 512; j++) {
168  sgnl.AddPoint((Short_t)frame->dataPoint[j]);
169  }
170  fSignalEvent->AddSignal(sgnl);
171 
172  RESTDebug << "AsAdId, AgetId, chnId, max value: " << frame->boardId << ", " << frame->chipId
173  << ", " << frame->channelId << ", " << sgnl.GetMaxValue() << RESTendl;
174 
175  } else {
176  RESTWarning << "TRestRawUSTCToSignalProcess : unmatched signal frame!" << RESTendl;
177  RESTWarning << "ID (supposed, received): " << fCurrentEvent << ", " << frame->evId << RESTendl;
178  RESTWarning << "Time (supposed, received) : " << evtTime << ", " << frame->eventTime << RESTendl;
179  RESTWarning << RESTendl;
180  fSignalEvent->SetOK(false);
181  fCurrentEvent++;
182  ClearBuffer();
183  return fSignalEvent;
184  }
185  }
186 
187  ClearBuffer();
188 
189  if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) {
190  cout << "------------------------------------" << endl;
191  GetChar();
192  }
193  fSignalEvent->SetTimeStamp(tSt);
194  fSignalEvent->SetRunOrigin(fRunOrigin);
195  fSignalEvent->SetSubRunOrigin(fSubRunOrigin);
196 
197  // cout << fSignalEvent->GetNumberOfSignals() << endl;
198  // if( fSignalEvent->GetNumberOfSignals( ) == 0 ) return nullptr;
199  fCurrentEvent++;
200 
201  return fSignalEvent;
202 }
203 
205  for (unsigned int i = 0; i < errorevents.size(); i++) {
206  RESTWarning << "Event " << errorevents[i] << " contains error !" << RESTendl;
207  }
208  if (errorevents.size() > 0 && unknownerrors > 0) {
209  RESTWarning << "There are also " << unknownerrors << " errors from unknown events! " << RESTendl;
210  } else if (unknownerrors > 0) {
211  RESTWarning << "There are " << unknownerrors << " errors from unknown events! " << RESTendl;
212  }
213 
214  errorevents.clear();
215 }
216 
217 bool TRestRawUSTCToSignalProcess::FillBuffer() {
218 #ifdef Incoherent_Event_Generation
219  bool unknowncurrentevent = false;
220  if (fEventBuffer[fCurrentBuffer].size() > 0) {
221  fCurrentEvent = fEventBuffer[fCurrentBuffer][0].evId;
222  } else {
223  unknowncurrentevent = true;
224  }
225 
226  while (1)
227 #else
228  while (fLastBufferedId < fCurrentEvent + ((int)fEventBuffer.size() - 1) / 2)
229 #endif
230  {
231  bool errortag = false;
232  bool breaktag = false;
233  USTCDataFrame frame;
234  if (!GetNextFrame(frame)) {
235  break;
236  }
237  if (!ReadFrameData(frame)) {
238  RESTWarning << "error reading frame data in file " << fCurrentFile << RESTendl;
239  FixToNextFrame(fInputFiles[fCurrentFile]);
240  GetNextFrame(frame);
241  ReadFrameData(frame);
242  errortag = true;
243  }
244 #ifdef Incoherent_Event_Generation
245  if (unknowncurrentevent) {
246  cout << frame.evId << endl;
247  fCurrentEvent = frame.evId;
248  unknowncurrentevent = false;
249  }
250 
251  if (frame.evId != fCurrentEvent) {
252  breaktag = true;
253  }
254 #else
255  if (frame.evId >= fCurrentEvent + ((int)fEventBuffer.size() - 1) / 2) {
256  breaktag = true;
257  }
258 #endif // Incoherent_Event_Generation
259 
260  if (!AddBuffer(frame)) {
261  errortag = true;
262  }
263 
264  if (errortag) {
265  if (frame.evId != -1) {
266  if (errorevents.size() == 0) {
267  errorevents.push_back(frame.evId);
268  } else {
269  for (unsigned int i = 0; i < errorevents.size(); i++) {
270  if (errorevents[i] == frame.evId) {
271  break;
272  } else if (i == errorevents.size() - 1) {
273  errorevents.push_back(frame.evId);
274  break;
275  }
276  }
277  }
278 
279  } else {
280  unknownerrors++;
281  }
282  }
283 
284  if (breaktag) {
285  fLastBufferedId = frame.evId;
286  break;
287  }
288  }
289  for (unsigned int i = 0; i < errorevents.size(); i++) {
290  if (errorevents[i] == fCurrentEvent) return false;
291  }
292  return true;
293 }
294 
295 bool TRestRawUSTCToSignalProcess::OpenNextFile(USTCDataFrame& frame) {
296  if (fCurrentFile < (int)fInputFiles.size() - 1) // try to get frame form next file
297  {
298  fCurrentFile++;
299  return GetNextFrame(frame);
300  } else {
301  return false;
302  }
303 }
304 
305 bool TRestRawUSTCToSignalProcess::GetNextFrame(USTCDataFrame& frame) {
306  if (fInputFiles[fCurrentFile] == nullptr) {
307  return OpenNextFile(frame);
308  }
309 #ifdef V4_Readout_Format
310  while (1) {
311  UChar_t Protocol[PROTOCOL_SIZE];
312  if (fread(Protocol, PROTOCOL_SIZE, 1, fInputFiles[fCurrentFile]) != 1 ||
313  feof(fInputFiles[fCurrentFile])) {
314  fclose(fInputFiles[fCurrentFile]);
315  fInputFiles[fCurrentFile] = nullptr;
316  return OpenNextFile(frame);
317  }
318  totalBytesReaded += PROTOCOL_SIZE;
319 
320  if (!(Protocol[0] ^ 0xac) && !(Protocol[1] ^ 0x0f)) {
321  // the first 2 bytes must be 0xac0f, otherwise it is wrong
322 
323  int flag = Protocol[2] >> 5;
324  if (flag & 0x1) {
325  // this is the evt_ending frame
326  memcpy(fEnding, Protocol, PROTOCOL_SIZE);
327  if (fread(fEnding + PROTOCOL_SIZE, ENDING_SIZE - PROTOCOL_SIZE, 1,
328  fInputFiles[fCurrentFile]) != 1 ||
329  feof(fInputFiles[fCurrentFile])) {
330  fclose(fInputFiles[fCurrentFile]);
331  fInputFiles[fCurrentFile] = nullptr;
332  return OpenNextFile(frame);
333  }
334  totalBytesReaded += ENDING_SIZE;
335  } else if (flag & 0x2) {
336  // this is the evt_header frame
337  memcpy(fHeader, Protocol, PROTOCOL_SIZE);
338  if (fread(fHeader + PROTOCOL_SIZE, HEADER_SIZE - PROTOCOL_SIZE, 1,
339  fInputFiles[fCurrentFile]) != 1 ||
340  feof(fInputFiles[fCurrentFile])) {
341  fclose(fInputFiles[fCurrentFile]);
342  fInputFiles[fCurrentFile] = nullptr;
343  return OpenNextFile(frame);
344  }
345  totalBytesReaded += HEADER_SIZE;
346  } else {
347  // this is the evt_data frame
348  memcpy(frame.data, Protocol, PROTOCOL_SIZE);
349  if (fread(frame.data + PROTOCOL_SIZE, DATA_SIZE - PROTOCOL_SIZE, 1,
350  fInputFiles[fCurrentFile]) != 1 ||
351  feof(fInputFiles[fCurrentFile])) {
352  fclose(fInputFiles[fCurrentFile]);
353  fInputFiles[fCurrentFile] = nullptr;
354  return OpenNextFile(frame);
355  }
356  totalBytesReaded += DATA_SIZE;
357  return true;
358  }
359  } else {
360  return false;
361  }
362  }
363 #else
364  if (fread(frame.data, DATA_SIZE, 1, fInputFiles[fCurrentFile]) != 1 || feof(fInputFiles[fCurrentFile])) {
365  fclose(fInputFiles[fCurrentFile]);
366  fInputFiles[fCurrentFile] = nullptr;
367  return OpenNextFile(frame);
368  }
369  totalBytesReaded += DATA_SIZE;
370 
371  if (frame.data[0] * 0x100 + frame.data[1] != 0xEEEE) {
372  RESTarning << "wrong header!" << RESTendl;
373  return false;
374  }
375 #endif // V4_Readout_Format
376 
377  return true;
378 }
379 
380 // it find the next flag of frame, e.g. 0xffff or 0xac0f
381 void TRestRawUSTCToSignalProcess::FixToNextFrame(FILE* f) {
382  if (f == nullptr) return;
383  UChar_t buffer[PROTOCOL_SIZE];
384  int n = 0;
385  while (1) {
386  if (fread(buffer, PROTOCOL_SIZE, 1, f) != 1 || feof(f)) {
387  return;
388  }
389  n += PROTOCOL_SIZE;
390 #ifdef V4_Readout_Format
391  if (!(buffer[0] ^ 0xac) && !(buffer[1] ^ 0x0f)) {
392  int flag = buffer[2] >> 5;
393  if (flag & 0x2) {
394  // we have meet the next event header
395  memcpy(fHeader, buffer, PROTOCOL_SIZE);
396  if (fread(fHeader + PROTOCOL_SIZE, HEADER_SIZE - PROTOCOL_SIZE, 1,
397  fInputFiles[fCurrentFile]) != 1 ||
398  feof(fInputFiles[fCurrentFile])) {
399  fclose(f);
400  f = nullptr;
401  break;
402  }
403  n += HEADER_SIZE;
404  RESTWarning << "successfully switched to next frame ( + " << n << " byte)" << RESTendl;
405  RESTWarning << RESTendl;
406  break;
407  }
408  }
409 #else
410  if (!(buffer[0] ^ 0xff) && !(buffer[1] ^ 0xff) && !(buffer[2] ^ 0xff) && !(buffer[3] ^ 0xff)) {
411  RESTWarning << "successfully switched to next frame ( + " << n << " byte)" << RESTendl;
412  RESTWarning << RESTendl;
413  break;
414  }
415 #endif
416  }
417  totalBytesReaded += n;
418 }
419 
420 bool TRestRawUSTCToSignalProcess::ReadFrameData(USTCDataFrame& frame) {
421 #ifdef V3_Readout_Format_Long
422 
423  // EEEE | E0A0 | 246C 0686 4550 504E | 0001 | 2233 4455 6677 | (A098)(A09C)...
424  // | FFFF FFFF
425  // 0~1header | 2~3board number | 4~11event time | 12~13channel id(0~63)
426  // | 14~19event id | [chip id + data(0~4095)]*512 | ending
427  frame.boardId = frame.data[2] & 0x0F;
428  frame.chipId = (frame.data[3] & 0xF0) / 16 - 10;
429  frame.readoutType = frame.data[3] & 0x0F;
430  Long64_t tmp = (Long64_t)frame.data[5] * 0x10000 + (Long64_t)frame.data[6] * 0x100 +
431  (Long64_t)frame.data[7]; // we omit the first byte in case the number is too large
432  frame.eventTime = tmp * 0x100000000 + (Long64_t)frame.data[8] * 0x1000000 +
433  (Long64_t)frame.data[9] * 0x10000 + (Long64_t)frame.data[10] * 0x100 +
434  (Long64_t)frame.data[11];
435  frame.channelId = frame.data[12] * 0x100 + frame.data[13];
436  frame.evId = (frame.data[16] & 0x7F) * 0x1000000 + frame.data[17] * 0x10000 + frame.data[18] * 0x100 +
437  frame.data[19]; // we omit the first 17 bits in case the number
438  // is too large
439 
440  frame.signalId = frame.boardId * 4 * 64 + frame.chipId * 64 + frame.channelId;
441 #endif
442 
443 #ifdef V3_Readout_Format_Short
444  // EEEE | E0A0 | 246C 0686 | 0001 | 2233 | (A098)(A09C)... | FFFF
445  // 0~1header | 2~3board number | 4~7event time | 8~9channel id(0~63) |
446  // 10~11event id | [chip id + data(0~4095)]*512 | ending
447  frame.boardId = frame.data[2] & 0x0F;
448  frame.chipId = (frame.data[3] & 0xF0) / 16 - 10;
449  frame.readoutType = frame.data[3] & 0x0F;
450  Long64_t tmp = (Long64_t)frame.data[4] * 0x1000000 + (Long64_t)frame.data[5] * 0x10000 +
451  (Long64_t)frame.data[6] * 0x100 + (Long64_t)frame.data[7];
452  frame.eventTime = tmp;
453  frame.channelId = frame.data[8] * 0x100 + frame.data[9];
454  frame.evId = frame.data[10] * 256 + frame.data[11];
455 
456  frame.signalId = frame.boardId * 4 * 64 + frame.chipId * 64 + frame.channelId;
457 
458 #endif // Long_Readout_Format
459 
460 #ifdef V4_Readout_Format
461 
462  // the evt header frame
463  // AC0F | 401C | 0300 |
464  // 010A 3140 0000 |
465  // 0500 0000 | .... | .... | 8E95 B452 0~1Protocol | 2~3
466  // 010+size | 4~5:
467  // 00000011+ETYPE(2)+ST(1)+SOURCEID(5) | 6~11 time stamp(inverted) | 12~15
468  // event id(inverted) | not used
469  // | ending
470  frame.readoutType = fHeader[5] & 0xc0;
471 
472  int t_high = fHeader[10] * 0x100 + fHeader[11];
473  int t_mid = fHeader[8] * 0x100 + fHeader[9];
474  int t_low = fHeader[6] * 0x100 + fHeader[7];
475  Long64_t tmp = (Long64_t)t_high * 0x100000000 + (Long64_t)t_mid * 0x10000 + (Long64_t)t_low;
476  frame.eventTime = tmp;
477 
478  int id_high = fHeader[14] * 0x100 + fHeader[15];
479  int id_low = fHeader[12] * 0x100 + fHeader[13];
480  frame.evId = id_high * 0x10000 + id_low;
481 
482  // the signal frame
483  // AC0F | 0404 | C000 | (3163)(316C)... | 0000 BCEB 5742
484  // 0~1Protocol | 2~3 not used | 4~5: 11+card(5)+chip(2)+channel(7) |
485  // [0011+data(0~4095)]*512 | ending
486  // event info(time, id, etc.) is in event header
487  frame.boardId = (frame.data[4] & 0x3e) >> 1;
488  frame.chipId = (frame.data[4] & 0x01) * 2 + (frame.data[5] >> 7);
489  frame.channelId = frame.data[5] & 0x7f;
490 
491  frame.signalId = frame.boardId * 4 * 68 + frame.chipId * 68 + frame.channelId;
492 
493  fChannelOffset.insert(frame.boardId * 4 * 68 + frame.chipId * 68);
494 #endif
495 
496  // sampling point data
497  for (int i = 0; i < 512; i++) {
498  int pos = i * 2 + DATA_OFFSET;
499  frame.dataPoint[i] = (int)((frame.data[pos] & 0x0F) * 0x100 + frame.data[pos + 1]);
500  }
501 
502  // if (frame.data[DATA_SIZE - 4] * 0x1000000 + frame.data[DATA_SIZE - 3] *
503  // 0x10000 +
504  // frame.data[DATA_SIZE - 2] * 0x100 + frame.data[DATA_SIZE - 1] !=
505  // 0xFFFFFFFF) {
506  // warning << "wrong ending of frame! Event Id : " << frame.evId << "
507  // Channel Id : " << frame.channelId
508  // << endl;
509  // return false;
510  //}
511 
514  return true;
515 }
516 
517 bool TRestRawUSTCToSignalProcess::AddBuffer(USTCDataFrame& frame) {
518 #ifdef Incoherent_Event_Generation
519  if (frame.evId == fCurrentEvent) {
520  fEventBuffer[fCurrentBuffer].push_back(frame);
521  } else {
522  int pos = 1 + fCurrentBuffer;
523  if (pos >= fEventBuffer.size()) pos -= fEventBuffer.size();
524  fEventBuffer[pos].push_back(frame);
525  }
526 #else
527  if (frame.evId >= fCurrentEvent + (int)fEventBuffer.size()) {
528  RESTWarning << "too large event id for buffering!" << RESTendl;
529  RESTWarning << "this may due to the inconherence of event id. Increase the "
530  "buffer number!"
531  << RESTendl;
532  RESTWarning << "Current Event, Burrfering event : " << fCurrentEvent << ", " << frame.evId
533  << RESTendl;
534  return false;
535  }
536  if (frame.evId < fCurrentEvent) {
537  RESTWarning << "skipping a signal from old event!" << RESTendl;
538  RESTWarning << "the cause may be that too much events are mixing. Increase the "
539  "buffer number!"
540  << RESTendl;
541  RESTWarning << "Current Event, Burrfering event : " << fCurrentEvent << ", " << frame.evId
542  << RESTendl;
543  return false;
544  }
545  size_t pos = frame.evId - fCurrentEvent + fCurrentBuffer;
546  if (pos >= fEventBuffer.size()) pos -= fEventBuffer.size();
547  fEventBuffer[pos].push_back(frame);
548 #endif
549 
550  return true;
551 }
552 
553 void TRestRawUSTCToSignalProcess::ClearBuffer() {
554  fEventBuffer[fCurrentBuffer].clear();
555  fCurrentBuffer += 1;
556  if (fCurrentBuffer >= (int)fEventBuffer.size()) {
557  fCurrentBuffer -= fEventBuffer.size();
558  }
559 }
560 
561 Bool_t TRestRawUSTCToSignalProcess::EndReading() {
562  for (const auto& file : fInputFiles) {
563  if (file != nullptr) {
564  return false;
565  }
566  }
567 
568  for (const auto& eventBuffer : fEventBuffer) {
569  if (!eventBuffer.empty()) {
570  return false;
571  }
572  }
573 
574  return kTRUE;
575 }
A base class for any REST event.
Definition: TRestEvent.h:38
void Initialize() override
Making default settings.
A process to read USTC electronic binary format files generated.
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
Process one event.
void EndProcess() override
To be executed at the end of the run (outside event loop)
void InitProcess() override
To be executed at the beginning of the run (outside event loop)
void Initialize() override
Making default settings.
@ REST_Debug
+show the defined debug messages
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
Int_t StringToInteger(std::string in)
Gets an integer from a string.