10 #include <tracking/trackFindingCDC/display/EventDataPlotter.h>
12 #include <tracking/trackFindingCDC/display/SVGPrimitivePlotter.h>
13 #include <tracking/trackFindingCDC/display/BoundingBox.h>
15 #include <tracking/trackFindingCDC/eventdata/tracks/CDCSegmentPair.h>
16 #include <tracking/trackFindingCDC/eventdata/tracks/CDCAxialSegmentPair.h>
17 #include <tracking/trackFindingCDC/eventdata/tracks/CDCSegmentTriple.h>
18 #include <tracking/trackFindingCDC/eventdata/tracks/CDCTrack.h>
20 #include <tracking/trackFindingCDC/eventdata/segments/CDCWireHitCluster.h>
21 #include <tracking/trackFindingCDC/eventdata/segments/CDCSegment2D.h>
22 #include <tracking/trackFindingCDC/eventdata/segments/CDCSegment3D.h>
24 #include <tracking/trackFindingCDC/eventdata/hits/CDCTangent.h>
25 #include <tracking/trackFindingCDC/eventdata/hits/CDCRecoHit3D.h>
26 #include <tracking/trackFindingCDC/eventdata/hits/CDCRecoHit2D.h>
27 #include <tracking/trackFindingCDC/eventdata/hits/CDCWireHit.h>
29 #include <tracking/trackFindingCDC/topology/CDCWireTopology.h>
31 #include <tracking/trackFindingCDC/geometry/Circle2D.h>
33 #include <cdc/dataobjects/CDCSimHit.h>
34 #include <cdc/dataobjects/CDCHit.h>
36 #include <framework/logging/Logger.h>
38 #include <tracking/dataobjects/RecoTrack.h>
39 #include <mdst/dataobjects/MCParticle.h>
41 #include <TMatrixDSym.h>
46 using namespace TrackFindingCDC;
49 : m_ptrPrimitivePlotter(new SVGPrimitivePlotter(
50 AttributeMap{{
"stroke",
"orange"}, {
"stroke-width",
"0.55"}, {
"fill",
"none"}}))
52 , m_forwardFade(forwardFade)
59 : m_ptrPrimitivePlotter(std::move(ptrPrimitivePlotter))
61 , m_forwardFade(forwardFade)
63 B2ASSERT(
"EventDataPlotter initialized with nullptr. Using default backend SVGPrimitivePlotter.",
64 m_ptrPrimitivePlotter);
68 : m_ptrPrimitivePlotter(eventDataPlotter.m_ptrPrimitivePlotter->clone())
69 , m_animate(eventDataPlotter.m_animate)
70 , m_forwardFade(eventDataPlotter.m_forwardFade)
78 return primitivePlotter.
save(fileName);
88 return primitivePlotter.
clear();
172 primitivePlotter.
startGroup(groupAttributeMap);
186 const CDCHit& hit = *ptrHit;
203 const Circle2D interactionPoint(center, radius);
205 AttributeMap attributeMap{{
"fill",
"black"}, {
"stroke-width",
"0"}};
207 draw(interactionPoint, attributeMap);
223 primitivePlotter.
drawCircle(centerX, centerY, innerR, attributeMap);
239 primitivePlotter.
drawCircle(centerX, centerY, outerR, attributeMap);
252 float outerR = wireSuperLayer.getInnerCylindricalR();
253 primitivePlotter.
drawCircle(centerX, centerY, outerR, attributeMap);
267 primitivePlotter.
drawLine(startX, startY, endX, endY, attributeMap);
276 float radius = circle.
radius();
278 if (not attributeMap.count(
"fill") or attributeMap[
"fill"] !=
"") {
279 if (attributeMap.count(
"stroke")) {
280 attributeMap[
"fill"] = attributeMap[
"stroke"];
281 attributeMap.erase(
"stroke");
285 const Vector2D& pos = circle.
center();
290 primitivePlotter.
drawCircle(x, y, radius, attributeMap);
296 const float wireRadius = 0.25;
297 const Vector2D& refPos = wire.getRefPos2D();
299 draw(Circle2D(refPos, wireRadius), attributeMap);
304 const AttributeMap& attributeMap)
309 primitivePlotter.startGroup(attributeMap);
310 for (
const CDCWireLayer& wireLayer : wireSuperLayer) {
311 for (
const CDCWire& wire : wireLayer) {
315 primitivePlotter.endGroup();
321 for (
const CDCWireSuperLayer& wireSuperLayer : wireTopology.getWireSuperLayers()) {
323 wireSuperLayer.isAxial() ?
"black" :
"gray"
330 superLayerAttributeMap.insert(defaultSuperLayerAttributeMap.begin(),
331 defaultSuperLayerAttributeMap.end());
332 draw(wireSuperLayer, superLayerAttributeMap);
346 float x = position.X();
347 float y = position.Y();
350 primitivePlotter.drawCircle(x, y, radius, attributeMap);
353 const float momentumToArrowLength = 1.5;
356 float endX = x + momentum.X() * momentumToArrowLength;
357 float endY = y + momentum.Y() * momentumToArrowLength;
359 primitivePlotter.drawArrow(x, y, endX, endY, attributeMap);
361 primitivePlotter.endGroup();
368 draw(wireHit, attributeMap);
381 float x = refPos.x();
382 float y = refPos.y();
385 if (fabs(radius) < 100) {
386 primitivePlotter.drawCircle(x, y, radius, attributeMap);
389 primitivePlotter.endGroup();
398 const CDCWireHit& wireHit = recoHit2D.getWireHit();
403 const Vector2D& recoPos2D = recoHit2D.getRecoPos2D();
405 float x = refPos2D.x();
406 float y = refPos2D.y();
408 primitivePlotter.drawCircle(x, y, radius, attributeMap);
410 if (not recoPos2D.hasNAN()) {
411 float supportPointRadius = 0.2;
412 Circle2D supportPoint(recoPos2D, supportPointRadius);
413 draw(supportPoint, attributeMap);
416 primitivePlotter.endGroup();
425 const Vector2D fromPos = tangent.getFromRecoPos2D();
426 const float fromX = fromPos.x();
427 const float fromY = fromPos.y();
429 const Vector2D toPos = tangent.getToRecoPos2D();
430 const float toX = toPos.x();
431 const float toY = toPos.y();
433 primitivePlotter.drawLine(fromX, fromY, toX, toY, attributeMap);
435 float touchPointRadius = 0.015;
436 const Circle2D fromTouchPoint(fromPos, touchPointRadius);
437 draw(fromTouchPoint, attributeMap);
439 const Circle2D toTouchPoint(toPos, touchPointRadius);
440 draw(toTouchPoint, attributeMap);
444 const AttributeMap& attributeMap)
458 int charge = trajectory2D.getChargeSign();
460 defaultAttributeMap[
"stroke"] =
"red";
461 }
else if (charge < 0) {
462 defaultAttributeMap[
"stroke"] =
"blue";
464 defaultAttributeMap[
"stroke"] =
"green";
468 attributeMap.insert(defaultAttributeMap.begin(), defaultAttributeMap.end());
470 Vector2D trajectoryExit = trajectory2D.getOuterExit();
471 if (trajectoryExit.hasNAN()) {
475 trajectoryExit = trajectory2D.getInnerExit();
478 if (trajectory2D.getLocalCircle()->isCircle()) {
479 if (trajectoryExit.hasNAN()) {
482 const float radius = trajectory2D.getLocalCircle()->absRadius();
483 const Vector2D center = trajectory2D.getGlobalCircle().center();
484 float centerX = center.x();
485 float centerY = center.y();
487 primitivePlotter.drawCircle(centerX, centerY, radius);
490 const float radius = trajectory2D.getLocalCircle()->absRadius();
491 const Vector2D start = trajectory2D.getSupport();
492 float startX = start.x();
493 float startY = start.y();
495 float endX = trajectoryExit.x();
496 float endY = trajectoryExit.y();
498 const int curvature = -
charge;
499 const bool sweepFlag = curvature > 0;
503 const bool longArc = (trajectory2D.calcArcLength2D(trajectoryExit) > 0) ?
false :
true;
504 primitivePlotter.drawCircleArc(startX,
515 if (trajectoryExit.hasNAN()) {
516 B2WARNING(
"Could not compute point off exit in a straight line case.");
518 const Vector2D start = trajectory2D.getSupport();
519 float startX = start.x();
520 float startY = start.y();
522 float endX = trajectoryExit.x();
523 float endY = trajectoryExit.y();
524 primitivePlotter.drawLine(startX, startY, endX, endY, attributeMap);
553 const AttributeMap& attributeMap)
558 const CDCSegment2D* ptrFromSegment = axialSegmentPair.getStartSegment();
559 const CDCSegment2D* ptrToSegment = axialSegmentPair.getEndSegment();
561 if (not ptrFromSegment or not ptrToSegment)
return;
563 const CDCSegment2D& fromSegment = *ptrFromSegment;
564 const CDCSegment2D& toSegment = *ptrToSegment;
566 const Vector2D& fromPos = fromSegment.back().getWire().getRefPos2D();
567 const Vector2D& toPos = toSegment.front().getWire().getRefPos2D();
569 if (fromPos.hasNAN()) {
570 B2WARNING(
"Center of mass of first segment in a pair contains NAN values.");
574 if (toPos.hasNAN()) {
575 B2WARNING(
"Center of mass of second segment in a pair contains NAN values.");
579 const float fromX = fromPos.x();
580 const float fromY = fromPos.y();
582 const float toX = toPos.x();
583 const float toY = toPos.y();
585 primitivePlotter.drawArrow(fromX, fromY, toX, toY, attributeMap);
593 const CDCSegment2D* ptrFromSegment = segmentPair.getFromSegment();
594 const CDCSegment2D* ptrToSegment = segmentPair.getToSegment();
596 if (not ptrFromSegment or not ptrToSegment)
return;
598 const CDCSegment2D& fromSegment = *ptrFromSegment;
599 const CDCSegment2D& toSegment = *ptrToSegment;
601 const Vector2D& fromPos = fromSegment.back().getWire().getRefPos2D();
602 const Vector2D& toPos = toSegment.front().getWire().getRefPos2D();
604 if (fromPos.hasNAN()) {
605 B2WARNING(
"Center of mass of first segment in a pair contains NAN values.");
609 if (toPos.hasNAN()) {
610 B2WARNING(
"Center of mass of second segment in a pair contains NAN values.");
614 const float fromX = fromPos.x();
615 const float fromY = fromPos.y();
617 const float toX = toPos.x();
618 const float toY = toPos.y();
620 primitivePlotter.drawArrow(fromX, fromY, toX, toY, attributeMap);
628 const CDCSegment2D* ptrStartSegment = segmentTriple.getStartSegment();
629 const CDCSegment2D* ptrMiddleSegment = segmentTriple.getMiddleSegment();
630 const CDCSegment2D* ptrEndSegment = segmentTriple.getEndSegment();
632 if (not ptrStartSegment or not ptrMiddleSegment or not ptrEndSegment)
return;
634 const CDCSegment2D& startSegment = *ptrStartSegment;
635 const CDCSegment2D& middleSegment = *ptrMiddleSegment;
636 const CDCSegment2D& endSegment = *ptrEndSegment;
638 const Vector2D& startBackPos2D = startSegment.back().getRefPos2D();
639 const Vector2D& middleFrontPos2D = middleSegment.front().getRefPos2D();
640 const Vector2D& middleBackPos2D = middleSegment.back().getRefPos2D();
641 const Vector2D& endFrontPos2D = endSegment.front().getRefPos2D();
643 if (startBackPos2D.hasNAN()) {
644 B2WARNING(
"Back position of start segment in a triple contains NAN values.");
648 if (middleFrontPos2D.hasNAN()) {
649 B2WARNING(
"Front position of middle segment in a triple contains NAN values.");
653 if (middleBackPos2D.hasNAN()) {
654 B2WARNING(
"Back position of middle segment in a triple contains NAN values.");
658 if (endFrontPos2D.hasNAN()) {
659 B2WARNING(
"Front position of end segment in a triple contains NAN values.");
663 const float startBackX = startBackPos2D.x();
664 const float startBackY = startBackPos2D.y();
666 const float middleFrontX = middleFrontPos2D.x();
667 const float middleFrontY = middleFrontPos2D.y();
669 primitivePlotter.drawArrow(startBackX, startBackY, middleFrontX, middleFrontY, attributeMap);
671 const float middleBackX = middleBackPos2D.x();
672 const float middleBackY = middleBackPos2D.y();
674 const float endFrontX = endFrontPos2D.x();
675 const float endFrontY = endFrontPos2D.y();
677 primitivePlotter.drawArrow(middleBackX, middleBackY, endFrontX, endFrontY, attributeMap);
696 primitivePlotter.startGroup(attributeMap);
699 const CDCHit& hit = *ptrHit;
703 primitivePlotter.endGroup();
713 CDCTrajectory2D trajectory2D(pos.xy(), time, mom.xy(), charge);
714 draw(trajectory2D, attributeMap);
718 const AttributeMap& attributeMap)
720 draw(segment.getTrajectory2D(), attributeMap);
724 const AttributeMap& attributeMap)
726 draw(segmentTriple.getTrajectory3D().getTrajectory2D(), attributeMap);
731 draw(track.getStartTrajectory3D().getTrajectory2D(), attributeMap);
739 primitivePlotter.startGroup(attributeMap);
743 std::vector<std::array<float, 2>> points;
744 std::vector<std::array<float, 2>> tangents;
748 if (!recoHit->useInFit())
758 if (not fittedResult) {
759 B2WARNING(
"Skipping unfitted track point");
763 state.getPosMomCov(pos, mom, cov);
765 B2WARNING(
"Skipping state with strange pos, mom or cov");
774 points.push_back({{x, y}});
775 tangents.push_back({{px, py}});
777 primitivePlotter.drawCurve(points, tangents, attributeMap);
780 primitivePlotter.endGroup();