Project
Loading...
Searching...
No Matches
VisualisationEventOpenGLSerializer.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
19#include <fairlogger/Logger.h>
20#include <iostream>
21#include <fstream>
22#include <filesystem>
23
25{
26
45
46std::string detectors(const std::vector<std::string>& det, unsigned mask)
47{
48 std::string result;
49 std::string delim;
50 int bit = 1;
51 for (const auto& i : det) {
52 if (mask & bit) {
53 result += delim + i;
54 delim = ",";
55 }
56 bit = bit << 1;
57 }
58 return result;
59}
60
61const auto HEAD = "HEAD";
62const auto TTYP = "TTYP";
63const auto CELM = "CELM";
64const auto TELM = "TELM";
65const auto TIME = "TIME"; // track time
66const auto SXYZ = "SXYZ"; // track start xyz
67const auto CRGE = "CRGE"; // charge for track
68const auto ATPE = "ATPE"; // angles: theta,phi,eta for track
69const auto TGID = "TGID"; // track GID
70const auto TPID = "TPID"; // track PID
71const auto TXYZ = "TXYZ"; // track poinst x,y,z
72const auto CXYZ = "CXYZ"; // track clusters x,y,z
73
74const auto UXYZ = "UXYZ"; // global clusters x,y,z
75const auto UGID = "UGID"; // global GID
76const auto UTIM = "UTIM"; // global Time
77
78const auto CALO = "CALO"; // calo phi,eta,enargy
79const auto CALP = "CALP"; // calo PID
80const auto CALG = "CALG"; // calo GID
81const auto CALT = "CALT"; // calo PID
82
83const auto FINE = "FINE"; //
84
86{
87 static const std::vector<std::string> det_coma = {
88 "ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "ITS-TPC",
89 "TPC-TOF", "TPC-TRD", "MFT-MCH", "ITS-TPC-TRD", "ITS-TPC-TOF", "TPC-TRD-TOF", "MFT-MCH-MID", "ITS-TPC-TRD-TOF", "ITS-AB", "CTP",
90 "MCH-MID"};
91 std::ostringstream buf;
92 constexpr auto SIGSIZE = 512;
93 unsigned char data[SIGSIZE];
94 std::ofstream out(fileName, std::ios::out | std::ios::binary);
95 // head --bytes 512 fileName.eve
96 buf << "eve" << std::endl;
97 buf << "version=1.00" << std::endl;
98 buf << "run=" << event.getRunNumber() << std::endl;
99 buf << "firstTForbit=" << event.getFirstTForbit() << std::endl;
100 buf << "detectors=" << detectors(det_coma, event.getTrkMask()) << std::endl;
101 buf << "preview='"
102 << "dd if=thisFileName.eve of=thisFileName.png skip=20 bs=1 count=6000000" << std::endl;
103 buf << std::string(SIGSIZE, ' ');
104 memcpy((char*)&data[0], buf.str().c_str(), SIGSIZE);
105 data[SIGSIZE - 2] = '\n';
106 data[SIGSIZE - 1] = 0;
107 out.write((char*)&data[0], SIGSIZE); // <----0 SIGN
108
109 const auto trackNo = event.getTracksSpan().size();
110 int phsCount = 0;
111 int emcCount = 0;
112 {
113 for (const auto& calo : event.getCalorimetersSpan()) {
114 if (calo.getSource() == o2::dataformats::GlobalTrackID::PHS) {
115 phsCount++;
116 }
117 if (calo.getSource() == o2::dataformats::GlobalTrackID::EMC) {
118 emcCount++;
119 }
120 }
121 }
122
123 // header
124 {
125 const auto chunkHEAD = createChunk(HEAD, Header::last * 4);
126 const auto head = asUnsigned(chunkHEAD);
127 head[Header::version] = event.mEveVersion;
128 head[Header::runNumber] = event.getRunNumber();
129 unsigned long creationTime = event.getCreationTime();
130 head[Header::creationTimeLow] = creationTime;
131 head[Header::creationTimeHigh] = creationTime / (1L << 32);
132 ;
133 head[Header::firstTForbit] = event.getFirstTForbit();
134 head[Header::runType] = event.getRunType();
135 head[Header::trkMask] = event.getTrkMask();
136 head[Header::clMask] = event.getClMask();
137 head[Header::trackCount] = event.getTrackCount();
138 head[Header::clusterCount] = event.getClusterCount(); // clusterno
141 head[Header::primaryVertex] = event.getPrimaryVertex();
142 head[Header::tfCounter] = event.getTfCounter();
143 out.write(static_cast<char*>(chunkHEAD), chunkSize(chunkHEAD)); // <----1 HEAD
144 free(chunkHEAD);
145 }
146
147 // information about number of track by type
148 unsigned totalPoints = 0;
149 unsigned totalClusters = 0;
150 {
151 const auto chunkTELM = createChunk(TELM, trackNo); // number of track points for each track
152 const auto telm = asByte(chunkTELM);
153 const auto chunkTGID = createChunk(TGID, 4 * trackNo); // number of track points for each track
154 const auto tgid = asUnsigned(chunkTGID);
155 const auto chunkTPID = createChunk(TPID, 4 * trackNo); // number of track points for each track
156 const auto tpid = asUnsigned(chunkTPID);
157 const auto chunkCELM = createChunk(CELM, trackNo); // number of track clusters for each track
158 const auto celm = asByte(chunkCELM);
159
160 const auto chunkTTYP = createChunk(TTYP, 4 * 27);
161 const auto ttyp = asUnsigned(chunkTTYP);
162 unsigned index = 0;
163 for (const auto& track : event.getTracksSpan()) {
164 tgid[index] = track.mBGID;
165 tpid[index] = track.mPID;
166 const auto ttypeidx = track.mBGID.getSource();
167 ttyp[ttypeidx]++;
168 totalPoints += track.getPointCount(); // here to pre-compute (performance)
169 totalClusters += track.getClusterCount(); // here to pre-compute (performance)
170 telm[index] = track.getPointCount();
171 celm[index] = track.getClusterCount();
172 index++;
173 }
174 out.write(static_cast<char*>(chunkTTYP), chunkSize(chunkTTYP)); // <----2 TTYP
175 free(chunkTTYP);
176 out.write(static_cast<char*>(chunkTELM), chunkSize(chunkTELM)); // <----3 TELM
177 free(chunkTELM);
178 out.write(static_cast<char*>(chunkCELM), chunkSize(chunkCELM)); // <----3 CELM
179 free(chunkCELM);
180 out.write(static_cast<char*>(chunkTGID), chunkSize(chunkTGID)); // <----3 GIND
181 free(chunkTGID);
182 out.write(static_cast<char*>(chunkTPID), chunkSize(chunkTPID)); // <----3 TPID (tracks pid)
183 free(chunkTPID);
184 }
185
186 {
187 const auto chunkTXYZ = createChunk(TXYZ, totalPoints * 4 * 3);
188 const auto txyz = asFloat(chunkTXYZ);
189 unsigned tidx = 0; // track elem (point coordinate)positions
190
191 const auto chunkTIME = createChunk(TIME, trackNo * 4);
192 const auto time = asFloat(chunkTIME);
193 unsigned tno = 0; // track positions
194
195 const auto chunkSXYZ = createChunk(SXYZ, trackNo * 4 * 3);
196 const auto sxyz = asFloat(chunkSXYZ);
197 unsigned sxyzidx = 0; // starting point track positions
198
199 const auto chunkATPE = createChunk(ATPE, trackNo * 4 * 3);
200 const auto atpe = asFloat(chunkATPE);
201 unsigned atpeidx = 0; // starting point track positions
202
203 const auto chunkCRGE = createChunk(CRGE, trackNo);
204 const auto crge = asSignedByte(chunkCRGE);
205
206 const auto chunkCXYZ = createChunk(CXYZ, totalClusters * 4 * 3);
207 const auto cxyz = asFloat(chunkCXYZ);
208 unsigned cidx = 0; // cluster positions
209
210 for (const auto& track : event.getTracksSpan()) {
211 time[tno] = track.getTime();
212 crge[tno] = static_cast<signed char>(track.getCharge());
213 tno++;
214 sxyz[sxyzidx++] = track.getStartCoordinates()[0];
215 sxyz[sxyzidx++] = track.getStartCoordinates()[1];
216 sxyz[sxyzidx++] = track.getStartCoordinates()[2];
217
218 atpe[atpeidx++] = track.getTheta();
219 atpe[atpeidx++] = track.getPhi();
220 atpe[atpeidx++] = track.mEta;
221
222 for (unsigned i = 0; i < track.mPolyX.size(); i++) {
223 txyz[tidx++] = track.mPolyX[i];
224 txyz[tidx++] = track.mPolyY[i];
225 txyz[tidx++] = track.mPolyZ[i];
226 }
227 for (unsigned i = 0; i < track.getClusterCount(); i++) {
228 cxyz[cidx++] = track.getClustersSpan()[i].X();
229 cxyz[cidx++] = track.getClustersSpan()[i].Y();
230 cxyz[cidx++] = track.getClustersSpan()[i].Z();
231 }
232 }
233 out.write(static_cast<char*>(chunkTXYZ), chunkSize(chunkTXYZ)); // <----4 TXYZ
234 free(chunkTXYZ);
235 out.write(static_cast<char*>(chunkCXYZ), chunkSize(chunkCXYZ)); // <----4 CXYZ
236 free(chunkCXYZ);
237 out.write(static_cast<char*>(chunkTIME), chunkSize(chunkTIME)); // <----4 TIME
238 free(chunkTIME);
239 out.write(static_cast<char*>(chunkSXYZ), chunkSize(chunkSXYZ)); // <----4 SXYZ
240 free(chunkSXYZ);
241 out.write(static_cast<char*>(chunkCRGE), chunkSize(chunkCRGE)); // <----4 CRGE
242 free(chunkCRGE);
243 out.write(static_cast<char*>(chunkATPE), chunkSize(chunkATPE)); // <----4 CRGE
244 free(chunkATPE);
245 }
246
247 {
248 const auto chunkUXYZ = createChunk(UXYZ, clusterCount * 4 * 3); // X,Y,Z
249 const auto uxyz = asFloat(chunkUXYZ);
250 const auto chunkUTIM = createChunk(UTIM, clusterCount * 4); // time
251 const auto utim = asFloat(chunkUTIM);
252 const auto chunkUGID = createChunk(UGID, clusterCount * 4); // time
253 const auto ugid = asUnsigned(chunkUGID);
254 unsigned idx = 0; // positions
255
256 for (const auto& c : event.getClustersSpan()) {
257 utim[idx / 3] = c.mTime;
258 ugid[idx / 3] = serialize(c.mBGID);
259 uxyz[idx++] = c.X();
260 uxyz[idx++] = c.Y();
261 uxyz[idx++] = c.Z();
262 }
263 out.write(static_cast<char*>(chunkUGID), chunkSize(chunkUGID)); //
264 free(chunkUGID);
265 out.write(static_cast<char*>(chunkUTIM), chunkSize(chunkUTIM)); //
266 free(chunkUTIM);
267 out.write(static_cast<char*>(chunkUXYZ), chunkSize(chunkUXYZ)); //
268 free(chunkUXYZ);
269 }
270
271 {
272 const auto chunkCALO = createChunk(CALO, (phsCount + emcCount) * 4 * 3); // phi, eta, energy
273 const auto calo = asFloat(chunkCALO);
274 const auto chunkCALP = createChunk(CALP, (phsCount + emcCount) * 4); // PID
275 const auto calp = asUnsigned(chunkCALP);
276 const auto chunkCALG = createChunk(CALG, (phsCount + emcCount) * 4); // PID
277 const auto calg = asUnsigned(chunkCALG);
278 const auto chunkCALT = createChunk(CALT, (phsCount + emcCount) * 4); // PID
279 const auto calt = asFloat(chunkCALT);
280 unsigned idx = 0; // positions
281
282 for (const auto& c : event.getCalorimetersSpan()) {
283 if (c.getSource() == o2::dataformats::GlobalTrackID::PHS) {
284 calt[idx / 3] = c.getTime();
285 calp[idx / 3] = serialize(c.getPID());
286 calg[idx / 3] = serialize(c.getGID());
287 calo[idx++] = c.getPhi();
288 calo[idx++] = c.getEta();
289 calo[idx++] = c.getEnergy();
290 }
291 }
292 for (const auto& c : event.getCalorimetersSpan()) {
293 if (c.getSource() == o2::dataformats::GlobalTrackID::EMC) {
294 calt[idx / 3] = c.getTime();
295 calp[idx / 3] = serialize(c.getPID());
296 calg[idx / 3] = serialize(c.getGID());
297 calo[idx++] = c.getPhi();
298 calo[idx++] = c.getEta();
299 calo[idx++] = c.getEnergy();
300 }
301 }
302
303 out.write((char*)chunkCALO, chunkSize(chunkCALO)); //
304 free(chunkCALO);
305 out.write((char*)chunkCALP, chunkSize(chunkCALP)); //
306 free(chunkCALP);
307 out.write((char*)chunkCALG, chunkSize(chunkCALG)); //
308 free(chunkCALG);
309 out.write((char*)chunkCALT, chunkSize(chunkCALT)); //
310 free(chunkCALT);
311 }
312
313 {
314 const auto chunkFINE = createChunk(FINE, 0);
315 out.write(static_cast<char*>(chunkFINE), chunkSize(chunkFINE)); // <----5 FINE
316 free(chunkFINE);
317 }
318 out.close();
319}
320
321void* VisualisationEventOpenGLSerializer::createChunk(const char* lbl, unsigned size)
322{
323 const auto result = static_cast<unsigned char*>(calloc(4 * ((size + 3) / 4) + 8, 1));
324 result[0] = lbl[0];
325 result[1] = lbl[1];
326 result[2] = lbl[2];
327 result[3] = lbl[3];
328 const auto uResult = (unsigned*)&result[4];
329 *uResult = 4 * ((size + 3) / 4);
330 return result;
331}
332
333unsigned VisualisationEventOpenGLSerializer::chunkSize(void* chunk)
334{
335 const auto uResult = (unsigned*)((char*)chunk + 4);
336 return *uResult + 8;
337}
338
339long timestamp_from_filename(const std::string& s)
340{
341 const auto pos1 = s.find("tracks_");
342 if (pos1 == std::string::npos) {
343 return 0;
344 }
345 const auto pos2 = s.find('_', pos1 + 7);
346 if (pos2 == std::string::npos) {
347 return 0;
348 }
349 std::string::size_type sz; // alias of size_t
350 const auto str_dec = s.substr(pos1 + 7, pos2 - pos1 - 7);
351 const long li_dec = std::strtol(str_dec.c_str(), nullptr, 10);
352 return li_dec;
353}
354
356{
357 std::filesystem::path inputFilePath{fileName};
358 auto length = (long)std::filesystem::file_size(inputFilePath);
359 if (length == 0) {
360 return {}; // empty vector
361 }
362 std::vector<std::byte> buffer(length);
363 std::ifstream inputFile(fileName, std::ios_base::binary);
364 inputFile.read(reinterpret_cast<char*>(buffer.data()), length);
365 inputFile.close();
366
367 long position = 512;
368 char type[5];
369 type[0] = 0;
370 type[4] = 0; // ending 0 for string
371
372 auto trackCount = 0L;
373 auto clusterCount = 0L;
374 unsigned char* telm = nullptr;
375 unsigned char* celm = nullptr;
376 unsigned int* ttyp = nullptr;
377 float* txyz = nullptr;
378 float* cxyz = nullptr;
379
380 float* time = nullptr;
381 float* sxyz = nullptr;
382 signed char* crge = nullptr;
383 float* atpe = nullptr;
384 unsigned* tgid = nullptr;
385 unsigned* tpid = nullptr;
386
387 float* calo = nullptr;
388 unsigned* calp = nullptr;
389 unsigned* calg = nullptr;
390 float* calt = nullptr;
391
392 unsigned* ugid = nullptr;
393 float* utim = nullptr;
394 float* uxyz = nullptr;
395
396 unsigned phsCaloCount = 0;
397 unsigned emcCaloCount = 0;
398
399 while (true) {
400 for (auto c = 0; c < 4; c++) {
401 type[c] = (char)buffer.at(position + c);
402 }
403 auto* words = (unsigned*)(buffer.data() + position + 4);
404 position = position + *words + 8;
405 words++;
406 if (std::string(type) == HEAD) {
407 auto head = words;
408 event.mEveVersion = head[Header::version];
409 event.setRunNumber(head[Header::runNumber]);
410 // event.setCreationTime(head[Header::creationTimeLow]+head[Header::creationTimeHigh]*(1L<<32));
411 event.setCreationTime(timestamp_from_filename(fileName));
412 event.setFirstTForbit(head[Header::firstTForbit]);
413 event.setRunType((parameters::GRPECS::RunType)head[Header::runType]);
414 event.setTrkMask((int)head[Header::trkMask]);
415 phsCaloCount = head[Header::phsCount];
416 emcCaloCount = head[Header::emcCount];
417 event.setClMask((int)head[Header::clMask]);
420 event.setPrimaryVertex(head[11]);
421 event.setTfCounter(head[12]);
422 } else if (std::string(type) == TELM) {
423 telm = (unsigned char*)words;
424 } else if (std::string(type) == CELM) {
425 celm = (unsigned char*)words;
426 } else if (std::string(type) == TTYP) {
427 ttyp = (unsigned int*)words;
428 } else if (std::string(type) == TIME) {
429 time = (float*)words;
430 } else if (std::string(type) == TXYZ) {
431 txyz = (float*)words;
432 } else if (std::string(type) == CXYZ) {
433 cxyz = (float*)words;
434 } else if (std::string(type) == SXYZ) {
435 sxyz = (float*)words;
436 } else if (std::string(type) == CRGE) {
437 crge = (signed char*)words;
438 } else if (std::string(type) == ATPE) {
439 atpe = (float*)words;
440 } else if (std::string(type) == TGID) {
441 tgid = (unsigned*)words;
442 } else if (std::string(type) == TPID) {
443 tpid = (unsigned*)words;
444 } else if (std::string(type) == UXYZ) {
445 uxyz = (float*)words;
446 } else if (std::string(type) == UGID) {
447 ugid = (unsigned*)words;
448 } else if (std::string(type) == UTIM) {
449 utim = (float*)words;
450 } else if (std::string(type) == CALO) {
451 calo = (float*)words;
452 } else if (std::string(type) == CALP) {
453 calp = (unsigned*)words;
454 } else if (std::string(type) == CALG) {
455 calg = (unsigned*)words;
456 } else if (std::string(type) == CALT) {
457 calt = (float*)words;
458 } else if (std::string(type) == FINE) {
459 assert(telm != nullptr);
460 assert(celm != nullptr);
461 assert(ttyp != nullptr);
462 assert(txyz != nullptr);
463 assert(cxyz != nullptr);
464 assert(time != nullptr);
465 assert(sxyz != nullptr);
466 assert(crge != nullptr);
467 assert(atpe != nullptr);
468 assert(tgid != nullptr);
469 assert(tpid != nullptr);
470 assert(uxyz != nullptr);
471 assert(ugid != nullptr);
472 assert(utim != nullptr);
473 assert(calo != nullptr);
474 assert(calp != nullptr);
475 assert(calg != nullptr);
476 assert(calt != nullptr);
477 int ttypidx = 0; // tracks are stored in order ITS,TPC,... where ttyp cointains a number
478 int txyzidx = 0; // coordinates
479 int cxyzidx = 0; // coordinates
480 // TRACKS
481 for (auto t = 0; t < trackCount; t++) {
482 while (ttyp[ttypidx] == 0) {
483 ttypidx++;
484 }
485 ttyp[ttypidx]--;
486 auto track = event.addTrack({.time = time[t],
487 .charge = crge[t],
488 .PID = (int)tpid[t],
489 .startXYZ = {sxyz[3 * t + 0], sxyz[3 * t + 1], sxyz[3 * t + 2]},
490 .phi = atpe[3 * t + 1],
491 .theta = atpe[3 * t + 0],
492 .eta = atpe[3 * t + 2],
493 .gid = deserialize(tgid[t])});
494 track->mPolyX.reserve(telm[t]);
495 track->mPolyY.reserve(telm[t]);
496 track->mPolyZ.reserve(telm[t]);
497 while (telm[t]-- > 0) {
498 track->mPolyX.push_back(txyz[txyzidx++]);
499 track->mPolyY.push_back(txyz[txyzidx++]);
500 track->mPolyZ.push_back(txyz[txyzidx++]);
501 }
502 track->mClusters.reserve(celm[t]);
503 while (celm[t]-- > 0) {
504 VisualisationCluster cluster(cxyz + cxyzidx, 0, 0);
505 cxyzidx += 3;
506 track->mClusters.push_back(cluster);
507 }
508 }
509
510 // Clusters
511 for (auto c = 0u; c < clusterCount; c++) {
512 event.addGlobalCluster(uxyz + 3 * c, utim[c], deserialize(ugid[c]));
513 }
514
515 // Calos
516 auto idx = 0;
517 for (auto c = 0u; c < phsCaloCount + emcCaloCount; c++) {
518 auto phi = calo[idx++];
519 auto eta = calo[idx++];
520 auto energy = calo[idx++];
521 event.addCalo({.time = calt[c],
522 .energy = energy,
523 .phi = phi,
524 .eta = eta,
525 .PID = deserialize(calp[c]),
526 .gid = deserialize(calg[c])});
527 }
528
529 break;
530 }
531 }
532 return false;
533}
534
535} // namespace o2::event_visualisation
int16_t time
Definition RawEventData.h:4
int32_t i
Global index for barrel track: provides provenance (detectors combination), index in respective array...
uint32_t c
Definition RawData.h:2
bool fromFile(VisualisationEvent &event, std::string fileName) override
void toFile(const VisualisationEvent &event, std::string fileName) override
static unsigned serialize(o2::dataformats::GlobalTrackID gidValue)
static o2::dataformats::GlobalTrackID deserialize(unsigned seralizedValue)
struct _cl_event * event
Definition glcorearb.h:2982
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint buffer
Definition glcorearb.h:655
GLsizeiptr size
Definition glcorearb.h:659
GLuint index
Definition glcorearb.h:781
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLboolean * data
Definition glcorearb.h:298
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
GLint GLuint mask
Definition glcorearb.h:291
long timestamp_from_filename(const std::string &s)
std::string detectors(const std::vector< std::string > &det, unsigned mask)