diff --git a/EventVisualisation/Base/include/EventVisualisationBase/DirectoryLoader.h b/EventVisualisation/Base/include/EventVisualisationBase/DirectoryLoader.h index 100260bf906b1..183b40aaf3265 100644 --- a/EventVisualisation/Base/include/EventVisualisationBase/DirectoryLoader.h +++ b/EventVisualisation/Base/include/EventVisualisationBase/DirectoryLoader.h @@ -17,6 +17,7 @@ #define O2EVE_DIRECTORYLOADER_H #include +#include #include namespace o2 @@ -27,13 +28,13 @@ namespace event_visualisation class DirectoryLoader { private: - static int getNumberOfFiles(std::string& path, std::string& ext); - static std::string getLatestFile(std::string& path, std::string& ext); + static int getNumberOfFiles(std::string& path, std::vector& ext); + static std::string getLatestFile(std::string& path, std::vector& ext); public: - static std::deque load(const std::string& path, const std::string& marker, const std::string& ext); + static std::deque load(const std::string& path, const std::string& marker, const std::vector& ext); static void reduceNumberOfFiles(const std::string& path, const std::deque& files, std::size_t filesInFolder); - static void removeOldestFiles(std::string& path, std::string ext, int remaining); + static void removeOldestFiles(std::string& path, std::vector& ext, int remaining); }; } // namespace event_visualisation diff --git a/EventVisualisation/Base/include/EventVisualisationBase/FileWatcher.h b/EventVisualisation/Base/include/EventVisualisationBase/FileWatcher.h index 5e7822c88a38a..c6858abc218df 100644 --- a/EventVisualisation/Base/include/EventVisualisationBase/FileWatcher.h +++ b/EventVisualisation/Base/include/EventVisualisationBase/FileWatcher.h @@ -18,6 +18,7 @@ #include #include +#include namespace o2 { @@ -33,10 +34,11 @@ class FileWatcher std::string prevItem(const std::string& item) const; std::string mDataFolder; ///< folder being observed std::string mCurrentFile; ///< "current" file name + std::vector mExt; ///< extensions of files to be observed bool currentFileExist(); public: - FileWatcher(const std::string& path); + FileWatcher(const std::string& path, std::vector ext); void changeFolder(const std::string& path); ///< switch to observe other folder void saveCurrentFileToFolder(const std::string& destinationFolder); ///< copies int getSize() const; ///< include guards (so >=2 ) diff --git a/EventVisualisation/Base/src/DataSourceOnline.cxx b/EventVisualisation/Base/src/DataSourceOnline.cxx index 58979f1917c23..0f5b88430b39d 100644 --- a/EventVisualisation/Base/src/DataSourceOnline.cxx +++ b/EventVisualisation/Base/src/DataSourceOnline.cxx @@ -65,7 +65,7 @@ std::vector> DataSourceOnline return res; } -DataSourceOnline::DataSourceOnline(const std::string path) : mFileWatcher(path) +DataSourceOnline::DataSourceOnline(const std::string path) : mFileWatcher(path, {".json", ".root"}) { } diff --git a/EventVisualisation/Base/src/DirectoryLoader.cxx b/EventVisualisation/Base/src/DirectoryLoader.cxx index a5d45b34c02ea..9174e003643f7 100644 --- a/EventVisualisation/Base/src/DirectoryLoader.cxx +++ b/EventVisualisation/Base/src/DirectoryLoader.cxx @@ -22,11 +22,11 @@ using namespace std; using namespace o2::event_visualisation; -deque DirectoryLoader::load(const std::string& path, const std::string& marker, const std::string& ext) +deque DirectoryLoader::load(const std::string& path, const std::string& marker, const std::vector& ext) { deque result; for (const auto& entry : std::filesystem::directory_iterator(path)) { - if (entry.path().extension() == ext) { + if (std::find(ext.begin(), ext.end(), entry.path().extension()) != ext.end()) { result.push_back(entry.path().filename()); } } @@ -58,22 +58,22 @@ std::time_t to_time_t(TP tp) return system_clock::to_time_t(sctp); } -int DirectoryLoader::getNumberOfFiles(std::string& path, std::string& ext) +int DirectoryLoader::getNumberOfFiles(std::string& path, std::vector& ext) { int res = 0; for (const auto& entry : std::filesystem::directory_iterator(path)) { - if (entry.path().extension() == ext) { + if (std::find(ext.begin(), ext.end(), entry.path().extension()) != ext.end()) { res++; } } return res; } -std::string DirectoryLoader::getLatestFile(std::string& path, std::string& ext) +std::string DirectoryLoader::getLatestFile(std::string& path, std::vector& ext) { std::string oldest_file_name = ""; std::time_t oldest_file_time = LONG_MAX; for (const auto& entry : std::filesystem::directory_iterator(path)) { - if (entry.path().extension() == ext) { + if (std::find(ext.begin(), ext.end(), entry.path().extension()) != ext.end()) { auto file_time = entry.last_write_time(); std::time_t tt = to_time_t(file_time); if (tt < oldest_file_time) { @@ -85,7 +85,7 @@ std::string DirectoryLoader::getLatestFile(std::string& path, std::string& ext) return oldest_file_name; } -void DirectoryLoader::removeOldestFiles(std::string& path, std::string ext, int remaining) +void DirectoryLoader::removeOldestFiles(std::string& path, std::vector& ext, int remaining) { while (getNumberOfFiles(path, ext) > remaining) { LOG(info) << "removing oldest file in folder: " << path << " : " << getLatestFile(path, ext); diff --git a/EventVisualisation/Base/src/FileWatcher.cxx b/EventVisualisation/Base/src/FileWatcher.cxx index 805f06e596445..d796419bccf40 100644 --- a/EventVisualisation/Base/src/FileWatcher.cxx +++ b/EventVisualisation/Base/src/FileWatcher.cxx @@ -28,7 +28,7 @@ using namespace o2::event_visualisation; const char* FileWatcher::mLowGuard = " 0"; /// start guard const char* FileWatcher::mEndGuard = "~0"; /// stop guard -FileWatcher::FileWatcher(const string& path) +FileWatcher::FileWatcher(const string& path, std::vector ext) { //LOG(info) << "FileWatcher::FileWatcher(" << path << ")"; this->mDataFolder = path; @@ -36,6 +36,7 @@ FileWatcher::FileWatcher(const string& path) this->mFiles.clear(); this->mFiles.push_front(mLowGuard); this->mFiles.push_back(mEndGuard); + this->mExt = ext; //LOG(info) << "FileWatcher" << this->getSize(); } @@ -131,7 +132,7 @@ bool FileWatcher::refresh() LOG(info) << "previous:" << previous; LOG(info) << "currentFile:" << this->mCurrentFile; - this->mFiles = DirectoryLoader::load(this->mDataFolder, "_", ".json"); // already sorted according part staring with marker + this->mFiles = DirectoryLoader::load(this->mDataFolder, "_", this->mExt); // already sorted according part staring with marker if (this->mCurrentFile != mEndGuard) { if (this->mFiles.empty()) { this->mCurrentFile = mEndGuard; // list empty - stick to last element diff --git a/EventVisualisation/DataConverter/CMakeLists.txt b/EventVisualisation/DataConverter/CMakeLists.txt index cc7501c0d0ac8..51b6507bff093 100644 --- a/EventVisualisation/DataConverter/CMakeLists.txt +++ b/EventVisualisation/DataConverter/CMakeLists.txt @@ -10,12 +10,28 @@ # or submit itself to any jurisdiction. o2_add_library(EventVisualisationDataConverter - SOURCES src/VisualisationEvent.cxx + SOURCES src/VisualisationEvent.cxx src/VisualisationTrack.cxx src/VisualisationCluster.cxx src/VisualisationCalo.cxx src/VisualisationEventSerializer.cxx src/VisualisationEventJSONSerializer.cxx + src/VisualisationEventROOTSerializer.cxx PUBLIC_LINK_LIBRARIES RapidJSON::RapidJSON O2::ReconstructionDataFormats ) + +o2_add_executable(eve-convert + SOURCES src/converter.cxx + src/VisualisationEvent.cxx + src/VisualisationEventSerializer.cxx + src/VisualisationEventJSONSerializer.cxx + src/VisualisationEventROOTSerializer.cxx + src/VisualisationTrack.cxx + src/VisualisationCluster.cxx + src/VisualisationCalo.cxx + PUBLIC_LINK_LIBRARIES + O2::EventVisualisationView + RapidJSON::RapidJSON + O2::ReconstructionDataFormats + ) diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEvent.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEvent.h index c2f64103473c6..e611bc118c479 100644 --- a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEvent.h +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEvent.h @@ -162,14 +162,17 @@ class VisualisationEvent mCalo.clear(); } + void afterLoading(); // compute internal fields which are not persisted + const VisualisationCluster& getCluster(int i) const { return mClusters[i]; }; size_t getClusterCount() const { return mClusters.size(); } // Returns number of clusters - void setWorkflowVersion(const std::string& workflowVersion) { this->mWorkflowVersion = workflowVersion; } void setWorkflowParameters(const std::string& workflowParameters) { this->mWorkflowParameters = workflowParameters; } std::string getCollisionTime() const { return this->mCollisionTime; } void setCollisionTime(std::string collisionTime) { this->mCollisionTime = collisionTime; } + void setEveVersion(std::string eveVersion) { this->mEveVersion = eveVersion; } + float getMinTimeOfTracks() const { return this->mMinTimeOfTracks; } float getMaxTimeOfTracks() const { return this->mMaxTimeOfTracks; } /// maximum time of tracks in the event @@ -202,7 +205,7 @@ class VisualisationEvent float mMinTimeOfTracks; /// minimum time of tracks in the event float mMaxTimeOfTracks; /// maximum time of tracks in the event - std::string mWorkflowVersion; /// workflow version used to generate this Event + std::string mEveVersion; /// workflow version used to generate this Event std::string mWorkflowParameters; /// workflow parameters used to generate this Event int mEventNumber; /// event number in file double mEnergy; /// energy of the collision diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventJSONSerializer.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventJSONSerializer.h index a4514e9710966..6b26a0d615789 100644 --- a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventJSONSerializer.h +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventJSONSerializer.h @@ -29,6 +29,8 @@ namespace event_visualisation class VisualisationEventJSONSerializer : public VisualisationEventSerializer { static int getIntOrDefault(rapidjson::Value& tree, const char* key, int defaultValue = 0); + float getFloatOrDefault(rapidjson::Value& tree, const char* key, float defaultValue = 0.0f); + std::string getStringOrDefault(rapidjson::Value& tree, const char* key, const char* defaultValue = ""); std::string toJson(const VisualisationEvent& event) const; void fromJson(VisualisationEvent& event, std::string json); diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventROOTSerializer.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventROOTSerializer.h new file mode 100644 index 0000000000000..040bc6e7071e6 --- /dev/null +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventROOTSerializer.h @@ -0,0 +1,46 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file VisualisationEventSerializer.h +/// \author Julian Myrcha +/// + +#ifndef O2EVE_VISUALISATIONEVENTROOTSERIALIZER_H +#define O2EVE_VISUALISATIONEVENTROOTSERIALIZER_H + +#include "EventVisualisationDataConverter/VisualisationEventSerializer.h" +#include "EventVisualisationDataConverter/VisualisationTrack.h" +#include +#include + +namespace o2 +{ +namespace event_visualisation +{ + +class VisualisationEventROOTSerializer : public VisualisationEventSerializer +{ + static void save(const char* name, int value); + static int readInt(TFile& f, const char* name); + static void save(const char* name, const std::string& value); + static std::string readString(TFile& f, const char* name); + + public: + bool fromFile(VisualisationEvent& event, std::string fileName) override; + void toFile(const VisualisationEvent& event, std::string fileName) override; + ~VisualisationEventROOTSerializer() override = default; +}; + +} // namespace event_visualisation +} // namespace o2 + +#endif // O2EVE_VISUALISATIONEVENTROOTSERIALIZER_H diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventSerializer.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventSerializer.h index e46cbf03d5a4e..33d5aae08d8ab 100644 --- a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventSerializer.h +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventSerializer.h @@ -18,6 +18,7 @@ #include "EventVisualisationDataConverter/VisualisationEvent.h" #include +#include namespace o2 { @@ -26,19 +27,14 @@ namespace event_visualisation class VisualisationEventSerializer { - static VisualisationEventSerializer* instance; + static std::map instances; protected: VisualisationEventSerializer() = default; static std::string fileNameIndexed(const std::string fileName, const int index); public: - static VisualisationEventSerializer* getInstance() { return instance; } - static void setInstance(VisualisationEventSerializer* newInstance) - { // take ownership - delete instance; - instance = newInstance; - } + static VisualisationEventSerializer* getInstance(std::string ext) { return instances[ext]; } virtual bool fromFile(VisualisationEvent& event, std::string fileName) = 0; virtual void toFile(const VisualisationEvent& event, std::string fileName) = 0; virtual ~VisualisationEventSerializer() = default; diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationTrack.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationTrack.h index 38db9b9a029f7..b08ac465c9ba6 100644 --- a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationTrack.h +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationTrack.h @@ -75,6 +75,7 @@ class VisualisationTrack void addChild(int childID); // Add xyz coordinates of the point along the track void addPolyPoint(float x, float y, float z); + void addPolyPoint(const float p[]); // Time getter float getTime() const { return mTime; } // Charge getter diff --git a/EventVisualisation/DataConverter/src/VisualisationEvent.cxx b/EventVisualisation/DataConverter/src/VisualisationEvent.cxx index f3cf2a708c635..712b592c9e46f 100644 --- a/EventVisualisation/DataConverter/src/VisualisationEvent.cxx +++ b/EventVisualisation/DataConverter/src/VisualisationEvent.cxx @@ -143,5 +143,15 @@ VisualisationEvent::VisualisationEvent() this->mCollisionTime = ""; // collision time not set } +void VisualisationEvent::afterLoading() +{ + this->mMinTimeOfTracks = std::numeric_limits::max(); + this->mMaxTimeOfTracks = std::numeric_limits::min(); + for (auto& v : this->mTracks) { + this->mMinTimeOfTracks = std::min(this->mMinTimeOfTracks, v.getTime()); + this->mMaxTimeOfTracks = std::max(this->mMaxTimeOfTracks, v.getTime()); + } +} + } // namespace event_visualisation } // namespace o2 diff --git a/EventVisualisation/DataConverter/src/VisualisationEventJSONSerializer.cxx b/EventVisualisation/DataConverter/src/VisualisationEventJSONSerializer.cxx index 295e65a9015f2..78f6d97832820 100644 --- a/EventVisualisation/DataConverter/src/VisualisationEventJSONSerializer.cxx +++ b/EventVisualisation/DataConverter/src/VisualisationEventJSONSerializer.cxx @@ -43,6 +43,7 @@ void VisualisationEventJSONSerializer::toFile(const VisualisationEvent& event, s bool VisualisationEventJSONSerializer::fromFile(VisualisationEvent& event, std::string fileName) { + LOG(info) << "VisualisationEventJSONSerializer <- " << fileName; if (FILE* file = fopen(fileName.c_str(), "r")) { fclose(file); // file exists } else { @@ -65,7 +66,6 @@ std::string VisualisationEventJSONSerializer::toJson(const VisualisationEvent& e Document::AllocatorType& allocator = tree.GetAllocator(); // compatibility verification - tree.AddMember("fileVersion", rapidjson::Value().SetInt(JSON_FILE_VERSION), allocator); tree.AddMember("runNumber", rapidjson::Value().SetInt(event.mRunNumber), allocator); tree.AddMember("clMask", rapidjson::Value().SetInt(event.mClMask), allocator); tree.AddMember("trkMask", rapidjson::Value().SetInt(event.mTrkMask), allocator); @@ -74,7 +74,7 @@ std::string VisualisationEventJSONSerializer::toJson(const VisualisationEvent& e tree.AddMember("primaryVertex", rapidjson::Value().SetInt(event.mPrimaryVertex), allocator); tree.AddMember("collisionTime", rapidjson::Value().SetString(event.mCollisionTime.c_str(), event.mCollisionTime.size()), allocator); - tree.AddMember("workflowVersion", rapidjson::Value().SetString(event.mWorkflowVersion.c_str(), event.mWorkflowVersion.size()), allocator); + tree.AddMember("eveVersion", rapidjson::Value().SetString(event.mEveVersion.c_str(), event.mEveVersion.size()), allocator); tree.AddMember("workflowParameters", rapidjson::Value().SetString(event.mWorkflowParameters.c_str(), event.mWorkflowParameters.size()), allocator); // Tracks tree.AddMember("trackCount", rapidjson::Value().SetInt(event.getTrackCount()), allocator); @@ -122,6 +122,24 @@ int VisualisationEventJSONSerializer::getIntOrDefault(rapidjson::Value& tree, co return defaultValue; } +float VisualisationEventJSONSerializer::getFloatOrDefault(rapidjson::Value& tree, const char* key, float defaultValue) +{ + if (tree.HasMember(key)) { + rapidjson::Value& jsonValue = tree[key]; + return jsonValue.GetFloat(); + } + return defaultValue; +} + +std::string VisualisationEventJSONSerializer::getStringOrDefault(rapidjson::Value& tree, const char* key, const char* defaultValue) +{ + if (tree.HasMember(key)) { + rapidjson::Value& jsonValue = tree[key]; + return jsonValue.GetString(); + } + return defaultValue; +} + void VisualisationEventJSONSerializer::fromJson(VisualisationEvent& event, std::string json) { event.mTracks.clear(); @@ -131,31 +149,15 @@ void VisualisationEventJSONSerializer::fromJson(VisualisationEvent& event, std:: rapidjson::Document tree; tree.Parse(json.c_str()); - auto version = 1; - if (tree.HasMember("fileVersion")) { - rapidjson::Value& jsonFileVersion = tree["fileVersion"]; - version = jsonFileVersion.GetInt(); - } - - o2::header::DataHeader::RunNumberType runNumber = 0; - if (tree.HasMember("runNumber")) { - rapidjson::Value& jsonRunNumber = tree["runNumber"]; - runNumber = jsonRunNumber.GetInt(); - } - event.setRunNumber(runNumber); - + event.setRunNumber(getIntOrDefault(tree, "runNumber", 0)); event.setClMask(getIntOrDefault(tree, "clMask")); event.setTrkMask(getIntOrDefault(tree, "trkMask")); event.setTfCounter(getIntOrDefault(tree, "tfCounter")); event.setFirstTForbit(getIntOrDefault(tree, "firstTForbit")); event.setPrimaryVertex(getIntOrDefault(tree, "primaryVertex")); - - auto collisionTime = "not specified"; - if (tree.HasMember("collisionTime")) { - rapidjson::Value& jsonCollisionTime = tree["collisionTime"]; - collisionTime = jsonCollisionTime.GetString(); - } - event.setCollisionTime(collisionTime); + event.setCollisionTime(getStringOrDefault(tree, "collisionTime", "not specified")); + event.mEveVersion = getStringOrDefault(tree, "eveVersion", "0.0"); + event.setWorkflowParameters(getStringOrDefault(tree, "workflowParameters", "1.0")); rapidjson::Value& trackCount = tree["trackCount"]; event.mTracks.reserve(trackCount.GetInt()); @@ -173,19 +175,13 @@ void VisualisationEventJSONSerializer::fromJson(VisualisationEvent& event, std:: } } - event.mMinTimeOfTracks = std::numeric_limits::max(); - event.mMaxTimeOfTracks = std::numeric_limits::min(); - for (auto& v : event.mTracks) { - event.mMinTimeOfTracks = std::min(event.mMinTimeOfTracks, v.getTime()); - event.mMaxTimeOfTracks = std::max(event.mMaxTimeOfTracks, v.getTime()); - } - rapidjson::Value& clusterCount = tree["clusterCount"]; event.mClusters.reserve(clusterCount.GetInt()); rapidjson::Value& jsonClusters = tree["mClusters"]; for (auto& v : jsonClusters.GetArray()) { event.mClusters.emplace_back(clusterFromJSON(v)); } + event.afterLoading(); } VisualisationCluster VisualisationEventJSONSerializer::clusterFromJSON(rapidjson::Value& tree) @@ -253,27 +249,26 @@ VisualisationTrack VisualisationEventJSONSerializer::trackFromJSON(rapidjson::Va { VisualisationTrack track; track.mClusters.clear(); + rapidjson::Value& jsonStartingXYZ = tree["jsonStartingXYZ"]; rapidjson::Value& jsonPolyX = tree["mPolyX"]; rapidjson::Value& jsonPolyY = tree["mPolyY"]; rapidjson::Value& jsonPolyZ = tree["mPolyZ"]; rapidjson::Value& count = tree["count"]; - track.mCharge = 0; - - if (tree.HasMember("source")) { - track.mSource = (o2::dataformats::GlobalTrackID::Source)tree["source"].GetInt(); - } else { - track.mSource = o2::dataformats::GlobalTrackID::TPC; // temporary - } - track.mPID = tree["source"].GetInt(); + track.mCharge = getIntOrDefault(tree, "charge", 0); + track.mTheta = getFloatOrDefault(tree, "theta", 0); + track.mPhi = getFloatOrDefault(tree, "phi", 0); + track.mEta = getFloatOrDefault(tree, "eta", 0); + track.mSource = (o2::dataformats::GlobalTrackID::Source)getIntOrDefault(tree, "source", (int)o2::dataformats::GlobalTrackID::TPC); + track.mPID = getIntOrDefault(tree, "PID", 0); track.mTime = tree["time"].GetFloat(); - if (tree.HasMember("gid")) { - track.mGID = tree["gid"].GetString(); - } else { - track.mGID = "track"; - } + track.mGID = getStringOrDefault(tree, "gid", "track"); track.mPolyX.reserve(count.GetInt()); track.mPolyY.reserve(count.GetInt()); track.mPolyZ.reserve(count.GetInt()); + auto startingXYZ = jsonStartingXYZ.GetArray(); + track.mStartCoordinates[0] = startingXYZ[0].GetFloat(); + track.mStartCoordinates[1] = startingXYZ[1].GetFloat(); + track.mStartCoordinates[2] = startingXYZ[2].GetFloat(); for (auto& v : jsonPolyX.GetArray()) { track.mPolyX.push_back(v.GetDouble()); } @@ -339,4 +334,4 @@ rapidjson::Value VisualisationEventJSONSerializer::jsonTree(const VisualisationT } } // namespace event_visualisation -} // namespace o2 \ No newline at end of file +} // namespace o2 diff --git a/EventVisualisation/DataConverter/src/VisualisationEventROOTSerializer.cxx b/EventVisualisation/DataConverter/src/VisualisationEventROOTSerializer.cxx new file mode 100644 index 0000000000000..c146842bec2b3 --- /dev/null +++ b/EventVisualisation/DataConverter/src/VisualisationEventROOTSerializer.cxx @@ -0,0 +1,329 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file VisualisationEventROOTSerializer.cxx +/// \brief ROOT serialization +/// \author julian.myrcha@cern.ch + +#include "EventVisualisationDataConverter/VisualisationEventROOTSerializer.h" +#include "FairLogger.h" +#include + +#include +#include +#include +#include +#include + +namespace o2 +{ +namespace event_visualisation +{ +constexpr int ROOT_FILE_VERSION = 1; + +void VisualisationEventROOTSerializer::save(const char* name, const std::string& value) +{ + TNamed obj(name, value); + obj.Write(); +} + +std::string VisualisationEventROOTSerializer::readString(TFile& f, const char* name) +{ + TNamed* v = (TNamed*)f.Get(name); + if (v == nullptr) { + return ""; + } + std::string result = v->GetTitle(); + free(v); + return result; +} + +void VisualisationEventROOTSerializer::save(const char* name, int value) +{ + TParameter obj; + obj.SetVal(value); + obj.Write(name); +} + +int VisualisationEventROOTSerializer::readInt(TFile& f, const char* name) +{ + TParameter* v = (TParameter*)f.Get(name); + if (v == nullptr) { + return 0; + } + int result = v->GetVal(); + free(v); + return result; +} + +void VisualisationEventROOTSerializer::toFile(const VisualisationEvent& event, std::string fileName) +{ + TFile f(fileName.c_str(), "recreate"); + + save("runNumber", event.mRunNumber); + save("clMask", event.mClMask); + save("trkMask", event.mTrkMask); + save("tfCounter", event.mTfCounter); + save("firstTForbit", event.mFirstTForbit); + save("primaryVertex", event.mPrimaryVertex); + save("collisionTime", event.mCollisionTime); + save("eveVersion", event.mEveVersion); + save("workflowParameters", event.mWorkflowParameters); + + // clusters + TNtuple xyz("xyz", "xyz", "x:y:z"); + long xyzPos = 0L; + TTree clusters("clusters", "Clusters"); + long cluster_xyz; + int cluster_source; + float cluster_time; + clusters.Branch("source", &cluster_source); + clusters.Branch("time", &cluster_time); + clusters.Branch("xyz", &cluster_xyz); + for (auto cluster : event.getClustersSpan()) { + cluster_source = cluster.getSource(); + cluster_time = cluster.Time(); + cluster_xyz = xyzPos; + xyz.Fill(cluster.X(), cluster.Y(), cluster.Z()); + xyzPos++; + clusters.Fill(); + } + + // Tracks + long track_xyz; // first track point + int track_points; // number of track points + int track_clusters; // number of track clusters + int track_source; + std::string track_GID; + float track_time; + int track_charge; + float track_theta; + float track_phi; + float track_eta; + int track_PID; + + TTree tracks("tracks", "Tracks"); + tracks.Branch("xyz", &track_xyz); + tracks.Branch("time", &track_time); + tracks.Branch("charge", &track_charge); + tracks.Branch("theta", &track_theta); + tracks.Branch("phi", &track_phi); + tracks.Branch("eta", &track_eta); + tracks.Branch("PID", &track_PID); + tracks.Branch("GID", &track_GID); + tracks.Branch("source", &track_source); + tracks.Branch("points", &track_points); + tracks.Branch("clusters", &track_clusters); + + for (auto track : event.getTracksSpan()) { + track_xyz = xyzPos; + track_time = std::isnan(track.mTime) ? 0 : track.mTime; + track_charge = track.mCharge; + track_theta = std::isnan(track.mTheta) ? 0 : track.mTheta; + track_phi = std::isnan(track.mPhi) ? 0 : track.mPhi; + track_eta = std::isnan(track.mEta) ? 0 : track.mEta; + track_PID = track.mPID; + track_GID = track.mGID; + track_source = track.mSource; + + xyz.Fill(track.mStartCoordinates[0], track.mStartCoordinates[1], track.mStartCoordinates[2]); + xyzPos++; + track_points = track.getPointCount(); + + for (size_t i = 0; i < track.getPointCount(); i++) { + xyz.Fill(track.mPolyX[i], track.mPolyY[i], track.mPolyZ[i]); + xyzPos++; + } + track_clusters = track.getClusterCount(); + for (auto cluster : track.getClustersSpan()) { + xyz.Fill(cluster.X(), cluster.Y(), cluster.Z()); + xyzPos++; + } + tracks.Fill(); + } + + // calorimeters + TTree calo("calo", "Calorimeters"); + int calo_source; + float calo_time; + float calo_energy; + float calo_eta; + float calo_phi; + std::string calo_GID; + int calo_PID; + + calo.Branch("source", &calo_source); + calo.Branch("time", &calo_time); + calo.Branch("energy", &calo_energy); + calo.Branch("eta", &calo_eta); + calo.Branch("phi", &calo_phi); + calo.Branch("GID", &calo_GID); + calo.Branch("PID", &calo_PID); + + for (auto calorimeter : event.getCalorimetersSpan()) { + calo_source = calorimeter.getSource(); + calo_time = calorimeter.getTime(); + calo_energy = calorimeter.getEnergy(); + calo_eta = calorimeter.getEta(); + calo_phi = calorimeter.getPhi(); + calo_GID = calorimeter.getGIDAsString(); + calo_PID = calorimeter.getPID(); + calo.Fill(); + } + tracks.Write(); + clusters.Write(); + calo.Write(); + xyz.Write(); +} + +bool VisualisationEventROOTSerializer::fromFile(VisualisationEvent& event, std::string fileName) +{ + LOG(info) << "VisualisationEventROOTSerializer <- " << fileName; + event.mTracks.clear(); + event.mClusters.clear(); + event.mCalo.clear(); + + TFile f(fileName.c_str()); + + event.setRunNumber(readInt(f, "runNumber")); + event.setClMask(readInt(f, "clMask")); + event.setTrkMask(readInt(f, "trkMask")); + event.setTfCounter(readInt(f, "tfCounter")); + event.setFirstTForbit(readInt(f, "firstTForbit")); + event.mPrimaryVertex = readInt(f, "primaryVertex"); + + event.setCollisionTime(readString(f, "collisionTime")); + event.mEveVersion = readString(f, "eveVersion"); + event.mWorkflowParameters = readString(f, "workflowParameters"); + + // xyz + TNtuple* xyz = (TNtuple*)f.Get("xyz"); + + // tracks + TTree* tracks = (TTree*)f.Get("tracks"); + long track_xyz; // first track point + int track_points; // number of track points + int track_clusters; // number of track clusters + int track_source; + std::string* track_GID = nullptr; + float track_time; + int track_charge; + float track_theta; + float track_phi; + float track_eta; + int track_PID; + + tracks->SetBranchAddress("xyz", &track_xyz); + tracks->SetBranchAddress("time", &track_time); + tracks->SetBranchAddress("charge", &track_charge); + tracks->SetBranchAddress("theta", &track_theta); + tracks->SetBranchAddress("phi", &track_phi); + tracks->SetBranchAddress("eta", &track_eta); + tracks->SetBranchAddress("PID", &track_PID); + tracks->SetBranchAddress("GID", &track_GID); + tracks->SetBranchAddress("source", &track_source); + tracks->SetBranchAddress("points", &track_points); + tracks->SetBranchAddress("clusters", &track_clusters); + + Int_t tracksNoOfEntries = (Int_t)tracks->GetEntries(); + for (Int_t i = 0; i < tracksNoOfEntries; i++) { + tracks->GetEntry(i); + VisualisationTrack track; + track.mTime = track_time; + track.mCharge = track_charge; + track.mTheta = track_theta; + track.mPhi = track_phi; + track.mEta = track_eta; + track.mPID = track_PID; + track.mGID = *track_GID; + track.mSource = (o2::dataformats::GlobalTrackID::Source)track_source; + xyz->GetEntry(track_xyz); + track.addStartCoordinates(xyz->GetArgs()); + for (size_t i = 0; i < track_points; i++) { + xyz->GetEntry(track_xyz + 1 + i); + track.addPolyPoint(xyz->GetArgs()); + } + for (size_t i = 0; i < track_clusters; i++) { + xyz->GetEntry(track_xyz + 1 + track_points + i); + VisualisationCluster cluster(xyz->GetArgs(), track.mTime); + cluster.mSource = track.mSource; + track.mClusters.emplace_back(cluster); + } + event.mTracks.emplace_back(track); + } + if (track_GID != nullptr) { + delete track_GID; + track_GID = nullptr; + } + + TTree* clusters = (TTree*)f.Get("clusters"); + long cluster_xyz; + int cluster_source; + float cluster_time; + clusters->SetBranchAddress("source", &cluster_source); + clusters->SetBranchAddress("time", &cluster_time); + clusters->SetBranchAddress("xyz", &cluster_xyz); + Int_t clustersNoOfEntries = (Int_t)clusters->GetEntries(); + for (Int_t i = 0; i < clustersNoOfEntries; i++) { + clusters->GetEntry(i); + xyz->GetEntry(cluster_xyz); + VisualisationCluster cluster(xyz->GetArgs(), cluster_time); + cluster.mSource = (o2::dataformats::GlobalTrackID::Source)cluster_source; + event.mClusters.emplace_back(cluster); + } + + // calorimeters + TTree* calo = (TTree*)f.Get("calo"); + int calo_source; + float calo_time; + float calo_energy; + float calo_eta; + float calo_phi; + std::string* calo_GID = nullptr; + int calo_PID; + + calo->SetBranchAddress("source", &calo_source); + calo->SetBranchAddress("time", &calo_time); + calo->SetBranchAddress("energy", &calo_energy); + calo->SetBranchAddress("eta", &calo_eta); + calo->SetBranchAddress("phi", &calo_phi); + calo->SetBranchAddress("GID", &calo_GID); + calo->SetBranchAddress("PID", &calo_PID); + + Int_t nentries = (Int_t)calo->GetEntries(); + for (Int_t i = 0; i < nentries; i++) { + calo->GetEntry(i); + VisualisationCalo calorimeter; + calorimeter.mSource = (o2::dataformats::GlobalTrackID::Source)calo_source; + calorimeter.mTime = calo_time; + calorimeter.mEnergy = calo_energy; + calorimeter.mEta = calo_eta; + calorimeter.mPhi = calo_phi; + if (calo_GID) { + calorimeter.mGID = *calo_GID; + } + calorimeter.mPID = calo_PID; + event.mCalo.emplace_back(calorimeter); + } + if (calo_GID != nullptr) { + delete calo_GID; + calo_GID = nullptr; + } + delete calo; + delete tracks; + delete clusters; + event.afterLoading(); + return true; +} + +} // namespace event_visualisation +} // namespace o2 diff --git a/EventVisualisation/DataConverter/src/VisualisationEventSerializer.cxx b/EventVisualisation/DataConverter/src/VisualisationEventSerializer.cxx index 159664f051801..3b10f8d028170 100644 --- a/EventVisualisation/DataConverter/src/VisualisationEventSerializer.cxx +++ b/EventVisualisation/DataConverter/src/VisualisationEventSerializer.cxx @@ -16,6 +16,7 @@ #include "EventVisualisationDataConverter/VisualisationEventSerializer.h" #include "EventVisualisationDataConverter/VisualisationEventJSONSerializer.h" +#include "EventVisualisationDataConverter/VisualisationEventROOTSerializer.h" #include "FairLogger.h" #include #include @@ -24,8 +25,9 @@ namespace o2 { namespace event_visualisation { - -VisualisationEventSerializer* VisualisationEventSerializer::instance = new VisualisationEventJSONSerializer(); +std::map VisualisationEventSerializer::instances = { + {".json", new o2::event_visualisation::VisualisationEventJSONSerializer()}, + {".root", new o2::event_visualisation::VisualisationEventROOTSerializer()}}; std::string VisualisationEventSerializer::fileNameIndexed(const std::string fileName, const int index) { diff --git a/EventVisualisation/DataConverter/src/VisualisationTrack.cxx b/EventVisualisation/DataConverter/src/VisualisationTrack.cxx index 45054dead8a2c..1138ff7bdf76f 100644 --- a/EventVisualisation/DataConverter/src/VisualisationTrack.cxx +++ b/EventVisualisation/DataConverter/src/VisualisationTrack.cxx @@ -73,6 +73,13 @@ void VisualisationTrack::addPolyPoint(float x, float y, float z) mPolyZ.push_back(z); } +void VisualisationTrack::addPolyPoint(const float p[]) +{ + mPolyX.push_back(p[0]); + mPolyY.push_back(p[1]); + mPolyZ.push_back(p[2]); +} + VisualisationCluster& VisualisationTrack::addCluster(float pos[]) { mClusters.emplace_back(pos, 0); diff --git a/EventVisualisation/DataConverter/src/converter.cxx b/EventVisualisation/DataConverter/src/converter.cxx new file mode 100644 index 0000000000000..ae3915fea2284 --- /dev/null +++ b/EventVisualisation/DataConverter/src/converter.cxx @@ -0,0 +1,57 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file converter.cxx +/// \author julian.myrcha@cern.ch + +#include "EventVisualisationView/Initializer.h" +#include "EventVisualisationView/Options.h" +#include +#include +#include +#include +#include +#include +#include +#include "FairLogger.h" + +int main(int argc, char** argv) +{ + LOG(info) << "Welcome in O2 event conversion tool"; + if (argc != 3) { + LOG(error) << "two filename required, second should point to not existent file"; + exit(-1); + } + + std::string src = argv[1]; + std::string dst = argv[2]; + + o2::event_visualisation::VisualisationEvent vEvent; + + auto srcSerializer = o2::event_visualisation::VisualisationEventSerializer::getInstance(std::filesystem::path(src).extension()); + auto dstSerializer = o2::event_visualisation::VisualisationEventSerializer::getInstance(std::filesystem::path(dst).extension()); + + std::chrono::time_point currentTime = std::chrono::high_resolution_clock::now(); + std::chrono::time_point endTime = std::chrono::high_resolution_clock::now(); + + srcSerializer->fromFile(vEvent, src); + endTime = std::chrono::high_resolution_clock::now(); + LOG(info) << "read took " + << std::chrono::duration_cast(endTime - currentTime).count() * 1e-6; + + currentTime = std::chrono::high_resolution_clock::now(); + dstSerializer->toFile(vEvent, dst); + endTime = std::chrono::high_resolution_clock::now(); + LOG(info) << "write took " + << std::chrono::duration_cast(endTime - currentTime).count() * 1e-6; + return 0; +} diff --git a/EventVisualisation/Detectors/CMakeLists.txt b/EventVisualisation/Detectors/CMakeLists.txt index 8862abd667bf9..28463b67d2a83 100644 --- a/EventVisualisation/Detectors/CMakeLists.txt +++ b/EventVisualisation/Detectors/CMakeLists.txt @@ -13,5 +13,5 @@ o2_add_library(EventVisualisationDetectors SOURCES src/DataReaderJSON.cxx PUBLIC_LINK_LIBRARIES - O2::EventVisualisationBase + O2::EventVisualisationBase ) diff --git a/EventVisualisation/Detectors/src/DataReaderJSON.cxx b/EventVisualisation/Detectors/src/DataReaderJSON.cxx index c33304bbec1d7..b6fb163b1ab89 100644 --- a/EventVisualisation/Detectors/src/DataReaderJSON.cxx +++ b/EventVisualisation/Detectors/src/DataReaderJSON.cxx @@ -17,6 +17,7 @@ #include "EventVisualisationDetectors/DataReaderJSON.h" #include "EventVisualisationDataConverter/VisualisationEventSerializer.h" #include "FairLogger.h" +#include namespace o2 { @@ -26,7 +27,8 @@ namespace event_visualisation VisualisationEvent DataReaderJSON::getEvent(std::string fileName) { VisualisationEvent vEvent; - VisualisationEventSerializer::getInstance()->fromFile(vEvent, fileName); + auto serializer = VisualisationEventSerializer::getInstance(std::filesystem::path(fileName).extension()); + serializer->fromFile(vEvent, fileName); return vEvent; } diff --git a/EventVisualisation/View/src/EventManagerFrame.cxx b/EventVisualisation/View/src/EventManagerFrame.cxx index 05f58ef4f2435..8098a9a3a334d 100644 --- a/EventVisualisation/View/src/EventManagerFrame.cxx +++ b/EventVisualisation/View/src/EventManagerFrame.cxx @@ -352,7 +352,8 @@ void EventManagerFrame::createOutreachScreenshot() } fileName = imageFolder + "/" + fileName.substr(0, fileName.find_last_of('.')) + ".png"; if (!std::filesystem::is_regular_file(fileName)) { - DirectoryLoader::removeOldestFiles(imageFolder, ".png", 10); + std::vector ext = {".png"}; + DirectoryLoader::removeOldestFiles(imageFolder, ext, 10); LOG(info) << "Outreach screenshot: " << fileName; Screenshot::perform(fileName, this->mEventManager->getDataSource()->getDetectorsMask(), this->mEventManager->getDataSource()->getRunNumber(), diff --git a/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h b/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h index ba87115d127e6..19ebbfae0908a 100644 --- a/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h +++ b/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h @@ -183,6 +183,7 @@ class EveWorkflowHelper float findLastMCHClusterPosition(const o2::mch::TrackMCH& track); void save(const std::string& jsonPath, + const std::string& ext, int numberOfFiles, o2::dataformats::GlobalTrackID::mask_t trkMask, o2::dataformats::GlobalTrackID::mask_t clMask, diff --git a/EventVisualisation/Workflow/include/EveWorkflow/FileProducer.h b/EventVisualisation/Workflow/include/EveWorkflow/FileProducer.h index a3a13808cb349..d35ddcaa78711 100644 --- a/EventVisualisation/Workflow/include/EveWorkflow/FileProducer.h +++ b/EventVisualisation/Workflow/include/EveWorkflow/FileProducer.h @@ -29,10 +29,11 @@ class FileProducer size_t mFilesInFolder; std::string mPath; std::string mName; + std::string mExt; public: - explicit FileProducer(const std::string& path, int filesInFolder = -1, - const std::string& name = "tracks_{timestamp}_{hostname}_{pid}.json"); + explicit FileProducer(const std::string& path, const std::string& ext, int filesInFolder = -1, + const std::string& name = "tracks_{timestamp}_{hostname}_{pid}{ext}"); [[nodiscard]] std::string newFileName() const; }; diff --git a/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h b/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h index ff72cbaefe505..bb39acea14796 100644 --- a/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h +++ b/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h @@ -51,12 +51,13 @@ class O2DPLDisplaySpec : public o2::framework::Task O2DPLDisplaySpec(bool useMC, o2::dataformats::GlobalTrackID::mask_t trkMask, o2::dataformats::GlobalTrackID::mask_t clMask, - std::shared_ptr dataRequest, const std::string& jsonPath, + std::shared_ptr dataRequest, const std::string& jsonPath, const std::string& ext, std::chrono::milliseconds timeInterval, int numberOfFiles, int numberOfTracks, bool eveHostNameMatch, int minITSTracks, int minTracks, bool filterITSROF, bool filterTime, const EveWorkflowHelper::Bracket& timeBracket, bool removeTPCEta, const EveWorkflowHelper::Bracket& etaBracket, bool trackSorting, int onlyNthEvent, bool primaryVertex, int maxPrimaryVertices) - : mUseMC(useMC), mTrkMask(trkMask), mClMask(clMask), mDataRequest(dataRequest), mJsonPath(jsonPath), mTimeInterval(timeInterval), mNumberOfFiles(numberOfFiles), mNumberOfTracks(numberOfTracks), mEveHostNameMatch(eveHostNameMatch), mMinITSTracks(minITSTracks), mMinTracks(minTracks), mFilterITSROF(filterITSROF), mFilterTime(filterTime), mTimeBracket(timeBracket), mRemoveTPCEta(removeTPCEta), mEtaBracket(etaBracket), mTrackSorting(trackSorting), mOnlyNthEvent(onlyNthEvent), mPrimaryVertexMode(primaryVertex), mMaxPrimaryVertices(maxPrimaryVertices) + : mUseMC(useMC), mTrkMask(trkMask), mClMask(clMask), mDataRequest(dataRequest), mJsonPath(jsonPath), mExt(ext), mTimeInterval(timeInterval), mNumberOfFiles(numberOfFiles), mNumberOfTracks(numberOfTracks), mEveHostNameMatch(eveHostNameMatch), mMinITSTracks(minITSTracks), mMinTracks(minTracks), mFilterITSROF(filterITSROF), mFilterTime(filterTime), mTimeBracket(timeBracket), mRemoveTPCEta(removeTPCEta), mEtaBracket(etaBracket), mTrackSorting(trackSorting), mOnlyNthEvent(onlyNthEvent), mPrimaryVertexMode(primaryVertex), mMaxPrimaryVertices(maxPrimaryVertices) + { this->mTimeStamp = std::chrono::high_resolution_clock::now() - timeInterval; // first run meets condition } @@ -80,6 +81,7 @@ class O2DPLDisplaySpec : public o2::framework::Task EveWorkflowHelper::Bracket mTimeBracket; // [min, max] range in TF time for the filter EveWorkflowHelper::Bracket mEtaBracket; // [min, max] eta range for the TPC tracks removal std::string mJsonPath; // folder where files are stored + std::string mExt; // extension of created files (".json" or ".root") std::chrono::milliseconds mTimeInterval; // minimal interval between files in milliseconds int mNumberOfFiles; // maximum number of files in folder - newer replaces older int mNumberOfTracks; // maximum number of track in single file (0 means no limit) diff --git a/EventVisualisation/Workflow/src/AO2DConverter.cxx b/EventVisualisation/Workflow/src/AO2DConverter.cxx index 7937649a01244..488e0ce28034e 100644 --- a/EventVisualisation/Workflow/src/AO2DConverter.cxx +++ b/EventVisualisation/Workflow/src/AO2DConverter.cxx @@ -74,7 +74,7 @@ struct AO2DConverter { mHelper->mEvent.setTfCounter(mTfCounter); mHelper->mEvent.setFirstTForbit(mTfOrbit); - mHelper->save(jsonPath, -1, GlobalTrackID::MASK_ALL, GlobalTrackID::MASK_NONE, mRunNumber, collision.collisionTime()); + mHelper->save(jsonPath, ".root", -1, GlobalTrackID::MASK_ALL, GlobalTrackID::MASK_NONE, mRunNumber, collision.collisionTime()); mHelper->clear(); } }; diff --git a/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx b/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx index 4a226abd54af6..1132fec727808 100644 --- a/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx +++ b/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx @@ -323,11 +323,11 @@ void EveWorkflowHelper::draw(std::size_t primaryVertexIdx, bool sortTracks) } } -void EveWorkflowHelper::save(const std::string& jsonPath, int numberOfFiles, +void EveWorkflowHelper::save(const std::string& jsonPath, const std::string& ext, int numberOfFiles, o2::dataformats::GlobalTrackID::mask_t trkMask, o2::dataformats::GlobalTrackID::mask_t clMask, o2::header::DataHeader::RunNumberType runNumber, o2::framework::DataProcessingHeader::CreationTime creation) { - mEvent.setWorkflowVersion(o2_eve_version); + mEvent.setEveVersion(o2_eve_version); mEvent.setRunNumber(runNumber); std::time_t timeStamp = std::time(nullptr); std::string asciiTimeStamp = std::asctime(std::localtime(&timeStamp)); @@ -339,8 +339,8 @@ void EveWorkflowHelper::save(const std::string& jsonPath, int numberOfFiles, asciiCreationTime.pop_back(); // remove trailing \n mEvent.setCollisionTime(asciiCreationTime); - FileProducer producer(jsonPath, numberOfFiles); - VisualisationEventSerializer::getInstance()->toFile(mEvent, producer.newFileName()); + FileProducer producer(jsonPath, ext, numberOfFiles); + VisualisationEventSerializer::getInstance(ext)->toFile(mEvent, producer.newFileName()); } std::vector EveWorkflowHelper::getTrackPoints(const o2::track::TrackPar& trc, float minR, float maxR, float maxStep, float minZ, float maxZ) diff --git a/EventVisualisation/Workflow/src/FileProducer.cxx b/EventVisualisation/Workflow/src/FileProducer.cxx index 03e78cfeb3cee..541afdefc4553 100644 --- a/EventVisualisation/Workflow/src/FileProducer.cxx +++ b/EventVisualisation/Workflow/src/FileProducer.cxx @@ -30,11 +30,12 @@ using std::chrono::duration_cast; using std::chrono::milliseconds; using std::chrono::system_clock; -FileProducer::FileProducer(const std::string& path, int filesInFolder, const std::string& name) +FileProducer::FileProducer(const std::string& path, const std::string& ext, int filesInFolder, const std::string& name) { this->mFilesInFolder = filesInFolder; this->mPath = path; this->mName = name; + this->mExt = ext; o2::utils::createDirectoriesIfAbsent(path); // create folder if not exists (fails if no rights) } @@ -46,17 +47,13 @@ std::string FileProducer::newFileName() const gethostname(hostname, _POSIX_HOST_NAME_MAX); auto pid = getpid(); - auto result = fmt::format(this->mName, fmt::arg("hostname", hostname), fmt::arg("pid", pid), fmt::arg("timestamp", millisec_since_epoch)); - // auto files = DirectoryLoader::load(this->mPath, "_", ".json"); // already sorted starting by part of name at pos - - // if (this->mFilesInFolder > 0) { - // while (files.size() >= this->mFilesInFolder) { - // auto front = files.front(); - // files.pop_front(); - // std::remove((this->mPath + "/" + front).c_str()); // delete file - // } - // } - DirectoryLoader::reduceNumberOfFiles(this->mPath, DirectoryLoader::load(this->mPath, "_", ".json"), this->mFilesInFolder); + auto result = fmt::format(this->mName, + fmt::arg("hostname", hostname), + fmt::arg("pid", pid), + fmt::arg("timestamp", millisec_since_epoch), + fmt::arg("ext", this->mExt)); + std::vector ext = {".json", ".root"}; + DirectoryLoader::reduceNumberOfFiles(this->mPath, DirectoryLoader::load(this->mPath, "_", ext), this->mFilesInFolder); return this->mPath + "/" + result; } diff --git a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx index ee1ce51ada8db..da05b5dee719b 100644 --- a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx +++ b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx @@ -51,6 +51,7 @@ void customize(std::vector& workflowOptions) { std::vector options{ {"jsons-folder", VariantType::String, "jsons", {"name of the folder to store json files"}}, + {"use-json-format", VariantType::Bool, false, {"instead of root format (default) use json format"}}, {"eve-hostname", VariantType::String, "", {"name of the host allowed to produce files (empty means no limit)"}}, {"eve-dds-collection-index", VariantType::Int, -1, {"number of dpl collection allowed to produce files (-1 means no limit)"}}, {"number-of_files", VariantType::Int, 150, {"maximum number of json files in folder"}}, @@ -153,7 +154,7 @@ void O2DPLDisplaySpec::run(ProcessingContext& pc) helper.mEvent.setTfCounter(tinfo.tfCounter); helper.mEvent.setFirstTForbit(tinfo.firstTForbit); helper.mEvent.setPrimaryVertex(pv); - helper.save(this->mJsonPath, this->mNumberOfFiles, this->mTrkMask, this->mClMask, tinfo.runNumber, tinfo.creation); + helper.save(this->mJsonPath, this->mExt, this->mNumberOfFiles, this->mTrkMask, this->mClMask, tinfo.runNumber, tinfo.creation); jsonsSaved++; } @@ -210,6 +211,11 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) WorkflowSpec specs; std::string jsonFolder = cfgc.options().get("jsons-folder"); + std::string ext = ".root"; // root files are default format + auto useJsonFormat = cfgc.options().get("use-json-format"); + if (useJsonFormat) { + ext = ".json"; + } std::string eveHostName = cfgc.options().get("eve-hostname"); o2::conf::ConfigurableParam::updateFromString(cfgc.options().get("configKeyValues")); bool useMC = !cfgc.options().get("disable-mc"); @@ -309,7 +315,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) "o2-eve-export", dataRequest->inputs, {}, - AlgorithmSpec{adaptFromTask(useMC, srcTrk, srcCl, dataRequest, jsonFolder, timeInterval, numberOfFiles, numberOfTracks, eveHostNameMatch, minITSTracks, minTracks, filterITSROF, filterTime, timeBracket, removeTPCEta, etaBracket, tracksSorting, onlyNthEvent, primaryVertexMode, maxPrimaryVertices)}}); + AlgorithmSpec{adaptFromTask(useMC, srcTrk, srcCl, dataRequest, jsonFolder, ext, timeInterval, numberOfFiles, numberOfTracks, eveHostNameMatch, minITSTracks, minTracks, filterITSROF, filterTime, timeBracket, removeTPCEta, etaBracket, tracksSorting, onlyNthEvent, primaryVertexMode, maxPrimaryVertices)}}); // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(cfgc, specs);