GRSISort
Created by P.C. Bender
Developement Team: P.C. Bender, R. Dunlop, V. Bildstein
An extension of the ROOT analysis Framework
offsetfind.cxx
Go to the documentation of this file.
1 // g++ offsetfind.cxx `root-config --cflags --libs` -I${GRSISYS}/include -L${GRSISYS}/libraries -lMidasFormat
2 // -lXMLParser -ooffsetfind
3 
4 #include "TMidasFile.h"
5 #include "TMidasEvent.h"
6 #include "TFragment.h"
7 #include "TTree.h"
8 #include "TChannel.h"
9 #include "TH2D.h"
10 #include "TTreeIndex.h"
11 #include "TVirtualIndex.h"
12 #include "Globals.h"
13 #include "TF1.h"
14 #include "TMath.h"
15 #include "TString.h"
16 #include "TPolyMarker.h"
17 
18 #include <vector>
19 #include <iostream>
20 
21 class TEventTime {
22 public:
23  explicit TEventTime(std::shared_ptr<TMidasEvent> event)
24  {
25  event->SetBankList();
26 
27  void* ptr;
28  int banksize = event->LocateBank(nullptr, "GRF1", &ptr);
29 
30  uint32_t type = 0xffffffff;
31  uint32_t value = 0xffffffff;
32 
33  // int64_t time = 0;
34 
35  for(int x = 0; x < banksize; x++) {
36  value = *(reinterpret_cast<int*>(ptr) + x);
37  type = value & 0xf0000000;
38 
39  switch(type) {
40  case 0x80000000:
41  dettype = value & 0x0000000F;
42  chanadd = (value & 0x0003fff0) >> 4;
43  break;
44  case 0xa0000000: timelow = value & 0x0fffffff; break;
45  case 0xb0000000: timehigh = value & 0x00003fff; break;
46  };
47  }
48  timemidas = (unsigned int)(event->GetTimeStamp());
49  if(timemidas < low_timemidas) {
51  }
52 
53  SetDigitizer();
54 
55  if(GetTimeStamp() < lowest_time || lowest_time == -1) {
57  best_dig = Digitizer();
58  }
59  }
60 
61  ~TEventTime() = default;
62 
63  int64_t GetTimeStamp()
64  {
65  long time = timehigh;
66  time = time<<28;
67  time |= timelow & 0x0fffffff;
68  return time;
69  }
70  int TimeStampHigh() { return timehigh; }
71 
72  unsigned long MidasTime() { return timemidas; }
73 
74  int Digitizer() { return digitizernum; }
75 
76  int DetectorType() { return dettype; }
77 
78  void SetDigitizer()
79  {
80  // Maybe make a map somewhere of digitizer vs address
81  digitizernum = chanadd & 0x0000ff00;
82  digmap.insert(std::pair<int, int>(digitizernum, digmap.size()));
83  }
84 
85  static void OrderDigitizerMap()
86  {
87  std::map<int, int>::iterator it;
88  int index = 0;
89  for(it = digmap.begin(); it != digmap.end(); it++) {
90  it->second = index++;
91  }
92  }
93 
94  inline static int NDigitizers() { return digmap.size(); }
95 
96  inline static int GetBestDigitizer() { return best_dig; }
97 
98  static unsigned long GetLowestMidasTime() { return low_timemidas; }
99 
100  int DigIndex() { return digmap.find(digitizernum)->second; }
101 
102  static std::map<int, int> digmap;
103  static unsigned long low_timemidas;
104  static int best_dig;
105  static int64_t lowest_time;
106 
107 private:
108  int timelow;
109  int timehigh;
110  unsigned long timemidas;
111  int dettype;
112  int chanadd;
114 };
115 
116 unsigned long TEventTime::low_timemidas = -1;
117 int64_t TEventTime::lowest_time = -1;
118 int TEventTime::best_dig = 0;
119 std::map<int, int> TEventTime::digmap;
120 
121 int QueueEvents(TMidasFile* infile, std::vector<TEventTime*>* eventQ)
122 {
123  int events_read = 0;
124  const int total_events = 1E7;
125  std::shared_ptr<TMidasEvent> event = std::make_shared<TMidasEvent>();
126  eventQ->reserve(total_events);
127 
128  while(infile->Read(event) > 0 && eventQ->size() < total_events) {
129  switch(event->GetEventId()) {
130  case 0x8000:
131  printf(DRED "start of run\n");
132  event->Print();
133  printf(RESET_COLOR);
134  break;
135  case 0x8001:
136  printf(DGREEN "end of run\n");
137  event->Print();
138  printf(RESET_COLOR);
139  break;
140  default:
141  if(event->GetEventId() != 1) {
142  break;
143  }
144  events_read++;
145  eventQ->push_back(
146  new TEventTime(event)); // I'll keep 3G data in here for now in case we need to use it for time stamping
147  break;
148  };
149  if(events_read % 250000 == 0) {
150  printf(DYELLOW "\tQUEUEING EVENT %d/%d \r" RESET_COLOR, events_read, total_events);
151  fflush(stdout);
152  }
153  }
155  printf("\n");
156  return 0;
157 }
158 
159 void CheckHighTimeStamp(std::vector<TEventTime*>* eventQ, int64_t* correction)
160 {
161  // This function should return an array of corrections
162 
163  auto* midvshigh = new TList;
164  printf(DBLUE "Correcting High time stamps...\n" RESET_COLOR);
165  // These first four are for looking to see if high time-stamp reset
166  std::map<int, int>::iterator mapit;
167  for(mapit = TEventTime::digmap.begin(); mapit != TEventTime::digmap.end(); mapit++) {
168  auto* midvshighhist = new TH2D(Form("midvshigh_0x%04x", mapit->first), Form("midvshigh_0x%04x", mapit->first),
169  5000, 0, 5000, 5000, 0, 5000);
170  midvshigh->Add(midvshighhist);
171  }
172 
173  unsigned int lowmidtime = TEventTime::GetLowestMidasTime();
174 
175  // MidasTimeStamp is the only time we can trust at this level.
176 
177  // int fEntries = eventQ->size();
178 
179  int FragsIn = 0;
180 
181  FragsIn++;
182  int* lowest_hightime;
183  lowest_hightime = new int[TEventTime::NDigitizers()];
184  // Clear lowest hightime
185  for(int i = 0; i < TEventTime::NDigitizers(); i++) {
186  lowest_hightime[i] = 0;
187  }
188 
189  std::vector<TEventTime*>::iterator it;
190 
191  for(it = eventQ->begin(); it != eventQ->end(); it++) {
192  // This makes the plot, might not be required
193  int hightime = (*it)->TimeStampHigh();
194  unsigned long midtime = (*it)->MidasTime() - lowmidtime;
195  if(midtime > 20) {
196  break; // 20 seconds seems like plenty enough time
197  }
198 
199  if((*it)->DetectorType() == 1) {
200  (dynamic_cast<TH2D*>(midvshigh->At((*it)->DigIndex())))->Fill(midtime, hightime);
201  if(hightime < lowest_hightime[(*it)->DigIndex()]) {
202  lowest_hightime[TEventTime::digmap.at((*it)->DigIndex())] = hightime;
203  }
204  }
205  }
206 
207  // find lowest digitizer
208  int lowest_dig = 0;
209  for(mapit = TEventTime::digmap.begin(); mapit != TEventTime::digmap.end(); mapit++) {
210  if(lowest_hightime[mapit->second] < lowest_hightime[lowest_dig]) {
211  lowest_dig = mapit->second;
212  }
213  }
214 
215  midvshigh->Print();
216  printf("The lowest digitizer is %d\n", lowest_dig);
217  printf("***** High time shifts *******\n");
218  for(mapit = TEventTime::digmap.begin(); mapit != TEventTime::digmap.end(); mapit++) {
219  printf("0x%04x:\t %d\n", mapit->first, lowest_hightime[mapit->second]);
220  // Calculate the shift to 0 all digitizers
221  correction[mapit->second] = ((lowest_hightime[mapit->second] - lowest_hightime[lowest_dig]) & 0x00003fff)<<28;
222  }
223  printf("********************\n");
224 
225  midvshigh->Write();
226  midvshigh->Delete();
227  delete[] lowest_hightime;
228 }
229 
230 void GetRoughTimeDiff(std::vector<TEventTime*>* eventQ, int64_t* correction)
231 {
232  // We want the MIDAS time stamps to still be the way we index these events, but we want to index on low time stamps
233  // next
234  printf(DBLUE "Looking for rough time differences...\n" RESET_COLOR);
235 
236  auto* roughlist = new TList;
237  // These first four are for looking to see if high time-stamp reset
238 
239  std::map<int, bool> keep_filling;
240  std::map<int, int>::iterator mapit;
241  for(mapit = TEventTime::digmap.begin(); mapit != TEventTime::digmap.end(); mapit++) {
242  auto* roughhist =
243  new TH1C(Form("rough_0x%04x", mapit->first), Form("rough_0x%04x", mapit->first), 50E6, -25E6, 25E6);
244  roughlist->Add(roughhist);
245  keep_filling[mapit->first] = true;
246  }
247 
248  // The "best digitizer" is set when we fill the event Q
249  printf(DYELLOW "Using the best digitizer 0x%04x\n" RESET_COLOR, TEventTime::GetBestDigitizer());
250 
251  TH1C* fillhist; // This pointer is useful later to clean up a lot of messiness
252 
253  std::vector<TEventTime*>::iterator hit1;
254  std::vector<TEventTime*>::iterator hit2;
255  int event1count = 0;
256  const int range = 1000;
257  for(hit1 = eventQ->begin(); hit1 != eventQ->end(); hit1++) { // This steps hit1 through the eventQ
258  // We want to have the first hit be in the "good digitizer"
259  if(event1count % 250000 == 0) {
260  printf("Processing Event %d /%lu \r", event1count, eventQ->size());
261  }
262  fflush(stdout);
263  event1count++;
264 
265  if((*hit1)->Digitizer() != TEventTime::GetBestDigitizer()) {
266  continue;
267  }
268 
269  int64_t time1 = (*hit1)->GetTimeStamp() - correction[(*hit1)->DigIndex()];
270 
271  if(event1count > range) {
272  hit2 = hit1 - range;
273  } else {
274  hit2 = eventQ->begin();
275  }
276  // Now that we have the best digitizer, we can start looping through the events
277  int event2count = 0;
278  while(hit2 != eventQ->end() && event2count < range * 2) {
279  event2count++;
280  if(hit1 == hit2) {
281  continue;
282  }
283  int digitizer = (*hit2)->Digitizer();
284  if(keep_filling[digitizer]) {
285  fillhist =
286  dynamic_cast<TH1C*>(roughlist->At((*hit2)->DigIndex())); // This is where that pointer comes in handy
287  int64_t time2 = (*hit2)->GetTimeStamp() - correction[(*hit2)->DigIndex()];
288  Int_t bin = static_cast<Int_t>(time2 - time1);
289 
290  if(fillhist->FindBin(bin) > 0 && fillhist->FindBin(bin) < fillhist->GetNbinsX()) {
291  if(fillhist->GetBinContent(fillhist->Fill(bin)) > 126) {
292  keep_filling[digitizer] = false;
293  printf("\nDigitizer 0x%04x is done filling\n", digitizer);
294  }
295  }
296 
297  hit2++;
298  }
299  }
300  }
301 
302  for(mapit = TEventTime::digmap.begin(); mapit != TEventTime::digmap.end(); mapit++) {
303  fillhist = dynamic_cast<TH1C*>(roughlist->At(mapit->second));
304  correction[mapit->second] += static_cast<int64_t>(fillhist->GetBinCenter(fillhist->GetMaximumBin()));
305  }
306 
307  printf("***** Rough time shifts *******\n");
308  for(mapit = TEventTime::digmap.begin(); mapit != TEventTime::digmap.end(); mapit++) {
309 #ifdef OS_DARWIN
310  printf("0x%04x:\t %lld\n", mapit->first, correction[mapit->second]);
311 #else
312  printf("0x%04x:\t %ld\n", mapit->first, correction[mapit->second]);
313 #endif
314  }
315  printf("********************\n");
316 
317  roughlist->Print();
318  roughlist->Write();
319  roughlist->Delete();
320 }
321 
322 void GetTimeDiff(std::vector<TEventTime*>* eventQ, int64_t* correction)
323 {
324  // We want the MIDAS time stamps to still be the way we index these events, but we want to index on low time stamps
325  // next
326  printf(DBLUE "Looking for final time differences...\n" RESET_COLOR);
327 
328  auto* list = new TList;
329  // These first four are for looking to see if high time-stamp reset
330 
331  std::map<int, int>::iterator mapit;
332  for(mapit = TEventTime::digmap.begin(); mapit != TEventTime::digmap.end(); mapit++) {
333  auto* hist =
334  new TH1D(Form("timediff_0x%04x", mapit->first), Form("timediff_0x%04x", mapit->first), 1000, -500, 500);
335  list->Add(hist);
336  }
337 
338  // The "best digitizer" is set when we fill the event Q
339  printf(DYELLOW "Using the best digitizer 0x%04x\n" RESET_COLOR, TEventTime::GetBestDigitizer());
340 
341  TH1D* fillhist; // This pointer is useful later to clean up a lot of messiness
342 
343  std::vector<TEventTime*>::iterator hit1;
344  std::vector<TEventTime*>::iterator hit2;
345  int event1count = 0;
346  const int range = 1250;
347  for(hit1 = eventQ->begin(); hit1 != eventQ->end(); hit1++) { // This steps hit1 through the eventQ
348  // We want to have the first hit be in the "good digitizer"
349  if(event1count % 75000 == 0) {
350  printf("Processing Event %d / %lu \r", event1count, eventQ->size());
351  }
352  fflush(stdout);
353 
354  event1count++;
355  // We need to make sure that that if we have a digitizer of 0, we have a detector type of 1
356  if((*hit1)->Digitizer() == 0 && (*hit1)->DetectorType() != 1) {
357  continue;
358  }
359 
360  if((*hit1)->Digitizer() != TEventTime::GetBestDigitizer()) {
361  continue;
362  }
363 
364  int64_t time1 = (*hit1)->GetTimeStamp() - correction[(*hit1)->DigIndex()];
365  ;
366 
367  if(event1count > range) {
368  hit2 = hit1 - range;
369  } else {
370  hit2 = eventQ->begin();
371  }
372  // Now that we have the best digitizer, we can start looping through the events
373  int event2count = 0;
374  while(hit2 != eventQ->end() && event2count < range * 2) {
375  event2count++;
376  // We need to make sure that that if we have a digitizer of 0, we have a detector type of 1
377  if((*hit2)->Digitizer() == 0 && (*hit2)->DetectorType() != 1) {
378  continue;
379  }
380 
381  if(hit1 != hit2) {
382  // int digitizer = (*hit2)->Digitizer();
383  fillhist = dynamic_cast<TH1D*>(list->At((*hit2)->DigIndex())); // This is where that pointer comes in handy
384  int64_t time2 = (*hit2)->GetTimeStamp() - correction[(*hit2)->DigIndex()];
385  if(time2 - time1 < 2147483647 &&
386  time2 - time1 > -2147483647) { // Make sure we are casting this to 32 bit properly
387  Int_t bin = static_cast<Int_t>(time2 - time1);
388 
389  fillhist->Fill(bin);
390  }
391  }
392  hit2++;
393  }
394  }
395  for(mapit = TEventTime::digmap.begin(); mapit != TEventTime::digmap.end(); mapit++) {
396  fillhist = dynamic_cast<TH1D*>(list->At(mapit->second));
397  correction[mapit->second] += static_cast<int64_t>(fillhist->GetBinCenter(fillhist->GetMaximumBin()));
398  auto* pm = new TPolyMarker;
399  pm->SetNextPoint(fillhist->GetBinCenter(fillhist->GetMaximumBin()),
400  fillhist->GetBinContent(fillhist->GetMaximumBin()) + 10);
401  pm->SetMarkerStyle(23);
402  pm->SetMarkerColor(kRed);
403  pm->SetMarkerSize(1.3);
404  fillhist->GetListOfFunctions()->Add(pm);
405  // fillhist->Draw();
406  }
407 
408  printf("***** Final time shifts *******\n");
409  for(mapit = TEventTime::digmap.begin(); mapit != TEventTime::digmap.end(); mapit++) {
410 #ifdef OS_DARWIN
411  printf("0x%04x:\t %lld\n", mapit->first, correction[mapit->second]);
412 #else
413  printf("0x%04x:\t %ld\n", mapit->first, correction[mapit->second]);
414 #endif
415  }
416  printf("********************\n");
417 
418  list->Print();
419  list->Write();
420  list->Delete();
421 }
422 
423 int main(int argc, char** argv)
424 {
425 
426  if(argc != 2) {
427  printf("Usage: ./offsetfind <input.mid>\n");
428  return 1;
429  }
430 
431  auto* infile = new TMidasFile;
432  infile->Open(argv[1]);
433 
434  auto* outfile = new TFile("outfile.root", "RECREATE");
435 
436  std::cout<<"SIZE: "<<TEventTime::digmap.size()<<std::endl;
437  auto* eventQ = new std::vector<TEventTime*>;
438  QueueEvents(infile, eventQ);
439  std::cout<<"SIZE: "<<TEventTime::digmap.size()<<std::endl;
440 
441  int64_t* correction;
442  correction = new int64_t[TEventTime::NDigitizers()];
443  CheckHighTimeStamp(eventQ, correction);
444  GetRoughTimeDiff(eventQ, correction);
445  GetTimeDiff(eventQ, correction);
446 
447  // Have to do deleting on Q if we move to a next step of fixing the MIDAS File
448  infile->Close();
449  outfile->Close();
450  delete[] correction;
451  delete infile;
452 }
TEventTime(std::shared_ptr< TMidasEvent > event)
Definition: offsetfind.cxx:23
unsigned long MidasTime()
Definition: offsetfind.cxx:72
#define DRED
Definition: Globals.h:17
#define RESET_COLOR
Definition: Globals.h:4
static void OrderDigitizerMap()
Definition: offsetfind.cxx:85
static std::map< int, int > digmap
Definition: offsetfind.cxx:102
#define DGREEN
Definition: Globals.h:16
void GetRoughTimeDiff(std::vector< TEventTime *> *eventQ, int64_t *correction)
Definition: offsetfind.cxx:230
int TimeStampHigh()
Definition: offsetfind.cxx:70
static int best_dig
Definition: offsetfind.cxx:104
static unsigned long GetLowestMidasTime()
Definition: offsetfind.cxx:98
int main(int argc, char **argv)
Definition: offsetfind.cxx:423
#define DYELLOW
Definition: Globals.h:15
int DigIndex()
Definition: offsetfind.cxx:100
int digitizernum
Definition: offsetfind.cxx:113
static int64_t lowest_time
Definition: offsetfind.cxx:105
static int NDigitizers()
Definition: offsetfind.cxx:94
Reader for MIDAS .mid files.
Definition: TMidasFile.h:32
static unsigned long low_timemidas
Definition: offsetfind.cxx:103
static int GetBestDigitizer()
Definition: offsetfind.cxx:96
void SetDigitizer()
Definition: offsetfind.cxx:78
int Read(std::shared_ptr< TRawEvent > event) override
Read one event from the file.
Definition: TMidasFile.cxx:330
~TEventTime()=default
int64_t GetTimeStamp()
Definition: offsetfind.cxx:63
bool Open(const char *filename) override
Open input file.
Definition: TMidasFile.cxx:116
void GetTimeDiff(std::vector< TEventTime *> *eventQ, int64_t *correction)
Definition: offsetfind.cxx:322
void CheckHighTimeStamp(std::vector< TEventTime *> *eventQ, int64_t *correction)
Definition: offsetfind.cxx:159
TH1D * hist
Definition: UserFillObj.h:3
unsigned long timemidas
Definition: offsetfind.cxx:110
int DetectorType()
Definition: offsetfind.cxx:76
int Digitizer()
Definition: offsetfind.cxx:74
int QueueEvents(TMidasFile *infile, std::vector< TEventTime *> *eventQ)
Definition: offsetfind.cxx:121
#define DBLUE
Definition: Globals.h:14