#include "TEveManager.h" #include "TEveGeoNode.h" #include "TEvePointSet.h" #include "TEveBoxSet.h" #include "TEveLine.h" #include "TEveScene.h" #include "TEveEventManager.h" #include "TEveWindow.h" #include "TEveTrackPropagator.h" #include "TTree.h" #include "TEveTrack.h" #include "TEveViewer.h" #include "TGLViewer.h" #include "TEveBrowser.h" #include "TH2D.h" #include "TCanvas.h" #include "TGTab.h" #include "TGedEditor.h" #include "TEveGedEditor.h" #include "TGLSAViewer.h" #include "TEveTrans.h" #include "TPaveText.h" #include "TSystem.h" #include "TGLWidget.h" #include "TEveLegoEventHandler.h" #include "TGLEmbeddedViewer.h" #include "TGeoManager.h" #include "TGeoMaterial.h" #include "TGeoMedium.h" #include "TGeoVolume.h" #include "TGeoTrack.h" #include "TParticle.h" #include "TRandom.h" #include "TTimer.h" #include "TPad.h" #include "TROOT.h" #include "RtypesCore.h" #include "TMath.h" #include "Math/GenVector/PositionVector3D.h" #include "Math/GenVector/Cylindrical3D.h" #include "TEveCaloLegoOverlay.h" #include "TEveCalo.h" //============================================================================== // Forward declarations //------------------------------------------------------------------------------ TEveCalo3D* MakeCalo3D(TEveCaloData* data, TEveWindowSlot* slot); TEveCaloLego* MakeCaloLego(TEveCaloData* data, TEveWindowSlot* slot); void MakeViewerScene(TEveWindowSlot* slot, TEveViewer*& v, TEveScene*& s); //============================================================================== // Constants. //------------------------------------------------------------------------------ const Double_t kX_max = 300; // Top Volume Box dimensions const Double_t kY_max = 300; const Double_t kZ_max = 300; const Double_t kR_min = 240; // child Tube dimensions const Double_t kR_max = 250; const Double_t kZ_d = 300; const TLorentzVector vrtxo = TLorentzVector(0., 0., 0., 0.); // collision point const TEveVectorD origin = TEveVectorD(0., 0., 0.); const Int_t kSleep = 800; // time loop delay in [ms] Double_t kCenter[3] = {0., 0., 0.}; // GL camera center (geometry) Double_t kfov = 30.; Double_t kdolly = 0.; Double_t khRotate = TMath::Pi()/30.; Double_t kvRotate = TMath::Pi()/8.; //------------------------------------------------------------------------------ void pbr_create_geo() { // define a new geometry object "EZB_sim_geo" if (gGeoManager) { delete gGeoManager; } // new call below initializes gGeoManager global pointer new TGeoManager("EZB_sim_geo", "simple detector geometry-cube enclosure+cylinder"); //-- materials definitions TGeoMaterial *matVacuum = new TGeoMaterial("Vacuum", 0,0,0); TGeoMaterial *matAl = new TGeoMaterial("Al", 26.98,13,2.7); //-- media definitions TGeoMedium *Vacuum = new TGeoMedium("Vacuum",1, matVacuum); TGeoMedium *Al = new TGeoMedium("Root Material",2, matAl); matVacuum->SetTransparency(80); matAl->SetTransparency(70); // [0] this is the top volume cube TGeoVolume *top = gGeoManager->MakeBox("TOP",Vacuum,kX_max,kY_max,kZ_max); gGeoManager->SetTopVisible(); gGeoManager->SetTopVolume(top); top->SetFillColor(3); // [1] this is the cylinder TGeoVolume *vcylinder= gGeoManager->MakeTube("Cylinder",Al, kR_min, kR_max, kZ_d); // Al <-> nullptr <- placeholder for TGeoMedium* vcylinder->SetLineColor(kGreen); TGeoShape *scylinder= vcylinder->GetShape(); top->AddNode(vcylinder,1); gGeoManager->CloseGeometry(); } void qpbr_tracks() { Double_t rfP0 = 1.0; // set incoming beam particle momentum Double_t rfE0 = 10.0; // set incoming beam particle energy Double_t tauc = 1.0; // collision time (arbitrary) //_ geometry rendering pbr_create_geo(); TEveManager::Create(); // this initializes gEve global pointer TEveGeoTopNode* top = new TEveGeoTopNode(gGeoManager, gGeoManager->GetTopNode()); // "/TOP_1/Cylinder_1" top->SetVisOption(0); top->SetVisLevel(6); gEve->AddGlobalElement(top); //_ end geometry rendering //_ track generation auto propag = new TEveTrackPropagator(); propag->SetStepper(TEveTrackPropagator::kRungeKutta); propag->SetMaxR(kR_min); // these set maximum extents of track propagation propag->SetMaxZ(kZ_d); //propag->SetRnrDecay(kFALSE); auto tracks = new TEveElementList("Tracks"); auto pmc = new TEvePathMarkD(TEvePathMarkD::kDecay, origin, tauc ); // collision vertex mark // at the origin TEveVector4D endpoint; Double_t Rho; Double_t Phi = 0.; Double_t rfE; Int_t itrk = 0; TTree *tep = new TTree("tep", "TTree itrk,x,y,z,t,E"); // endpoint storage for hits on Cylinder_1 tep->Branch("itrk",&itrk,"itrk/I"); tep->Branch("x",&endpoint.fX,"x/D"); tep->Branch("y",&endpoint.fY,"y/D"); tep->Branch("z",&endpoint.fZ,"z/D"); tep->Branch("t",&endpoint.fT,"t/D"); tep->Branch("E",&rfE,"E/D"); //////////////////////////////// // 2x primary particle beams // //////////////////////////////// const Int_t Nptracks = 2; auto p1 = new TParticle(); auto p2 = new TParticle(); // primary vertex p1->SetProductionVertex(0.,0., kZ_max ,0.); p2->SetProductionVertex(0.,0.,-kZ_max ,0.); p1->SetMomentum(0.,0.,-rfP0,rfE0); p2->SetMomentum(0.,0.,+rfP0,rfE0); auto track = new TEveTrack(p1,0,propag); track->AddPathMark(*pmc); track->MakeTrack(); //_generate track time (track 0) auto trackp = propag->GetLastPoints(); endpoint = trackp.back(); endpoint += TEveVector4D(0.0,0.0,0.0, tauc); endpoint.Dump(); //_end generate track time track->SetElementName("Beam 0"); track->SetMainColor(kYellow); tracks->AddElement(track); TEveTrack *track0 = track; track = new TEveTrack(p2,1,propag); track->AddPathMark(*pmc); track->MakeTrack(); //_generate track time (track 1) trackp = propag->GetLastPoints(); endpoint = trackp.back(); endpoint += TEveVector4D(0.0,0.0,0.0, tauc); endpoint.Dump(); //_end generate track time track->SetElementName("Beam 1"); track->SetMainColor(kYellow); tracks->AddElement(track); TEveTrack *track1 = track; ///////////////////////////////////////////////////////////////// // 4x secondary particle products (arbitrary Energy+Momentum) // ///////////////////////////////////////////////////////////////// auto rnd = gRandom; const Int_t Nstracks = 4; for (Int_t i =Nptracks; i<(Nstracks+Nptracks); i++) { auto p = new TParticle(); rfE = rnd->Uniform(rfE0); p->SetProductionVertex(vrtxo); p->SetMomentum(4.*pow(-1,i),0.,(1.+i)*pow(-1,i),rfE); auto track = new TEveTrack(p,i,propag); track->MakeTrack(); //_establish parent-child linkage track0->AddElement(track); track1->AddElement(track); track->AddParent(track0); track->AddParent(track1); //_end establish parent-child linkage //_generate track time (track i) trackp = propag->GetLastPoints(); endpoint = trackp.back(); endpoint += TEveVector4D(0.0,0.0,0.0, tauc+i); // detection time (arbitrary) endpoint.Dump(); //_end generate track time track->SetMainColor(kBlue); track->SetName(Form("p %d",i-Nptracks+1)); track->SetLineColor((pow(-1,i) > 0 ? kBlue : kRed)); track->SetRnrPoints(kTRUE); track->SetMarkerStyle(4); track->PrintPathMarks(); //_detect Cylinder_1 hits Rho = TMath::Sqrt(endpoint.fX*endpoint.fX+endpoint.fY*endpoint.fY); if(Rho == kR_min) { // we have a hit, store x,y,z,t,E itrk = i; cout << "track " << itrk << " matches" << endl; tep->Fill(); // store to tree } //_end detect Cylinder_1 hits } gEve->GetEventScene()->AddElement(tracks); gEve->GetDefaultViewer()->SetName("Viewer - GL"); gEve->GetDefaultViewer()->SetElementName("GL"); //_ end track generation gEve->FullRedraw3D(kTRUE, kTRUE); // setup camera view auto vGL = gEve->GetDefaultGLViewer(); //vGL->CurrentCamera().SetExternalCenter(kTRUE); vGL->SetCurrentCamera(TGLViewer::kCameraPerspXOZ); vGL->CurrentCamera().Configure(kfov,kdolly,kCenter,khRotate,kvRotate); vGL->RequestDraw(TGLRnrCtx::kLODHigh); //_create lego plots (on TCanvas) tep->Print(); tep->Show(1); tep->Scan("z:E"); const Double_t k1eps = 1.0 + 0.01; // small tolerance to ensure values at the min/max boundaries are counted TH2D *h2 = new TH2D("ZPhiE","Z,Phi vs E",10,-(kZ_d*k1eps),(kZ_d*k1eps),10,-(TMath::Pi()*k1eps),(TMath::Pi()*k1eps)); ROOT::Math::Cylindrical3D< Double_t > p3D; Int_t nentries = (Int_t)tep->GetEntries(); for (Int_t i=0; iGetEntry(i); p3D.SetXYZ(endpoint.fX,endpoint.fY,endpoint.fZ); Rho = p3D.Rho(); Phi = p3D.Phi(); cout<< "Rho Z Phi rfE "<Fill(Rho,Phi,rfE); h2->Fill(p3D.Z(),Phi,rfE); } //h2->Draw("lego2 0"); //_end create lego plots on TCanvas //_create two-tabbed TEve display // Create the second tab auto slot = TEveWindow::CreateWindowInTab(gEve->GetBrowser()->GetTabRight()); gEve->GetBrowser()->GetTabRight()->SetTab(1); //_create two vertical slots in tab #2 // Set new window for 2 vertical sub-slots TEveWindowPack* packH = slot->MakePack(); packH->SetElementName("Composite"); packH->SetShowTitleBar(kFALSE); slot = packH->NewSlot(); TEveWindowPack* pack0 = slot->MakePack(); pack0->SetShowTitleBar(kFALSE); auto slotTop = pack0->NewSlot(); auto slotsBottom = pack0->NewSlot(); //_create two horizontal slots in bottom tab #2 TEveWindowPack* pack1 = slotsBottom->MakePack(); pack1->SetHorizontal(); pack1->SetShowTitleBar(kFALSE); auto slotBottLeft = pack1->NewSlot(); auto slotBottRight = pack1->NewSlot(); //create bottom lego plot in Eve auto data = new TEveCaloDataHist(); data->AddHistogram((TH2F *)h2); data->RefSliceInfo(0).Setup("ECAL", 0.000, kRed ); data->GetEtaBins()->SetTitleFont(100); data->GetEtaBins()->SetTitle("Z "); data->GetPhiBins()->SetTitleFont(100); data->GetPhiBins()->SetTitle("Phi "); data->IncDenyDestroy(); gEve->AddToListTree(data, kFALSE); auto lego = MakeCaloLego(data, slotBottLeft); //_end create bottom lego plot in Eve //_create lego animation (on TCanvas) slotBottRight->StartEmbedding(); auto c2 = new TCanvas("Animation", "Animation"); slotBottRight->StopEmbedding(); std::string s; TPaveText *pt = new TPaveText(-0.95,1.09,-0.33,0.92); TH2D *h2a = new TH2D("ZPhiEa","Z,Phi vs E",10,-(kZ_d*k1eps),(kZ_d*k1eps),10,-(TMath::Pi()*k1eps),(TMath::Pi()*k1eps)); //Sort tep TTree in order of endpoint.fT (time) Int_t *index = new Int_t[nentries]; tep->Draw("t","","goff"); // this extracts TMath::Sort(nentries,tep->GetV1(),index, kFALSE); // and sorts the t-values for (Int_t i=0;iGetEntry(index[i]); p3D.SetXYZ(endpoint.fX,endpoint.fY,endpoint.fZ); h2a->Fill(p3D.Z(),p3D.Phi(),rfE); cout << "i= " << i << " index ="<< index[i] << p3D.Z() << " " << p3D.Rho() << " " << p3D.Phi() << " " << rfE << " " << endpoint.fT << endl; h2a->Draw("lego2 0"); pt->Clear(); s = "t = " + std::to_string(endpoint.fT); pt->AddText(s.c_str()); pt->Draw(); c2->Update(); //gSystem->ProcessEvents(); gSystem->Sleep(kSleep); // in millisec } //_end create lego animation //_end create two horizontal slots in bottom tab #2 //create top track plot in Eve auto v = new TEveViewer("GL-2"); v->SpawnGLEmbeddedViewer(gEve->GetEditor()); v->AddScene(gEve->GetGlobalScene()); v->AddScene(gEve->GetEventScene()); slotTop->ReplaceWindow(v); vGL = v->GetGLViewer(); vGL->SetCurrentCamera(TGLViewer::kCameraPerspXOZ); vGL->CurrentCamera().Configure(1.1*kfov,kdolly,kCenter,khRotate,kvRotate); vGL->RequestDraw(TGLRnrCtx::kLODHigh); //_end create top track plot in Eve //_end create two vertical slots in tab #2 //_end create two-tabbed TEve display gEve->GetBrowser()->GetTabRight()->SetTab(2); } //______________________________________________________________________________ //__________ _________ //__________ Following taken from tutorials/eve/calorimeters.C _________ //______________________________________________________________________________ //______________________________________________________________________________ void MakeViewerScene(TEveWindowSlot* slot, TEveViewer*& v, TEveScene*& s) { // Create a scene and a viewer in the given slot. v = new TEveViewer("Viewer."); v->SpawnGLViewer(gEve->GetEditor()); slot->ReplaceWindow(v); gEve->GetViewers()->AddElement(v); s = gEve->SpawnNewScene("Scene."); v->AddScene(s); } //______________________________________________________________________________ TEveCaloLego* MakeCaloLego(TEveCaloData* data, TEveWindowSlot* slot) { // Eta-phi lego view. TEveViewer* v; TEveScene* s; if (slot) { MakeViewerScene(slot, v, s); } else { v = gEve->GetDefaultViewer(); s = gEve->GetEventScene(); } v->SetElementName("Viewer - Lego"); s->SetElementName("Scene - Lego"); auto lego = new TEveCaloLego(data); s->AddElement(lego); // By the default lego extends is (1x1x1). Resize it to put in 'natural' // coordinates, so that y extend in 2*Pi and set height of lego two times // smaller than y extend to have better view in 3D perspective. lego->InitMainTrans(); // Set rotation and scaling for lego plot lego->RefMainTrans().SetRotByAngles( 6.8 , 0. , 0. ); lego->RefMainTrans().SetScale( 0.1, 10.0 , 7.0 ); auto glv = v->GetGLViewer(); // draws scales and axis on borders of window TEveCaloLegoOverlay* overlay = new TEveCaloLegoOverlay(); glv->AddOverlayElement(overlay); overlay->SetCaloLego(lego); // set event handler to move from perspective to orthographic view. //glv->SetCurrentCamera(TGLViewer::kCameraOrthoXOY); //glv->SetCurrentCamera(TGLViewer::kCameraOrthoXnOZ); //glv->SetCurrentCamera(TGLViewer::kCameraOrthoXOZ); glv->SetCurrentCamera(TGLViewer::kCameraPerspXOZ); Double_t kfov = 0.85; Double_t kdolly = 0.; Double_t kcenter[3] = {2.,0., 2.}; // GL camera center (lego plot) Double_t khrotate = TMath::Pi(); Double_t kvrotate = TMath::Pi(); khrotate= 1.00; // ~1/3*Pi kvrotate= 4.712; // ~3/2*Pi //kvrotate= 1.; glv->CurrentCamera().Configure( kfov, kdolly, kcenter, khrotate, kvrotate); glv->RequestDraw(TGLRnrCtx::kLODHigh); glv->SetEventHandler(new TEveLegoEventHandler(glv->GetGLWidget(), glv, lego)); gEve->AddToListTree(lego, kTRUE); gEve->FullRedraw3D(kFALSE, kFALSE); return lego; }