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