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