BmnRoot 26.10.0-18-g4e3414f9
Software framework of the BM@N experiment
Loading...
Searching...
No Matches
BmnConverter.cxx
Go to the documentation of this file.
1#include "BmnConverter.h"
2// STL
3#include <algorithm>
4#include <arpa/inet.h> /* For ntohl for Big Endian LAND. */
5#include <bitset>
6#include <chrono>
7#include <filesystem>
8#include <iostream>
9#include <mutex>
10#include <unistd.h>
11// ROOT
13#include <ROOT/RDataFrame.hxx>
15// BmnRoot
16#include "BmnConverterTools.h"
17#include "BmnRawDataDecoder.h"
18#include "FairLogger.h"
19#include "TStopwatch.h"
20#include "TSystem.h"
21#include "TTree.h"
22#include "UniDetectorParameter.h"
23#include "UniRawFile.h"
24#include "UniRun.h"
25
26namespace fs = std::filesystem;
27
28BmnConverter::BmnConverter(uint32_t threadCount, uint32_t period, TString outDir, bool tempFileOnDisk)
29 : temp_file_on_disk(tempFileOnDisk)
30 , fPeriodId(period)
31 , fRawRunHdrName("RawRunHeader")
32 , fMetadataName("RawRunMetadata")
33 , fRawTreeName("BMN_RAW")
34 , fRawTreeSpillName("BMN_RAW_SPILLS")
35 , fRootDirPath(outDir)
36 // , fRootFileOut(nullptr)
37 , spillHeader(nullptr)
38 , runHeader(make_unique<DigiRunHeader>(fPeriodId))
39 , metadata(make_unique<BmnMetadataRaw>())
40 // , fMerger(fMerger)
41 , fExportJsonBlocks(false)
42 , tai_utc_dif(0)
43 , fCurWaitingThread(nullptr)
44{
45 TTree::SetMaxTreeSize(1'000'000'000'000); // 932 GB
47 LOGF(info, ANSI_COLOR_BLUE "Starting converter's constructor" ANSI_COLOR_RESET);
49 LOGF(info, "concurrency: %u", std::thread::hardware_concurrency());
50 if (fRootDirPath.Length() == 0)
51 fRootDirPath = fs::current_path();
52 bool dc = fs::create_directories(fRootDirPath.Data());
53 LOGF(info, "Directory: %s was %s", fRootDirPath.Data(), dc ? "created" : "already present");
54 fRootFileName = TString::Format("%s/raw_temp_%d.root", fRootDirPath.Data(), getpid());
57
58 if (threadCount == 0) {
59 if (std::thread::hardware_concurrency() <= 1)
60 fThreadCnt = 1; // either 1 core or no info
61 else
62 fThreadCnt = std::thread::hardware_concurrency() - 1;
63 } else
64 fThreadCnt = threadCount;
66 LOGF(info, "Creating %u%s", fThreadCnt, (fThreadCnt == 1 ? " converter thread" : " converter threads"));
67 for (uint32_t i = 0; i < fThreadCnt; i++) {
68 BmnConverterThread* tmp = fThreads->Add(0);
69 tmp->SetPeriod(fPeriodId);
71 tmp->SetMerger(fMerger.get());
72 tmp->CreateTrees();
73 tmp->RegisterBranches();
75 }
76 LoadConfig();
77 // bool convertMSC = conf.get<bool>("Decoder.ProcessMSC", false);
78 // if (convertMSC) {
79 /*fRawTreeSpills = new TTree("BMN_RAW_SPILLS", "BMN_RAW_SPILLS");
80 auto spill_reg_fun = [&] (TString name, TObject * ar) -> void {
81 TBranch *b = fRawTreeSpills->Branch(name, &ar);
82 LOGF(debug1, "Register branch %p : %s", (void*) b, name.Data());
83 return;
84 };*/
85 /*for(int i = 0; i < fThreadCnt; i++)
86 fThreads->GetThread(i)->RegisterSpillBranches();
87}*/
88 LOGF(info, "Created %u%s", fThreadCnt, (fThreadCnt == 1 ? " converter thread" : " converter threads"));
89 LOGF(info, ANSI_COLOR_BLUE "Finished creating converter\n" ANSI_COLOR_RESET);
90}
91
93{
94 if (fDecoderConfigFileName.length() == 0)
95 fDecoderConfigFileName = string(getenv("VMCWORKDIR")) + "/config/bmnconf.json";
96 pt::read_json(fDecoderConfigFileName, conf);
97 fExportJsonBlocks = conf.get<bool>("Decoder.ExportJson", false);
98 bool ExportExternalSpillStat = conf.get<bool>("Decoder.ExportExternalSpillStat", false);
99 for (uint32_t i = 0; i < fThreadCnt; i++) {
100 BmnConverterThread* tmp = fThreads->GetThread(i);
101 tmp->SetExportExternalSpillStat(ExportExternalSpillStat);
102 }
103 return kBMNSUCCESS;
104}
105
107{
108 LOGF(info, "Creating temporary output root file");
109 fRootFileName = TString::Format("%s/raw_temp_%u.root", fRootDirPath.Data(), fRunId); //, getpid());
110 fMerger = make_unique<ROOT::TBufferMerger>(fRootFileName.Data());
111 // fRootFileOut = new TFile(fRootFileName, "recreate");
112 if (!fMerger) {
113 // if (!fRootFileOut->IsOpen()) {
114 // delete fRootFileOut;
115 LOGF(error, "Couldn't access the output file!!!!!\n");
116 return kBMNERROR;
117 }
118 LOGF(info, "Created temporary output root file");
119 return kBMNSUCCESS;
120}
121
122Int_t BmnConverter::GetSpillNumber(vector<SysPoint>* spillEnds, vector<SysPoint>* spillStarts, SysPoint time)
123{
124 auto t = std::upper_bound(spillEnds->begin(), spillEnds->end(), time);
125 if (t == spillEnds->end()) {
126 return -1; // currently no spill end;
127 } else {
128 if (time < (*spillStarts)[t - spillEnds->begin()]) {
129 return -2;
130 }
131 return t - spillEnds->begin();
132 }
133}
134
135Int_t BmnConverter::GetSpillNumber(vector<SysPoint>* spillEnds, vector<SysPoint>* spillStarts, TTimeStamp time)
136{
138 return GetSpillNumber(spillEnds, spillStarts, p);
139}
140
142{
143 fThreads->Finish();
145 for (UInt_t i = 0; i < fThreadCnt; i++) {
146 LOGF(info, "WriteTree for thread %u", i);
147 tmp = fThreads->GetThread(i);
148 // tmp->WriteTree();
149 // tmp->WriteTreeSpills();
150 tmp->FinalizeFile();
151 }
152 {
153 auto file = fMerger->GetFile();
154 file->WriteObject(runHeader.get(), fRawRunHdrName.Data());
155 file->WriteObject(metadata.get(), fMetadataName.Data());
156 file->Write();
157 file->Close();
158 file.reset();
159 }
160 LOGF(info, "main thread objects written");
161 // LOGF(info, "main thread file closed");
162 //// fMerger->Close();
163 fMerger.reset();
164 // LOGF(info, "fMerger reset");
165 // {
166 // TFile file(fRootFileName, "update");
167 // TTree* ev_tree = static_cast<TTree*>(file.Get(fRawTreeName));
168 // Int_t build_status = ev_tree->BuildIndex("BmnEventHeader.fEventId");
169 // LOGF(info, "Building tree index: %d", build_status);
170 // ev_tree->Write();//"", TObject::kOverwrite);
171 // file.Close();
172 // }
173}
174
176{
177 LOGF(info, ANSI_COLOR_BLUE "Starting to write spills" ANSI_COLOR_RESET);
178 TStopwatch* timer = new TStopwatch();
179 timer->Start();
181 LOGF(info, "Preparing temporary file for read access");
182 OutputTrees();
183 LOGF(info, "Trees written");
184 TFile* fRootFileOut = new TFile(fRootFileName, "read");
185 if (!fRootFileOut->IsOpen()) {
186 delete fRootFileOut;
187 LOGF(error, "Couldn't access the temp file!!!!!\n");
188 return;
189 }
190 for (UInt_t i = 0; i < fThreadCnt; i++) {
191 fThreads->GetThread(i)->SetTrees((TTree*)(fRootFileOut->Get(fRawTreeName + to_string(i))),
192 (TTree*)(fRootFileOut->Get(fRawTreeSpillName + to_string(i))));
193 }
194 set<int> spillCheck;
195 for (size_t i = 0; i < vecTree.size(); i++)
196 spillCheck.insert(vecTree[i].first);
197 for (size_t i = 0; i < vecTreeSpills.size(); i++)
198 spillCheck.insert(vecTreeSpills[i].first);
199 LOGF(info, "Starting to write %d spills", spillCheck.size());
200 for (auto t : spillCheck) {
201 {
202 ROOT::TBufferMerger merger(to_string(fRunId) + (TString) "_s" + to_string(t) + ".root", "recreate");
204 for (UInt_t i = 0; i < fThreadCnt; i++) {
205 tmp = fThreads->GetWaitingThread();
206 tmp->SetMerger(&merger);
207 tmp->SetData(3, t);
208 tmp->Execute();
209 }
210 fThreads->Finish();
211 }
212 TFile file(to_string(fRunId) + (TString) "_s" + to_string(t) + ".root", "update");
213 file.WriteObject(runHeader.get(), fRawRunHdrName.Data());
214 file.WriteObject(metadata.get(), fMetadataName.Data());
215 file.Close();
216 if (t == -2)
217 LOGF(info, "Finished writing weird events (spill %d)", t);
218 else if (t == -1)
219 LOGF(info, "Finished writing unfinished spill (spill %d)", t);
220 else
221 LOGF(info, "Finished writing spill %d", t);
222 }
224 fRootFileOut->Close();
225 Close();
226 timer->Stop();
227 LOGF(info, ANSI_COLOR_BLUE "Finished writing spills in %.3fs\n" ANSI_COLOR_RESET, timer->RealTime());
228}
229
231{
232 fThreads->Finish();
233 LOGF(info, ANSI_COLOR_BLUE "Starting to split events by spills" ANSI_COLOR_RESET);
234 TStopwatch* timer = new TStopwatch();
235 timer->Start();
236 vector<SysPoint> spillEnds;
237 vector<SysPoint> spillStarts;
238 for (auto t : fSpillMap) {
239 spillStarts.push_back(t.second.start_ts);
240 spillEnds.push_back(t.second.stop_ts);
241 LOGF(info, "Spill:\n\tstart ts:%s\n\tstop ts:%s", BmnFunctionSet::TimePoint2String(t.second.start_ts),
242 BmnFunctionSet::TimePoint2String(t.second.stop_ts));
243 }
244 std::sort(spillEnds.begin(), spillEnds.end());
245 // for (size_t i = 0; i < spillEnds.size(); i++) {
246 // LOGF(info, "Spill end detected at: %s", spillEnds[i].AsString());
247 // }
248 vector<TTree*> tmp;
249 for (UInt_t i = 0; i < fThreadCnt; i++) {
250 tmp.push_back(fThreads->GetThread(i)->fRawTree);
251 tmp.push_back(fThreads->GetThread(i)->fRawTreeSpills);
252 }
253 vecTree.clear();
254 vecTreeSpills.clear();
255 for (size_t i = 0; i < tmp.size(); i += 2) {
256 int n = tmp[i]->GetEntriesFast();
257 TBranch* branch = tmp[i]->GetBranch("BmnEventHeader.");
258 for (int j = 0; j < n; j++) {
259 branch->GetEntry(j);
260 vecTree.push_back(make_pair(
261 GetSpillNumber(&spillEnds, &spillStarts, fThreads->GetThread(i / 2)->eventHeaderDAQ->GetEventTimeTS()),
262 make_pair(i / 2, j)));
263 }
264 }
265 for (size_t i = 1; i < tmp.size(); i += 2) {
266 int n = tmp[i]->GetEntriesFast();
267 TBranch* branch = tmp[i]->GetBranch("MSC");
268 TBranch* branchT0 = tmp[i]->GetBranch("T0Raw");
269 for (int j = 0; j < n; j++) {
270 BmnConverterThread* th = fThreads->GetThread(i / 2);
271 SysPoint ts{SysPoint::min()};
272 branch->GetEntry(j);
273 if (th->msc->GetEntriesFast() > 0) {
274 ts = ((BmnMSCDigit<UChar_t>*)(th->msc->First()))->GetTime();
275 LOGF(debug2, "branchMSC ts\t%s", BmnFunctionSet::TimePoint2String(ts));
276 } else {
277 branchT0->GetEntry(j);
278 if (th->t0raw->GetEntriesFast() > 0) {
279 ts = ((BmnT0Raw*)(th->t0raw->First()))->GetTime();
280 LOGF(debug2, "branchT0 ts\t%s", BmnFunctionSet::TimePoint2String(ts));
281 ts -= 1s; // temp crutches to fit into the spill time
282 } else
283 continue;
284 }
285 vecTreeSpills.push_back(make_pair(GetSpillNumber(&spillEnds, &spillStarts, ts), make_pair(i / 2, j)));
286 LOGF(debug2, "GetSpillNumber %d", GetSpillNumber(&spillEnds, &spillStarts, ts));
287 }
288 }
289 for (UInt_t i = 0; i < fThreadCnt; i++) {
290 fThreads->GetThread(i)->RegisterBranches();
291 fThreads->GetThread(i)->RegisterSpillBranches();
292 }
293 std::sort(vecTree.begin(), vecTree.end());
294 std::sort(vecTreeSpills.begin(), vecTreeSpills.end());
295 runHeader->SetSpillMap(fSpillMap);
296 timer->Stop();
297 LOGF(info, ANSI_COLOR_BLUE "Finished splitting events by spills in %.3fs\n" ANSI_COLOR_RESET, timer->RealTime());
298}
299
301{
302 fThreads->Finish();
303 LOGF(info, "Starting separating events by spill");
304 TStopwatch* timer = new TStopwatch();
305 timer->Start();
306
307 treeTimeMap.clear();
308 treeTimeMapDiv.clear();
309
310 vector<SysPoint> spillEnds;
311 vector<SysPoint> spillStarts;
312 for (auto t : fSpillMap) {
313 spillStarts.push_back(t.second.start_ts);
314 spillEnds.push_back(t.second.stop_ts);
315 LOGF(info, "Spill:\n\tstart ts: %s\n\tstop ts: %s", BmnFunctionSet::TimePoint2String(t.second.start_ts),
316 BmnFunctionSet::TimePoint2String(t.second.stop_ts));
317 }
318 std::sort(spillEnds.begin(), spillEnds.end());
319 for (size_t i = 0; i < spillEnds.size(); i++) {
320 LOGF(info, "Spill end detected at: %s", BmnFunctionSet::TimePoint2String(spillEnds[i]));
321 }
322
323 for (uint32_t i = 0; i < fThreadCnt; i++) {
324 BmnConverterThread* th = fThreads->GetThread(i);
325 TTree* tree = th->fRawTree;
326 int64_t n = tree->GetEntriesFast();
327 TBranch* branch = tree->GetBranch("BmnEventHeader.");
328 for (int64_t iEntry = 0; iEntry < n; iEntry++) {
329 branch->GetEntry(iEntry);
330 // treeTimeMap.emplace(th->eventHeaderDAQ->GetEventTimeTP(), make_pair(tree, iEntry));
332 int32_t sn = GetSpillNumber(&spillEnds, &spillStarts, tp);
333 treeTimeMapDiv[sn].emplace(tp, make_pair(tree, iEntry));
334 }
335 }
336 for (const auto& [spill_id, mm] : treeTimeMapDiv) {
337 // const int32_t& spill_id = pmm.first;
338 // const auto& mm = pmm.second;
339 LOGF(info, "t %d", spill_id);
340 TFile file(to_string(fRunId) + (TString) "_s" + to_string(spill_id) + ".root", "recreate");
341 TTree* sortedTree = mm.begin()->second.first->CloneTree(0);
342 sortedTree->SetAutoSave(0);
343 sortedTree->SetAutoFlush(0);
344 sortedTree->SetBasketSize("*", 1073741824);
345 if (!file.IsOpen()) {
346 LOGF(error, "Couldn't access the output file!!!!!\n");
347 break; // return kBMNERROR;
348 }
349 LOGF(info, "TFile open");
350 for (const pair<const SysPoint, TreePE>& el : mm) {
351 const TreePE& pe = el.second;
352 pe.first->GetEntry(pe.second);
353 sortedTree->Fill();
354 }
355 file.WriteObject(runHeader.get(), fRawRunHdrName.Data());
356 file.WriteObject(metadata.get(), fMetadataName.Data());
357 file.Close();
358 if (spill_id == -2)
359 LOGF(info, "Finished writing weird events (spill %d)", spill_id);
360 else if (spill_id == -1)
361 LOGF(info, "Finished writing unfinished spill (spill %d)", spill_id);
362 else
363 LOGF(info, "Finished writing spill %d", spill_id);
364 }
365
366 Close();
367 timer->Stop();
368 LOGF(info, ANSI_COLOR_BLUE "Finished splitting events by spills in %.3fs\n" ANSI_COLOR_RESET, timer->RealTime());
369}
370
372{
373 TObjArray* brList = inTree->GetListOfBranches(); // ioman->GetBranchNameList();
374 if (inTree->GetEntry(0) == 0) {
375 LOGF(error, "Input tree is empty! Recreating empty output...");
376 // for (Int_t i = 0; i < brList->GetEntries(); i++) {
377 // TString str = static_cast<TObjString*> (brList->At(i))->GetString();
378 // TObject *obj = ioman->GetObject(str);
379 // TClass *cl = TClass::GetClass(obj->ClassName());
380 //// printf("ClassName: %s\n", obj->ClassName());
381 // if (cl == TClonesArray::Class()) {
382 // TClonesArray * inTCA = static_cast<TClonesArray*> (obj);
383 // TClonesArray * newTCA = new TClonesArray(inTCA->GetClass());
384 // fTreeTemp->Branch(str.Data(), &newTCA);
385 // fArrVecIn.push_back(inTCA);
386 // fArrVec.push_back(newTCA);
387 //
388 // } else {
389 // TNamed* inObj = static_cast<TNamed *> (obj);
390 //// printf(" in obj n: %s t: %s\n", inObj->GetName(), inObj->GetTitle());
391 // TObject* workObj = inObj->Clone(/*TString(inObj->GetName()) + "_clone." + str*/)/*funcNew(0)*/;
392 //// printf("new obj n: %s t: %s\n", workObj->GetName(), workObj->GetTitle());
393 // /*TBranch *b = */fTreeTemp->Branch(str.Data(), "TObject", workObj);
394 //// printf(" branch 0x%016lX\n", (uint64_t)b);
395 // fNamVecIn.push_back(inObj);
396 // fNamVec.push_back(workObj);
397 // }
398 // return;
399 }
400 for (Int_t i = 0; i < brList->GetEntries(); i++) {
401 TBranch* br = static_cast<TBranch*>(brList->At(i));
402 TString str(br->GetName());
403 TObject* obj = *(reinterpret_cast<TObject**>(br->GetAddress()));
404 LOGF(debug, "obj->ClassName() %s", obj->ClassName());
405 TClass* cl = TClass::GetClass(obj->ClassName());
406 LOGF(debug, "ClassName: %s", br->ClassName());
407 if (cl == TClonesArray::Class()) {
408 TClonesArray* inTCA = static_cast<TClonesArray*>(obj);
409 LOGF(debug, "TCA->GetClass()->GetName() %s", inTCA->GetClass()->GetName());
410 outTree->Branch(str.Data(), &inTCA);
411 fArrVec.push_back(inTCA);
412
413 } else {
414 TNamed* inObj = static_cast<TNamed*>(obj);
415 outTree->Branch(str.Data(), "TObject", inObj);
416 fNamVec.push_back(inObj);
417 }
418 }
419 return;
420}
421
422BmnStatus BmnConverter::FeedEvent(UInt_t* buf, UInt_t len, Int_t type)
423{
424 fEventId = buf[0];
425 if (type == 1) {
427 QuickProcessEvent(buf, len);
428 return kBMNSUCCESS;
429 } else if (type == 2) {
431 QuickConvertStatEvent(buf, len);
432 return kBMNSUCCESS;
433 } else
434 return kBMNERROR;
435}
436
438{
439 if (getRunId) {
440 BmnFileProp prop;
442 fRunId = prop.GetRunId();
443 }
444 if (getSubName)
446 fRawFileIn = fopen(name, "rb");
447 if (fRawFileIn == nullptr) {
448 LOGF(error, "Couldn't open file %s!!!!!\n", name.Data());
449 return kBMNERROR;
450 }
451 LOGF(info, ANSI_COLOR_BLUE "Starting to convert file %s" ANSI_COLOR_RESET, name.Data());
452 LOGF(info, "Period ID: %u, Run ID: %u, Subname: %s", fPeriodId, fRunId, fSubName.Data());
453 // if (!fRootFileOut)
454 // if (CreateTempFile() == kBMNERROR)
455 // return kBMNERROR;
456 for (UInt_t i = 0; i < fThreadCnt; i++)
457 fThreads->GetThread(i)->SetInitData(&vecTree, &vecTreeSpills);
458 TStopwatch* timer = new TStopwatch();
459 timer->Start();
461 // while ((ConvertRawToRootIterateFileReadFaster() != kBMNERROR)) {
462 // if ((fStartEventId == 0) && (fEventId))
463 // fStartEventId = fEventId;
464 // if (cc++>10000)
465 // break;
466 }
467 // LOGF(info,"tq size %ld ",fThreads->threadQueue.size());
468 if (fCurWaitingThread) { // crutch
469 fCurWaitingThread->CancelReady();
470 fCurWaitingThread = nullptr;
471 }
472 // LOGF(info,"tq size %ld ",fThreads->threadQueue.size());
473 fThreads->Finish();
474 timer->Stop();
475 LOGF(info, ANSI_COLOR_BLUE "Converted file %s in %.3fs\n" ANSI_COLOR_RESET, name.Data(), timer->RealTime());
476 std::fclose(fRawFileIn);
477 return kBMNSUCCESS;
478}
479
481{
482 // TStopwatch sw;
483 // sw.Start();
484 // printf("fMaxEvent %lu, fNSignalEvents %u, fMaxEvent %lu\n", fMaxEvent, fNSignalEvents, fMaxEvent);
486 // if (fMaxEvent > 0 && fNSignalEvents >= fMaxEvent) return kBMNERROR;
487 if (fread(&fDat, kWORDSIZE, 1, fRawFileIn) != 1)
488 return kBMNERROR;
489 // fCurentPositionRawFile = ftello64(fRawFileIn);
490 // if (fCurentPositionRawFile >= fLengthRawFile) return kBMNERROR;
491 switch (fDat) {
492 case SYNC_EVENT:
493 case SYNC_EVENT_OLD:
495 LOGF(debug2, ANSI_COLOR_BLUE "SYNC_EVENT %08X" ANSI_COLOR_RESET, fDat);
496 // read number of bytes in event
497 if (fread(&fDat, kWORDSIZE, 1, fRawFileIn) != 1)
498 return kBMNERROR;
499 if (fDat % kNBYTESINWORD) {
500 LOGF(error, "WTF?? in the main event: fDat == %u", fDat);
501 }
502 fDat = fDat / kNBYTESINWORD + (fPeriodId <= 7 ? 1 : 0); // bytes --> words
503 // printf("ev length %d\n", fDat);
504 // read array of current event data and process them
505 if (fread(data, kWORDSIZE, fDat, fRawFileIn) != fDat)
506 return kBMNERROR;
507 fEventId = data[0];
508 LOGF(debug, ANSI_COLOR_BLUE "iEv = %u" ANSI_COLOR_RESET, fEventId);
509 if (fEventId <= 0) {
510 return kBMNCONTINUE; // skip bad events
511 }
513 // ProcessEvent(data, fDat);
514
515 // LOGF(trace, "evType %d", fCurEvType);
516 // LOGF(debug, "eventHeaderDAQ %p", (void*) eventHeaderDAQ);
517 // LOGF(debug1, "isSpillStart %d", isSpillStart);
518 // if (isSpillStart == kTRUE)
519 // isSpillStart = kFALSE;
520 // fNTotalEvents++;
521 // fNSignalEvents++;
522 // nSpillEvents++;
523 break;
524 case SYNC_EOS:
526 case SYNC_STAT:
527 LOGF(debug2, ANSI_COLOR_BLUE "SYNC_STAT %08X" ANSI_COLOR_RESET, fDat);
528 if (fDat == SYNC_STAT)
530 // read number of bytes in event
531 if (fread(&fDat, kWORDSIZE, 1, fRawFileIn) != 1)
532 return kBMNERROR;
533 if (fDat % kNBYTESINWORD) {
534 LOGF(error, "WTF?? in the STAT: fDat == %u", fDat);
535 }
536 LOGF(debug3, "STAT ev length bytes %d", fDat);
537 fDat = fDat / kNBYTESINWORD + (fPeriodId <= 7 ? 1 : 0); // bytes --> words
538 // read array of current event data and process them
539 if (fread(data, kWORDSIZE, fDat, fRawFileIn) != fDat)
540 return kBMNERROR;
541 // ConvertStatEvent(data, fDat);
543 break;
544 case SYNC_RUN_START:
545 LOGF(debug, "RUN START");
546 case SYNC_RUN_STOP:
547 if (fDat == SYNC_RUN_STOP)
548 LOGF(debug, "RUN STOP");
549 if (fread(&fDat, kWORDSIZE, 1, fRawFileIn) != 1)
550 return kBMNERROR;
551 if (fread(data, 1, fDat, fRawFileIn) != fDat)
552 return kBMNERROR;
554 break;
555 case SYNC_FILE_BEGIN:
556 LOGF(debug, "FILE BEGIN");
557 case SYNC_FILE_END:
558 if (fDat == SYNC_FILE_END)
559 LOGF(debug, "FILE END");
560 if (fread(&fDat, kWORDSIZE, 1, fRawFileIn) != 1)
561 return kBMNERROR;
562 if (fread(data, 1, fDat, fRawFileIn) != fDat)
563 return kBMNERROR;
565 break;
566 case SYNC_JSON:
567 if (fread(&fDat, kWORDSIZE, 1, fRawFileIn) != 1)
568 return kBMNERROR;
569 LOGF(debug, "SYNC JSON len %u", fDat);
570 if (fread(data, 1, fDat, fRawFileIn) != fDat)
571 return kBMNERROR;
573 break;
574 default:
575 LOGF(error, "unrecognized sync %08X", fDat);
576 break;
577 }
578 return kBMNSUCCESS;
579}
580
581// BmnStatus BmnConverter::FeedSpill(TString name, Bool_t getRunId, Bool_t getSubName)
582//{ // Can be rewritten to work in multiple threads
583// if (getRunId)
584// fRunId = BmnRawDataDecoder::GetRunIdFromFile(name);
585// if (getSubName)
586// fSubName = BmnRawDataDecoder::GetSubNameFromFile(name);
587// TFile* fileIn = new TFile(name, "read");
588// if (fileIn == nullptr) {
589// LOGF(error, "Couldn't open file %s!!!!!\n", name.Data());
590// return kBMNERROR;
591// }
592// LOGF(info, ANSI_COLOR_BLUE "Starting to recover spill file %s" ANSI_COLOR_RESET, name.Data());
593// LOGF(info, "Period ID: %u, Run ID: %u, Subname: %s", fPeriodId, fRunId, fSubName.Data());
594// if (!fRootFileOut->IsOpen()) {
595// delete fRootFileOut;
596// LOGF(error, "Couldn't access the output file!!!!!\n");
597// return kBMNERROR;
598// }
599// TTree* tree = (TTree*)(fileIn->Get("BMN_RAW"));
600// TTree* treeSpills = (TTree*)(fileIn->Get("BMN_RAW_SPILLS"));
601// if (!tree || !treeSpills) {
602// LOGF(error, "Couldn't find needed trees in the spill file\n");
603// return kBMNERROR;
604// }
605// TStopwatch* timer = new TStopwatch();
606// timer->Start();
607// fThreads->Finish();
608// Int_t sigN = tree->GetEntriesFast(), statN = treeSpills->GetEntriesFast();
609// Int_t totalSigN = 0, totalStatN = 0;
610// for (UInt_t i = 0; i < fThreadCnt; i++) {
611// BmnConverterThread* tmp = fThreads->GetThread(i);
612// Int_t curSigN = sigN / fThreadCnt + (sigN % fThreadCnt > i ? 1 : 0);
613// Int_t curStatN = statN / fThreadCnt + (statN % fThreadCnt > i ? 1 : 0);
614// tree->SetBranchAddress("BmnEventHeader.", &(tmp->eventHeaderDAQ));
615// tree->SetBranchAddress("SYNC", &(tmp->sync));
616// tree->SetBranchAddress("ADC32", &(tmp->adc32));
617// tree->SetBranchAddress("ADC64", &(tmp->adc64));
618// tree->SetBranchAddress("ADC128", &(tmp->adc128));
619// tree->SetBranchAddress("ADC", &(tmp->adc));
620// tree->SetBranchAddress("TDC", &(tmp->tdc));
621// tree->SetBranchAddress("TQDC_ADC", &(tmp->tqdc_adc));
622// tree->SetBranchAddress("TQDC_TDC", &(tmp->tqdc_tdc));
623// tree->SetBranchAddress("HRB", &(tmp->hrb));
624// treeSpills->SetBranchAddress("MSC", &(tmp->msc));
625// treeSpills->SetBranchAddress("T0Raw", &(tmp->t0raw));
626// for (int j = 0; j < curSigN; j++) {
627// tree->GetEntry(totalSigN++);
628// tmp->fRawTree->Fill();
629// }
630// for (int j = 0; j < curStatN; j++) {
631// treeSpills->GetEntry(totalStatN++);
632// tmp->fRawTreeSpills->Fill();
633// }
634// LOGF(info, "Finished copying events to thread %d", i);
635// }
636// fileIn->Close();
637// fRootFileOut->cd();
638// timer->Stop();
639// LOGF(info, ANSI_COLOR_BLUE "Recovered spill file %s in %.3fs\n" ANSI_COLOR_RESET, name.Data(),
640// timer->RealTime()); return kBMNSUCCESS;
641// }
642
643void BmnConverter::QuickConvertStatEvent(UInt_t* d, UInt_t& len)
644{
645 BmnConverterThread* tmp = fThreads->GetWaitingThread();
646 tmp->SetData(2, len, d, fCurEvType, fRunId, fEventId);
647 tmp->Execute();
648}
649
650void BmnConverter::QuickProcessEvent(UInt_t* d, UInt_t& len)
651{
652 BmnConverterThread* tmp = fThreads->GetWaitingThread();
653 tmp->SetData(1, len, d, fCurEvType, fRunId, fEventId);
654 tmp->Execute();
655}
656
658{
659 // LOGF(info, "QuickConvertStatEvent thread %d", tmp->GetId());
660 tmp->SetData(2, len, nullptr, fCurEvType, fRunId, fEventId);
661 tmp->Execute();
662 tmp = nullptr;
663 // LOGF(info, "QuickConvertStatEvent thread %d done", tmp->GetId());
664}
665
667{
668 // LOGF(info, "QuickProcessEvent thread %d", tmp->GetId());
669 tmp->SetData(1, len, nullptr, fCurEvType, fRunId, fEventId);
670 tmp->Execute();
671 // LOGF(info, "QuickProcessEvent thread %d done", tmp->GetId());
672 tmp = nullptr;
673}
674
676{
677 try {
678 UInt_t idx = 0;
679 idx++; // skip evId (it is 0)
680 DeviceHeader* dh = reinterpret_cast<DeviceHeader*>(d + idx);
681 idx += sizeof(DeviceHeader) / kNBYTESINWORD;
682 // dh->Print();
683 UInt_t str_len = len - idx * kNBYTESINWORD;
684 string str(reinterpret_cast<const char*>(d + idx), str_len);
685 json j = json::parse(str);
686 // cout << "json type : " << j.type_name() << endl;
687 // Int_t key_cnt(0);
688 for (json::iterator it = j.begin(); it != j.end(); ++it) {
689 // std::cout << "["<< key_cnt <<"] : "<< it.key() << '\n';
690 string jkey(it.key());
691 // printf("j[%d] : %s\n", key_cnt++, jkey.c_str());
692 if (!jkey.compare("status")) {
693 auto& j_runtime = it.value()["runTime"];
694 auto j_spill = j_runtime["spill"];
695 Int_t phase = static_cast<Int_t>(j_spill["phase"]);
696 // UInt_t curSpillTimeMs = j_spill["curSpillTimeMs"];
697 auto wr = j_runtime["time"]["WR"];
698 Int_t ns = static_cast<Int_t>(wr["ns"]);
699 Int_t sec = static_cast<Int_t>(wr["sec"]);
700 if (tai_utc_dif == 0)
701 tai_utc_dif = GetUTCShift(TTimeStamp(time_t(sec), ns)); // crutch
702 sec -= tai_utc_dif;
704 // skip invalid timestamps
705 if (!ss.times_valid)
706 continue;
707 // if (ts_spill_start > eventHeaderDAQ->GetSpillStartTS()) {
708 // eventHeaderDAQ->SetSpillStartTS(ts_spill_start); // @TODO: rewrite with basing on
709 // spill map eventHeaderDAQ->GetSpillId()++; LOGF(debug, "spill_id %d",
710 // eventHeaderDAQ->GetSpillId());
711 // }
712 LOGF(info, "JSON status phase %d", phase);
713 LOGF(info, "ts :\t%s start", BmnFunctionSet::TimePoint2String(ss.start_ts));
714 if (phase == 0)
715 LOGF(info, "ts :\t%s stop", BmnFunctionSet::TimePoint2String(ss.stop_ts));
716 auto spill_it = fSpillMap.find(ss.start_ts);
717 if (spill_it == fSpillMap.end()) {
718 bool inserted;
719 std::tie(spill_it, inserted) = fSpillMap.insert(
720 make_pair(ss.start_ts,
721 BmnSpillInfo{// .jsons = vector<json>(1, it.value()),
722 .start_ts = ss.start_ts,
723 .stop_ts = ss.start_ts}));
724 LOGF(debug, "spill record inserted %d", inserted);
725 }
726 BmnSpillInfo& info = spill_it->second;
727 // info.jsons.push_back(it.value());
728 if (info.stop_ts < ss.stop_ts)
729 info.stop_ts = ss.stop_ts;
730 if (fExportJsonBlocks) {
731 std::ofstream outfile(Form("j_%s_%d_%9d_%09d_%02X_%08X_phase_%d.json", jkey.c_str(), fRunId, sec,
732 ns, dh->DeviceId, dh->Serial, phase),
733 std::ofstream::binary);
734 outfile << std::setw(4) << j << std::endl;
735 outfile.close();
736 }
737 metadata->SpillStatusVec().push_back(move(ss));
738 } else {
739 LOGF(info, "JSON config");
740 if (!jkey.compare("config")) {
741 string start_DT = it.value()["meta"]["startDateTime"];
742 if (fExportJsonBlocks) {
743 std::ofstream outfile(Form("j_%s_%d_%s_%02X_%08X.json", jkey.c_str(), fRunId, start_DT.data(),
744 dh->DeviceId, dh->Serial),
745 std::ofstream::binary);
746 outfile << std::setw(4) << j << std::endl;
747 outfile.close();
748 }
749 BmnStatus jconfigStatus =
750 BmnConverterTools::ParseJsonConfig(it.value(), runHeader->GetTrigConfig());
751 if (jconfigStatus == kBMNERROR)
752 LOGF(error, "Parsing JSON config failed!");
753 } else
754 LOGF(info, "Unknown json key %s", jkey.data());
755 }
756 }
757 } catch (std::exception& ex) {
758 LOGF(error, "Exception for JSON block: %s", ex.what());
759 }
760 return kBMNSUCCESS;
761}
762
764{
765 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1972, 1, 1, 0, 0, 9), 10));
766 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1972, 7, 1, 0, 0, 10), 11));
767 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1973, 1, 1, 0, 0, 11), 12));
768 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1974, 1, 1, 0, 0, 12), 13));
769 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1975, 1, 1, 0, 0, 13), 14));
770 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1976, 1, 1, 0, 0, 14), 15));
771 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1977, 1, 1, 0, 0, 15), 16));
772 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1978, 1, 1, 0, 0, 16), 17));
773 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1979, 1, 1, 0, 0, 17), 18));
774 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1980, 1, 1, 0, 0, 18), 19));
775 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1981, 7, 1, 0, 0, 19), 20));
776 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1982, 7, 1, 0, 0, 20), 21));
777 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1983, 7, 1, 0, 0, 21), 22));
778 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1985, 7, 1, 0, 0, 22), 23));
779 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1988, 1, 1, 0, 0, 23), 24));
780 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1990, 1, 1, 0, 0, 24), 25));
781 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1991, 1, 1, 0, 0, 25), 26));
782 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1992, 7, 1, 0, 0, 26), 27));
783 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1993, 7, 1, 0, 0, 27), 28));
784 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1994, 7, 1, 0, 0, 28), 29));
785 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1996, 1, 1, 0, 0, 29), 30));
786 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1997, 7, 1, 0, 0, 30), 31));
787 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(1999, 1, 1, 0, 0, 31), 32));
788 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(2006, 1, 1, 0, 0, 32), 33));
789 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(2009, 1, 1, 0, 0, 33), 34));
790 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(2012, 7, 1, 0, 0, 34), 35));
791 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(2015, 7, 1, 0, 0, 35), 36));
792 leaps.insert(pair<TTimeStamp, Int_t>(TTimeStamp(2017, 1, 1, 0, 0, 36), 37));
793 utc_valid = TTimeStamp(2026, 1, 1, 0, 0, 1);
794 return kBMNSUCCESS;
795}
796
798{
799 if (t < leaps.begin()->first) {
800 LOGF(warning, "Wrong time! %s", t.AsString());
801 return 0;
802 }
803 if (t > utc_valid)
804 LOGF(warning, "Warning! Leap seconds table expired!");
805 Int_t shift = 0;
806 auto it = leaps.lower_bound(t);
807 if ((it == leaps.end()))
808 it--;
809 else if (it->first > t)
810 it--;
811 shift = it->second;
812 return shift;
813}
int i
Definition P4_F32vec4.h:22
bool Bool_t
int Int_t
char * Form(const char *fmt,...)
BmnStatus
Define status code.
Definition BmnEnums.h:93
@ kBMNERROR
Error.
Definition BmnEnums.h:95
@ kBMNSUCCESS
Success.
Definition BmnEnums.h:94
@ kBMNCONTINUE
Definition BmnEnums.h:98
@ kBMNSTAT
Statistics.
Definition BmnEnums.h:147
@ kBMNEOS
End of spill.
Definition BmnEnums.h:146
@ kBMNPAYLOAD
spill event.
Definition BmnEnums.h:145
@ kBMNEMPTY
No event (wrong sync word or metadata payload).
Definition BmnEnums.h:148
std::chrono::time_point< SysClock > SysPoint
#define ANSI_COLOR_RESET
Definition BmnMath.h:18
#define ANSI_COLOR_BLUE
Definition BmnMath.h:17
const uint32_t SYNC_RUN_START
Definition RawTypes.h:10
const uint32_t SYNC_EVENT
Definition RawTypes.h:5
const uint32_t SYNC_EOS
Definition RawTypes.h:8
const uint32_t SYNC_STAT
Definition RawTypes.h:7
const uint32_t SYNC_JSON
Definition RawTypes.h:9
const uint32_t SYNC_RUN_STOP
Definition RawTypes.h:11
const uint32_t kNBYTESINWORD
Definition RawTypes.h:19
const uint32_t SYNC_FILE_BEGIN
Definition RawTypes.h:12
const uint32_t SYNC_FILE_END
Definition RawTypes.h:13
const uint32_t SYNC_EVENT_OLD
Definition RawTypes.h:6
const size_t kWORDSIZE
Definition RawTypes.h:18
void SetMerger(TBufferMerger *m)
void SetPeriod(uint32_t v)
void SetExportExternalSpillStat(bool v)
void SetData(Int_t taskId, Int_t len=0, const uint32_t *data=nullptr, BmnEventType fCurEvType=kBMNEMPTY, uint32_t fRunId=7444, uint32_t fEventId=-1)
BmnEventHeader * eventHeaderDAQ
static TString GetSubNameAfterRunId(TString name)
static BmnStatus ParseRawFileName(const TString &s, BmnFileProp &prop)
static BmnStatus ParseJsonConfig(json &j, BmnTrigConfig &trig_conf)
static BmnStatus ParseComplexTLV(const uint32_t *buf, UInt_t &len, UInt_t &runId)
static SpillStatus ParseJsonStatus(json &j, Int_t tai_utc_dif=0)
uint32_t fRunId
void QuickProcessEvent(UInt_t *d, UInt_t &len)
map< int32_t, MapTP2TreePE > treeTimeMapDiv
BmnStatus ParseJsonTLV(UInt_t *buf, UInt_t &len)
Bool_t fExportJsonBlocks
TString fRawRunHdrName
uint32_t data[10000000]
BmnConverterThread * fCurWaitingThread
BmnStatus FeedEvent(UInt_t *buf, UInt_t len, Int_t type)
BmnStatus FeedFile(TString name, Bool_t getRunId=kTRUE, Bool_t getSubName=kTRUE)
TString fRootDirPath
multimap< SysPoint, TreePE > treeTimeMap
void ReproduceBranches(TTree *inTree, TTree *outTree)
uint32_t fPeriodId
BmnThreadManager< BmnConverterThread > * fThreads
vector< TClonesArray * > fArrVec
uint32_t fThreadCnt
void QuickConvertStatEvent(UInt_t *buf, UInt_t &len)
BmnStatus LoadConfig()
vector< TObject * > fNamVec
unique_ptr< DigiRunHeader > runHeader
void SeparateEventsBySpills()
unique_ptr< BmnMetadataRaw > metadata
TString fRawTreeName
BmnConverter(uint32_t threadCount=0, uint32_t period=8, TString outDir=".", bool tempFileOnDisk=false)
BmnStatus CreateTempFile()
TString fMetadataName
map< SysPoint, BmnSpillInfo > fSpillMap
uint32_t fEventId
BmnEventType fCurEvType
BmnStatus ConvertRawToRootIterateFileRead()
pt::ptree conf
void SeparateEventsBySpillsTM()
TString fRawTreeSpillName
TTimeStamp utc_valid
bool temp_file_on_disk
TString fSubName
map< TTimeStamp, Int_t > leaps
FILE * fRawFileIn
BmnSpillHeader * spillHeader
uint32_t fDat
vector< pair< int, pair< int, int > > > vecTree
Int_t GetUTCShift(TTimeStamp t)
Int_t GetSpillNumber(vector< SysPoint > *spillEnds, vector< SysPoint > *spillStarts, SysPoint time)
BmnStatus InitUTCShift()
TString fRootFileName
unique_ptr< ROOT::TBufferMerger > fMerger
string fDecoderConfigFileName
vector< pair< int, pair< int, int > > > vecTreeSpills
SysPoint GetEventTimeTP()
uint32_t GetRunId() const
Definition BmnFileProp.h:22
static std::string TimePoint2String(SysPoint p)
static SysPoint TimeStamp2TP(TTimeStamp p)
Class BmnMetadataRaw for the configuration and raw spill information.
T0 module spill settings and counts.
Definition BmnT0Raw.h:70
virtual char * GetAddress() const
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
static TClass * GetClass(Bool_t load=kTRUE, Bool_t silent=kFALSE)
TClass * GetClass() const
static TClass * Class()
T * Get(const char *namecycle)
std::enable_if_t<!std::is_base_of< TObject, T >::value, Int_t > WriteObject(const T *obj, const char *name, Option_t *option="", Int_t bufsize=0)
virtual Bool_t IsOpen() const
void Close(Option_t *option="") override
const char * GetName() const override
Int_t GetEntriesFast() const
Int_t GetEntries() const override
TObject * At(Int_t idx) const override
TObject * First() const override
virtual const char * ClassName() const
Double_t RealTime()
void Start(Bool_t reset=kTRUE)
void Stop()
const char * Data() const
static TString Format(const char *fmt,...)
const char * AsString(const Option_t *option="") const
virtual Int_t Fill()
virtual TBranch * GetBranch(const char *name)
virtual Int_t GetEntry(Long64_t entry, Int_t getall=0)
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
virtual void SetAutoSave(Long64_t autos=-300000000)
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
virtual TObjArray * GetListOfBranches()
virtual Long64_t GetEntriesFast() const
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
virtual void SetAutoFlush(Long64_t autof=-30000000)
virtual Int_t Branch(const char *folder, Int_t bufsize=32000, Int_t splitlevel=99)
pair< TTree *, uint64_t > TreePE
*brief user defined string literal for JSON values *sa std::size_t n
Definition json.hpp:20362
void EnableThreadSafety()
void EnableImplicitMT(ROOT::EIMTConfig config)
void DisableImplicitMT()
SysPoint stop_ts
Class SpillStatus raw spill status from JSON block.
Definition SpillStatus.h:20
SysPoint start_ts
Definition SpillStatus.h:39
bool times_valid
Definition SpillStatus.h:46
SysPoint stop_ts
Definition SpillStatus.h:40