Logo ROOT   6.18/05
Reference Guide
collection_proxies.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_eve7
3/// This example display collection of ??? in web browser
4///
5/// \macro_code
6///
7
8
9#include "ROOT/REveDataClasses.hxx"
10//#include "ROOT/REveDataProxyBuilderBase.hxx"
11//#include "ROOT/REveDataSimpleProxyBuilder.hxx"
12#include "ROOT/REveDataSimpleProxyBuilderTemplate.hxx"
13#include "ROOT/REveManager.hxx"
14#include "ROOT/REveScalableStraightLineSet.hxx"
15#include "ROOT/REveViewContext.hxx"
16#include <ROOT/REveGeoShape.hxx>
17#include <ROOT/REveJetCone.hxx>
18#include <ROOT/REvePointSet.hxx>
19#include <ROOT/REveProjectionBases.hxx>
20#include <ROOT/REveProjectionManager.hxx>
21#include <ROOT/REveScene.hxx>
22#include <ROOT/REveTableProxyBuilder.hxx>
23#include <ROOT/REveTableInfo.hxx>
24#include <ROOT/REveTrack.hxx>
25#include <ROOT/REveTrackPropagator.hxx>
26#include <ROOT/REveViewer.hxx>
27#include <ROOT/REveViewContext.hxx>
28
29#include "TGeoTube.h"
30#include "TList.h"
31#include "TParticle.h"
32#include "TRandom.h"
33#include "TApplication.h"
34
35
36namespace REX = ROOT::Experimental;
37
38bool gRhoZView = false;
39
40REX::REveManager *eveMng = nullptr;
41
42//==============================================================================
43//============== EMULATE FRAMEWORK CLASSES =====================================
44//==============================================================================
45
46
47// a demo class, can be provided from experiment framework
48class XYJet : public TParticle
49{
50private:
51 float m_etaSize{0};
52 float m_phiSize{0};
53
54public:
55 float GetEtaSize() const { return m_etaSize; }
56 float GetPhiSize() const { return m_phiSize; }
57 void SetEtaSize(float iEtaSize) { m_etaSize = iEtaSize; }
58 void SetPhiSize(float iPhiSize) { m_phiSize = iPhiSize; }
59 XYJet(Int_t pdg, Int_t status, Int_t mother1, Int_t mother2, Int_t daughter1, Int_t daughter2, Double_t px, Double_t py, Double_t pz, Double_t etot):
60 TParticle(pdg, status, mother1, mother2, daughter1, daughter2, px, py, pz, etot, 0, 0, 0, 0) {}
61
62 ClassDef(XYJet, 1);
63};
64
65class Event {
66public:
67 int eventId{0};
68 int N_tracks{0};
69 int N_jets{0};
70
71 Event() = default;
72
73 void MakeJets(int N)
74 {
75 TRandom &r = *gRandom;
76 r.SetSeed(0);
77 TList* list = new TList();
78 list->SetName("XYJets");
79 for (int i = 1; i <= N; ++i)
80 {
81 double pt = r.Uniform(0.5, 10);
82 double eta = r.Uniform(-2.55, 2.55);
83 double phi = r.Uniform(-TMath::Pi(), TMath::Pi());
84
85 double px = pt * std::cos(phi);
86 double py = pt * std::sin(phi);
87 double pz = pt * (1. / (std::tan(2*std::atan(std::exp(-eta)))));
88
89 auto jet = new XYJet(0, 0, 0, 0, 0, 0, px, py, pz, std::sqrt(px*px + py*py + pz*pz + 80*80));
90 jet->SetEtaSize(r.Uniform(0.02, 0.2));
91 jet->SetPhiSize(r.Uniform(0.01, 0.3));
92 list->Add(jet);
93 }
94 m_data.push_back(list);
95 }
96
97 void MakeParticles(int N)
98 {
99 TRandom &r = *gRandom;
100 r.SetSeed(0);
101 TList* list = new TList();
102 list->SetName("XYTracks");
103 for (int i = 1; i <= N; ++i)
104 {
105 double pt = r.Uniform(0.5, 10);
106 double eta = r.Uniform(-2.55, 2.55);
107 double phi = r.Uniform(0, TMath::TwoPi());
108
109 double px = pt * std::cos(phi);
110 double py = pt * std::sin(phi);
111 double pz = pt * (1. / (std::tan(2*std::atan(std::exp(-eta)))));
112
113 printf("Event::MakeParticles %2d: pt=%.2f, eta=%.2f, phi=%.2f\n", i, pt, eta, phi);
114
115 auto particle = new TParticle(0, 0, 0, 0, 0, 0,
116 px, py, pz, std::sqrt(px*px + py*py + pz*pz + 80*80),
117 0, 0, 0, 0 );
118
119 int pdg = 11 * (r.Integer(2) > 0 ? 1 : -1);
120 particle->SetPdgCode(pdg);
121
122 list->Add(particle);
123 }
124 m_data.push_back(list);
125 }
126
127 std::vector<TList*> m_data;
128
129 void Clear() {
130 for (auto &l : m_data)
131 delete l;
132 m_data.clear();
133 }
134
135 void Create() {
136 Clear();
137 MakeJets(4);
138 MakeParticles(10);
139 eventId++;
140 }
141};
142
143//==============================================================================
144//============ PROXY BUILDERS ================================================
145//==============================================================================
146class XYJetProxyBuilder: public REX::REveDataSimpleProxyBuilderTemplate<XYJet>
147{
148 virtual bool HaveSingleProduct() const { return false; }
149
150 using REveDataSimpleProxyBuilderTemplate<XYJet>::BuildViewType;
151 virtual void BuildViewType(const XYJet& dj, REX::REveElement* iItemHolder, std::string viewType, const REX::REveViewContext* context)
152 {
153 auto jet = new REX::REveJetCone();
154 jet->SetCylinder(context->GetMaxR(), context->GetMaxZ());
155 jet->AddEllipticCone(dj.Eta(), dj.Phi(), dj.GetEtaSize(), dj.GetPhiSize());
156 SetupAddElement(jet, iItemHolder, true);
157
158 REX::REveVector p1;
159 REX::REveVector p2;
160
161 float size = 50.f * dj.Pt(); // values are saved in scale
162 double theta = dj.Theta();
163 // printf("%s jet theta = %f, phi = %f \n", iItemHolder->GetCName(), theta, dj.Phi());
164 double phi = dj.Phi();
165
166
167 if (viewType == "Projected" )
168 {
169 static const float_t offr = 6;
170 float r_ecal = context->GetMaxR() + offr;
171 float z_ecal = context->GetMaxZ() + offr;
172
173 float transAngle = abs(atan(r_ecal/z_ecal));
174 double r(0);
175 bool debug = false;
176 if ( theta < transAngle || 3.14-theta < transAngle)
177 {
178 z_ecal = context->GetMaxZ() + offr/transAngle;
179 r = z_ecal/fabs(cos(theta));
180 }
181 else
182 {
183 debug = 3;
184 r = r_ecal/sin(theta);
185 }
186
187 p1.Set( 0., (phi<TMath::Pi() ? r*fabs(sin(theta)) : -r*fabs(sin(theta))), r*cos(theta));
188 p2.Set( 0., (phi<TMath::Pi() ? (r+size)*fabs(sin(theta)) : -(r+size)*fabs(sin(theta))), (r+size)*cos(theta) );
189
190
191 auto marker = new REX::REveScalableStraightLineSet("jetline");
192 marker->SetScaleCenter(p1.fX, p1.fY, p1.fZ);
193 marker->AddLine(p1, p2);
194
195 marker->SetLineWidth(4);
196 if (debug)
197 marker->AddMarker(0, 0.9);
198
199 SetupAddElement(marker, iItemHolder, true);
200 }
201
202 jet->SetName(Form("element %s", iItemHolder->GetName().c_str()));
203 }
204};
205
206class TrackProxyBuilder : public REX::REveDataSimpleProxyBuilderTemplate<TParticle>
207{
208 using REveDataSimpleProxyBuilderTemplate<TParticle>::Build;
209 virtual void Build(const TParticle& p, REX::REveElement* iItemHolder, const REX::REveViewContext* context)
210 {
211 const TParticle *x = &p;
212 // printf("============== BUILD track %s (pt=%f, eta=%f) \n", iItemHolder->GetCName(), p.Pt(), p.Eta());
213 auto track = new REX::REveTrack((TParticle*)(x), 1, context->GetPropagator());
214 track->MakeTrack();
215 SetupAddElement(track, iItemHolder, true);
216 // iItemHolder->AddElement(track);
217 track->SetName(Form("element %s id=%d", iItemHolder->GetCName(), track->GetElementId()));
218 }
219};
220
221
222//==============================================================================
223//==============================================================================
224// ================= XY MANGER ================================================
225//==============================================================================
226//==============================================================================
227class XYManager
228{
229private:
230 Event *m_event{nullptr};
231
232 std::vector<REX::REveScene *> m_scenes;
233 REX::REveViewContext *m_viewContext{nullptr};
234 REX::REveProjectionManager *m_mngRhoZ{nullptr};
235
236 std::vector<REX::REveDataProxyBuilderBase *> m_builders;
237 REX::REveScene *m_collections{nullptr};
238 bool m_inEventLoading{false};
239
240public:
241 XYManager(Event* event): m_event(event)
242 {
243 //view context
244 float r = 300;
245 float z = 300;
246 auto prop = new REX::REveTrackPropagator();
247 prop->SetMagFieldObj(new REX::REveMagFieldDuo(350, -3.5, 2.0));
248 prop->SetMaxR(r);
249 prop->SetMaxZ(z);
250 prop->SetMaxOrbs(6);
251 prop->IncRefCount();
252
253 m_viewContext = new REX::REveViewContext();
254 m_viewContext->SetBarrel(r, z);
255 m_viewContext->SetTrackPropagator(prop);
256
257 // table specs
258 auto tableInfo = new REX::REveTableViewInfo();
259 tableInfo->table("XYTracks").
260 column("pt", 1, "Pt").
261 column("eta", 3, "Eta").
262 column("phi", 3, "Phi");
263
264 tableInfo->table("XYJets").
265 column("eta", 1, "Eta").
266 column("phi", 1, "Phi").
267 column("etasize", 2, "GetEtaSize").
268 column("phisize", 2, "GetPhiSize");
269
270 m_viewContext->SetTableViewInfo(tableInfo);
271
272 createScenesAndViews();
273 }
274
275 void createScenesAndViews()
276 {
277 // collections
278 m_collections = eveMng->SpawnNewScene("Collections","Collections");
279
280 // 3D
281 m_scenes.push_back(eveMng->GetEventScene());
282
283 // Geometry
284 auto b1 = new REX::REveGeoShape("Barrel 1");
285 float dr = 3;
286 b1->SetShape(new TGeoTube(m_viewContext->GetMaxR() , m_viewContext->GetMaxR() + dr, m_viewContext->GetMaxZ()));
287 b1->SetMainColor(kCyan);
288 eveMng->GetGlobalScene()->AddElement(b1);
289
290 // RhoZ
291 if (gRhoZView) {
292 auto rhoZEventScene = eveMng->SpawnNewScene("RhoZ Scene","Projected");
293 m_mngRhoZ = new REX::REveProjectionManager(REX::REveProjection::kPT_RhoZ);
294 m_mngRhoZ->SetImportEmpty(true);
295 auto rhoZView = eveMng->SpawnNewViewer("RhoZ View", "");
296 rhoZView->AddScene(rhoZEventScene);
297 m_scenes.push_back(rhoZEventScene);
298
299 auto pgeoScene = eveMng->SpawnNewScene("Projection Geometry","xxx");
300 m_mngRhoZ->ImportElements(b1,pgeoScene );
301 rhoZView->AddScene(pgeoScene);
302 }
303
304 // Table
305 if (1) {
306 auto tableScene = eveMng->SpawnNewScene("Tables", "Tables");
307 auto tableView = eveMng->SpawnNewViewer("Table", "Table View");
308 tableView->AddScene(tableScene);
309 tableScene->AddElement(m_viewContext->GetTableViewInfo());
310 m_scenes.push_back(tableScene);
311 }
312
313 }
314
315 // this should be handeled with framefor plugins
316 REX::REveDataProxyBuilderBase* makeGLBuilderForType(TClass* c)
317 {
318 std::string cn = c->GetName();
319 // printf("proxy builder for type %s\n", c->GetName());
320 if (cn == "XYJet") {
321 return new XYJetProxyBuilder();
322 }
323 else
324 {
325 return new TrackProxyBuilder();
326 }
327 }
328
329 void LoadCurrentEvent(REX::REveDataCollection* collection)
330 {
331 // printf("load current event \n");
332 for (auto &l : m_event->m_data) {
333 TIter next(l);
334 if (collection->GetName() == std::string(l->GetName()))
335 {
336 // printf("collection for list %s %s\n", collection->GetCName(), l->GetName());
337 collection->ClearItems();
338 collection->DestroyElements();
339
340 for (int i = 0; i <= l->GetLast(); ++i)
341 {
342 TString pname; pname.Form("item %2d", i);
343 collection->AddItem(l->At(i), pname.Data(), "");
344 }
345 }
346 //collections->RefChildren())
347 }
348 }
349
350 void NextEvent()
351 {
352 m_inEventLoading = true;
353 for (auto &el: m_collections->RefChildren())
354 {
355 auto c = dynamic_cast<REX::REveDataCollection *>(el);
356 LoadCurrentEvent(c);
357 c->ApplyFilter();
358 }
359
360 for (auto proxy : m_builders) {
361 proxy->Build();
362 }
363 m_inEventLoading = false;
364 }
365
366 void addCollection(REX::REveDataCollection* collection, bool makeTable)
367 {
368 // load data
369 LoadCurrentEvent(collection);
370
371 // GL view types
372 auto glBuilder = makeGLBuilderForType(collection->GetItemClass());
373 glBuilder->SetCollection(collection);
374 glBuilder->SetHaveAWindow(true);
375 for (auto scene : m_scenes) {
376 REX::REveElement *product = glBuilder->CreateProduct(scene->GetTitle(), m_viewContext);
377 if (strncmp(scene->GetCTitle(), "Table", 5) == 0) continue;
378 if (!strncmp(scene->GetCTitle(), "Projected", 8)) {
379 m_mngRhoZ->ImportElements(product, scene);
380 }
381 else {
382 scene->AddElement(product);
383 }
384 }
385 m_builders.push_back(glBuilder);
386 glBuilder->Build();
387
388 if (makeTable) {
389 // Table view types {
390 auto tableBuilder = new REX::REveTableProxyBuilder();
391 tableBuilder->SetHaveAWindow(true);
392 tableBuilder->SetCollection(collection);
393 REX::REveElement* tablep = tableBuilder->CreateProduct("table-type", m_viewContext);
394
395 auto tableMng = m_viewContext->GetTableViewInfo();
396 tableMng->SetDisplayedCollection(collection->GetElementId());
397 tableMng->AddDelegate([=](REX::ElementId_t elId) { tableBuilder->DisplayedCollectionChanged(elId); });
398
399 for (REX::REveScene* scene : m_scenes) {
400 if (strncmp(scene->GetCTitle(), "Table", 5) == 0) {
401 scene->AddElement(tablep);
402 tableBuilder->Build(collection, tablep, m_viewContext );
403 }
404 }
405
406 m_builders.push_back(tableBuilder);
407 }
408
409 m_collections->AddElement(collection);
410 collection->SetHandlerFunc([&] (REX::REveDataCollection* collection) { this->CollectionChanged( collection ); });
411 collection->SetHandlerFuncIds([&] (REX::REveDataCollection* collection, const REX::REveDataCollection::Ids_t& ids) { this->ModelChanged( collection, ids ); });
412 }
413
414 void finishViewCreate()
415 {
416 auto mngTable = m_viewContext->GetTableViewInfo();
417 if (mngTable) {
418 for (auto &el : m_collections->RefChildren())
419 {
420 if (el->GetName() == "XYTracks")
421 mngTable->SetDisplayedCollection(el->GetElementId());
422 }
423 }
424 }
425
426 void CollectionChanged(REX::REveDataCollection* collection) {
427 printf("collection changes not implemented %s!\n", collection->GetCName());
428 }
429
430 void ModelChanged(REX::REveDataCollection* collection, const REX::REveDataCollection::Ids_t& ids) {
431 if (m_inEventLoading) return;
432
433 for (auto proxy : m_builders) {
434 if (proxy->Collection() == collection) {
435 // printf("Model changes check proxy %s: \n", proxy->Type().c_str());
436 proxy->ModelChanges(ids);
437 }
438 }
439 }
440};
441
442
443//==============================================================================
444
445class EventManager : public REX::REveElement
446{
447private:
448 Event* m_event;
449 XYManager* m_xymng;
450
451public:
452 EventManager(Event* e, XYManager* m): m_event(e), m_xymng(m) {}
453
454 virtual ~EventManager() {}
455
456 virtual void NextEvent()
457 {
458 m_event->Create();
459 m_xymng->NextEvent();
460 }
461
462 virtual void QuitRoot()
463 {
464 printf("Quit ROOT\n");
466 }
467};
468
469//______________________________________________________________________________
470
471
472void collection_proxies(bool proj=true)
473{
474 eveMng = REX::REveManager::Create();
475
476 auto event = new Event();
477 event->Create();
478 event->N_tracks = 10;
479 event->N_jets = 4;
480
481 gRhoZView = true;
482
483 // debug settings
484 auto xyManager = new XYManager(event);
485
486 if (1) {
487 REX::REveDataCollection* trackCollection = new REX::REveDataCollection("XYTracks");
488 trackCollection->SetItemClass(TParticle::Class());
489 trackCollection->SetMainColor(kGreen);
490 //trackCollection->SetFilterExpr("i.Pt() > 0.1 && std::abs(i.Eta()) < 1");
491 xyManager->addCollection(trackCollection, true);
492 }
493
494 if (1) {
495 REX::REveDataCollection* jetCollection = new REX::REveDataCollection("XYJets");
496 jetCollection->SetItemClass(XYJet::Class());
497 jetCollection->SetMainColor(kRed);
498 xyManager->addCollection(jetCollection, false);
499 }
500
501 auto eventMng = new EventManager(event, xyManager);
502 eventMng->SetName("EventManager");
503 eveMng->GetWorld()->AddElement(eventMng);
504
505 eveMng->GetWorld()->AddCommand("QuitRoot", "sap-icon://log", eventMng, "QuitRoot()");
506 eveMng->GetWorld()->AddCommand("NextEvent", "sap-icon://step", eventMng, "NextEvent()");
507
508 eveMng->Show();
509}
void Class()
Definition: Class.C:29
ROOT::R::TRInterface & r
Definition: Object.C:4
#define c(i)
Definition: RSha256.hxx:101
#define e(i)
Definition: RSha256.hxx:103
int Int_t
Definition: RtypesCore.h:41
double Double_t
Definition: RtypesCore.h:55
#define ClassDef(name, id)
Definition: Rtypes.h:326
@ kRed
Definition: Rtypes.h:64
@ kGreen
Definition: Rtypes.h:64
@ kCyan
Definition: Rtypes.h:64
R__EXTERN TApplication * gApplication
Definition: TApplication.h:165
#define N
double cos(double)
double atan(double)
double tan(double)
double sqrt(double)
double sin(double)
double exp(double)
R__EXTERN TRandom * gRandom
Definition: TRandom.h:62
char * Form(const char *fmt,...)
virtual void Terminate(Int_t status=0)
Terminate the application by call TSystem::Exit() unless application has been told to return from Run...
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
void SetName(const char *name)
Definition: TCollection.h:204
Cylindrical tube class.
Definition: TGeoTube.h:18
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
Description of the dynamic properties of a particle.
Definition: TParticle.h:26
TParticle()
reference to the particle record in PDG database
Definition: TParticle.cxx:63
This is the base class for the ROOT Random number generators.
Definition: TRandom.h:27
Basic string class.
Definition: TString.h:131
const char * Data() const
Definition: TString.h:364
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
void collection_proxies(bool proj=true)
REX::REveManager * eveMng
bool gRhoZView
TPaveText * pt
REX::REveViewer * rhoZView
Definition: event_demo.C:40
REX::REveScene * rhoZEventScene
Definition: event_demo.C:38
Double_t x[n]
Definition: legend1.C:17
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
constexpr Double_t Pi()
Definition: TMath.h:38
constexpr Double_t TwoPi()
Definition: TMath.h:45
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4