Belle II Software development
EVEVisualization.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9//For GFTrack visualisation:
10/* Copyright 2011, Technische Universitaet Muenchen,
11 Author: Karl Bicker
12
13 This file is part of GENFIT.
14
15 GENFIT is free software: you can redistribute it and/or modify
16 it under the terms of the GNU Lesser General Public License as published
17 by the Free Software Foundation, either version 3 of the License, or
18 (at your option) any later version.
19
20 GENFIT is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public License
26 along with GENFIT. If not, see <http://www.gnu.org/licenses/>.
27*/
28#include <display/EVEVisualization.h>
29
30#include <display/VisualRepMap.h>
31#include <display/EveGeometry.h>
32#include <display/EveVisBField.h>
33#include <display/ObjectInfo.h>
34
35#include <vxd/geometry/GeoCache.h>
36#include <klm/bklm/geometry/GeometryPar.h>
37#include <cdc/geometry/CDCGeometryPar.h>
38#include <cdc/dataobjects/CDCRecoHit.h>
39#include <cdc/translators/RealisticTDCCountTranslator.h>
40#include <arich/dbobjects/ARICHGeometryConfig.h>
41#include <simulation/dataobjects/MCParticleTrajectory.h>
42#include <svd/reconstruction/SVDRecoHit.h>
43#include <top/geometry/TOPGeometryPar.h>
44
45#include <genfit/AbsMeasurement.h>
46#include <genfit/PlanarMeasurement.h>
47#include <genfit/SpacepointMeasurement.h>
48#include <genfit/WireMeasurement.h>
49#include <genfit/WireMeasurementNew.h>
50#include <genfit/WirePointMeasurement.h>
51#include <genfit/DetPlane.h>
52#include <genfit/Exception.h>
53#include <genfit/KalmanFitterInfo.h>
54#include <genfit/GblFitterInfo.h>
55
56#include <framework/dataobjects/DisplayData.h>
57#include <framework/logging/Logger.h>
58#include <framework/utilities/ColorPalette.h>
59#include <framework/geometry/VectorUtil.h>
60
61#include <Math/VectorUtil.h>
62#include <TEveArrow.h>
63#include <TEveBox.h>
64#include <TEveCalo.h>
65#include <TEveManager.h>
66#include <TEveGeoShape.h>
67#include <TEveLine.h>
68#include <TEvePointSet.h>
69#include <TEveSelection.h>
70#include <TEveStraightLineSet.h>
71#include <TEveTriangleSet.h>
72#include <TEveText.h>
73#include <TEveTrack.h>
74#include <TEveTrackPropagator.h>
75#include <TGeoEltu.h>
76#include <TGeoMatrix.h>
77#include <TGeoManager.h>
78#include <TGeoSphere.h>
79#include <TGeoTube.h>
80#include <TGLLogicalShape.h>
81#include <TParticle.h>
82#include <TMath.h>
83#include <TVectorD.h>
84#include <TMatrixD.h>
85#include <TMatrixDSymEigen.h>
86
87#include <boost/math/special_functions/fpclassify.hpp>
88#include <boost/scoped_ptr.hpp>
89#include <boost/algorithm/string/find.hpp>
90#include <boost/algorithm/string/trim.hpp>
91#include <boost/algorithm/string/classification.hpp>
92
93#include <cassert>
94#include <cmath>
95
96using namespace Belle2;
97using namespace Belle2::TangoPalette;
98
99namespace {
101 template <class T> void destroyEveElement(T*& el)
102 {
103 if (!el) return;
104 if (el->GetDenyDestroy() > 1)
105 B2WARNING("destroyEveElement(): Element " << el->GetName() << " has unexpected refcount " << el->GetDenyDestroy());
106
107 el->DecDenyDestroy(); //also deletes el when refcount <= 0
108 el = nullptr;
109 }
110
117 void fixGeoShapeRefCount(TEveGeoShape* eveshape)
118 {
119 TGeoShape* s = eveshape->GetShape();
120 //Remove(obj) usually takes about 20us, but since usually s is at the end, we can shorten this
121 if (gGeoManager->GetListOfShapes()->Last() == s)
122 gGeoManager->GetListOfShapes()->RemoveAt(gGeoManager->GetListOfShapes()->GetLast());
123 else
124 gGeoManager->GetListOfShapes()->Remove(s);
125 }
126}
127
128const int EVEVisualization::c_recoHitColor = getTColorID("Orange", 1);
130const int EVEVisualization::c_trackColor = getTColorID("Sky Blue", 2);
131const int EVEVisualization::c_recoTrackColor = getTColorID("Sky Blue", 1);
132const int EVEVisualization::c_trackMarkerColor = getTColorID("Chameleon", 3);
133const int EVEVisualization::c_klmClusterColor = getTColorID("Chameleon", 1);
134
136 m_assignToPrimaries(false),
137 m_eclData(0),
138 m_bfield(new EveVisBField())
139{
140 setErrScale();
141
142 TGLLogicalShape::SetIgnoreSizeForCameraInterest(kTRUE); // Allows the visualization of the "small" error ellipsoid.
143
144 //create new containers
145 m_trackpropagator = new TEveTrackPropagator();
146 m_trackpropagator->IncDenyDestroy();
147 m_trackpropagator->SetMagFieldObj(m_bfield, false);
148 m_trackpropagator->SetFitDaughters(false); //most secondaries are no longer immediate daughters since we might discard those!
149 m_trackpropagator->SetMaxR(EveGeometry::getMaxR()); //don't draw tracks outside detector
150 //TODO is this actually needed?
151 m_trackpropagator->SetMaxStep(1.0); //make sure to reeval magnetic field often enough
152
153 m_tracklist = new TEveTrackList(m_trackpropagator);
154 m_tracklist->IncDenyDestroy();
155 m_tracklist->SetName("MCParticles");
156 m_tracklist->SelectByP(c_minPCut, FLT_MAX); //don't show too many particles by default...
157
158 m_gftrackpropagator = new TEveTrackPropagator();
159 m_gftrackpropagator->IncDenyDestroy();
160 m_gftrackpropagator->SetMagFieldObj(m_bfield, false);
161 m_gftrackpropagator->SetMaxOrbs(0.5); //stop after track markers
162
163 m_consttrackpropagator = new TEveTrackPropagator();
164 m_consttrackpropagator->IncDenyDestroy();
165 m_consttrackpropagator->SetMagField(0, 0, -1.5);
167
168 m_calo3d = new TEveCalo3D(NULL, "ECLClusters");
169 m_calo3d->SetBarrelRadius(125.80); //inner radius of ECL barrel
170 m_calo3d->SetForwardEndCapPos(196.5); //inner edge of forward endcap
171 m_calo3d->SetBackwardEndCapPos(-102.0); //inner edge of backward endcap
172 m_calo3d->SetMaxValAbs(2.1);
173 m_calo3d->SetRnrFrame(false, false); //don't show crystal grid
174 m_calo3d->IncDenyDestroy();
175
176 //Stop eve from deleting contents... (which might already be deleted)
177 gEve->GetSelection()->IncDenyDestroy();
178 gEve->GetHighlight()->IncDenyDestroy();
179
180 clearEvent();
181}
182
183void EVEVisualization::setOptions(const std::string& opts) { m_options = opts; }
184
185void EVEVisualization::setErrScale(double errScale) { m_errorScale = errScale; }
186
188{
189 if (!gEve)
190 return; //objects are probably already freed by Eve
191
192 //Eve objects
193 destroyEveElement(m_eclData);
194 destroyEveElement(m_unassignedRecoHits);
195 destroyEveElement(m_tracklist);
196 destroyEveElement(m_trackpropagator);
197 destroyEveElement(m_gftrackpropagator);
198 destroyEveElement(m_consttrackpropagator);
199 destroyEveElement(m_calo3d);
200 delete m_bfield;
201}
202
203void EVEVisualization::addTrackCandidate(const std::string& collectionName,
204 const RecoTrack& recoTrack)
205{
206 const TString label = ObjectInfo::getIdentifier(&recoTrack);
207 // parse the option string ------------------------------------------------------------------------
208 bool drawHits = false;
209
210 if (m_options != "") {
211 for (size_t i = 0; i < m_options.length(); i++) {
212 if (m_options.at(i) == 'H') drawHits = true;
213 }
214 }
215 // finished parsing the option string -------------------------------------------------------------
216
217
218 //track seeds
219 const B2Vector3D& track_pos = recoTrack.getPositionSeed();
220 const B2Vector3D& track_mom = recoTrack.getMomentumSeed();
221
222 TEveStraightLineSet* lines = new TEveStraightLineSet("RecoHits for " + label);
223 lines->SetMainColor(c_recoTrackColor);
224 lines->SetMarkerColor(c_recoTrackColor);
225 lines->SetMarkerStyle(6);
226 lines->SetMainTransparency(60);
227
228 if (drawHits) {
229 // Loop over all hits in the track (three different types)
230 for (const RecoHitInformation::UsedPXDHit* pxdHit : recoTrack.getPXDHitList()) {
231 addRecoHit(pxdHit, lines);
232 }
233
234 for (const RecoHitInformation::UsedSVDHit* svdHit : recoTrack.getSVDHitList()) {
235 addRecoHit(svdHit, lines);
236 }
237
238 for (const RecoHitInformation::UsedCDCHit* cdcHit : recoTrack.getCDCHitList()) {
239 addRecoHit(cdcHit, lines);
240 }
241 }
242
243 TEveRecTrack rectrack;
244 rectrack.fP.Set(track_mom);
245 rectrack.fV.Set(track_pos);
246
247 TEveTrack* track_lines = new TEveTrack(&rectrack, m_gftrackpropagator);
248 track_lines->SetName(label); //popup label set at end of function
249 track_lines->SetPropagator(m_gftrackpropagator);
250 track_lines->SetLineColor(c_recoTrackColor);
251 track_lines->SetLineWidth(1);
252 track_lines->SetTitle(ObjectInfo::getTitle(&recoTrack));
253
254 track_lines->SetCharge((int)recoTrack.getChargeSeed());
255
256
257 track_lines->AddElement(lines);
258 addToGroup(collectionName, track_lines);
259 addObject(&recoTrack, track_lines);
260}
261
262void EVEVisualization::addTrackCandidateImproved(const std::string& collectionName,
263 const RecoTrack& recoTrack)
264{
265 const TString label = ObjectInfo::getIdentifier(&recoTrack);
266 // parse the option string ------------------------------------------------------------------------
267 bool drawHits = false;
268
269 if (m_options != "") {
270 for (size_t i = 0; i < m_options.length(); i++) {
271 if (m_options.at(i) == 'H') drawHits = true;
272 }
273 }
274 // finished parsing the option string -------------------------------------------------------------
275
276 // Create a track as a polyline through reconstructed points
277 // FIXME this is snatched from PrimitivePlotter, need to add extrapolation out of CDC
278 TEveLine* track = new TEveLine(); // We are going to just add points with SetNextPoint
279 std::vector<ROOT::Math::XYZVector> posPoints; // But first we'll have to sort them as in RecoHits axial and stereo come in blocks
280 track->SetName(label); //popup label set at end of function
281 track->SetLineColor(c_recoTrackColor);
282 track->SetLineWidth(3);
283 track->SetTitle(ObjectInfo::getTitle(&recoTrack));
284 track->SetSmooth(true);
285
286 for (auto recoHit : recoTrack.getRecoHitInformations()) {
287 // skip for reco hits which have not been used in the fit (and therefore have no fitted information on the plane
288 if (!recoHit->useInFit())
289 continue;
290
291 // Need TVector3 here for genfit interface below
292 TVector3 pos;
293 TVector3 mom;
294 TMatrixDSym cov;
295
296 try {
297 const auto* trackPoint = recoTrack.getCreatedTrackPoint(recoHit);
298 const auto* fittedResult = trackPoint->getFitterInfo();
299 if (not fittedResult) {
300 B2WARNING("Skipping unfitted track point");
301 continue;
302 }
303 const genfit::MeasuredStateOnPlane& state = fittedResult->getFittedState();
304 state.getPosMomCov(pos, mom, cov);
305 } catch (const genfit::Exception&) {
306 B2WARNING("Skipping state with strange pos, mom or cov");
307 continue;
308 }
309
310 posPoints.push_back(ROOT::Math::XYZVector(pos.X(), pos.Y(), pos.Z()));
311 }
312
313 sort(posPoints.begin(), posPoints.end(),
314 [](const ROOT::Math::XYZVector & a, const ROOT::Math::XYZVector & b) -> bool {
315 return a.X() * a.X() + a.Y() * a.Y() > b.X() * b.X() + b.Y() * b.Y();
316 });
317 for (auto vec : posPoints) {
318 track->SetNextPoint(vec.X(), vec.Y(), vec.Z());
319 }
320 // add corresponding hits ---------------------------------------------------------------------
321 TEveStraightLineSet* lines = new TEveStraightLineSet("RecoHits for " + label);
322 lines->SetMainColor(c_recoTrackColor);
323 lines->SetMarkerColor(c_recoTrackColor);
324 lines->SetMarkerStyle(6);
325 lines->SetMainTransparency(60);
326
327 if (drawHits) {
328 // Loop over all hits in the track (three different types)
329 for (const RecoHitInformation::UsedPXDHit* pxdHit : recoTrack.getPXDHitList()) {
330 addRecoHit(pxdHit, lines);
331 }
332
333 for (const RecoHitInformation::UsedSVDHit* svdHit : recoTrack.getSVDHitList()) {
334 addRecoHit(svdHit, lines);
335 }
336
337 for (const RecoHitInformation::UsedCDCHit* cdcHit : recoTrack.getCDCHitList()) {
338 addRecoHit(cdcHit, lines);
339 }
340 }
341
342 track->AddElement(lines);
343 addToGroup(collectionName, track);
344 addObject(&recoTrack, track);
345}
346
347void EVEVisualization::addCDCTriggerTrack(const std::string& collectionName,
348 const CDCTriggerTrack& trgTrack)
349{
350 const TString label = ObjectInfo::getIdentifier(&trgTrack);
351
352 B2Vector3D track_pos = B2Vector3D(0, 0, trgTrack.getZ0());
353 B2Vector3D track_mom = (trgTrack.getChargeSign() == 0) ?
354 trgTrack.getDirection() * 1000 :
355 trgTrack.getMomentum(1.5);
356
357 TEveRecTrack rectrack;
358 rectrack.fP.Set(track_mom);
359 rectrack.fV.Set(track_pos);
360
361 TEveTrack* track_lines = new TEveTrack(&rectrack, m_consttrackpropagator);
362 track_lines->SetName(label); //popup label set at end of function
363 track_lines->SetPropagator(m_consttrackpropagator);
364 track_lines->SetLineColor(kOrange + 2);
365 track_lines->SetLineWidth(1);
366 track_lines->SetTitle(ObjectInfo::getTitle(&trgTrack) +
367 TString::Format("\ncharge: %d, phi: %.2fdeg, pt: %.2fGeV, theta: %.2fdeg, z: %.2fcm",
368 trgTrack.getChargeSign(),
369 trgTrack.getPhi0() * 180 / M_PI,
370 trgTrack.getTransverseMomentum(1.5),
371 trgTrack.getDirection().Theta() * 180 / M_PI,
372 trgTrack.getZ0()));
373
374
375 track_lines->SetCharge(trgTrack.getChargeSign());
376
377 // show 2D tracks with dashed lines
378 if (trgTrack.getZ0() == 0 && trgTrack.getCotTheta() == 0)
379 track_lines->SetLineStyle(2);
380
381 addToGroup(collectionName, track_lines);
382 addObject(&trgTrack, track_lines);
383}
384
386{
387 // load the pion fit hypothesis or the hypothesis which is the closest in mass to a pion
388 // the tracking will not always successfully fit with a pion hypothesis
389 const TrackFitResult* fitResult = belle2Track->getTrackFitResultWithClosestMass(Const::pion);
390 if (!fitResult) {
391 B2ERROR("Track without TrackFitResult skipped.");
392 return;
393 }
394 const RecoTrack* track = belle2Track->getRelated<RecoTrack>();
395
396 const TString label = ObjectInfo::getIdentifier(belle2Track) + " (" + ObjectInfo::getIdentifier(fitResult) + ")";
397
398 // parse the option string ------------------------------------------------------------------------
399 bool drawDetectors = false;
400 bool drawHits = false;
401 bool drawPlanes = false;
402
403 if (m_options != "") {
404 for (size_t i = 0; i < m_options.length(); i++) {
405 if (m_options.at(i) == 'D') drawDetectors = true;
406 if (m_options.at(i) == 'H') drawHits = true;
407 if (m_options.at(i) == 'P') drawPlanes = true;
408 }
409 }
410 // finished parsing the option string -------------------------------------------------------------
411
412 // We loop over all points (scattering non-measurement points for GBL)
413 // and for Kalman we skip those with no measurements, which should
414 // not be there
415 bool isPruned = (track == nullptr);
416
417
418 TEveRecTrackD recTrack;
419 const B2Vector3D& poca = fitResult->getPosition();
420 recTrack.fV.Set(poca);
421
422 const B2Vector3D& poca_momentum = fitResult->getMomentum();
423 if (std::isfinite(poca_momentum.Mag()))
424 recTrack.fP.Set(poca_momentum);
425 else //use 1TeV momentum for tracks without curvature
426 recTrack.fP.Set(B2Vector3D(fitResult->getHelix().getDirection() * 1000));
427
428 recTrack.fSign = fitResult->getChargeSign();
429 TEveTrack* eveTrack = new TEveTrack(&recTrack, m_gftrackpropagator);
430 eveTrack->SetName(label);
431
432
433 if (track) {
434 const genfit::AbsTrackRep* representation;
435
436 if (m_drawCardinalRep) {
437 representation = track->getCardinalRepresentation();
438 B2DEBUG(100, "Draw cardinal rep");
439 } else {
440 const auto& representations = track->getRepresentations();
441 if (representations.empty()) {
442 B2ERROR("No representations found in the reco track!");
443 return;
444 }
445 B2DEBUG(100, "Draw representation number 0.");
446 representation = representations.front();
447 }
448
449 if (!track->hasTrackFitStatus(representation)) {
450 B2ERROR("RecoTrack without FitStatus: will be skipped!");
451 return;
452 }
453
454 const genfit::FitStatus* fitStatus = track->getTrackFitStatus(representation);
455
456 isPruned = fitStatus->isTrackPruned();
457
458 // GBL and Kalman cannot mix in a track.
459 // What is 0 after first loop will stay 0:
460 genfit::KalmanFitterInfo* fi = 0;
461 genfit::KalmanFitterInfo* prevFi = 0;
462 genfit::GblFitterInfo* gfi = 0;
463 genfit::GblFitterInfo* prevGFi = 0;
464 const genfit::MeasuredStateOnPlane* fittedState(NULL);
465 const genfit::MeasuredStateOnPlane* prevFittedState(NULL);
466
467
468 const auto& hitPoints = track->getHitPointsWithMeasurement();
469 const unsigned int numpoints = hitPoints.size();
470
471 int hitCounter = -1;
472 for (genfit::TrackPoint* tp : hitPoints) { // loop over all points in the track
473 hitCounter++;
474
475 // get the fitter infos ------------------------------------------------------------------
476 if (! tp->hasFitterInfo(representation)) {
477 B2ERROR("trackPoint has no fitterInfo for rep");
478 continue;
479 }
480
481 genfit::AbsFitterInfo* fitterInfo = tp->getFitterInfo(representation);
482
483 fi = dynamic_cast<genfit::KalmanFitterInfo*>(fitterInfo);
484 gfi = dynamic_cast<genfit::GblFitterInfo*>(fitterInfo);
485
486 if (!gfi && !fi) {
487 B2ERROR("Can only display KalmanFitterInfo or GblFitterInfo");
488 continue;
489 }
490
491 if (gfi && fi)
492 B2FATAL("AbsFitterInfo dynamic-casted to both KalmanFitterInfo and GblFitterInfo!");
493
494
495 if (fi && ! tp->hasRawMeasurements()) {
496 B2ERROR("trackPoint has no raw measurements");
497 continue;
498 }
499
500 if (fi && ! fi->hasPredictionsAndUpdates()) {
501 B2ERROR("KalmanFitterInfo does not have all predictions and updates");
502 continue;
503 }
504
505 try {
506 if (gfi)
507 fittedState = &(gfi->getFittedState(true));
508 if (fi)
509 fittedState = &(fi->getFittedState(true));
510 } catch (genfit::Exception& e) {
511 B2ERROR(e.what() << " - can not get fitted state");
512 continue;
513 }
514
515 ROOT::Math::XYZVector track_pos = ROOT::Math::XYZVector(representation->getPos(*fittedState));
516
517 // draw track if corresponding option is set ------------------------------------------
518 if (prevFittedState != NULL) {
519
520 TEvePathMark::EType_e markType = TEvePathMark::kReference;
521 if (hitCounter + 1 == static_cast<int>(numpoints)) //track should stop here.
522 markType = TEvePathMark::kDecay;
523
524 // Kalman: non-null prevFi ensures that the previous fitter info was also KalmanFitterInfo
525 if (fi && prevFi) {
526 makeLines(eveTrack, prevFittedState, fittedState, representation, markType, m_drawErrors);
527 if (m_drawErrors) { // make sure to draw errors in both directions
528 makeLines(eveTrack, prevFittedState, fittedState, representation, markType, m_drawErrors, 0);
529 }
530 //these are currently disabled.
531 //TODO: if activated, I want to have a separate TEveStraightLineSet instead of eveTrack (different colors/options)
532 if (m_drawForward)
533 makeLines(eveTrack, prevFi->getForwardUpdate(), fi->getForwardPrediction(), representation, markType, m_drawErrors, 0);
534 if (m_drawBackward)
535 makeLines(eveTrack, prevFi->getBackwardPrediction(), fi->getBackwardUpdate(), representation, markType, m_drawErrors);
536 // draw reference track if corresponding option is set ------------------------------------------
537 if (m_drawRefTrack && fi->hasReferenceState() && prevFi->hasReferenceState())
538 makeLines(eveTrack, prevFi->getReferenceState(), fi->getReferenceState(), representation, markType, false);
539 }
540
541 // GBL: non-null prevGFi ensures that the previous fitter info was also GblFitterInfo
542 if (gfi && prevGFi) {
543 makeLines(eveTrack, prevFittedState, fittedState, representation, markType, m_drawErrors);
544 if (m_drawErrors) {
545 makeLines(eveTrack, prevFittedState, fittedState, representation, markType, m_drawErrors, 0);
546 }
547
548 if (m_drawRefTrack && gfi->hasReferenceState() && prevGFi->hasReferenceState()) {
549 genfit::StateOnPlane prevSop = prevGFi->getReferenceState();
550 genfit::StateOnPlane sop = gfi->getReferenceState();
551 makeLines(eveTrack, &prevSop, &sop, representation, markType, false);
552 }
553 }
554
555 }
556 prevFi = fi; // Kalman
557 prevGFi = gfi; // GBL
558 prevFittedState = fittedState;
559
560
561 //loop over all measurements for this point (e.g. u and v-type strips)
562 const int numMeasurements = tp->getNumRawMeasurements();
563 for (int iMeasurement = 0; iMeasurement < numMeasurements; iMeasurement++) {
564 const genfit::AbsMeasurement* m = tp->getRawMeasurement(iMeasurement);
565
566 TVectorT<double> hit_coords;
567 TMatrixTSym<double> hit_cov;
568
569 if (fi) {
570 // Kalman
571 genfit::MeasurementOnPlane* mop = fi->getMeasurementOnPlane(iMeasurement);
572 hit_coords.ResizeTo(mop->getState());
573 hit_cov.ResizeTo(mop->getCov());
574 hit_coords = mop->getState();
575 hit_cov = mop->getCov();
576 }
577 if (gfi) {
578 // GBL - has only one measurement (other should be already merged before the track is constructed)
579 // That means tp->getNumRawMeasurements() returns 1 for tracks fitted by GBL, because GBLfit Module
580 // merges all corresponding SVD strips to 2D combined clusters.
581 genfit::MeasurementOnPlane gblMeas = gfi->getMeasurement();
582 hit_coords.ResizeTo(gblMeas.getState());
583 hit_cov.ResizeTo(gblMeas.getCov());
584 hit_coords = gblMeas.getState();
585 hit_cov = gblMeas.getCov();
586 }
587
588 // finished getting the hit infos -----------------------------------------------------
589
590 // sort hit infos into variables ------------------------------------------------------
591 ROOT::Math::XYZVector o = ROOT::Math::XYZVector(fittedState->getPlane()->getO());
592 ROOT::Math::XYZVector u = ROOT::Math::XYZVector(fittedState->getPlane()->getU());
593 ROOT::Math::XYZVector v = ROOT::Math::XYZVector(fittedState->getPlane()->getV());
594
595 bool planar_hit = false;
596 bool planar_pixel_hit = false;
597 bool space_hit = false;
598 bool wire_hit = false;
599 bool wirepoint_hit = false;
600 double_t hit_u = 0;
601 double_t hit_v = 0;
602 double_t plane_size = 4;
603
604 int hit_coords_dim = m->getDim();
605
606 if (dynamic_cast<const genfit::PlanarMeasurement*>(m) != NULL) {
607 planar_hit = true;
608 if (hit_coords_dim == 1) {
609 hit_u = hit_coords(0);
610 } else if (hit_coords_dim == 2) {
611 planar_pixel_hit = true;
612 hit_u = hit_coords(0);
613 hit_v = hit_coords(1);
614 }
615 } else if (dynamic_cast<const genfit::SpacepointMeasurement*>(m) != NULL) {
616 space_hit = true;
617 } else if (dynamic_cast<const CDCRecoHit*>(m)
618 || dynamic_cast<const genfit::WireMeasurement*>(m)
619 || dynamic_cast<const genfit::WireMeasurementNew*>(m)) {
620 wire_hit = true;
621 hit_u = fabs(hit_coords(0));
622 hit_v = v.Dot(track_pos - o); // move the covariance tube so that the track goes through it
623 if (dynamic_cast<const genfit::WirePointMeasurement*>(m) != NULL) {
624 wirepoint_hit = true;
625 hit_v = hit_coords(1);
626 }
627 } else {
628 B2ERROR("Hit " << hitCounter << ", Measurement " << iMeasurement << ": Unknown measurement type: skipping hit!");
629 break;
630 }
631
632 // finished setting variables ---------------------------------------------------------
633
634 // draw planes if corresponding option is set -----------------------------------------
635 if (drawPlanes || (drawDetectors && planar_hit)) {
636 ROOT::Math::XYZVector move(0, 0, 0);
637 if (wire_hit) move = v * (v.Dot(track_pos - o)); // move the plane along the wire until the track goes through it
638 TEveBox* box = boxCreator(o + move, u, v, plane_size, plane_size, 0.01);
639 if (drawDetectors && planar_hit) {
640 box->SetMainColor(kCyan);
641 } else {
642 box->SetMainColor(kGray);
643 }
644 box->SetMainTransparency(50);
645 eveTrack->AddElement(box);
646 }
647 // finished drawing planes ------------------------------------------------------------
648
649 // draw detectors if option is set, only important for wire hits ----------------------
650 if (drawDetectors) {
651
652 if (wire_hit) {
653 TEveGeoShape* det_shape = new TEveGeoShape("det_shape");
654 det_shape->SetShape(new TGeoTube(std::max(0., (double)(hit_u - 0.0105 / 2.)), hit_u + 0.0105 / 2., plane_size));
655 fixGeoShapeRefCount(det_shape);
656
657 ROOT::Math::XYZVector norm = u.Cross(v);
658 TGeoRotation det_rot("det_rot", (u.Theta() * 180) / TMath::Pi(), (u.Phi() * 180) / TMath::Pi(),
659 (norm.Theta() * 180) / TMath::Pi(), (norm.Phi() * 180) / TMath::Pi(),
660 (v.Theta() * 180) / TMath::Pi(), (v.Phi() * 180) / TMath::Pi()); // move the tube to the right place and rotate it correctly
661 ROOT::Math::XYZVector move = v * (v.Dot(track_pos - o)); // move the tube along the wire until the track goes through it
662 TGeoCombiTrans det_trans(o.X() + move.X(),
663 o.Y() + move.Y(),
664 o.Z() + move.Z(),
665 &det_rot);
666 det_shape->SetTransMatrix(det_trans);
667 det_shape->SetMainColor(kCyan);
668 det_shape->SetMainTransparency(25);
669 if ((drawHits && (hit_u + 0.0105 / 2 > 0)) || !drawHits) {
670 eveTrack->AddElement(det_shape);
671 }
672 }
673
674 }
675 // finished drawing detectors ---------------------------------------------------------
676
677 if (drawHits) {
678
679 // draw planar hits, with distinction between strip and pixel hits ----------------
680 if (planar_hit) {
681 if (!planar_pixel_hit) {
682 //strip hit
684 const SVDRecoHit* recoHit = dynamic_cast<const SVDRecoHit*>(m);
685 if (!recoHit) {
686 B2WARNING("SVD recohit couldn't be converted... ");
687 continue;
688 }
689
690 const VXD::SensorInfoBase& sensor = geo.getSensorInfo(recoHit->getSensorID());
691 double du, dv;
692 ROOT::Math::XYZVector a = o; //defines position of sensor plane
693 double hit_res_u = hit_cov(0, 0);
694 if (recoHit->isU()) {
695 du = std::sqrt(hit_res_u);
696 dv = sensor.getLength();
697 a += hit_u * u;
698 } else {
699 du = sensor.getWidth();
700 dv = std::sqrt(hit_res_u);
701 a += hit_u * v;
702 }
703 double depth = sensor.getThickness();
704 TEveBox* hit_box = boxCreator(a, u, v, du, dv, depth);
705 hit_box->SetName("SVDRecoHit");
706 hit_box->SetMainColor(c_recoHitColor);
707 hit_box->SetMainTransparency(0);
708 eveTrack->AddElement(hit_box);
709 } else {
710 //pixel hit
711 // calculate eigenvalues to draw error-ellipse ----------------------------
712 TMatrixDSymEigen eigen_values(hit_cov);
713 TEveGeoShape* cov_shape = new TEveGeoShape("PXDRecoHit");
714 const TVectorD& ev = eigen_values.GetEigenValues();
715 const TMatrixD& eVec = eigen_values.GetEigenVectors();
716 double pseudo_res_0 = m_errorScale * std::sqrt(ev(0));
717 double pseudo_res_1 = m_errorScale * std::sqrt(ev(1));
718 // finished calcluating, got the values -----------------------------------
719
720 // calculate the semiaxis of the error ellipse ----------------------------
721 cov_shape->SetShape(new TGeoEltu(pseudo_res_0, pseudo_res_1, 0.0105));
722 fixGeoShapeRefCount(cov_shape);
723 ROOT::Math::XYZVector pix_pos = o + hit_u * u + hit_v * v;
724 ROOT::Math::XYZVector u_semiaxis = (pix_pos + eVec(0, 0) * u + eVec(1, 0) * v) - pix_pos;
725 ROOT::Math::XYZVector v_semiaxis = (pix_pos + eVec(0, 1) * u + eVec(1, 1) * v) - pix_pos;
726 ROOT::Math::XYZVector norm = u.Cross(v);
727 // finished calculating ---------------------------------------------------
728
729 // rotate and translate everything correctly ------------------------------
730 TGeoRotation det_rot("det_rot", (u_semiaxis.Theta() * 180) / TMath::Pi(), (u_semiaxis.Phi() * 180) / TMath::Pi(),
731 (v_semiaxis.Theta() * 180) / TMath::Pi(), (v_semiaxis.Phi() * 180) / TMath::Pi(),
732 (norm.Theta() * 180) / TMath::Pi(), (norm.Phi() * 180) / TMath::Pi());
733 TGeoCombiTrans det_trans(pix_pos.X(), pix_pos.Y(), pix_pos.Z(), &det_rot);
734 cov_shape->SetTransMatrix(det_trans);
735 // finished rotating and translating --------------------------------------
736
737 cov_shape->SetMainColor(c_recoHitColor);
738 cov_shape->SetMainTransparency(0);
739 eveTrack->AddElement(cov_shape);
740 }
741 }
742 // finished drawing planar hits ---------------------------------------------------
743
744 // draw spacepoint hits -----------------------------------------------------------
745 if (space_hit) {
746
747 // get eigenvalues of covariance to know how to draw the ellipsoid ------------
748 TMatrixDSymEigen eigen_values(m->getRawHitCov());
749 TEveGeoShape* cov_shape = new TEveGeoShape("SpacePoint Hit");
750 cov_shape->SetShape(new TGeoSphere(0., 1.));
751 fixGeoShapeRefCount(cov_shape);
752 const TVectorD& ev = eigen_values.GetEigenValues();
753 const TMatrixD& eVec = eigen_values.GetEigenVectors();
754 ROOT::Math::XYZVector eVec1(eVec(0, 0), eVec(1, 0), eVec(2, 0));
755 ROOT::Math::XYZVector eVec2(eVec(0, 1), eVec(1, 1), eVec(2, 1));
756 ROOT::Math::XYZVector eVec3(eVec(0, 2), eVec(1, 2), eVec(2, 2));
757 // got everything we need -----------------------------------------------------
758
759
760 TGeoRotation det_rot("det_rot", (eVec1.Theta() * 180) / TMath::Pi(), (eVec1.Phi() * 180) / TMath::Pi(),
761 (eVec2.Theta() * 180) / TMath::Pi(), (eVec2.Phi() * 180) / TMath::Pi(),
762 (eVec3.Theta() * 180) / TMath::Pi(), (eVec3.Phi() * 180) / TMath::Pi()); // the rotation is already clear
763
764 // set the scaled eigenvalues -------------------------------------------------
765 double pseudo_res_0 = m_errorScale * std::sqrt(ev(0));
766 double pseudo_res_1 = m_errorScale * std::sqrt(ev(1));
767 double pseudo_res_2 = m_errorScale * std::sqrt(ev(2));
768 // finished scaling -----------------------------------------------------------
769
770 // rotate and translate -------------------------------------------------------
771 TGeoGenTrans det_trans(o.X(), o.Y(), o.Z(),
772 //std::sqrt(pseudo_res_0/pseudo_res_1/pseudo_res_2), std::sqrt(pseudo_res_1/pseudo_res_0/pseudo_res_2), std::sqrt(pseudo_res_2/pseudo_res_0/pseudo_res_1), // this workaround is necessary due to the "normalization" performed in TGeoGenTrans::SetScale
773 //1/(pseudo_res_0),1/(pseudo_res_1),1/(pseudo_res_2),
774 pseudo_res_0, pseudo_res_1, pseudo_res_2,
775 &det_rot);
776 cov_shape->SetTransMatrix(det_trans);
777 // finished rotating and translating ------------------------------------------
778
779 cov_shape->SetMainColor(c_recoHitColor);
780 cov_shape->SetMainTransparency(10);
781 eveTrack->AddElement(cov_shape);
782 }
783 // finished drawing spacepoint hits -----------------------------------------------
784
785 // draw wire hits -----------------------------------------------------------------
786 if (wire_hit) {
787 const double cdcErrorScale = 1.0;
788 TEveGeoShape* cov_shape = new TEveGeoShape("CDCRecoHit");
789 double pseudo_res_0 = cdcErrorScale * std::sqrt(hit_cov(0, 0));
790 double pseudo_res_1 = plane_size;
791 if (wirepoint_hit) pseudo_res_1 = cdcErrorScale * std::sqrt(hit_cov(1, 1));
792
793 cov_shape->SetShape(new TGeoTube(std::max(0., (double)(hit_u - pseudo_res_0)), hit_u + pseudo_res_0, pseudo_res_1));
794 fixGeoShapeRefCount(cov_shape);
795 ROOT::Math::XYZVector norm = u.Cross(v);
796
797 // rotate and translate -------------------------------------------------------
798 TGeoRotation det_rot("det_rot", (u.Theta() * 180) / TMath::Pi(), (u.Phi() * 180) / TMath::Pi(),
799 (norm.Theta() * 180) / TMath::Pi(), (norm.Phi() * 180) / TMath::Pi(),
800 (v.Theta() * 180) / TMath::Pi(), (v.Phi() * 180) / TMath::Pi());
801 TGeoCombiTrans det_trans(o.X() + hit_v * v.X(),
802 o.Y() + hit_v * v.Y(),
803 o.Z() + hit_v * v.Z(),
804 &det_rot);
805 cov_shape->SetTransMatrix(det_trans);
806 // finished rotating and translating ------------------------------------------
807
808 cov_shape->SetMainColor(c_recoHitColor);
809 cov_shape->SetMainTransparency(50);
810 eveTrack->AddElement(cov_shape);
811 }
812 // finished drawing wire hits -----------------------------------------------------
813 }
814
815 }
816 }
817
818 auto& firstref = eveTrack->RefPathMarks().front();
819 auto& lastref = eveTrack->RefPathMarks().back();
820 double f = firstref.fV.Distance(recTrack.fV);
821 double b = lastref.fV.Distance(recTrack.fV);
822 if (f > 100 and f > b) {
823 B2WARNING("Decay vertex is much closer to POCA than first vertex, reversing order of track points... (this is intended for cosmic tracks, if you see this message in other context it might indicate a problem)");
824 //last ref is better than first...
825 lastref.fType = TEvePathMarkD::kReference;
826 firstref.fType = TEvePathMarkD::kDecay;
827 std::reverse(eveTrack->RefPathMarks().begin(), eveTrack->RefPathMarks().end());
828 }
829 }
830 eveTrack->SetTitle(TString::Format("%s\n"
831 "pruned: %s\n"
832 "pT=%.3f, pZ=%.3f\n"
833 "pVal: %e",
834 label.Data(),
835 isPruned ? " yes" : "no",
836 poca_momentum.Pt(), poca_momentum.Pz(),
837 fitResult->getPValue()
838 ));
839 eveTrack->SetLineColor(c_trackColor);
840 eveTrack->SetLineStyle(1);
841 eveTrack->SetLineWidth(3.0);
842
843
844 addToGroup("Fitted Tracks", eveTrack);
845 if (track)
846 addObject(track, eveTrack);
847 addObject(belle2Track, eveTrack);
848}
849
850TEveBox* EVEVisualization::boxCreator(const ROOT::Math::XYZVector& o, ROOT::Math::XYZVector u, ROOT::Math::XYZVector v, float ud,
851 float vd, float depth)
852{
853 //force minimum width of polygon to deal with Eve limits
854 float min = 0.04;
855 if (vd < min)
856 vd = min;
857 if (ud < min)
858 ud = min;
859 if (depth < min)
860 depth = min;
861
862 TEveBox* box = new TEveBox;
863 box->SetPickable(true);
864
865 ROOT::Math::XYZVector norm = u.Cross(v);
866 u *= (0.5 * ud);
867 v *= (0.5 * vd);
868 norm *= (0.5 * depth);
869
870
871 for (int k = 0; k < 8; ++k) {
872 // Coordinates for all eight corners of the box
873 // as two parallel rectangles, with vertices specified in clockwise direction
874 int signU = ((k + 1) & 2) ? -1 : 1;
875 int signV = (k & 4) ? -1 : 1;
876 int signN = (k & 2) ? -1 : 1;
877 float vertex[3];
878 // for (int i = 0; i < 3; ++i) {
879 // vertex[i] = o(i) + signU * u(i) + signV * v(i) + signN * norm(i);
880 // }
881 vertex[0] = o.X() + signU * u.X() + signV * v.X() + signN * norm.X();
882 vertex[1] = o.Y() + signU * u.Y() + signV * v.Y() + signN * norm.Y();
883 vertex[2] = o.Z() + signU * u.Z() + signV * v.Z() + signN * norm.Z();
884 box->SetVertex(k, vertex);
885 }
886
887 return box;
888}
889
890void EVEVisualization::makeLines(TEveTrack* eveTrack, const genfit::StateOnPlane* prevState, const genfit::StateOnPlane* state,
891 const genfit::AbsTrackRep* rep,
892 TEvePathMark::EType_e markType, bool drawErrors, int markerPos)
893{
894 using namespace genfit;
895
896 // Need TVector3 for genfit interface
897 TVector3 pos, dir, oldPos, oldDir;
898 rep->getPosDir(*state, pos, dir);
899 rep->getPosDir(*prevState, oldPos, oldDir);
900
901 double distA = (pos - oldPos).Mag();
902 double distB = distA;
903 if ((pos - oldPos)*oldDir < 0)
904 distA *= -1.;
905 if ((pos - oldPos)*dir < 0)
906 distB *= -1.;
907
908 TEvePathMark mark(
909 markType,
910 TEveVector(pos.X(), pos.Y(), pos.Z()),
911 TEveVector(dir.X(), dir.Y(), dir.Z())
912 );
913 eveTrack->AddPathMark(mark);
914
915
916 if (drawErrors) {
917 const MeasuredStateOnPlane* measuredState;
918 if (markerPos == 0)
919 measuredState = dynamic_cast<const MeasuredStateOnPlane*>(prevState);
920 else
921 measuredState = dynamic_cast<const MeasuredStateOnPlane*>(state);
922
923 if (measuredState != NULL) {
924
925 // step for evaluate at a distance from the original plane
926 ROOT::Math::XYZVector eval;
927 if (markerPos == 0)
928 eval = 0.2 * distA * oldDir;
929 else
930 eval = -0.2 * distB * dir;
931
932
933 // get cov at first plane
934 TMatrixDSym cov;
935 // Need TVector3 for genfit interface
936 TVector3 position, direction;
937 rep->getPosMomCov(*measuredState, position, direction, cov);
938
939 // get eigenvalues & -vectors
940 TMatrixDSymEigen eigen_values(cov.GetSub(0, 2, 0, 2));
941 const TVectorD& ev = eigen_values.GetEigenValues();
942 const TMatrixD& eVec = eigen_values.GetEigenVectors();
943 ROOT::Math::XYZVector eVec1, eVec2;
944 // limit
945 static const double maxErr = 1000.;
946 double ev0 = std::min(ev(0), maxErr);
947 double ev1 = std::min(ev(1), maxErr);
948 double ev2 = std::min(ev(2), maxErr);
949
950 // get two largest eigenvalues/-vectors
951 if (ev0 < ev1 && ev0 < ev2) {
952 eVec1.SetXYZ(eVec(0, 1), eVec(1, 1), eVec(2, 1));
953 eVec1 *= sqrt(ev1);
954 eVec2.SetXYZ(eVec(0, 2), eVec(1, 2), eVec(2, 2));
955 eVec2 *= sqrt(ev2);
956 } else if (ev1 < ev0 && ev1 < ev2) {
957 eVec1.SetXYZ(eVec(0, 0), eVec(1, 0), eVec(2, 0));
958 eVec1 *= sqrt(ev0);
959 eVec2.SetXYZ(eVec(0, 2), eVec(1, 2), eVec(2, 2));
960 eVec2 *= sqrt(ev2);
961 } else {
962 eVec1.SetXYZ(eVec(0, 0), eVec(1, 0), eVec(2, 0));
963 eVec1 *= sqrt(ev0);
964 eVec2.SetXYZ(eVec(0, 1), eVec(1, 1), eVec(2, 1));
965 eVec2 *= sqrt(ev1);
966 }
967
968 if (eVec1.Cross(eVec2).Dot(eval) < 0)
969 eVec2 *= -1;
970 //assert(eVec1.Cross(eVec2)*eval > 0);
971
972 ROOT::Math::XYZVector oldEVec1(eVec1);
973
974 const int nEdges = 24;
975 std::vector<ROOT::Math::XYZVector> vertices;
976
977 vertices.push_back(ROOT::Math::XYZVector(position));
978
979 // vertices at plane
980 for (int i = 0; i < nEdges; ++i) {
981 const double angle = 2 * TMath::Pi() / nEdges * i;
982 vertices.push_back(ROOT::Math::XYZVector(position) + cos(angle)*eVec1 + sin(angle)*eVec2);
983 }
984
985
986
987 SharedPlanePtr newPlane(new DetPlane(*(measuredState->getPlane())));
988 newPlane->setO(position + XYZToTVector(eval));
989
990 MeasuredStateOnPlane stateCopy(*measuredState);
991 try {
992 rep->extrapolateToPlane(stateCopy, newPlane);
993 } catch (Exception& e) {
994 B2ERROR(e.what());
995 return;
996 }
997
998 // get cov at 2nd plane
999 rep->getPosMomCov(stateCopy, position, direction, cov);
1000
1001 // get eigenvalues & -vectors
1002 {
1003 TMatrixDSymEigen eigen_values2(cov.GetSub(0, 2, 0, 2));
1004 const TVectorD& eVal = eigen_values2.GetEigenValues();
1005 const TMatrixD& eVect = eigen_values2.GetEigenVectors();
1006 // limit
1007 ev0 = std::min(eVal(0), maxErr);
1008 ev1 = std::min(eVal(1), maxErr);
1009 ev2 = std::min(eVal(2), maxErr);
1010
1011 // get two largest eigenvalues/-vectors
1012 if (ev0 < ev1 && ev0 < ev2) {
1013 eVec1.SetXYZ(eVect(0, 1), eVect(1, 1), eVect(2, 1));
1014 eVec1 *= sqrt(ev1);
1015 eVec2.SetXYZ(eVect(0, 2), eVect(1, 2), eVect(2, 2));
1016 eVec2 *= sqrt(ev2);
1017 } else if (ev1 < ev0 && ev1 < ev2) {
1018 eVec1.SetXYZ(eVect(0, 0), eVect(1, 0), eVect(2, 0));
1019 eVec1 *= sqrt(ev0);
1020 eVec2.SetXYZ(eVect(0, 2), eVect(1, 2), eVect(2, 2));
1021 eVec2 *= sqrt(ev2);
1022 } else {
1023 eVec1.SetXYZ(eVect(0, 0), eVect(1, 0), eVect(2, 0));
1024 eVec1 *= sqrt(ev0);
1025 eVec2.SetXYZ(eVect(0, 1), eVect(1, 1), eVect(2, 1));
1026 } eVec2 *= sqrt(ev1);
1027 }
1028
1029 if (eVec1.Cross(eVec2).Dot(eval) < 0)
1030 eVec2 *= -1;
1031 //assert(eVec1.Cross(eVec2)*eval > 0);
1032
1033 if (oldEVec1.Dot(eVec1) < 0) {
1034 eVec1 *= -1;
1035 eVec2 *= -1;
1036 }
1037
1038 // vertices at 2nd plane
1039 double angle0 = ROOT::Math::VectorUtil::Angle(eVec1, oldEVec1);
1040 if (eVec1.Dot(eval.Cross(oldEVec1)) < 0)
1041 angle0 *= -1;
1042 for (int i = 0; i < nEdges; ++i) {
1043 const double angle = 2 * TMath::Pi() / nEdges * i - angle0;
1044 vertices.push_back(ROOT::Math::XYZVector(position) + cos(angle)*eVec1 + sin(angle)*eVec2);
1045 }
1046
1047 vertices.push_back(ROOT::Math::XYZVector(position));
1048
1049
1050 TEveTriangleSet* error_shape = new TEveTriangleSet(vertices.size(), nEdges * 2);
1051 for (unsigned int k = 0; k < vertices.size(); ++k) {
1052 error_shape->SetVertex(k, vertices[k].X(), vertices[k].Y(), vertices[k].Z());
1053 }
1054
1055 assert(vertices.size() == 2 * nEdges + 2);
1056
1057 int iTri(0);
1058 for (int i = 0; i < nEdges; ++i) {
1059 //error_shape->SetTriangle(iTri++, 0, i+1, (i+1)%nEdges+1);
1060 error_shape->SetTriangle(iTri++, i + 1, i + 1 + nEdges, (i + 1) % nEdges + 1);
1061 error_shape->SetTriangle(iTri++, (i + 1) % nEdges + 1, i + 1 + nEdges, (i + 1) % nEdges + 1 + nEdges);
1062 //error_shape->SetTriangle(iTri++, 2*nEdges+1, i+1+nEdges, (i+1)%nEdges+1+nEdges);
1063 }
1064
1065 //assert(iTri == nEdges*4);
1066
1067 error_shape->SetMainColor(c_trackColor);
1068 error_shape->SetMainTransparency(25);
1069 eveTrack->AddElement(error_shape);
1070 }
1071 }
1072}
1073
1074void EVEVisualization::addSimHit(const CDCSimHit* hit, const MCParticle* particle)
1075{
1076 addSimHit(ROOT::Math::XYZVector(hit->getPosWire()), particle);
1077}
1078void EVEVisualization::addSimHit(const PXDSimHit* hit, const MCParticle* particle)
1079{
1081 const ROOT::Math::XYZVector& global_pos = geo.getSensorInfo(hit->getSensorID()).pointToGlobal(hit->getPosIn());
1082 addSimHit(global_pos, particle);
1083}
1084void EVEVisualization::addSimHit(const SVDSimHit* hit, const MCParticle* particle)
1085{
1087 const ROOT::Math::XYZVector& global_pos = geo.getSensorInfo(hit->getSensorID()).pointToGlobal(hit->getPosIn());
1088 addSimHit(global_pos, particle);
1089}
1090void EVEVisualization::addSimHit(const KLMSimHit* hit, const MCParticle* particle)
1091{
1092 const ROOT::Math::XYZVector& global_pos = hit->getPosition();
1093 addSimHit(global_pos, particle);
1094}
1095void EVEVisualization::addSimHit(const ROOT::Math::XYZVector& v, const MCParticle* particle)
1096{
1097 MCTrack* track = addMCParticle(particle);
1098 if (!track)
1099 return; //hide hits from this particle
1100 track->simhits->SetNextPoint(v.X(), v.Y(), v.Z());
1101}
1102
1104{
1105 if (!particle) {
1106 if (!m_mcparticleTracks[nullptr].simhits) {
1107 const TString pointsTitle("Unassigned SimHits");
1108 m_mcparticleTracks[nullptr].simhits = new TEvePointSet(pointsTitle);
1109 m_mcparticleTracks[nullptr].simhits->SetTitle(pointsTitle);
1110 m_mcparticleTracks[nullptr].simhits->SetMarkerStyle(6);
1111 m_mcparticleTracks[nullptr].simhits->SetMainColor(c_unassignedHitColor);
1112 //m_mcparticleTracks[nullptr].simhits->SetMainTransparency(50);
1113 m_mcparticleTracks[nullptr].track = NULL;
1114 }
1115 return &m_mcparticleTracks[nullptr];
1116 }
1117
1118 if (m_hideSecondaries and !particle->hasStatus(MCParticle::c_PrimaryParticle)) {
1119 return NULL;
1120 }
1121 if (m_assignToPrimaries) {
1122 while (!particle->hasStatus(MCParticle::c_PrimaryParticle) and particle->getMother())
1123 particle = particle->getMother();
1124 }
1125
1126 if (!m_mcparticleTracks[particle].track) {
1127 const ROOT::Math::XYZVector& p = particle->getMomentum();
1128 const ROOT::Math::XYZVector& vertex = particle->getProductionVertex();
1129 const int pdg = particle->getPDG();
1130 TParticle tparticle(pdg, particle->getStatus(),
1131 (particle->getMother() ? particle->getMother()->getIndex() : 0), 0, particle->getFirstDaughter(), particle->getLastDaughter(),
1132 p.X(), p.Y(), p.Z(), particle->getEnergy(),
1133 vertex.X(), vertex.Y(), vertex.Z(), particle->getProductionTime());
1134 TEveMCTrack mctrack;
1135 mctrack = tparticle;
1136 mctrack.fTDecay = particle->getDecayTime();
1137 mctrack.fVDecay.Set(B2Vector3D(particle->getDecayVertex()));
1138 mctrack.fDecayed = !boost::math::isinf(mctrack.fTDecay);
1139 mctrack.fIndex = particle->getIndex();
1140 m_mcparticleTracks[particle].track = new TEveTrack(&mctrack, m_trackpropagator);
1141
1142 //Check if there is a trajectory stored for this particle
1143 const auto mcTrajectories = particle->getRelationsTo<MCParticleTrajectory>();
1144 bool hasTrajectory(false);
1145 for (auto rel : mcTrajectories.relations()) {
1146 //Trajectories with negative weight are from secondary daughters which
1147 //were ignored so we don't use them.
1148 if (rel.weight <= 0) continue;
1149 //Found one, let's add tose point as reference points to the TEveTrack.
1150 //This will force the track propagation to visit all points in order but
1151 //provide smooth helix interpolation between the points
1152 const MCParticleTrajectory& trajectory = dynamic_cast<const MCParticleTrajectory&>(*rel.object);
1153 for (const MCTrajectoryPoint& pt : trajectory) {
1154 m_mcparticleTracks[particle].track->AddPathMark(
1155 TEvePathMark(
1156 //Add the last trajectory point as decay point to prevent TEve to
1157 //propagate beyond the end of the track. So lets compare the adress
1158 //to the address of last point and choose the pathmark accordingly
1159 (&pt == &trajectory.back()) ? TEvePathMark::kDecay : TEvePathMark::kReference,
1160 TEveVector(pt.x, pt.y, pt.z),
1161 TEveVector(pt.px, pt.py, pt.pz)
1162 ));
1163 }
1164 //"There can only be One" -> found a trajectory, stop the loop
1165 hasTrajectory = true;
1166 break;
1167 }
1168
1169 //If we have the full trajectory there is no need to add additional path marks
1170 if (!hasTrajectory) {
1171 //add daughter vertices - improves track rendering as lost momentum is taken into account
1172 for (int iDaughter = particle->getFirstDaughter(); iDaughter <= particle->getLastDaughter(); iDaughter++) {
1173 if (iDaughter == 0)
1174 continue; //no actual daughter
1175
1176 const MCParticle* daughter = StoreArray<MCParticle>()[iDaughter - 1];
1177
1178 TEvePathMarkD refMark(TEvePathMarkD::kDaughter);
1179 refMark.fV.Set(B2Vector3D(daughter->getProductionVertex()));
1180 refMark.fP.Set(B2Vector3D(daughter->getMomentum()));
1181 refMark.fTime = daughter->getProductionTime();
1182 m_mcparticleTracks[particle].track->AddPathMark(refMark);
1183 }
1184
1185 //neutrals and very short-lived particles should stop somewhere
1186 //(can result in wrong shapes for particles stopped in the detector, so not used there)
1187 if ((TMath::Nint(particle->getCharge()) == 0 or !particle->hasStatus(MCParticle::c_StoppedInDetector))
1188 and mctrack.fDecayed) {
1189 TEvePathMarkD decayMark(TEvePathMarkD::kDecay);
1190 decayMark.fV.Set(B2Vector3D(particle->getDecayVertex()));
1191 m_mcparticleTracks[particle].track->AddPathMark(decayMark);
1192 }
1193 }
1194 TString particle_name(mctrack.GetName());
1195
1196 //set track title (for popup)
1197 const MCParticle* mom = particle->getMother();
1198 if (mom) {
1199 m_mcparticleTracks[particle].parentParticle = mom;
1200 addMCParticle(mom);
1201 }
1202
1203 TString title = ObjectInfo::getTitle(particle);
1204 if (!hasTrajectory) {
1205 //Hijack the mother label to show that the track position is only
1206 //extrapolated, not known from simulation
1207 title += "\n(track estimated from initial momentum)";
1208 //Also, show those tracks with dashed lines
1209 m_mcparticleTracks[particle].track->SetLineStyle(2);
1210 }
1211
1212 m_mcparticleTracks[particle].track->SetTitle(title);
1213
1214 //add some color (avoid black & white)
1215 switch (abs(pdg)) {
1216 case 11:
1217 m_mcparticleTracks[particle].track->SetLineColor(kAzure);
1218 break;
1219 case 13:
1220 m_mcparticleTracks[particle].track->SetLineColor(kCyan + 1);
1221 break;
1222 case 22:
1223 m_mcparticleTracks[particle].track->SetLineColor(kSpring);
1224 break;
1225 case 211:
1226 m_mcparticleTracks[particle].track->SetLineColor(kGray + 1);
1227 break;
1228 case 321:
1229 m_mcparticleTracks[particle].track->SetLineColor(kRed + 1);
1230 break;
1231 case 2212:
1232 m_mcparticleTracks[particle].track->SetLineColor(kOrange - 2);
1233 break;
1234 default:
1235 m_mcparticleTracks[particle].track->SetLineColor(kMagenta);
1236 }
1237
1238 //create point set for hits
1239 const TString pointsTitle = "SimHits for " + ObjectInfo::getIdentifier(particle) + " - " + particle_name;
1240 m_mcparticleTracks[particle].simhits = new TEvePointSet(pointsTitle);
1241 m_mcparticleTracks[particle].simhits->SetTitle(pointsTitle);
1242 m_mcparticleTracks[particle].simhits->SetMarkerStyle(6);
1243 m_mcparticleTracks[particle].simhits->SetMainColor(m_mcparticleTracks[particle].track->GetLineColor());
1244 //m_mcparticleTracks[particle].simhits->SetMainTransparency(50);
1245 addObject(particle, m_mcparticleTracks[particle].track);
1246 }
1247 return &m_mcparticleTracks[particle];
1248}
1249
1251{
1252 for (auto& mcTrackPair : m_mcparticleTracks) {
1253 MCTrack& mcTrack = mcTrackPair.second;
1254 if (mcTrack.track) {
1255 if (mcTrack.simhits->Size() > 0) {
1256 mcTrack.track->AddElement(mcTrack.simhits);
1257 } else {
1258 //if we don't add it, remove empty collection
1259 destroyEveElement(mcTrack.simhits);
1260 }
1261
1262 TEveElement* parent = m_tracklist;
1263 if (mcTrack.parentParticle) {
1264 const auto& parentIt = m_mcparticleTracks.find(mcTrack.parentParticle);
1265 if (parentIt != m_mcparticleTracks.end()) {
1266 parent = parentIt->second.track;
1267 }
1268 }
1269 parent->AddElement(mcTrack.track);
1270 } else { //add simhits directly
1271 gEve->AddElement(mcTrack.simhits);
1272 }
1273 }
1274 gEve->AddElement(m_tracklist);
1275 m_tracklist->MakeTracks();
1276 m_tracklist->SelectByP(c_minPCut, FLT_MAX); //don't show too many particles by default...
1277
1278 for (size_t i = 0; i < m_options.length(); i++) {
1279 if (m_options.at(i) == 'M') {
1280 m_gftrackpropagator->SetRnrDaughters(true);
1281 m_gftrackpropagator->SetRnrReferences(true);
1282 //m_gftrackpropagator->SetRnrFV(true); //TODO: this crashes?
1283 TMarker m;
1284 m.SetMarkerColor(c_trackMarkerColor);
1285 m.SetMarkerStyle(1); //a single pixel
1286 m.SetMarkerSize(1); //ignored.
1287 m_gftrackpropagator->RefPMAtt() = m;
1288 m_gftrackpropagator->RefFVAtt() = m;
1289 }
1290 }
1291
1292 m_consttrackpropagator->SetMagField(0, 0, -1.5);
1293
1294 m_eclData->DataChanged(); //update limits (Empty() won't work otherwise)
1295 if (!m_eclData->Empty()) {
1296 m_eclData->SetAxisFromBins(0.0,
1297 0.0); //epsilon_x/y = 0 so we don't merge neighboring bins. This avoids some rendering issues with projections of small clusters.
1298 m_calo3d->SetData(m_eclData);
1299 }
1300 gEve->AddElement(m_calo3d);
1301
1304 gEve->AddElement(m_unassignedRecoHits);
1305 }
1306
1307}
1308
1310{
1311 if (!gEve)
1312 return;
1313
1315 for (auto& groupPair : m_groups) {
1316 //store visibility, invalidate pointers
1317 if (groupPair.second.group)
1318 groupPair.second.visible = groupPair.second.group->GetRnrState();
1319 groupPair.second.group = nullptr;
1320 }
1321
1322 m_mcparticleTracks.clear();
1323 m_shownRecohits.clear();
1324 m_tracklist->DestroyElements();
1325
1326 //remove ECL data from event
1327 m_calo3d->SetData(NULL);
1328 m_calo3d->DestroyElements();
1329
1330 //lower energy threshold for ECL
1331 float ecl_threshold = 0.01;
1332 if (m_eclData)
1333 ecl_threshold = m_eclData->GetSliceThreshold(0);
1334
1335 destroyEveElement(m_eclData);
1336 m_eclData = new TEveCaloDataVec(1); //#slices
1337 m_eclData->IncDenyDestroy();
1338 m_eclData->RefSliceInfo(0).Setup("ECL", ecl_threshold, kRed);
1339
1342 destroyEveElement(m_unassignedRecoHits);
1343
1344 gEve->GetSelection()->RemoveElements();
1345 gEve->GetHighlight()->RemoveElements();
1346 //other things are cleaned up by TEve...
1347}
1348
1349
1350
1351
1352void EVEVisualization::addVertex(const genfit::GFRaveVertex* vertex)
1353{
1354 ROOT::Math::XYZVector v = ROOT::Math::XYZVector(vertex->getPos());
1355 TEvePointSet* vertexPoint = new TEvePointSet(ObjectInfo::getInfo(vertex));
1356 //sadly, setting a title for a TEveGeoShape doesn't result in a popup...
1357 vertexPoint->SetTitle(ObjectInfo::getTitle(vertex));
1358 vertexPoint->SetMainColor(c_recoHitColor);
1359 vertexPoint->SetNextPoint(v.X(), v.Y(), v.Z());
1360
1361 TMatrixDSymEigen eigen_values(vertex->getCov());
1362 TEveGeoShape* det_shape = new TEveGeoShape(ObjectInfo::getInfo(vertex) + " Error");
1363 det_shape->SetShape(new TGeoSphere(0., 1.)); //Initially created as a sphere, then "scaled" into an ellipsoid.
1364 fixGeoShapeRefCount(det_shape);
1365 const TVectorD& ev = eigen_values.GetEigenValues(); //Assigns the eigenvalues into the "ev" matrix.
1366 const TMatrixD& eVec = eigen_values.GetEigenVectors(); //Assigns the eigenvalues into the "eVec" matrix.
1367 //Define the 3 eigenvectors of the covariance matrix as objects of the ROOT::Math::XYZVector class using constructor.
1368 ROOT::Math::XYZVector eVec1(eVec(0, 0), eVec(1, 0), eVec(2, 0));
1369 //eVec(i,j) uses the method/overloaded operator ( . ) of the TMatrixT class to return the matrix entry.
1370 ROOT::Math::XYZVector eVec2(eVec(0, 1), eVec(1, 1), eVec(2, 1));
1371 ROOT::Math::XYZVector eVec3(eVec(0, 2), eVec(1, 2), eVec(2, 2));
1372 // got everything we need ----------------------------------------------------- //Eigenvalues(semi axis) of the covariance matrix accquired!
1373
1374
1375 TGeoRotation det_rot("det_rot", (eVec1.Theta() * 180) / TMath::Pi(), (eVec1.Phi() * 180) / TMath::Pi(),
1376 (eVec2.Theta() * 180) / TMath::Pi(), (eVec2.Phi() * 180) / TMath::Pi(),
1377 (eVec3.Theta() * 180) / TMath::Pi(), (eVec3.Phi() * 180) / TMath::Pi()); // the rotation is already clear
1378
1379 // set the scaled eigenvalues -------------------------------------------------
1380 //"Scaled" eigenvalues pseudo_res (lengths of the semi axis) are the sqrt of the eigenvalues.
1381 double pseudo_res_0 = std::sqrt(ev(0));
1382 double pseudo_res_1 = std::sqrt(ev(1));
1383 double pseudo_res_2 = std::sqrt(ev(2));
1384
1385 //B2INFO("The pseudo_res_0/1/2 are " << pseudo_res_0 << "," << pseudo_res_1 << "," << pseudo_res_2); //shows the scaled eigenvalues
1386
1387
1388
1389 // rotate and translate -------------------------------------------------------
1390 TGeoGenTrans det_trans(v.X(), v.Y(), v.Z(), pseudo_res_0, pseudo_res_1, pseudo_res_2,
1391 &det_rot); //Puts the ellipsoid at the position of the vertex, v(0)=v.X(), operator () overloaded.
1392 det_shape->SetTransMatrix(det_trans);
1393 // finished rotating and translating ------------------------------------------
1394
1395 det_shape->SetMainColor(kOrange); //The color of the error ellipsoid.
1396 det_shape->SetMainTransparency(0);
1397
1398 vertexPoint->AddElement(det_shape);
1399 addToGroup("Vertices", vertexPoint);
1400 addObject(vertex, vertexPoint);
1401}
1402
1403
1405{
1406
1407 // only display c_nPhotons hypothesis clusters
1408 if (cluster->hasHypothesis(ECLCluster::EHypothesisBit::c_nPhotons)) {
1409
1410 const float phi = cluster->getPhi();
1411 float dPhi = cluster->getUncertaintyPhi();
1412 float dTheta = cluster->getUncertaintyTheta();
1413 if (dPhi >= M_PI / 4 or dTheta >= M_PI / 4 or cluster->getUncertaintyEnergy() == 1.0) {
1414 B2WARNING("Found ECL cluster with broken errors (unit matrix or too large). Using 0.05 as error in phi/theta. The 3x3 error matrix previously was:");
1415 cluster->getCovarianceMatrix3x3().Print();
1416 dPhi = dTheta = 0.05;
1417 }
1418
1419 if (!std::isfinite(dPhi) or !std::isfinite(dTheta)) {
1420 B2ERROR("ECLCluster phi or theta error is NaN or infinite, skipping cluster!");
1421 return;
1422 }
1423
1424 //convert theta +- dTheta into eta +- dEta
1425 ROOT::Math::XYZVector thetaLow;
1426 VectorUtil::setPtThetaPhi(thetaLow, 1.0, cluster->getTheta() - dTheta, phi);
1427 ROOT::Math::XYZVector thetaHigh;
1428 VectorUtil::setPtThetaPhi(thetaHigh, 1.0, cluster->getTheta() + dTheta, phi);
1429 float etaLow = thetaLow.Eta();
1430 float etaHigh = thetaHigh.Eta();
1431 if (etaLow > etaHigh) {
1432 std::swap(etaLow, etaHigh);
1433 }
1434
1435 int id = m_eclData->AddTower(etaLow, etaHigh, phi - dPhi, phi + dPhi);
1436 m_eclData->FillSlice(0, cluster->getEnergy(ECLCluster::EHypothesisBit::c_nPhotons));
1438 }
1439}
1440
1442{
1443 const double layerThicknessCm = 3.16; //TDR, Fig 10.2
1444 const double layerDistanceCm = 9.1 - layerThicknessCm;
1445
1446 // Pposition of first RPC plane.
1447 ROOT::Math::XYZVector position = cluster->getClusterPosition();
1448 ROOT::Math::XYZVector startPos(position.X(), position.Y(), position.Z());
1449 ROOT::Math::XYZVector dir; //direction of cluster stack, Mag() == distance between planes
1450 ROOT::Math::XYZVector a, b; //defines RPC plane
1451 bool isBarrel = (startPos.Z() > -175.0 and startPos.Z() < 270.0);
1452 if (isBarrel) {
1453 //barrel
1454 b = ROOT::Math::XYZVector(0, 0, 1);
1455 a = startPos.Cross(b).Unit();
1456 double c = M_PI / 4.0;
1457 double offset = c / 2.0 + M_PI;
1458 VectorUtil::setPhi(a, int((a.Phi() + offset) / (c))*c - M_PI);
1459 ROOT::Math::XYZVector perp = b.Cross(a);
1460
1461 const double barrelRadiusCm = 204.0;
1462 VectorUtil::setMag(startPos, barrelRadiusCm / perp.Dot(startPos.Unit()));
1463
1464 dir = startPos.Unit();
1465 VectorUtil::setMag(dir, (layerDistanceCm + layerThicknessCm) / perp.Dot(dir));
1466 } else {
1467 //endcap
1468 b = ROOT::Math::XYZVector(startPos.X(), startPos.Y(), 0).Unit();
1469 a = startPos.Cross(b).Unit();
1470 double endcapStartZ = 284;
1471 if (startPos.Z() < 0)
1472 endcapStartZ = -189.5;
1473
1474 double scaleFac = endcapStartZ / startPos.Z();
1475 VectorUtil::setMag(startPos, startPos.R() * scaleFac);
1476
1477 dir = startPos.Unit();
1478 VectorUtil::setMag(dir, (layerDistanceCm + layerThicknessCm) / fabs(dir.Z()));
1479 }
1480
1481 for (int i = 0; i < cluster->getLayers(); i++) {
1482 ROOT::Math::XYZVector layerPos = startPos;
1483 layerPos += (cluster->getInnermostLayer() + i) * dir;
1484 auto* layer = boxCreator(layerPos, a, b, 20.0, 20.0, layerThicknessCm / 2);
1485 layer->SetMainColor(c_klmClusterColor);
1486 layer->SetMainTransparency(70);
1487 layer->SetName(ObjectInfo::getIdentifier(cluster));
1488 layer->SetTitle(ObjectInfo::getTitle(cluster));
1489
1490 addToGroup(std::string("KLMClusters/") + ObjectInfo::getIdentifier(cluster).Data(), layer);
1491 addObject(cluster, layer);
1492 }
1493}
1494
1496{
1498 const bklm::Module* module = m_GeoPar->findModule(bklm2dhit->getSection(), bklm2dhit->getSector(), bklm2dhit->getLayer());
1499
1500 CLHEP::Hep3Vector global;
1501 //+++ global coordinates of the hit
1502 global[0] = bklm2dhit->getPositionX();
1503 global[1] = bklm2dhit->getPositionY();
1504 global[2] = bklm2dhit->getPositionZ();
1505
1506 //+++ local coordinates of the hit
1507 CLHEP::Hep3Vector local = module->globalToLocal(global);
1508 //double localU = local[1]; //phi
1509 //double localV = local[2]; //z
1510 int Nphistrip = bklm2dhit->getPhiStripMax() - bklm2dhit->getPhiStripMin() + 1;
1511 int Nztrip = bklm2dhit->getZStripMax() - bklm2dhit->getZStripMin() + 1;
1512 double du = module->getPhiStripWidth() * Nphistrip;
1513 double dv = module->getZStripWidth() * Nztrip;
1514
1515 //Let's do some simple thing
1516 CLHEP::Hep3Vector localU(local[0], local[1] + 1.0, local[2]);
1517 CLHEP::Hep3Vector localV(local[0], local[1], local[2] + 1.0);
1518
1519 CLHEP::Hep3Vector globalU = module->localToGlobal(localU);
1520 CLHEP::Hep3Vector globalV = module->localToGlobal(localV);
1521
1522 ROOT::Math::XYZVector o(global[0], global[1], global[2]);
1523 ROOT::Math::XYZVector u(globalU[0], globalU[1], globalU[2]);
1524 ROOT::Math::XYZVector v(globalV[0], globalV[1], globalV[2]);
1525
1526 //Lest's just assign the depth is 1.0 cm (thickness of a layer), better to update
1527 TEveBox* bklmbox = boxCreator(o, u - o, v - o, du, dv, 1.0);
1528
1529 bklmbox->SetMainColor(kGreen);
1530 //bklmbox->SetName((std::to_string(hitModule)).c_str());
1531 bklmbox->SetName("BKLMHit2d");
1532
1533 addToGroup("BKLM2dHits", bklmbox);
1534 addObject(bklm2dhit, bklmbox);
1535}
1536
1538{
1539 const double du = 2.0;
1540 const double dv = 2.0;
1541 ROOT::Math::XYZVector hitPosition = eklm2dhit->getPosition();
1542 ROOT::Math::XYZVector o(hitPosition.X(), hitPosition.Y(), hitPosition.Z());
1543 ROOT::Math::XYZVector u(1.0, 0.0, 0.0);
1544 ROOT::Math::XYZVector v(0.0, 1.0, 0.0);
1545 TEveBox* eklmbox = boxCreator(o, u, v, du, dv, 4.0);
1546 eklmbox->SetMainColor(kGreen);
1547 eklmbox->SetName("EKLMHit2d");
1548 addToGroup("EKLM2dHits", eklmbox);
1549 addObject(eklm2dhit, eklmbox);
1550}
1551
1553{
1554 const VXD::GeoCache& aGeometry = VXD::GeoCache::getInstance();
1555
1556 VxdID sensorID = roi->getSensorID();
1557 const VXD::SensorInfoBase& aSensorInfo = aGeometry.getSensorInfo(sensorID);
1558
1559 double minU = aSensorInfo.getUCellPosition(roi->getMinUid(), roi->getMinVid());
1560 double minV = aSensorInfo.getVCellPosition(roi->getMinVid());
1561 double maxU = aSensorInfo.getUCellPosition(roi->getMaxUid(), roi->getMaxVid());
1562 double maxV = aSensorInfo.getVCellPosition(roi->getMaxVid());
1563
1564
1565 ROOT::Math::XYZVector localA(minU, minV, 0);
1566 ROOT::Math::XYZVector localB(minU, maxV, 0);
1567 ROOT::Math::XYZVector localC(maxU, minV, 0);
1568
1569 ROOT::Math::XYZVector globalA = aSensorInfo.pointToGlobal(localA);
1570 ROOT::Math::XYZVector globalB = aSensorInfo.pointToGlobal(localB);
1571 ROOT::Math::XYZVector globalC = aSensorInfo.pointToGlobal(localC);
1572
1573 TEveBox* ROIbox = boxCreator(globalB + globalC * 0.5, globalB - globalA, globalC - globalA, 1, 1, 0.01);
1574
1575 ROIbox->SetName(ObjectInfo::getIdentifier(roi));
1576 ROIbox->SetMainColor(kSpring - 9);
1577 ROIbox->SetMainTransparency(50);
1578
1579 addToGroup("ROIs", ROIbox);
1580 addObject(roi, ROIbox);
1581}
1582
1583void EVEVisualization::addRecoHit(const SVDCluster* hit, TEveStraightLineSet* lines)
1584{
1586 const VXD::SensorInfoBase& sensor = geo.getSensorInfo(hit->getSensorID());
1587
1588 ROOT::Math::XYZVector a, b;
1589 if (hit->isUCluster()) {
1590 const float u = hit->getPosition();
1591 a = sensor.pointToGlobal(ROOT::Math::XYZVector(sensor.getBackwardWidth() / sensor.getWidth(0) * u, -0.5 * sensor.getLength(), 0.0));
1592 b = sensor.pointToGlobal(ROOT::Math::XYZVector(sensor.getForwardWidth() / sensor.getWidth(0) * u, +0.5 * sensor.getLength(), 0.0));
1593 } else {
1594 const float v = hit->getPosition();
1595 a = sensor.pointToGlobal(ROOT::Math::XYZVector(-0.5 * sensor.getWidth(v), v, 0.0));
1596 b = sensor.pointToGlobal(ROOT::Math::XYZVector(+0.5 * sensor.getWidth(v), v, 0.0));
1597 }
1598
1599 lines->AddLine(a.X(), a.Y(), a.Z(), b.X(), b.Y(), b.Z());
1600 m_shownRecohits.insert(hit);
1601}
1602
1603void EVEVisualization::addRecoHit(const CDCHit* hit, TEveStraightLineSet* lines)
1604{
1606 const ROOT::Math::XYZVector& wire_pos_f = cdcgeo.wireForwardPosition(WireID(hit->getID()));
1607 const ROOT::Math::XYZVector& wire_pos_b = cdcgeo.wireBackwardPosition(WireID(hit->getID()));
1608
1609 lines->AddLine(wire_pos_f.X(), wire_pos_f.Y(), wire_pos_f.Z(), wire_pos_b.X(), wire_pos_b.Y(), wire_pos_b.Z());
1610 m_shownRecohits.insert(hit);
1611
1612}
1613
1614void EVEVisualization::addCDCHit(const CDCHit* hit, bool showTriggerHits)
1615{
1617 const B2Vector3D& wire_pos_f = cdcgeo.wireForwardPosition(WireID(hit->getID()));
1618 const B2Vector3D& wire_pos_b = cdcgeo.wireBackwardPosition(WireID(hit->getID()));
1619 static CDC::RealisticTDCCountTranslator tdcTranslator;
1620 TEveGeoShape* cov_shape = new TEveGeoShape("cov_shape");
1621 //TODO: leftrightflag not set! (same for other parameters, unsure which ones should be set)
1622 double driftLength = tdcTranslator.getDriftLength(hit->getTDCCount(), WireID(hit->getID()));
1623 double driftLengthRes = tdcTranslator.getDriftLengthResolution(driftLength, WireID(hit->getID()));
1624 driftLengthRes = std::max(driftLengthRes, 0.005);
1625 const double lengthOfWireSection = 3.0;
1626
1627 //z in wire direction, x,y orthogonal
1628 const B2Vector3D zaxis = wire_pos_b - wire_pos_f;
1629 const B2Vector3D xaxis = zaxis.Orthogonal();
1630 const B2Vector3D yaxis = xaxis.Cross(zaxis);
1631
1632 // move to z=0
1633 const B2Vector3D midPoint = wire_pos_f - zaxis * (wire_pos_f.Z() / zaxis.Z());
1634
1635 cov_shape->SetShape(new TGeoTube(std::max(0., (double)(driftLength - driftLengthRes)), driftLength + driftLengthRes,
1636 lengthOfWireSection));
1637 fixGeoShapeRefCount(cov_shape);
1638
1639 TGeoRotation det_rot("det_rot",
1640 xaxis.Theta() * 180 / TMath::Pi(), xaxis.Phi() * 180 / TMath::Pi(),
1641 yaxis.Theta() * 180 / TMath::Pi(), yaxis.Phi() * 180 / TMath::Pi(),
1642 zaxis.Theta() * 180 / TMath::Pi(), zaxis.Phi() * 180 / TMath::Pi()
1643 );
1644
1645 TGeoCombiTrans det_trans(midPoint.X(), midPoint.Y(), midPoint.Z(), &det_rot);
1646 cov_shape->SetTransMatrix(det_trans);
1647
1648 // get relation to trigger track segments
1649 bool isPartOfTS = false;
1650 const auto segments = hit->getRelationsFrom<CDCTriggerSegmentHit>();
1651 if (showTriggerHits && segments.size() > 0) {
1652 isPartOfTS = true;
1653 }
1654
1655 if (hit->getISuperLayer() % 2 == 0) {
1656 if (isPartOfTS)
1657 cov_shape->SetMainColor(kCyan + 3);
1658 else
1659 cov_shape->SetMainColor(kCyan);
1660 } else {
1661 if (isPartOfTS)
1662 cov_shape->SetMainColor(kPink + 6);
1663 else
1664 cov_shape->SetMainColor(kPink + 7);
1665 }
1666
1667 cov_shape->SetMainTransparency(50);
1668 cov_shape->SetName(ObjectInfo::getIdentifier(hit));
1669 cov_shape->SetTitle(ObjectInfo::getInfo(hit) + TString::Format("\nWire ID: %d\nADC: %d\nTDC: %d",
1670 hit->getID(), hit->getADCCount(), hit->getTDCCount()));
1671
1672 addToGroup("CDCHits", cov_shape);
1673 addObject(hit, cov_shape);
1674 if (isPartOfTS) {
1675 addToGroup("CDCTriggerSegmentHits", cov_shape);
1676 for (auto rel : segments.relations()) {
1677 addObject(rel.object, cov_shape);
1678 }
1679 }
1680}
1681
1682void EVEVisualization::addCDCTriggerSegmentHit(const std::string& collectionName, const CDCTriggerSegmentHit* hit)
1683{
1685 TEveStraightLineSet* shape = new TEveStraightLineSet();
1686
1687 // get center wire
1688 unsigned iL = WireID(hit->getID()).getICLayer();
1689 if (hit->getPriorityPosition() < 3) iL -= 1;
1690 unsigned nWires = cdcgeo.nWiresInLayer(iL);
1691 unsigned iCenter = hit->getIWire();
1692 if (hit->getPriorityPosition() == 1) iCenter += 1;
1693
1694 // a track segment consists of 11 wires (15 in SL0) in a special configuration
1695 // -> get the shift with respect to the center wire (*) for all wires
1696 // SL 1-8:
1697 // _ _ _
1698 // |_|_|_|
1699 // |_|_|
1700 // |*|
1701 // |_|_|
1702 // |_|_|_|
1703 std::vector<int> layershift = { -2, -1, 0, 1, 2};
1704 std::vector<std::vector<float>> cellshift = {
1705 { -1, 0, 1},
1706 { -0.5, 0.5},
1707 { 0},
1708 { -0.5, 0.5},
1709 { -1, 0, 1}
1710 };
1711 // SL 0:
1712 // _ _ _ _ _
1713 // |_|_|_|_|_|
1714 // |_|_|_|_|
1715 // |_|_|_|
1716 // |_|_|
1717 // |*|
1718 if (hit->getISuperLayer() == 0) {
1719 layershift = { 0, 1, 2, 3, 4};
1720 cellshift = {
1721 { 0},
1722 { -0.5, 0.5},
1723 { -1, 0, 1},
1724 { -1.5, -0.5, 0.5, 1.5},
1725 { -2, -1, 0, 1, 2}
1726 };
1727 }
1728
1729 // draw all cells in segment
1730 for (unsigned il = 0; il < layershift.size(); ++il) {
1731 for (unsigned ic = 0; ic < cellshift[il].size(); ++ic) {
1732 ROOT::Math::XYZVector corners[2][2];
1733 for (unsigned ir = 0; ir < 2; ++ir) {
1734 double r = cdcgeo.fieldWireR(iL + layershift[il] - ir);
1735 double fz = cdcgeo.fieldWireFZ(iL + layershift[il] - ir);
1736 double bz = cdcgeo.fieldWireBZ(iL + layershift[il] - ir);
1737 for (unsigned iphi = 0; iphi < 2; ++iphi) {
1738 double phib = (iCenter + cellshift[il][ic] + iphi - 0.5) * 2 * M_PI / nWires;
1739 double phif = phib + cdcgeo.nShifts(iL + layershift[il]) * M_PI / nWires;
1740
1741 ROOT::Math::XYZVector pos_f = ROOT::Math::XYZVector(cos(phif) * r, sin(phif) * r, fz);
1742 ROOT::Math::XYZVector pos_b = ROOT::Math::XYZVector(cos(phib) * r, sin(phib) * r, bz);
1743 ROOT::Math::XYZVector zaxis = pos_b - pos_f;
1744 corners[ir][iphi] = pos_f - zaxis * (pos_f.Z() / zaxis.Z());
1745 }
1746 }
1747
1748 shape->AddLine(corners[0][0].X(), corners[0][0].Y(), 0,
1749 corners[0][1].X(), corners[0][1].Y(), 0);
1750 shape->AddLine(corners[0][1].X(), corners[0][1].Y(), 0,
1751 corners[1][1].X(), corners[1][1].Y(), 0);
1752 shape->AddLine(corners[1][1].X(), corners[1][1].Y(), 0,
1753 corners[1][0].X(), corners[1][0].Y(), 0);
1754 shape->AddLine(corners[1][0].X(), corners[1][0].Y(), 0,
1755 corners[0][0].X(), corners[0][0].Y(), 0);
1756 }
1757 }
1758
1759 if (hit->getISuperLayer() % 2 == 0) {
1760 shape->SetMainColor(kCyan + 3);
1761 } else {
1762 shape->SetMainColor(kPink + 6);
1763 }
1764
1765 shape->SetName(ObjectInfo::getIdentifier(hit));
1766 shape->SetTitle(ObjectInfo::getTitle(hit) +
1767 TString::Format("\nPriority: %d\nLeft/Right: %d",
1768 hit->getPriorityPosition(), hit->getLeftRight()));
1769 addToGroup(collectionName, shape);
1770 addObject(hit, shape);
1771}
1772
1774{
1776
1777 int hitModule = hit->getModule();
1778 float fi = arichGeo->getDetectorPlane().getSlotPhi(hitModule);
1779
1780 ROOT::Math::XYZVector centerPos3D = hit->getPosition();
1781
1782 ROOT::Math::RotationZ rotZ(fi);
1783 ROOT::Math::XYZVector channelX(1, 0, 0);
1784 ROOT::Math::XYZVector channelY(0, 1, 0);
1785 channelX = rotZ * channelX;
1786 channelY = rotZ * channelY;
1787
1788 auto* arichbox = boxCreator(centerPos3D,
1789 arichGeo->getMasterVolume().momentumToGlobal(channelX),
1790 arichGeo->getMasterVolume().momentumToGlobal(channelY),
1791 0.49, 0.49, 0.05);
1792 arichbox->SetMainColor(kOrange + 10);
1793 arichbox->SetName((std::to_string(hitModule)).c_str());
1794
1795 addToGroup("ARICHHits", arichbox);
1796 addObject(hit, arichbox);
1797}
1798
1800{
1801 /* TOP module ID -> #digits */
1802 std::map<int, int> m_topSummary;
1803 for (const TOPDigit& hit : digits) {
1804 int mod = hit.getModuleID();
1805 ++m_topSummary[mod];
1806 }
1807 int maxcount = 0;
1808 for (auto modCountPair : m_topSummary) {
1809 if (modCountPair.second > maxcount)
1810 maxcount = modCountPair.second;
1811 }
1812 for (auto modCountPair : m_topSummary) {
1813 const auto& topmod = TOP::TOPGeometryPar::Instance()->getGeometry()->getModule(modCountPair.first);
1814 double phi = topmod.getPhi();
1815 double r_center = topmod.getRadius();
1816 double z = topmod.getZc();
1817
1818 ROOT::Math::XYZVector centerPos3D;
1819 VectorUtil::setMagThetaPhi(centerPos3D, r_center, M_PI / 2, phi);
1820 centerPos3D.SetZ(z);
1821
1822 B2Vector3D channelX(1, 0, 0); channelX.RotateZ(phi);
1823 B2Vector3D channelY(0, 1, 0); channelY.RotateZ(phi);
1824
1825 //bar is a bit thicker so we can mouse over without getting the geometry
1826 auto* moduleBox = boxCreator(centerPos3D, channelX, channelY,
1827 3.0 * topmod.getBarThickness(), topmod.getBarWidth(), topmod.getBarLength());
1828 moduleBox->SetMainColor(kAzure + 10);
1829 double weight = double(modCountPair.second) / maxcount;
1830 moduleBox->SetMainTransparency(90 - weight * 50);
1831 moduleBox->SetName(("TOP module " + std::to_string(modCountPair.first)).c_str());
1832 moduleBox->SetTitle(TString::Format("#TOPDigits: %d ", modCountPair.second));
1833
1834 addToGroup("TOP Modules", moduleBox);
1835 //associate all TOPDigits with this module.
1836 for (const TOPDigit& hit : digits) {
1837 if (modCountPair.first == hit.getModuleID())
1838 addObject(&hit, moduleBox);
1839 }
1840 }
1841}
1842
1843
1845{
1846 for (const auto& labelPair : displayData.m_labels) {
1847 TEveText* text = new TEveText(labelPair.first.c_str());
1848 text->SetName(labelPair.first.c_str());
1849 text->SetTitle(labelPair.first.c_str());
1850 text->SetMainColor(kGray + 1);
1851 const ROOT::Math::XYZVector& p = labelPair.second;
1852 text->PtrMainTrans()->SetPos(p.X(), p.Y(), p.Z());
1853 addToGroup("DisplayData", text);
1854 }
1855
1856 for (const auto& pointPair : displayData.m_pointSets) {
1857 TEvePointSet* points = new TEvePointSet(pointPair.first.c_str());
1858 points->SetTitle(pointPair.first.c_str());
1859 points->SetMarkerStyle(7);
1860 points->SetMainColor(kGreen);
1861 for (const auto& p : pointPair.second) {
1862 points->SetNextPoint(p.X(), p.Y(), p.Z());
1863 }
1864 addToGroup("DisplayData", points);
1865 }
1866
1867 int randomColor = 2; //primary colours, changing rapidly with index
1868 for (const auto& arrow : displayData.m_arrows) {
1869 const ROOT::Math::XYZVector pos = arrow.start;
1870 const ROOT::Math::XYZVector dir = arrow.end - pos;
1871 TEveArrow* eveArrow = new TEveArrow(dir.X(), dir.Y(), dir.Z(), pos.X(), pos.Y(), pos.Z());
1872 eveArrow->SetName(arrow.name.c_str());
1873 eveArrow->SetTitle(arrow.name.c_str());
1874 int arrowColor = arrow.color;
1875 if (arrowColor == -1) {
1876 arrowColor = randomColor;
1877 randomColor++;
1878 }
1879 eveArrow->SetMainColor(arrowColor);
1880
1881 //add label
1882 TEveText* text = new TEveText(arrow.name.c_str());
1883 text->SetMainColor(arrowColor);
1884 //place label in middle of arrow, with some slight offset
1885 // orthogonal direction is arbitrary, set smallest component zero
1886 ROOT::Math::XYZVector orthogonalDir;
1887 if (std::abs(dir.X()) < std::abs(dir.Y())) {
1888 if (std::abs(dir.X()) < std::abs(dir.Z())) {
1889 orthogonalDir.SetCoordinates(0, dir.Z(), -dir.Y());
1890 } else {
1891 orthogonalDir.SetCoordinates(dir.Y(), -dir.X(), 0);
1892 }
1893 } else {
1894 if (std::abs(dir.Y()) < std::abs(dir.Z())) {
1895 orthogonalDir.SetCoordinates(-dir.Z(), 0, dir.X());
1896 } else {
1897 orthogonalDir.SetCoordinates(dir.Y(), -dir.X(), 0);
1898 }
1899 }
1900 const ROOT::Math::XYZVector& labelPos = pos + 0.5 * dir + 0.1 * orthogonalDir;
1901 text->PtrMainTrans()->SetPos(labelPos.X(), labelPos.Y(), labelPos.Z());
1902 eveArrow->AddElement(text);
1903 addToGroup("DisplayData", eveArrow);
1904 }
1905
1906}
1907void EVEVisualization::addObject(const TObject* dataStoreObject, TEveElement* visualRepresentation)
1908{
1909 VisualRepMap::getInstance()->add(dataStoreObject, visualRepresentation);
1910}
1911
1912void EVEVisualization::addToGroup(const std::string& name, TEveElement* elem)
1913{
1914 //slashes at beginning and end are ignored
1915 const std::string& groupName = boost::algorithm::trim_copy_if(name, boost::algorithm::is_any_of("/"));
1916
1917 TEveElementList* group = m_groups[groupName].group;
1918 if (!group) {
1919 group = new TEveElementList(groupName.c_str(), groupName.c_str());
1920 group->SetRnrState(m_groups[groupName].visible);
1921 m_groups[groupName].group = group;
1922
1923 //if groupName contains '/', remove last bit and add to parent group
1924 //e.g. if groupName=A/B/C, call addToGroup("A/B", groupC)
1925 auto lastSlash = boost::algorithm::find_last(groupName, "/");
1926 if (lastSlash) {
1927 const std::string parentGroup(groupName.begin(), lastSlash.begin());
1928 const std::string thisGroup(lastSlash.end(), groupName.end());
1929 group->SetElementName(thisGroup.c_str());
1930 addToGroup(parentGroup, group);
1931 } else {
1932 gEve->AddElement(group);
1933 }
1934 }
1935 group->AddElement(elem);
1936}
1937
Datastore class that holds photon hits. Input to the reconstruction.
Definition: ARICHHit.h:23
DataType Phi() const
The azimuth angle.
Definition: B2Vector3.h:151
DataType Pz() const
access variable Z (= .at(2) without boundary check)
Definition: B2Vector3.h:441
DataType Z() const
access variable Z (= .at(2) without boundary check)
Definition: B2Vector3.h:435
DataType Theta() const
The polar angle.
Definition: B2Vector3.h:153
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
Definition: B2Vector3.h:296
DataType X() const
access variable X (= .at(0) without boundary check)
Definition: B2Vector3.h:431
B2Vector3< DataType > Orthogonal() const
Vector orthogonal to this one.
Definition: B2Vector3.h:277
DataType Y() const
access variable Y (= .at(1) without boundary check)
Definition: B2Vector3.h:433
DataType Mag() const
The magnitude (rho in spherical coordinate system).
Definition: B2Vector3.h:159
void RotateZ(DataType angle)
Rotates the B2Vector3 around the z-axis.
Definition: B2Vector3.h:359
DataType Pt() const
The transverse component (R in cylindrical coordinate system).
Definition: B2Vector3.h:198
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition: CDCHit.h:40
This class is used to transfer CDC information to the track fit.
Definition: CDCRecoHit.h:32
Example Detector.
Definition: CDCSimHit.h:21
Combination of several CDCHits to a track segment hit for the trigger.
Track created by the CDC trigger.
The Class for CDC Geometry Parameters.
int nShifts(int layerId) const
Returns number shift.
double fieldWireR(int layerId) const
Returns radius of field wire in each layer.
const B2Vector3D wireForwardPosition(uint layerId, int cellId, EWirePosition set=c_Base) const
Returns the forward position of the input sense wire.
const B2Vector3D wireBackwardPosition(uint layerId, int cellId, EWirePosition set=c_Base) const
Returns the backward position of the input sense wire.
unsigned nWiresInLayer(int layerId) const
Returns wire numbers in a layer.
double fieldWireBZ(int layerId) const
Returns backward z position of field wire in each layer.
double fieldWireFZ(int layerId) const
Returns forward z position of field wire in each layer.
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
Translator mirroring the realistic Digitization.
double getDriftLength(unsigned short tdcCount, const WireID &wireID=WireID(), double timeOfFlightEstimator=0, bool leftRight=false, double z=0, double alpha=0, double theta=static_cast< double >(TMath::Pi()/2.), unsigned short adcCount=0) override
Get Drift length.
double getDriftLengthResolution(double driftLength, const WireID &wireID=WireID(), bool leftRight=false, double z=0, double alpha=0, double=static_cast< double >(TMath::Pi()/2.)) override
Get position resolution^2 corresponding to the drift length from getDriftLength of this class.
static const ChargedStable pion
charged pion particle
Definition: Const.h:661
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
Add custom information to the display.
Definition: DisplayData.h:55
std::vector< Arrow > m_arrows
List of arrows.
Definition: DisplayData.h:114
std::map< std::string, std::vector< ROOT::Math::XYZVector > > m_pointSets
name -> points map
Definition: DisplayData.h:108
std::vector< std::pair< std::string, ROOT::Math::XYZVector > > m_labels
text labels (to be shown at a given position).
Definition: DisplayData.h:109
ECL cluster data.
Definition: ECLCluster.h:27
@ c_nPhotons
CR is split into n photons (N1)
void clearEvent()
clear event data.
void setOptions(const std::string &opts)
Set the display options.
static constexpr double c_minPCut
don't show MCParticles with momentum below this cutoff.
void addTrackCandidateImproved(const std::string &collectionName, const RecoTrack &recoTrack)
Add a RecoTrack, but use stored genfit track representation to make visualisation objects.
EveVisBField * m_bfield
The global magnetic field.
TEveBox * boxCreator(const ROOT::Math::XYZVector &o, ROOT::Math::XYZVector u, ROOT::Math::XYZVector v, float ud, float vd, float depth)
Create a box around o, oriented along u and v with widths ud, vd and depth and return a pointer to th...
TEveStraightLineSet * m_unassignedRecoHits
Unassigned recohits.
static const int c_recoHitColor
Color for reco hits.
void addCDCHit(const CDCHit *hit, bool showTriggerHits=false)
show CDCHits directly.
std::map< const MCParticle *, MCTrack > m_mcparticleTracks
map MCParticles to MCTrack (so hits can be added to the correct track).
void addBKLMHit2d(const KLMHit2d *bklm2dhit)
Add a reconstructed 2d hit in the BKLM.
void setErrScale(double errScale=1.)
Set the scaling factor for the visualization of track hit errors.
bool m_drawRefTrack
Draw reference track in addTrack.
void addVertex(const genfit::GFRaveVertex *vertex)
Add a vertex point and its covariance matrix.
bool m_drawForward
draw forward in addTrack
TEveCalo3D * m_calo3d
Object for the energy bar visualisation.
bool m_drawCardinalRep
Draw cardinal representation in addTrack.
void addCDCTriggerTrack(const std::string &collectionName, const CDCTriggerTrack &track)
Add a CDCTriggerTrack.
void addCDCTriggerSegmentHit(const std::string &collectionName, const CDCTriggerSegmentHit *hit)
show outline of track segments.
TEveTrackPropagator * m_trackpropagator
Track propagator for MCParticles.
std::map< std::string, ElementGroup > m_groups
name -> grouping element.
void addSimHit(const CDCSimHit *hit, const MCParticle *particle)
Add a CDCSimHit.
void addECLCluster(const ECLCluster *cluster)
Add a reconstructed cluster in the ECL.
TEveTrackList * m_tracklist
parent object for MC tracks.
void addToGroup(const std::string &name, TEveElement *elem)
Add 'elem' to the element group 'name' (created if necessary).
void makeTracks()
Create visual representation of all tracks.
void addRecoHit(const SomeVXDHit *hit, TEveStraightLineSet *lines)
adds given VXD hit to lines.
void addTrack(const Belle2::Track *belle2Track)
Add this genfit::Track to event data.
bool m_unassignedRecoHitsVisibility
is m_unassignedRecoHits visible?
static const int c_trackMarkerColor
Color for track markers.
TEveTrackPropagator * m_gftrackpropagator
Track propagator for genfit::Tracks (different mainly because of drawing options)
std::string m_options
Option string for genfit::Track visualisation.
static const int c_trackColor
Color for tracks.
static const int c_unassignedHitColor
Color for unassigned (reco)hits.
bool m_hideSecondaries
If true, secondary MCParticles (and hits created by them) will not be shown.
void addEKLMHit2d(const KLMHit2d *eklm2dhit)
Add a reconstructed 2d hit in the EKLM.
void addARICHHit(const ARICHHit *hit)
Add recontructed hit in ARICH.
void showUserData(const DisplayData &displayData)
Add user-defined data (labels, points, etc.)
std::set< const TObject * > m_shownRecohits
List of shown recohits (PXDCluster, SVDCluster, CDCHit).
bool m_drawBackward
draw backward in addTrack
TEveTrackPropagator * m_consttrackpropagator
Track propagator for CDCTriggerTracks (uses constant B field)
bool m_assignToPrimaries
If true, hits created by secondary particles (e.g.
bool m_drawErrors
Draw errors in addTrack.
double m_errorScale
Rescale PXD/SVD errors with this factor to ensure visibility.
void addTOPDigits(const StoreArray< TOPDigit > &digits)
Add TOPDigits (shown aggregated per module).
void addROI(const ROIid *roi)
Add a Region Of Interest, computed by the PXDDataReduction module.
void addKLMCluster(const KLMCluster *cluster)
Add a reconstructed cluster in the KLM.
static const int c_klmClusterColor
Color for KLMCluster objects.
MCTrack * addMCParticle(const MCParticle *particle)
Return MCTrack for given particle, add it if it doesn't exist yet.
TEveCaloDataVec * m_eclData
ECL cluster data.
static const int c_recoTrackColor
Color for TrackCandidates.
void addTrackCandidate(const std::string &collectionName, const RecoTrack &recoTrack)
Add a RecoTrack, to evaluate track finding.
void addObject(const TObject *dataStoreObject, TEveElement *visualRepresentation)
Generic function to keep track of which objects have which visual representation.
void makeLines(TEveTrack *eveTrack, const genfit::StateOnPlane *prevState, const genfit::StateOnPlane *state, const genfit::AbsTrackRep *rep, TEvePathMark::EType_e markType, bool drawErrors, int markerPos=1)
Create hit visualisation for the given options, and add them to 'eveTrack'.
Provide magnetic field values for TEveTrackPropagator.
Definition: EveVisBField.h:19
KLM cluster data.
Definition: KLMCluster.h:28
KLM 2d hit.
Definition: KLMHit2d.h:33
int getLayer() const
Get layer number.
Definition: KLMHit2d.h:132
int getZStripMax() const
Get last strip number for z plane.
Definition: KLMHit2d.h:202
int getSection() const
Get section number.
Definition: KLMHit2d.h:96
float getPositionZ() const
Get hit global position z coordinate.
Definition: KLMHit2d.h:306
int getSector() const
Get sector number.
Definition: KLMHit2d.h:114
float getPositionX() const
Get hit global position x coordinate.
Definition: KLMHit2d.h:288
int getPhiStripMin() const
Get strip number for phi plane.
Definition: KLMHit2d.h:218
int getZStripMin() const
Get strip number for z plane.
Definition: KLMHit2d.h:194
ROOT::Math::XYZVector getPosition() const
Get hit global position.
Definition: KLMHit2d.h:315
int getPhiStripMax() const
Get last strip number for phi plane.
Definition: KLMHit2d.h:226
float getPositionY() const
Get hit global position y coordinate.
Definition: KLMHit2d.h:297
KLM simulation hit.
Definition: KLMSimHit.h:31
Class to save the full simulated trajectory of a particle.
const MCTrajectoryPoint & back() const
return reference to the last point
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
@ c_StoppedInDetector
bit 3: Particle was stopped in the detector (the simulation volume).
Definition: MCParticle.h:53
The PXD Cluster class This class stores all information about reconstructed PXD clusters The position...
Definition: PXDCluster.h:30
Class PXDSimHit - Geant4 simulated hit for the PXD.
Definition: PXDSimHit.h:24
ROIid stores the U and V ids and the sensor id of the Region Of Interest.
Definition: ROIid.h:25
This is the Reconstruction Event-Data Model Track.
Definition: RecoTrack.h:79
std::vector< Belle2::RecoTrack::UsedPXDHit * > getPXDHitList() const
Return an unsorted list of pxd hits.
Definition: RecoTrack.h:449
std::vector< Belle2::RecoTrack::UsedSVDHit * > getSVDHitList() const
Return an unsorted list of svd hits.
Definition: RecoTrack.h:452
std::vector< Belle2::RecoTrack::UsedCDCHit * > getCDCHitList() const
Return an unsorted list of cdc hits.
Definition: RecoTrack.h:455
ROOT::Math::XYZVector getPositionSeed() const
Return the position seed stored in the reco track. ATTENTION: This is not the fitted position.
Definition: RecoTrack.h:480
const genfit::TrackPoint * getCreatedTrackPoint(const RecoHitInformation *recoHitInformation) const
Get a pointer to the TrackPoint that was created from this hit.
Definition: RecoTrack.cc:230
std::vector< RecoHitInformation * > getRecoHitInformations(bool getSorted=false) const
Return a list of all RecoHitInformations associated with the RecoTrack.
Definition: RecoTrack.cc:557
short int getChargeSeed() const
Return the charge seed stored in the reco track. ATTENTION: This is not the fitted charge.
Definition: RecoTrack.h:508
ROOT::Math::XYZVector getMomentumSeed() const
Return the momentum seed stored in the reco track. ATTENTION: This is not the fitted momentum.
Definition: RecoTrack.h:487
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
The SVD Cluster class This class stores all information about reconstructed SVD clusters.
Definition: SVDCluster.h:29
SVDRecoHit - an extended form of SVDHit containing geometry information.
Definition: SVDRecoHit.h:47
bool isU() const
Is the coordinate u or v?
Definition: SVDRecoHit.h:91
VxdID getSensorID() const
Get the compact ID.
Definition: SVDRecoHit.h:82
Class SVDSimHit - Geant4 simulated hit for the SVD.
Definition: SVDSimHit.h:26
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
Class to store TOP digitized hits (output of TOPDigitizer or raw data unpacker) relations to TOPSimHi...
Definition: TOPDigit.h:24
const TOPGeometry * getGeometry() const
Returns pointer to geometry object using basf2 units.
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
Values of the result of a track fit with a given particle hypothesis.
Helix getHelix() const
Conversion to framework Helix (without covariance).
short getChargeSign() const
Return track charge (1 or -1).
double getPValue() const
Getter for Chi2 Probability of the track fit.
ROOT::Math::XYZVector getMomentum() const
Getter for vector of momentum at closest approach of track in r/phi projection.
ROOT::Math::XYZVector getPosition() const
Getter for vector of position at closest approach of track in r/phi projection.
Class that bundles various TrackFitResults.
Definition: Track.h:25
const TrackFitResult * getTrackFitResultWithClosestMass(const Const::ChargedStable &requestedType) const
Return the track fit for a fit hypothesis with the closest mass.
Definition: Track.cc:104
Class to faciliate easy access to sensor information of the VXD like coordinate transformations or pi...
Definition: GeoCache.h:39
const SensorInfoBase & getSensorInfo(Belle2::VxdID id) const
Return a referecne to the SensorInfo of a given SensorID.
Definition: GeoCache.cc:67
static GeoCache & getInstance()
Return a reference to the singleton instance.
Definition: GeoCache.cc:214
Base class to provide Sensor Information for PXD and SVD.
double getVCellPosition(int vID) const
Return the position of a specific strip/pixel in v direction.
double getUCellPosition(int uID, int vID=-1) const
Return the position of a specific strip/pixel in u direction.
ROOT::Math::XYZVector pointToGlobal(const ROOT::Math::XYZVector &local, bool reco=false) const
Convert a point from local to global coordinates.
void addCluster(const TObject *dataStoreObject, TEveCaloData *caloData, int towerID)
Selection inside TEveCalo* is complicated, use this to keep track of ECL clusters.
static VisualRepMap * getInstance()
get instance pointer.
Definition: VisualRepMap.cc:36
void clear()
Remove all contents in map.
Definition: VisualRepMap.cc:46
void add(const TObject *dataStoreObject, TEveElement *visualRepresentation)
Generic function to keep track of which objects have which visual representation.
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
Class to identify a wire inside the CDC.
Definition: WireID.h:34
unsigned short getICLayer() const
Getter for continuous layer numbering.
Definition: WireID.cc:24
Provides BKLM geometry parameters for simulation, reconstruction etc (from Gearbox or DataBase)
Definition: GeometryPar.h:37
const Module * findModule(int section, int sector, int layer) const
Get the pointer to the definition of a module.
Definition: GeometryPar.cc:721
static GeometryPar * instance(void)
Static method to get a reference to the singleton GeometryPar instance.
Definition: GeometryPar.cc:27
Define the geometry of a BKLM module Each sector [octant] contains Modules.
Definition: Module.h:76
static constexpr auto XYZToTVector
Helper function to convert XYZVector to TVector3.
Definition: VectorUtil.h:24
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:516
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
const TOPGeoModule & getModule(int moduleID) const
Returns module.
Definition: TOPGeometry.cc:42
double eval(const std::vector< double > &spl, const std::vector< double > &vals, double x)
Evaluate spline (zero order or first order) in point x.
Definition: tools.h:115
double getMaxR()
find a point that is inside the top node.
Definition: EveGeometry.cc:184
TString getIdentifier(const TObject *obj)
Where is this object in the datastore?
Definition: ObjectInfo.cc:105
TString getInfo(const TObject *obj)
Get object info HTML (e.g.
Definition: ObjectInfo.cc:55
TString getTitle(const TObject *obj)
Get plain text for TEve object titles (shown on mouse-over).
Definition: ObjectInfo.cc:68
Implements a colour palette, see http://sobac.com/sobac/tangocolors.htm.
Definition: ColorPalette.h:23
int getTColorID(const std::string &tangoName, int tangoId=1)
Get TColor ID for given name in tango colour palette.
Definition: ColorPalette.cc:39
Abstract base class for different kinds of events.
Hold MC tracks and associated visualisation objects.
TEvePointSet * simhits
simhit positions.
const MCParticle * parentParticle
parent particle, or nullptr.
TEveTrack * track
the actual MC track.
Small struct to encode a position/momentum without additional overhead.