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