Belle II Software  release-08-01-10
EventDataPlotter.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 #include <tracking/trackFindingCDC/display/EventDataPlotter.h>
9 
10 #include <tracking/trackFindingCDC/display/SVGPrimitivePlotter.h>
11 #include <tracking/trackFindingCDC/display/BoundingBox.h>
12 
13 #include <tracking/trackFindingCDC/eventdata/tracks/CDCSegmentPair.h>
14 #include <tracking/trackFindingCDC/eventdata/tracks/CDCAxialSegmentPair.h>
15 #include <tracking/trackFindingCDC/eventdata/tracks/CDCSegmentTriple.h>
16 #include <tracking/trackFindingCDC/eventdata/tracks/CDCTrack.h>
17 
18 #include <tracking/trackFindingCDC/eventdata/segments/CDCWireHitCluster.h>
19 #include <tracking/trackFindingCDC/eventdata/segments/CDCSegment2D.h>
20 #include <tracking/trackFindingCDC/eventdata/segments/CDCSegment3D.h>
21 
22 #include <tracking/trackFindingCDC/eventdata/hits/CDCTangent.h>
23 #include <tracking/trackFindingCDC/eventdata/hits/CDCRecoHit3D.h>
24 #include <tracking/trackFindingCDC/eventdata/hits/CDCRecoHit2D.h>
25 #include <tracking/trackFindingCDC/eventdata/hits/CDCWireHit.h>
26 
27 #include <tracking/trackFindingCDC/topology/CDCWireTopology.h>
28 
29 #include <tracking/trackFindingCDC/geometry/Circle2D.h>
30 
31 #include <cdc/dataobjects/CDCSimHit.h>
32 #include <cdc/dataobjects/CDCHit.h>
33 
34 #include <framework/logging/Logger.h>
35 
36 #include <tracking/dataobjects/RecoTrack.h>
37 #include <mdst/dataobjects/MCParticle.h>
38 
39 #include <TMatrixDSym.h>
40 
41 #include <cmath>
42 
43 using namespace Belle2;
44 using namespace TrackFindingCDC;
45 
46 EventDataPlotter::EventDataPlotter(bool animate, bool forwardFade)
47  : m_ptrPrimitivePlotter(new SVGPrimitivePlotter(
48  AttributeMap{{"stroke", "orange"}, {"stroke-width", "0.55"}, {"fill", "none"}}))
49 , m_animate(animate)
50 , m_forwardFade(forwardFade)
51 {
52 }
53 
54 EventDataPlotter::EventDataPlotter(std::unique_ptr<PrimitivePlotter> ptrPrimitivePlotter,
55  bool animate,
56  bool forwardFade)
57  : m_ptrPrimitivePlotter(std::move(ptrPrimitivePlotter))
58  , m_animate(animate)
59  , m_forwardFade(forwardFade)
60 {
61  B2ASSERT("EventDataPlotter initialized with nullptr. Using default backend SVGPrimitivePlotter.",
63 }
64 
66  : m_ptrPrimitivePlotter(eventDataPlotter.m_ptrPrimitivePlotter->clone())
67  , m_animate(eventDataPlotter.m_animate)
68  , m_forwardFade(eventDataPlotter.m_forwardFade)
69 {
70 }
71 
72 const std::string EventDataPlotter::save(const std::string& fileName)
73 {
75  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
76  return primitivePlotter.save(fileName);
77  } else {
78  return "";
79  }
80 }
81 
83 {
85  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
86  return primitivePlotter.clear();
87  }
88 }
89 
91 {
93  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
94  return primitivePlotter.getBoundingBox();
95  } else {
96  return BoundingBox(0, 0, 0, 0);
97  }
98 }
99 
101 {
102  if (m_ptrPrimitivePlotter) {
103  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
104  return primitivePlotter.setBoundingBox(boundingBox);
105  }
106 }
107 
109 {
110  if (m_ptrPrimitivePlotter) {
111  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
112  return primitivePlotter.getCanvasWidth();
113  } else {
114  return NAN;
115  }
116 }
117 
119 {
120  if (m_ptrPrimitivePlotter) {
121  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
122  return primitivePlotter.getCanvasHeight();
123  } else {
124  return NAN;
125  }
126 }
127 
129 {
130  if (m_ptrPrimitivePlotter) {
131  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
132  primitivePlotter.setCanvasWidth(width);
133  }
134 }
135 
137 {
138  if (m_ptrPrimitivePlotter) {
139  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
140  primitivePlotter.setCanvasHeight(height);
141  }
142 }
143 
145 {
146  if (m_ptrPrimitivePlotter) {
147  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
148  primitivePlotter.startGroup(attributeMap);
149  }
150 }
151 
153 {
154  if (m_ptrPrimitivePlotter) {
155  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
156  primitivePlotter.endGroup();
157  }
158 }
159 
161 {
162  // In case the event should be animated
163  // uncover the group of elements at the time of flight of the CDCSimHit.
164  if (not m_ptrPrimitivePlotter) return;
165  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
166 
167  if (m_animate) {
168  float tof = simHit.getFlightTime();
169  AttributeMap groupAttributeMap{{"_showAt", getAnimationTimeFromNanoSeconds(tof)}};
170  primitivePlotter.startGroup(groupAttributeMap);
171 
172  } else {
173  primitivePlotter.startGroup();
174  }
175 }
176 
178 {
179  if (not m_ptrPrimitivePlotter) return;
180  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
181 
182  if (m_animate) {
183  if (ptrHit) {
184  const CDCHit& hit = *ptrHit;
185  const CDCSimHit* ptrSimHit = hit.getRelated<CDCSimHit>();
186  if (ptrSimHit) {
187  const CDCSimHit& simHit = *ptrSimHit;
188  startAnimationGroup(simHit);
189  return;
190  }
191  }
192  }
193  primitivePlotter.startGroup();
194 }
195 
197 {
198  Vector2D center(0.0, 0.0);
199  float radius = 1.0;
200 
201  const Circle2D interactionPoint(center, radius);
202 
203  AttributeMap attributeMap{{"fill", "black"}, {"stroke-width", "0"}};
204 
205  draw(interactionPoint, attributeMap);
206 }
207 
209 {
210  if (not m_ptrPrimitivePlotter) return;
211  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
212 
213  const CDCWireTopology& wireTopology = CDCWireTopology::getInstance();
214 
215  const CDCWireSuperLayer& wireSuperLayer = wireTopology.getWireSuperLayers().front();
216 
217  float centerX = 0.0;
218  float centerY = 0.0;
219  float innerR = wireSuperLayer.getInnerCylindricalR();
220 
221  primitivePlotter.drawCircle(centerX, centerY, innerR, attributeMap);
222 }
223 
225 {
226  if (not m_ptrPrimitivePlotter) return;
227  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
228 
229  const CDCWireTopology& wireTopology = CDCWireTopology::getInstance();
230 
231  const CDCWireSuperLayer& wireSuperLayer = wireTopology.getWireSuperLayers().back();
232 
233  float centerX = 0.0;
234  float centerY = 0.0;
235  float outerR = wireSuperLayer.getOuterCylindricalR();
236 
237  primitivePlotter.drawCircle(centerX, centerY, outerR, attributeMap);
238 }
239 
241 {
242  if (not m_ptrPrimitivePlotter) return;
243  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
244 
245  const CDCWireTopology& wireTopology = CDCWireTopology::getInstance();
246 
247  for (const CDCWireSuperLayer& wireSuperLayer : wireTopology.getWireSuperLayers()) {
248  float centerX = 0.0;
249  float centerY = 0.0;
250  float outerR = wireSuperLayer.getInnerCylindricalR();
251  primitivePlotter.drawCircle(centerX, centerY, outerR, attributeMap);
252  }
253  drawOuterCDCWall(attributeMap);
254 }
255 
256 void EventDataPlotter::drawLine(float startX,
257  float startY,
258  float endX,
259  float endY,
260  const AttributeMap& attributeMap)
261 {
262  if (not m_ptrPrimitivePlotter) return;
263  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
264 
265  primitivePlotter.drawLine(startX, startY, endX, endY, attributeMap);
266 }
267 
269 void EventDataPlotter::draw(const Circle2D& circle, AttributeMap attributeMap)
270 {
271  if (not m_ptrPrimitivePlotter) return;
272  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
273 
274  float radius = circle.radius();
275 
276  if (not attributeMap.count("fill") or attributeMap["fill"] != "") {
277  if (attributeMap.count("stroke")) {
278  attributeMap["fill"] = attributeMap["stroke"];
279  attributeMap.erase("stroke");
280  }
281  }
282 
283  const Vector2D& pos = circle.center();
284 
285  float x = pos.x();
286  float y = pos.y();
287 
288  primitivePlotter.drawCircle(x, y, radius, attributeMap);
289 }
290 
292 void EventDataPlotter::draw(const CDCWire& wire, const AttributeMap& attributeMap)
293 {
294  const float wireRadius = 0.25;
295  const Vector2D& refPos = wire.getRefPos2D();
296 
297  draw(Circle2D(refPos, wireRadius), attributeMap);
298 }
299 
301 void EventDataPlotter::draw(const CDCWireSuperLayer& wireSuperLayer,
302  const AttributeMap& attributeMap)
303 {
304  if (not m_ptrPrimitivePlotter) return;
305  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
306 
307  primitivePlotter.startGroup(attributeMap);
308  for (const CDCWireLayer& wireLayer : wireSuperLayer) {
309  for (const CDCWire& wire : wireLayer) {
310  draw(wire);
311  }
312  }
313  primitivePlotter.endGroup();
314 }
315 
317 void EventDataPlotter::draw(const CDCWireTopology& wireTopology, AttributeMap attributeMap)
318 {
319  for (const CDCWireSuperLayer& wireSuperLayer : wireTopology.getWireSuperLayers()) {
320  AttributeMap defaultSuperLayerAttributeMap{{"fill",
321  wireSuperLayer.isAxial() ? "black" : "gray"
322  },
323  {"stroke", "none"}};
324 
325  AttributeMap superLayerAttributeMap(attributeMap);
326 
327  // Insert the values as defaults. Does not overwrite attributes with the same name.
328  superLayerAttributeMap.insert(defaultSuperLayerAttributeMap.begin(),
329  defaultSuperLayerAttributeMap.end());
330  draw(wireSuperLayer, superLayerAttributeMap);
331  }
332 }
333 
335 void EventDataPlotter::draw(const CDCSimHit& simHit, const AttributeMap& attributeMap)
336 {
337  if (not m_ptrPrimitivePlotter) return;
338  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
339 
340  startAnimationGroup(simHit);
341 
342  // Draw hit position as a small circle
343  ROOT::Math::XYZVector position = simHit.getPosTrack();
344  float x = position.X();
345  float y = position.Y();
346  float radius = 0.2;
347 
348  primitivePlotter.drawCircle(x, y, radius, attributeMap);
349 
350  // Draw momentum as an arrow proportional to the transverse component of the momentum
351  const float momentumToArrowLength = 1.5;
352 
353  ROOT::Math::XYZVector momentum = simHit.getMomentum();
354  float endX = x + momentum.X() * momentumToArrowLength;
355  float endY = y + momentum.Y() * momentumToArrowLength;
356 
357  primitivePlotter.drawArrow(x, y, endX, endY, attributeMap);
358 
359  primitivePlotter.endGroup();
360 }
361 
363 void EventDataPlotter::draw(const CDCHit& hit, const AttributeMap& attributeMap)
364 {
365  CDCWireHit wireHit(&hit);
366  draw(wireHit, attributeMap);
367 }
368 
370 void EventDataPlotter::draw(const CDCWireHit& wireHit, const AttributeMap& attributeMap)
371 {
372  if (not m_ptrPrimitivePlotter) return;
373  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
374 
375  startAnimationGroup(wireHit.getHit());
376 
377  const Vector2D& refPos = wireHit.getRefPos2D();
378 
379  float x = refPos.x();
380  float y = refPos.y();
381  float radius = wireHit.getRefDriftLength();
382 
383  if (fabs(radius) < 100) {
384  primitivePlotter.drawCircle(x, y, radius, attributeMap);
385  }
386 
387  primitivePlotter.endGroup();
388 }
389 
391 void EventDataPlotter::draw(const CDCRecoHit2D& recoHit2D, const AttributeMap& attributeMap)
392 {
393  if (not m_ptrPrimitivePlotter) return;
394  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
395 
396  const CDCWireHit& wireHit = recoHit2D.getWireHit();
397 
398  startAnimationGroup(wireHit.getHit());
399 
400  const Vector2D& refPos2D = wireHit.getRefPos2D();
401  const Vector2D& recoPos2D = recoHit2D.getRecoPos2D();
402 
403  float x = refPos2D.x();
404  float y = refPos2D.y();
405  float radius = wireHit.getRefDriftLength();
406  primitivePlotter.drawCircle(x, y, radius, attributeMap);
407 
408  if (not recoPos2D.hasNAN()) {
409  float supportPointRadius = 0.2;
410  Circle2D supportPoint(recoPos2D, supportPointRadius);
411  draw(supportPoint, attributeMap);
412  }
413 
414  primitivePlotter.endGroup();
415 }
416 
418 void EventDataPlotter::draw(const CDCTangent& tangent, const AttributeMap& attributeMap)
419 {
420  if (not m_ptrPrimitivePlotter) return;
421  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
422 
423  const Vector2D fromPos = tangent.getFromRecoPos2D();
424  const float fromX = fromPos.x();
425  const float fromY = fromPos.y();
426 
427  const Vector2D toPos = tangent.getToRecoPos2D();
428  const float toX = toPos.x();
429  const float toY = toPos.y();
430 
431  primitivePlotter.drawLine(fromX, fromY, toX, toY, attributeMap);
432 
433  float touchPointRadius = 0.015;
434  const Circle2D fromTouchPoint(fromPos, touchPointRadius);
435  draw(fromTouchPoint, attributeMap);
436 
437  const Circle2D toTouchPoint(toPos, touchPointRadius);
438  draw(toTouchPoint, attributeMap);
439 }
440 
442  const AttributeMap& attributeMap)
443 {
444  draw(recoHit3D.getRecoHit2D(), attributeMap);
445 }
446 
448 void EventDataPlotter::draw(const CDCTrajectory2D& trajectory2D, AttributeMap attributeMap)
449 {
450  if (not m_ptrPrimitivePlotter) return;
451  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
452 
453  AttributeMap defaultAttributeMap{};
454 
455  // Make the default color charge dependent
456  int charge = trajectory2D.getChargeSign();
457  if (charge > 0) {
458  defaultAttributeMap["stroke"] = "red";
459  } else if (charge < 0) {
460  defaultAttributeMap["stroke"] = "blue";
461  } else {
462  defaultAttributeMap["stroke"] = "green";
463  }
464 
465  // Add attributes if not present
466  attributeMap.insert(defaultAttributeMap.begin(), defaultAttributeMap.end());
467 
468  Vector2D trajectoryExit = trajectory2D.getOuterExit();
469  if (trajectoryExit.hasNAN()) {
470  // Curlers do not leave the CDC
471  // Stop the trajectory at the inner wall to be able to
472  // see the start point
473  trajectoryExit = trajectory2D.getInnerExit();
474  }
475 
476  if (trajectory2D.getLocalCircle()->isCircle()) {
477  if (trajectoryExit.hasNAN()) {
478  // No exit point out of the cdc could be detected.
479  // Draw full circle
480  const float radius = trajectory2D.getLocalCircle()->absRadius();
481  const Vector2D center = trajectory2D.getGlobalCircle().center();
482  float centerX = center.x();
483  float centerY = center.y();
484 
485  primitivePlotter.drawCircle(centerX, centerY, radius);
486 
487  } else {
488  const float radius = trajectory2D.getLocalCircle()->absRadius();
489  const Vector2D start = trajectory2D.getSupport();
490  float startX = start.x();
491  float startY = start.y();
492 
493  float endX = trajectoryExit.x();
494  float endY = trajectoryExit.y();
495 
496  const int curvature = -charge;
497  const bool sweepFlag = curvature > 0;
498 
499  // check if exit point is on the close or
500  // on the far side of the circle
501  const bool longArc = (trajectory2D.calcArcLength2D(trajectoryExit) > 0) ? false : true;
502  primitivePlotter.drawCircleArc(startX,
503  startY,
504  endX,
505  endY,
506  radius,
507  longArc,
508  sweepFlag,
509  attributeMap);
510  }
511  } else {
512  // trajectory is a straight line
513  if (trajectoryExit.hasNAN()) {
514  B2WARNING("Could not compute point off exit in a straight line case.");
515  } else {
516  const Vector2D start = trajectory2D.getSupport();
517  float startX = start.x();
518  float startY = start.y();
519 
520  float endX = trajectoryExit.x();
521  float endY = trajectoryExit.y();
522  primitivePlotter.drawLine(startX, startY, endX, endY, attributeMap);
523  }
524  }
525 }
526 
527 void EventDataPlotter::draw(const CDCWireHitCluster& wireHitCluster, const AttributeMap& attributeMap)
528 {
529  drawRange(wireHitCluster, attributeMap);
530 }
531 
532 void EventDataPlotter::draw(const CDCSegment2D& segment2D, const AttributeMap& attributeMap)
533 {
534  if (m_forwardFade) {
535  drawRangeWithFade(segment2D, attributeMap);
536  } else {
537  drawRange(segment2D, attributeMap);
538  }
539 }
540 
541 void EventDataPlotter::draw(const CDCSegment3D& segment3D, const AttributeMap& attributeMap)
542 {
543  if (m_forwardFade) {
544  drawRange(segment3D, attributeMap);
545  } else {
546  drawRange(segment3D, attributeMap);
547  }
548 }
549 
550 void EventDataPlotter::draw(const CDCAxialSegmentPair& axialSegmentPair,
551  const AttributeMap& attributeMap)
552 {
553  if (not m_ptrPrimitivePlotter) return;
554  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
555 
556  const CDCSegment2D* ptrFromSegment = axialSegmentPair.getStartSegment();
557  const CDCSegment2D* ptrToSegment = axialSegmentPair.getEndSegment();
558 
559  if (not ptrFromSegment or not ptrToSegment) return;
560 
561  const CDCSegment2D& fromSegment = *ptrFromSegment;
562  const CDCSegment2D& toSegment = *ptrToSegment;
563 
564  const Vector2D& fromPos = fromSegment.back().getWire().getRefPos2D();
565  const Vector2D& toPos = toSegment.front().getWire().getRefPos2D();
566 
567  if (fromPos.hasNAN()) {
568  B2WARNING("Center of mass of first segment in a pair contains NAN values.");
569  return;
570  }
571 
572  if (toPos.hasNAN()) {
573  B2WARNING("Center of mass of second segment in a pair contains NAN values.");
574  return;
575  }
576 
577  const float fromX = fromPos.x();
578  const float fromY = fromPos.y();
579 
580  const float toX = toPos.x();
581  const float toY = toPos.y();
582 
583  primitivePlotter.drawArrow(fromX, fromY, toX, toY, attributeMap);
584 }
585 
586 void EventDataPlotter::draw(const CDCSegmentPair& segmentPair, const AttributeMap& attributeMap)
587 {
588  if (not m_ptrPrimitivePlotter) return;
589  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
590 
591  const CDCSegment2D* ptrFromSegment = segmentPair.getFromSegment();
592  const CDCSegment2D* ptrToSegment = segmentPair.getToSegment();
593 
594  if (not ptrFromSegment or not ptrToSegment) return;
595 
596  const CDCSegment2D& fromSegment = *ptrFromSegment;
597  const CDCSegment2D& toSegment = *ptrToSegment;
598 
599  const Vector2D& fromPos = fromSegment.back().getWire().getRefPos2D();
600  const Vector2D& toPos = toSegment.front().getWire().getRefPos2D();
601 
602  if (fromPos.hasNAN()) {
603  B2WARNING("Center of mass of first segment in a pair contains NAN values.");
604  return;
605  }
606 
607  if (toPos.hasNAN()) {
608  B2WARNING("Center of mass of second segment in a pair contains NAN values.");
609  return;
610  }
611 
612  const float fromX = fromPos.x();
613  const float fromY = fromPos.y();
614 
615  const float toX = toPos.x();
616  const float toY = toPos.y();
617 
618  primitivePlotter.drawArrow(fromX, fromY, toX, toY, attributeMap);
619 }
620 
621 void EventDataPlotter::draw(const CDCSegmentTriple& segmentTriple, const AttributeMap& attributeMap)
622 {
623  if (not m_ptrPrimitivePlotter) return;
624  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
625 
626  const CDCSegment2D* ptrStartSegment = segmentTriple.getStartSegment();
627  const CDCSegment2D* ptrMiddleSegment = segmentTriple.getMiddleSegment();
628  const CDCSegment2D* ptrEndSegment = segmentTriple.getEndSegment();
629 
630  if (not ptrStartSegment or not ptrMiddleSegment or not ptrEndSegment) return;
631 
632  const CDCSegment2D& startSegment = *ptrStartSegment;
633  const CDCSegment2D& middleSegment = *ptrMiddleSegment;
634  const CDCSegment2D& endSegment = *ptrEndSegment;
635 
636  const Vector2D& startBackPos2D = startSegment.back().getRefPos2D();
637  const Vector2D& middleFrontPos2D = middleSegment.front().getRefPos2D();
638  const Vector2D& middleBackPos2D = middleSegment.back().getRefPos2D();
639  const Vector2D& endFrontPos2D = endSegment.front().getRefPos2D();
640 
641  if (startBackPos2D.hasNAN()) {
642  B2WARNING("Back position of start segment in a triple contains NAN values.");
643  return;
644  }
645 
646  if (middleFrontPos2D.hasNAN()) {
647  B2WARNING("Front position of middle segment in a triple contains NAN values.");
648  return;
649  }
650 
651  if (middleBackPos2D.hasNAN()) {
652  B2WARNING("Back position of middle segment in a triple contains NAN values.");
653  return;
654  }
655 
656  if (endFrontPos2D.hasNAN()) {
657  B2WARNING("Front position of end segment in a triple contains NAN values.");
658  return;
659  }
660 
661  const float startBackX = startBackPos2D.x();
662  const float startBackY = startBackPos2D.y();
663 
664  const float middleFrontX = middleFrontPos2D.x();
665  const float middleFrontY = middleFrontPos2D.y();
666 
667  primitivePlotter.drawArrow(startBackX, startBackY, middleFrontX, middleFrontY, attributeMap);
668 
669  const float middleBackX = middleBackPos2D.x();
670  const float middleBackY = middleBackPos2D.y();
671 
672  const float endFrontX = endFrontPos2D.x();
673  const float endFrontY = endFrontPos2D.y();
674 
675  primitivePlotter.drawArrow(middleBackX, middleBackY, endFrontX, endFrontY, attributeMap);
676 }
677 
678 void EventDataPlotter::draw(const CDCTrack& track, const AttributeMap& attributeMap)
679 {
680  if (m_forwardFade) {
681  drawRangeWithFade(track, attributeMap);
682  } else {
683  drawRange(track, attributeMap);
684  }
685 }
686 
687 void EventDataPlotter::draw(const RecoTrack& recoTrack, const AttributeMap& attributeMap)
688 {
689  if (not m_ptrPrimitivePlotter) return;
690  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
691 
692  primitivePlotter.startGroup(attributeMap);
693  for (const CDCHit* ptrHit : recoTrack.getCDCHitList()) {
694  if (ptrHit) {
695  const CDCHit& hit = *ptrHit;
696  draw(hit);
697  }
698  }
699  primitivePlotter.endGroup();
700 }
701 
702 void EventDataPlotter::drawTrajectory(const MCParticle& mcParticle, const AttributeMap& attributeMap)
703 {
704  if (not mcParticle.isPrimaryParticle()) return;
705  Vector3D pos(mcParticle.getVertex());
706  Vector3D mom(mcParticle.getMomentum());
707  double charge = mcParticle.getCharge();
708  double time = mcParticle.getProductionTime();
709  CDCTrajectory2D trajectory2D(pos.xy(), time, mom.xy(), charge);
710  draw(trajectory2D, attributeMap);
711 }
712 
714  const AttributeMap& attributeMap)
715 {
716  draw(segment.getTrajectory2D(), attributeMap);
717 }
718 
720  const AttributeMap& attributeMap)
721 {
722  draw(segmentTriple.getTrajectory3D().getTrajectory2D(), attributeMap);
723 }
724 
725 void EventDataPlotter::drawTrajectory(const CDCTrack& track, const AttributeMap& attributeMap)
726 {
727  draw(track.getStartTrajectory3D().getTrajectory2D(), attributeMap);
728 }
729 
730 void EventDataPlotter::drawTrajectory(const RecoTrack& recoTrack, const AttributeMap& attributeMap)
731 {
732  if (not m_ptrPrimitivePlotter) return;
733  PrimitivePlotter& primitivePlotter = *m_ptrPrimitivePlotter;
734 
735  primitivePlotter.startGroup(attributeMap);
736 
737  bool fitSuccessful = not recoTrack.getRepresentations().empty() and recoTrack.wasFitSuccessful();
738  if (fitSuccessful) {
739  std::vector<std::array<float, 2>> points;
740  std::vector<std::array<float, 2>> tangents;
741 
742  for (auto recoHit : recoTrack.getRecoHitInformations()) {
743  // skip for reco hits which have not been used in the fit (and therefore have no fitted information on the plane
744  if (!recoHit->useInFit())
745  continue;
746 
747  TVector3 pos;
748  TVector3 mom;
749  TMatrixDSym cov;
750 
751  try {
752  const auto* trackPoint = recoTrack.getCreatedTrackPoint(recoHit);
753  const auto* fittedResult = trackPoint->getFitterInfo();
754  if (not fittedResult) {
755  B2WARNING("Skipping unfitted track point");
756  continue;
757  }
758  const genfit::MeasuredStateOnPlane& state = fittedResult->getFittedState();
759  state.getPosMomCov(pos, mom, cov);
760  } catch (const genfit::Exception&) {
761  B2WARNING("Skipping state with strange pos, mom or cov");
762  continue;
763  }
764 
765  float x = pos.X();
766  float y = pos.Y();
767  float px = mom.X();
768  float py = mom.Y();
769 
770  points.push_back({{x, y}});
771  tangents.push_back({{px, py}});
772  }
773  primitivePlotter.drawCurve(points, tangents, attributeMap);
774  }
775 
776  primitivePlotter.endGroup();
777 }
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition: CDCHit.h:40
Example Detector.
Definition: CDCSimHit.h:21
double getFlightTime() const
The method to get flight time.
Definition: CDCSimHit.h:184
B2Vector3D getPosTrack() const
The method to get position on the track.
Definition: CDCSimHit.h:217
B2Vector3D getMomentum() const
The method to get momentum.
Definition: CDCSimHit.h:193
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
ROOT::Math::XYZVector getVertex() const
Return production vertex position, shorthand for getProductionVertex().
Definition: MCParticle.h:183
float getCharge() const
Return the particle charge defined in TDatabasePDG.
Definition: MCParticle.cc:36
float getProductionTime() const
Return production time in ns.
Definition: MCParticle.h:159
ROOT::Math::XYZVector getMomentum() const
Return momentum.
Definition: MCParticle.h:198
This is the Reconstruction Event-Data Model Track.
Definition: RecoTrack.h:79
bool wasFitSuccessful(const genfit::AbsTrackRep *representation=nullptr) const
Returns true if the last fit with the given representation was successful.
Definition: RecoTrack.cc:336
const std::vector< genfit::AbsTrackRep * > & getRepresentations() const
Return a list of track representations. You are not allowed to modify or delete them!
Definition: RecoTrack.h:638
std::vector< Belle2::RecoTrack::UsedCDCHit * > getCDCHitList() const
Return an unsorted list of cdc hits.
Definition: RecoTrack.h:455
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
A two dimensional rectangle that keeps track of the extend of a drawing.
Definition: BoundingBox.h:21
Class representing a pair of reconstructed axial segements in adjacent superlayer.
const CDCAxialSegment2D * getStartSegment() const
Getter for the start segment.
const CDCAxialSegment2D * getEndSegment() const
Getter for the end segment.
Class representing a two dimensional reconstructed hit in the central drift chamber.
Definition: CDCRecoHit2D.h:47
Vector2D getRecoPos2D() const
Getter for the position in the reference plane.
Definition: CDCRecoHit2D.h:238
const CDCWireHit & getWireHit() const
Getter for the wire hit assoziated with the reconstructed hit.
Definition: CDCRecoHit2D.h:193
Class representing a three dimensional reconstructed hit.
Definition: CDCRecoHit3D.h:52
CDCRecoHit2D getRecoHit2D() const
Constructs a two dimensional reconstructed hit by carrying out the stereo ! projection to the wire re...
A reconstructed sequence of two dimensional hits in one super layer.
Definition: CDCSegment2D.h:39
A segment consisting of three dimensional reconstructed hits.
Definition: CDCSegment3D.h:26
Class representing a pair of one reconstructed axial segement and one stereo segment in adjacent supe...
const CDCSegment2D * getFromSegment() const
Getter for the from segment.
const CDCSegment2D * getToSegment() const
Getter for the to segment.
Class representing a triple of reconstructed segements in adjacent superlayer.
const CDCAxialSegment2D * getStartSegment() const
Getter for the start axial segment.
const CDCTrajectory3D & getTrajectory3D() const
Getter for the three dimensional helix trajectory.
const CDCAxialSegment2D * getEndSegment() const
Getter for the end axial segment.
const CDCStereoSegment2D * getMiddleSegment() const
Getter for the middle stereo segment.
Class representating a linear track piece between two oriented wire hits.
Definition: CDCTangent.h:40
Vector2D getToRecoPos2D() const
Getter for the touching point of the tangent to the second drift circle.
Definition: CDCTangent.h:70
const Vector2D & getFromRecoPos2D() const
Getter for the touching point of the tangent to the first drift circle.
Definition: CDCTangent.h:63
Class representing a sequence of three dimensional reconstructed hits.
Definition: CDCTrack.h:41
Particle trajectory as it is seen in xy projection represented as a circle.
PerigeeCircle getGlobalCircle() const
Getter for the circle in global coordinates.
Vector2D getOuterExit(double factor=1) const
Calculates the point where the trajectory meets the outer wall of the CDC.
double calcArcLength2D(const Vector2D &point) const
Calculate the travel distance from the start position of the trajectory.
ESign getChargeSign() const
Gets the charge sign of the trajectory.
Vector2D getSupport() const
Get the support point of the trajectory in global coordinates.
const UncertainPerigeeCircle & getLocalCircle() const
Getter for the cirlce in local coordinates.
Vector2D getInnerExit() const
Calculates the point where the trajectory meets the inner wall of the CDC.
CDCTrajectory2D getTrajectory2D() const
Getter for the two dimensional trajectory.
Class representing a hit wire in the central drift chamber.
Definition: CDCWireHit.h:55
const CDCHit * getHit() const
Getter for the CDCHit pointer into the StoreArray.
Definition: CDCWireHit.h:159
double getRefDriftLength() const
Getter for the drift length at the reference position of the wire.
Definition: CDCWireHit.h:224
const Vector2D & getRefPos2D() const
The two dimensional reference position (z=0) of the underlying wire.
Definition: CDCWireHit.cc:212
Class representating a sense wire layer in the central drift chamber.
Definition: CDCWireLayer.h:42
Class representating a sense wire superlayer in the central drift chamber.
double getInnerCylindricalR() const
Getter for the inner radius of the layer as retrived from the CDCGeometryPar by the inner most layer.
double getOuterCylindricalR() const
Getter for the outer radius of the layer as retrived from the CDCGeometryPar by the outer most layer.
Class representating the sense wire arrangement in the whole of the central drift chamber.
const std::vector< Belle2::TrackFindingCDC::CDCWireSuperLayer > & getWireSuperLayers() const
Getter for the underlying storing superlayer vector.
static CDCWireTopology & getInstance()
Getter for the singleton instance of the wire topology.
Class representing a sense wire in the central drift chamber.
Definition: CDCWire.h:58
const Vector2D & getRefPos2D() const
Getter for the wire reference position for 2D tracking Gives the wire's reference position projected ...
Definition: CDCWire.h:229
A two dimensional circle in its natural representation using center and radius as parameters.
Definition: Circle2D.h:26
double radius() const
Getter for the signed radius.
Definition: Circle2D.h:197
Vector2D center() const
Getter for the central point of the circle.
Definition: Circle2D.h:221
A class that can plot event related data types.
void drawInteractionPoint()
Marks the position of the interaction point with a filled circle.
float getCanvasHeight() const
Getter for the canvas height in pixels.
void setCanvasHeight(float height)
Setter for the canvas height in pixels The canvas height denotes the size of the image being produced...
void setBoundingBox(const BoundingBox &boundingBox)
Setter for the bounding box of all drawed objects.
bool m_forwardFade
Memory for the flag whether the orientation of tracks segments etc should be shown as diming opacity.
void drawOuterCDCWall(const AttributeMap &attributeMap=AttributeMap())
Draw the outer wall of the CDC.
void drawTrajectory(const MCParticle &mcParticle, const AttributeMap &attributeMap=AttributeMap())
Draws the trajectory that is represented by the MC particle.
void drawInnerCDCWall(const AttributeMap &attributeMap=AttributeMap())
Draw the inner wall of the CDC.
float getCanvasWidth() const
Getter for the canvas width in pixels.
PrimitivePlotter::AttributeMap AttributeMap
Forward the Attributre map from the primitive plotter.
void drawRange(const ARange &range, const AttributeMap &attributeMap=AttributeMap())
Draws a range iterable collection of drawable elements.
void startGroup(const AttributeMap &attributeMap=AttributeMap())
Indicates the start of a group of drawn elements.
bool m_animate
Memory for the flag if the event data should be animated. If animation is supported is backend depend...
void setCanvasWidth(float width)
Setter for the canvas width in pixels.
const std::string save(const std::string &fileName)
Saves the current plot stead to a file.
BoundingBox getBoundingBox() const
Getter for the current bounding box.
std::unique_ptr< PrimitivePlotter > m_ptrPrimitivePlotter
Reference to the primitivePlotter instance used as backend for the draw commands.
EventDataPlotter(bool animate=false, bool forwardFade=false)
Default constructor for ROOT compatibility. Uses an SVGPrimitivePlotter as backend.
void clear()
Clears all drawed elements from the plotter.
void drawSuperLayerBoundaries(const AttributeMap &attributeMap=AttributeMap())
Draw the super layer bounds of the CDC.
void drawRangeWithFade(const ARange &range, const AttributeMap &attributeMap=AttributeMap())
Draws a range iterable collection of drawable elements.
void draw(const Belle2::TrackFindingCDC::Circle2D &circle, AttributeMap attributeMap=AttributeMap())
Draws a filled circle.
void drawLine(float startX, float startY, float endX, float endY, const AttributeMap &attributeMap=AttributeMap())
Draws a straight Line.
void startAnimationGroup(const Belle2::CDCSimHit &simHit)
Start a group in the underlying plotter with an animation uncovering the elements at the time of flig...
void endGroup()
Indicates the end of a group of drawn elements.
std::string getAnimationTimeFromNanoSeconds(float nanoseconds)
Converts a time given in nanoseconds to a time sting of the from "%fs".
Vector2D center() const
Getter for the center of the circle. If it was a line both components will be infinity.
bool isCircle() const
Indicates if the perigee parameters represent a closed circle.
double absRadius() const
Gives the signed radius of the circle. If it was a line this will be infinity.
A base class for plots of primitive objects.
void setCanvasHeight(float height)
Setter for the canvas height in pixels The canvas height denotes the size of the image being produced...
void setBoundingBox(const BoundingBox &boundingBox)
Setter for the bounding box of all drawed objects.
float getCanvasWidth()
Getter for the canvas width in pixels.
virtual void startGroup(const AttributeMap &attributeMap=AttributeMap())
Indicates the start of a group of drawn elements.
void setCanvasWidth(float width)
Setter for the canvas width in pixels.
virtual void drawCircleArc(float startX, float startY, float endX, float endY, float radius, bool longArc, bool sweepFlag, const AttributeMap &attributeMap=AttributeMap())
Adds a circle arc to the plot.
virtual void drawArrow(float startX, float startY, float endX, float endY, const AttributeMap &attributeMap=AttributeMap())
Adds an arrow to the plot.
virtual const std::string save(const std::string &fileName)
Saves the current plot state to a file.
float getCanvasHeight()
Getter for the canvas height in pixels.
virtual void drawCurve(const std::vector< std::array< float, 2 >> &points, const std::vector< std::array< float, 2 >> &tangents, const AttributeMap &attributeMap=AttributeMap())
Adds a smooth curve to the plot.
virtual void clear()
Clears all drawed elements from the plotter.
virtual void drawLine(float startX, float startY, float endX, float endY, const AttributeMap &attributeMap=AttributeMap())
Adds a line to the plot.
const BoundingBox & getBoundingBox() const
Getter for the bounding box of all drawed objects.
virtual void drawCircle(float centerX, float centerY, float radius, const AttributeMap &attributeMap=AttributeMap())
Adds a circle to the plot.
virtual void endGroup()
Indicates the end of a group of drawn elements.
A concrete plotter that can draw primitive objects to standalone SVG files.
A two dimensional vector which is equipped with functions for correct handeling of orientation relat...
Definition: Vector2D.h:35
double x() const
Getter for the x coordinate.
Definition: Vector2D.h:607
bool hasNAN() const
Checks if one of the coordinates is NAN.
Definition: Vector2D.h:161
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:617
A three dimensional vector.
Definition: Vector3D.h:33
const Vector2D & xy() const
Getter for the xy projected vector ( reference ! )
Definition: Vector3D.h:508
Exception class for error handling in GENFIT (provides storage for diagnostic information)
Definition: Exception.h:48
#StateOnPlane with additional covariance matrix.
AbsFitterInfo * getFitterInfo(const AbsTrackRep *rep=nullptr) const
Get fitterInfo for rep. Per default, use cardinal rep.
Definition: TrackPoint.cc:170
bool isPrimaryParticle() const
Check if particle is a primary particle which was created by the generator (and not,...
Definition: MCParticle.h:595
Abstract base class for different kinds of events.