#ifndef VIS_HELPERS_H #define VIS_HELPERS_H #include #include #include #include #include static TEvePointSet* gVisPts = nullptr; static std::mutex gVisMutex; // Recommended: call once after opening TEve and adding a point set to gEve inline void SetVisPointSet(TEvePointSet* pts) { gVisPts = pts; } inline void UpdateVisPointSet(const std::vector& x, const std::vector& y, const std::vector& z) { if(!gVisPts) return; std::lock_guard lk(gVisMutex); gVisPts->Reset(); size_t n = std::min({x.size(), y.size(), z.size()}); for(size_t i=0; iSetNextPoint(x[i], y[i], z[i]); if(gEve) { gEve->Redraw3D(); gSystem->ProcessEvents(); } } // Fill a tree with pointlists (one entry per event); must have branches defined once by caller inline void RecordTreeXYZ(TTree* outTree, const std::vector& x, const std::vector& y, const std::vector& z) { if(!outTree) return; static std::vector tx, ty, tz; tx = x; ty = y; tz = z; if(outTree->GetBranch("x") == nullptr) outTree->Branch("x", &tx); if(outTree->GetBranch("y") == nullptr) outTree->Branch("y", &ty); if(outTree->GetBranch("z") == nullptr) outTree->Branch("z", &tz); // Do NOT call SetBranchAddress() for the branch we are filling. outTree->Fill(); outTree->GetCurrentFile()->Flush(); } inline void PushEventAndRecord(const std::vector& x, const std::vector& y, const std::vector& z, TTree* outTree = nullptr) { if(outTree) RecordTreeXYZ(outTree, x, y, z); UpdateVisPointSet(x,y,z); } #endif // VIS_HELPERS_H