ATLAS Offline Software
Loading...
Searching...
No Matches
FastCaloSimCaloExtrapolation Class Reference

#include <FastCaloSimCaloExtrapolation.h>

Inheritance diagram for FastCaloSimCaloExtrapolation:
Collaboration diagram for FastCaloSimCaloExtrapolation:

Public Types

enum  SUBPOS { SUBPOS_MID = TFCSExtrapolationState::SUBPOS_MID , SUBPOS_ENT = TFCSExtrapolationState::SUBPOS_ENT , SUBPOS_EXT = TFCSExtrapolationState::SUBPOS_EXT }
enum  HITPOSITION { INSIDE , OUTSIDE , ON }

Public Member Functions

 FastCaloSimCaloExtrapolation (const std::string &t, const std::string &n, const IInterface *p)
 ~FastCaloSimCaloExtrapolation ()=default
virtual StatusCode initialize () override final
virtual StatusCode finalize () override final
virtual void extrapolate (TFCSExtrapolationState &result, const TFCSTruthState *truth, const std::vector< G4FieldTrack > &caloSteps) const override final
virtual void extrapolate (TFCSExtrapolationState &result, const TFCSTruthState *truth) const override final

Protected Member Functions

const IFastCaloSimGeometryHelperGetCaloGeometry () const
bool extrapolateToCylinder (const std::vector< G4FieldTrack > &caloSteps, float cylR, float cylZ, Amg::Vector3D &extPos, Amg::Vector3D &momDir) const
 Finds best extrapolation extPos from the caloSteps for a cylinder defined by radius cylR and half-length cylZ as well as corresponding momentum direction.
void extrapolateToID (TFCSExtrapolationState &result, const std::vector< G4FieldTrack > &caloSteps, const TFCSTruthState *truth) const
 Extrapolates to ID using three uniquely defined cylinder surfaces.
void extrapolateToLayers (TFCSExtrapolationState &result, const std::vector< G4FieldTrack > &caloSteps, const TFCSTruthState *truth) const
 Extrapolates to all other layers of the calorimeter.
void findPCA (float cylR, float cylZ, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2, Amg::Vector3D &PCA) const
 Finds Point of Closest Approach (PCA) on the cylinder defined by radius cylR and half-length cylZ of a line segment spanned by two hit positions to a cylinder.
void getIterativePCA (float cylR, float cylZ, Amg::Vector3D &BoundA, Amg::Vector3D &BoundB, Amg::Vector3D &PCA) const
 Finds PCA iteratively given two bounds A and B on a line segment, used for (rare) cases with no easy analytical solutions.
bool extrapolateWithIntersection (const std::vector< G4FieldTrack > &caloSteps, float cylR, float cylZ, Amg::Vector3D &extPos, Amg::Vector3D &momDir) const
 Extrapolates position on cylinder by finding intersections of subsequent hit positions, intersection is considered if we detect a travel through the surface with the line segment or we find a forward intersection (in the travel direction of the particle) which lies on the line segment, returns false if no such postion is found.
bool extrapolateWithPCA (const std::vector< G4FieldTrack > &caloSteps, float cylR, float cylZ, Amg::Vector3D &extPos, Amg::Vector3D &momDir) const
 Extrapolates to the cylinder using the PCA to the polygon spanned by the individual line segments from the caloSteps.
int whichIntersection (float cylR, float cylZ, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2, Amg::Vector3D &intersectionA, Amg::Vector3D intersectionB) const
 Returns ID of more sensible intersection between line segment spanned by hitPos1 and hitPos2 and cylinder.
int circleLineIntersection2D (float circR, Amg::Vector3D &pointA, Amg::Vector3D &pointB, Amg::Vector3D &intersectA, Amg::Vector3D &intersectB) const
 Analytically computes 2D intersections between circle of radius circR and (infinite) line spanned by pointA nad pointB.
int cylinderLineIntersection (float cylR, float cylZ, Amg::Vector3D &pointA, Amg::Vector3D &pointB, Amg::Vector3D &intersectA, Amg::Vector3D &intersectB) const
 Analytically computes the intersection between the (infinite) line defined by pointA and pointB and the cylinder cover (without endcaps).
CylinderIntersections getCylinderIntersections (float cylR, float cylZ, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2) const
 Analytically computes the intersection between the (infinite) line spanned by hitPos1 and hitPos2 with a cylinder.
void minmaxeta (int sample, double eta, double &mineta, double &maxeta) const
bool isCaloBarrel (int sample) const
double deta (int sample, double eta) const
double rzmid (int sample, double eta) const
double rzent (int sample, double eta) const
double rzext (int sample, double eta) const
double rmid (int sample, double eta) const
double rent (int sample, double eta) const
double rext (int sample, double eta) const
double zmid (int sample, double eta) const
double zent (int sample, double eta) const
double zext (int sample, double eta) const
double rpos (int sample, double eta, int subpos=CaloSubPos::SUBPOS_MID) const
double zpos (int sample, double eta, int subpos=CaloSubPos::SUBPOS_MID) const
double rzpos (int sample, double eta, int subpos=CaloSubPos::SUBPOS_MID) const

Static Protected Member Functions

static double getPointLineSegmentDistance (Amg::Vector3D &point, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2)
 Computes the distance between a point and the line segment spanned by hitPos1 and hitPos2.
static bool isOnSegment (Amg::Vector3D &point, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2)
 Returns true if point lies on the line segment spanned by hitPos1 and hitPos2, otherwise returns false.
static bool cylinderEndcapIntersection (float cylR, float cylZ, bool positiveEndcap, Amg::Vector3D &pointA, Amg::Vector3D &pointB, Amg::Vector3D &intersection)
 Computes intersection between the (infinite) line spanned by pointA and pointB with the positive (negative) endcap of a cylinder, returns true if intersection is found.
static bool doesTravelThroughSurface (float cylR, float cylZ, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2)
 Returns true if the line segment spanned by hitPos1 and hitPos2 crosses the cylinder surface, false otherwise.
static enum HITPOSITION whereOnCylinder (float cylR, float cylZ, Amg::Vector3D &hitPos)
 Checks if position of hitPos is inside, outside or on the cylinder bounds.
static Amg::Vector3D projectOnCylinder (float cylR, float cylZ, Amg::Vector3D &hitPos)
 Projects position hitPos onto the cylinder surface and returns projected position.

Protected Attributes

FloatArrayProperty m_CaloBoundaryR {this, "CaloBoundaryR", {1148.0,120.0,41.0}}
FloatArrayProperty m_CaloBoundaryZ {this, "CaloBoundaryZ", {3550.0,4587.0,4587.0}}
PublicToolHandle< IFastCaloSimCaloTransportationm_CaloTransportation {this, "CaloTransportation", "FastCaloSimCaloTransportation"}
PublicToolHandle< IFastCaloSimGeometryHelperm_CaloGeometryHelper {this, "CaloGeometryHelper", "FastCaloSimGeometryHelper"}

Detailed Description

Definition at line 31 of file FastCaloSimCaloExtrapolation.h.

Member Enumeration Documentation

◆ HITPOSITION

Enumerator
INSIDE 
OUTSIDE 
ON 

Definition at line 48 of file FastCaloSimCaloExtrapolation.h.

48 {
49 INSIDE, //hit position is inside cylinder bounds
50 OUTSIDE, //hit position is outside cylinder bounds
51 ON //hit position is on cylinder bounds
52 };

◆ SUBPOS

Constructor & Destructor Documentation

◆ FastCaloSimCaloExtrapolation()

FastCaloSimCaloExtrapolation::FastCaloSimCaloExtrapolation ( const std::string & t,
const std::string & n,
const IInterface * p )

Definition at line 43 of file FastCaloSimCaloExtrapolation.cxx.

44 : base_class(t,n,p)
45{
46}

◆ ~FastCaloSimCaloExtrapolation()

FastCaloSimCaloExtrapolation::~FastCaloSimCaloExtrapolation ( )
default

Member Function Documentation

◆ circleLineIntersection2D()

int FastCaloSimCaloExtrapolation::circleLineIntersection2D ( float circR,
Amg::Vector3D & pointA,
Amg::Vector3D & pointB,
Amg::Vector3D & intersectA,
Amg::Vector3D & intersectB ) const
protected

Analytically computes 2D intersections between circle of radius circR and (infinite) line spanned by pointA nad pointB.

Definition at line 561 of file FastCaloSimCaloExtrapolation.cxx.

561 {
562 //find intersections intA and intB with line spanned by pointA and pointB
563 //returns number of intersections
564 //assumes circle lays in xy plane
565
566 double dx, dy, A, B, C, det, t;
567
568 dx = pointB[Amg::x] - pointA[Amg::x];
569 dy = pointB[Amg::y] - pointA[Amg::y];
570
571 A = dx * dx + dy * dy;
572 B = 2 * (dx * pointA[Amg::x] + dy * pointA[Amg::y]);
573 C = pointA[Amg::x] * pointA[Amg::x] + pointA[Amg::y] * pointA[Amg::y] - circR * circR;
574
575 det = B * B - 4 * A * C;
576
577 if (A <= 0.0000001 || det < 0){
578 ATH_MSG_DEBUG("[circleLineIntersection2D] No intersections.");
579 return 0;
580 }
581 else if (std::abs(det) < 0.00001){
582 //one solution, tangential case.
583 t = -B / (2 * A);
584 intersectA = {pointA[Amg::x] + t * dx, pointA[Amg::y] + t * dy, pointA[Amg::z]};
585 ATH_MSG_DEBUG("[circleLineIntersection2D] One intersection at ("<<intersectA[Amg::x]<<","<<intersectA[Amg::y]<<","<<intersectA[Amg::z]<<").");
586 return 1;
587 }
588 else{
589 // two solutions
590 t = (-B + std::sqrt(det)) / (2 * A);
591 intersectA = {pointA[Amg::x] + t * dx, pointA[Amg::y] + t * dy, pointA[Amg::z]};
592 t = (-B - std::sqrt(det)) / (2 * A);
593 intersectB = {pointA[Amg::x] + t * dx, pointA[Amg::y] + t * dy, pointB[Amg::z]};
594 ATH_MSG_DEBUG("[circleLineIntersection2D] Two intersections at ("<<intersectA[Amg::x]<<","<<intersectA[Amg::y]<<","<<intersectA[Amg::z]<<") and at ("<<intersectB[Amg::x]<<","<<intersectB[Amg::y]<<","<<intersectB[Amg::z]<<").");
595 return 2;
596 }
597
598
599}
#define ATH_MSG_DEBUG(x)
struct color C

◆ cylinderEndcapIntersection()

bool FastCaloSimCaloExtrapolation::cylinderEndcapIntersection ( float cylR,
float cylZ,
bool positiveEndcap,
Amg::Vector3D & pointA,
Amg::Vector3D & pointB,
Amg::Vector3D & intersection )
staticprotected

Computes intersection between the (infinite) line spanned by pointA and pointB with the positive (negative) endcap of a cylinder, returns true if intersection is found.

Definition at line 768 of file FastCaloSimCaloExtrapolation.cxx.

768 {
769
770 //normal and point on endcap defines the plane
771 Amg::Vector3D pointOnEndcap;
772 Amg::Vector3D normal(0, 0, 1);
773 positiveEndcap ? pointOnEndcap = {0, 0, cylZ} : pointOnEndcap = {0, 0, -cylZ};
774 Amg::Vector3D hitDir = (pointB - pointA);
775
776 double denom = normal.dot(hitDir);
777 if (std::abs(denom) > 1e-6) {
778 double t = normal.dot(pointOnEndcap - pointB)/denom;
779 //compute intersection regardless of direction (t>0 or t<0)
780 intersection = pointB + t*hitDir;
781 Amg::Vector3D v = intersection - pointOnEndcap;
782
783 //check if intersection is within cylR bounds
784 return std::sqrt(v.dot(v)) <= cylR;
785
786 }
787
788 return false;
789
790 }
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
Eigen::Matrix< double, 3, 1 > Vector3D

◆ cylinderLineIntersection()

int FastCaloSimCaloExtrapolation::cylinderLineIntersection ( float cylR,
float cylZ,
Amg::Vector3D & pointA,
Amg::Vector3D & pointB,
Amg::Vector3D & intersectA,
Amg::Vector3D & intersectB ) const
protected

Analytically computes the intersection between the (infinite) line defined by pointA and pointB and the cylinder cover (without endcaps).

Definition at line 726 of file FastCaloSimCaloExtrapolation.cxx.

726 {
727
728 //projections of points spanning the line onto the xy plane
729 Amg::Vector3D projPointA(pointA[Amg::x], pointA[Amg::y], 0);
730 Amg::Vector3D projPointB(pointB[Amg::x], pointB[Amg::y], 0);
731 Amg::Vector3D projDiff = projPointA - projPointB;
732
733 //calculate distance from (0,0,0) to line spanned by projPointA and projPointB
734 double projDiffNorm2 = projDiff.dot(projDiff);
735 double t = projPointA.dot(projDiff) / projDiffNorm2;
736 double d2 = projPointA.dot(projPointA) - t*t*projDiffNorm2;
737
738 if(d2 < 0){
739 ATH_MSG_COND("[cylinderLineIntersection] Got negative distance (d2="<<d2<<"). Forcing to 0.", d2 > -0.001);
740 d2 = 0;
741 }
742
743 //if distance larger than cylinder radius then there are no intersection and we are done
744 if(d2 > cylR*cylR) return 0;
745
746 double k = std::sqrt((cylR*cylR - d2)/projDiffNorm2);
747
748 intersectA = pointA + (t+k)*(pointB - pointA);
749 intersectB = pointA + (t-k)*(pointB - pointA);
750
751 //check if intersection is outside z bounds
752 bool IntAisValid = (intersectA[Amg::z] <= cylZ && intersectA[Amg::z] >= -cylZ);
753 bool IntBisValid = (intersectB[Amg::z] <= cylZ && intersectB[Amg::z] >= -cylZ);
754
755 if(IntAisValid && IntBisValid) return 2;
756 else if(IntAisValid) return 1;
757 else if(IntBisValid){
758 intersectA = intersectB;
759 return 1;
760 }
761
762
763 return 0;
764
765}
#define ATH_MSG_COND(MSG, CONDITION)

◆ deta()

double FastCaloSimCaloExtrapolation::deta ( int sample,
double eta ) const
protected

Definition at line 876 of file FastCaloSimCaloExtrapolation.cxx.

877{
878 return GetCaloGeometry()->deta(sample, eta);
879}
Scalar eta() const
pseudorapidity method
const IFastCaloSimGeometryHelper * GetCaloGeometry() const
virtual double deta(int sample, double eta) const =0

◆ doesTravelThroughSurface()

bool FastCaloSimCaloExtrapolation::doesTravelThroughSurface ( float cylR,
float cylZ,
Amg::Vector3D & hitPos1,
Amg::Vector3D & hitPos2 )
staticprotected

Returns true if the line segment spanned by hitPos1 and hitPos2 crosses the cylinder surface, false otherwise.

Definition at line 862 of file FastCaloSimCaloExtrapolation.cxx.

862 {
863 //travel through surface in case one hit position is outside and the other outside of cylinder surface
864 return (whereOnCylinder(cylR, cylZ, hitPos1) == INSIDE) ^ (whereOnCylinder(cylR, cylZ, hitPos2) == INSIDE);
865}
static enum HITPOSITION whereOnCylinder(float cylR, float cylZ, Amg::Vector3D &hitPos)
Checks if position of hitPos is inside, outside or on the cylinder bounds.

◆ extrapolate() [1/2]

void FastCaloSimCaloExtrapolation::extrapolate ( TFCSExtrapolationState & result,
const TFCSTruthState * truth ) const
finaloverridevirtual

Definition at line 80 of file FastCaloSimCaloExtrapolation.cxx.

80 {
81
82 ATH_MSG_DEBUG("[extrapolate] Initializing transport of track through calorimeter system with ATLAS tracking tools.");
83 std::vector<G4FieldTrack> caloSteps = m_CaloTransportation -> transport(truth, false);
84 ATH_MSG_DEBUG("[extrapolate] Finalized transport of track through calorimeter system with ATLAS tracking tools.");
85
86 extrapolate(result, truth, caloSteps);
87}
virtual void extrapolate(TFCSExtrapolationState &result, const TFCSTruthState *truth, const std::vector< G4FieldTrack > &caloSteps) const override final
PublicToolHandle< IFastCaloSimCaloTransportation > m_CaloTransportation

◆ extrapolate() [2/2]

void FastCaloSimCaloExtrapolation::extrapolate ( TFCSExtrapolationState & result,
const TFCSTruthState * truth,
const std::vector< G4FieldTrack > & caloSteps ) const
finaloverridevirtual

Definition at line 68 of file FastCaloSimCaloExtrapolation.cxx.

68 {
69
70 ATH_MSG_DEBUG("[extrapolate] Initializing extrapolation to ID-Calo boundary");
71 extrapolateToID(result, caloSteps, truth);
72
73 ATH_MSG_DEBUG("[extrapolate] Initializing extrapolation to calorimeter layers");
74 extrapolateToLayers(result, caloSteps, truth);
75
76 ATH_MSG_DEBUG("[extrapolate] Extrapolation done");
77
78}
void extrapolateToID(TFCSExtrapolationState &result, const std::vector< G4FieldTrack > &caloSteps, const TFCSTruthState *truth) const
Extrapolates to ID using three uniquely defined cylinder surfaces.
void extrapolateToLayers(TFCSExtrapolationState &result, const std::vector< G4FieldTrack > &caloSteps, const TFCSTruthState *truth) const
Extrapolates to all other layers of the calorimeter.

◆ extrapolateToCylinder()

bool FastCaloSimCaloExtrapolation::extrapolateToCylinder ( const std::vector< G4FieldTrack > & caloSteps,
float cylR,
float cylZ,
Amg::Vector3D & extPos,
Amg::Vector3D & momDir ) const
protected

Finds best extrapolation extPos from the caloSteps for a cylinder defined by radius cylR and half-length cylZ as well as corresponding momentum direction.

Definition at line 233 of file FastCaloSimCaloExtrapolation.cxx.

233 {
234
235 if(caloSteps.size() == 1){
236 Amg::Vector3D hitPos = Amg::Hep3VectorToEigen(caloSteps.at(0).GetPosition());
237 ATH_MSG_DEBUG("[extrapolateWithPCA(R="<<cylR<<",Z="<<cylZ<<")] Extrapolating single hit position to surface.");
238 extPos = projectOnCylinder(cylR, cylZ, hitPos);
239 momDir = Amg::Hep3VectorToEigen(caloSteps.at(0).GetMomentum());
240 return true;
241 }
242
243 //if we do not find any good intersections, extrapolate to closest point on surface
244 bool foundHit = extrapolateWithIntersection(caloSteps, cylR, cylZ, extPos, momDir) ? true : extrapolateWithPCA(caloSteps, cylR, cylZ, extPos, momDir);
245
246 if(foundHit){
247 ATH_MSG_DEBUG("[extrapolateToCylinder(R="<<cylR<<",Z="<<cylZ<<")::END] Extrapolated to cylinder with R="<<cylR<<" and Z="<<cylZ<<" at ("<< extPos[Amg::x]<<","<<extPos[Amg::y]<<","<<extPos[Amg::z]<<")");
248 }
249 else{
250 //this is not expected to ever happen
251 ATH_MSG_DEBUG("(R="<<cylR<<", Z="<<cylZ<<"::END) Extrapolation to cylinder surface failed!");
252 }
253
254
255 return foundHit;
256
257}
bool extrapolateWithPCA(const std::vector< G4FieldTrack > &caloSteps, float cylR, float cylZ, Amg::Vector3D &extPos, Amg::Vector3D &momDir) const
Extrapolates to the cylinder using the PCA to the polygon spanned by the individual line segments fro...
static Amg::Vector3D projectOnCylinder(float cylR, float cylZ, Amg::Vector3D &hitPos)
Projects position hitPos onto the cylinder surface and returns projected position.
bool extrapolateWithIntersection(const std::vector< G4FieldTrack > &caloSteps, float cylR, float cylZ, Amg::Vector3D &extPos, Amg::Vector3D &momDir) const
Extrapolates position on cylinder by finding intersections of subsequent hit positions,...
Amg::Vector3D Hep3VectorToEigen(const CLHEP::Hep3Vector &CLHEPvector)
Converts a CLHEP-based CLHEP::Hep3Vector into an Eigen-based Amg::Vector3D.

◆ extrapolateToID()

void FastCaloSimCaloExtrapolation::extrapolateToID ( TFCSExtrapolationState & result,
const std::vector< G4FieldTrack > & caloSteps,
const TFCSTruthState * truth ) const
protected

Extrapolates to ID using three uniquely defined cylinder surfaces.

Definition at line 90 of file FastCaloSimCaloExtrapolation.cxx.

90 {
91
92 ATH_MSG_DEBUG("Start extrapolateToID()");
93
94 //pT threshold of truth particles over which extrapolation failures will be printed as warnings
95 const float transverseMomWarningLimit = 500;
96
97 //initialize values
98 result.set_IDCaloBoundary_eta(-999.);
99 result.set_IDCaloBoundary_phi(-999.);
100 result.set_IDCaloBoundary_r(0);
101 result.set_IDCaloBoundary_z(0);
102 result.set_IDCaloBoundary_AngleEta(-999.);
103 result.set_IDCaloBoundary_Angle3D(-999.);
104
105 //magnitude of extrapolated position
106 double extPosDist = -1;
107
108 for (unsigned int surfID = 0; surfID<3; surfID++){
109
110 double R = m_CaloBoundaryR.value().at(surfID);
111 double Z = m_CaloBoundaryZ.value().at(surfID);
112
113 ATH_MSG_DEBUG("[ExtrapolateToID] Extrapolating to ID-Calo boundary with ID="<<surfID<<" R="<<R<<" Z="<<Z);
114
115 //extrapolated position and momentum direction at IDCaloBoundary
116 Amg::Vector3D extPos, momDir;
117
118 //main extrapolation call
119 if(!extrapolateToCylinder(caloSteps, R, Z, extPos, momDir)) continue;
120
121 double tolerance = 0.001;
122
123 //test if z inside previous cylinder within some tolerance
124 ATH_MSG_DEBUG("[ExtrapolateToID] Testing condition 1: hit z="<< extPos[Amg::z]);
125 if(surfID > 0 && std::abs(extPos[Amg::z]) < m_CaloBoundaryZ[surfID-1] - tolerance) continue;
126 ATH_MSG_DEBUG("[ExtrapolateToID] Passed condition 1.");
127
128 //test if r inside next cylinder within some tolerance
129 ATH_MSG_DEBUG("[ExtrapolateToID] Testing condition 2: hit r="<< extPos.perp());
130 if(surfID < m_CaloBoundaryR.size()-1 && extPos.perp() < m_CaloBoundaryR[surfID + 1] - tolerance) continue;
131 ATH_MSG_DEBUG("[ExtrapolateToID] Passed condition 2.");
132
133 ATH_MSG_DEBUG("[ExtrapolateToID] Testing condition 3: hit magnitude="<< extPos.mag());
134 if(extPosDist >= 0 && extPos.mag() > extPosDist) continue;
135 ATH_MSG_DEBUG("[ExtrapolateToID] Passed condition 3.");
136
137 extPosDist = extPos.mag();
138
139 result.set_IDCaloBoundary_eta(extPos.eta());
140 result.set_IDCaloBoundary_phi(extPos.phi());
141 result.set_IDCaloBoundary_r(extPos.perp());
142 result.set_IDCaloBoundary_z(extPos[Amg::z]);
143
144 ATH_MSG_DEBUG("[ExtrapolateToID] Setting IDCaloBoundary to eta="<<extPos.eta()<<" phi="<<extPos.phi()<< " r="<<extPos.perp()<<" z="<<extPos.z());
145
146 //compute angle between extrapolated position vector and momentum at IDCaloBoundary
147 //can be used to correct shower shapes for particles which do not originate from {0,0,0}
148 double Angle3D = Amg::angle(extPos, momDir);
149 double AngleEta = extPos.theta() - momDir.theta();
150 result.set_IDCaloBoundary_AngleEta(AngleEta);
151 result.set_IDCaloBoundary_Angle3D(Angle3D);
152
153 } //end of loop over surfaces
154
155 if(result.IDCaloBoundary_eta() == -999) ATH_MSG_COND("[ExtrapolateToID] Failed extrapolation to ID-Calo boundary. \n[ExtrapolateToID] Particle with truth vertex at (" << truth->vertex().X() <<","<<truth->vertex().Y()<<","<<truth->vertex().Z()<<")"<<" with"<<" PdgId="<<truth->pdgid()<<" pT="<<truth->Pt()<<" eta="<<truth->Eta()<<" phi="<<truth->Phi()<<" E="<<truth->E()<<" Ekin_off="<<truth->Ekin_off(), truth->Pt() < transverseMomWarningLimit);
156
157 ATH_MSG_DEBUG("[ExtrapolateToID] End extrapolateToID()");
158
159}
bool extrapolateToCylinder(const std::vector< G4FieldTrack > &caloSteps, float cylR, float cylZ, Amg::Vector3D &extPos, Amg::Vector3D &momDir) const
Finds best extrapolation extPos from the caloSteps for a cylinder defined by radius cylR and half-len...
int pdgid() const
const TLorentzVector & vertex() const
double Ekin_off() const
double angle(const Amg::Vector3D &v1, const Amg::Vector3D &v2)
calculates the opening angle between two vectors
double R(const INavigable4Momentum *p1, const double v_eta, const double v_phi)
constexpr double tolerance

◆ extrapolateToLayers()

void FastCaloSimCaloExtrapolation::extrapolateToLayers ( TFCSExtrapolationState & result,
const std::vector< G4FieldTrack > & caloSteps,
const TFCSTruthState * truth ) const
protected

Extrapolates to all other layers of the calorimeter.

Definition at line 162 of file FastCaloSimCaloExtrapolation.cxx.

163{
164 ATH_MSG_DEBUG("[extrapolateToLayers] Start extrapolate");
165
166 //pT threshold of truth particles over which extrapolation failures will be printed as warnings
167 const float transverseMomWarningLimit = 500;
168
170 // Start calo extrapolation
172
173 //only continue if inside the calo
174 if(std::abs(result.IDCaloBoundary_eta()) < 6){
175 //now try to extrapolate to all calo layers that contain energy
177 for(int subpos=SUBPOS_MID; subpos<=SUBPOS_EXT; ++subpos){
178
179 float cylR, cylZ;
180 if(isCaloBarrel(sample)){
181 cylR = std::abs(rpos(sample, result.IDCaloBoundary_eta(), subpos));
182 //EMB0 - EMB3 use z position of EME1 front end surface for extrapolation
183 //else extrapolate to cylinder with symmetrized maximum Z bounds
184 //set eta to a dummy value of 1000 and -1000 to force detector side
185 if(sample < 4) cylZ = result.IDCaloBoundary_eta() > 0 ? std::abs(zpos(5, 1000, 1)) : std::abs(zpos(5, -1000, 1));
186 else cylZ = 0.5*(std::abs(zpos(sample, 1000, subpos)) + std::abs(zpos(sample, -1000, subpos)));
187 }
188 else{
189 //if we are not at barrel surface, extrapolate to cylinder with maximum R to reduce extrapolation length
190 cylZ = std::abs(zpos(sample, result.IDCaloBoundary_eta(), subpos));
191 //calculate radius of cylinder we will extrapolate to
192 double mineta, maxeta, eta;
193 minmaxeta(sample, result.IDCaloBoundary_eta(), mineta, maxeta);
194 //get eta where we will look up the layer radius
195 eta = result.IDCaloBoundary_eta() > 0 ? mineta : maxeta;
196 //calculate azimuthal angle from pseudorapidity
197 double theta = 2*std::atan(std::exp(-eta));
198 //calculate maximum R of last cell of layer from z and theta
199 cylR = std::abs(cylZ*std::sqrt((1/(std::cos(theta)*std::cos(theta))) - 1));
200 }
201
202 Amg::Vector3D extPos, momDir;
203 if(extrapolateToCylinder(caloSteps, cylR, cylZ, extPos, momDir)){
204
205 //scale the extrapolation to fit the radius of the cylinder in the case of barrel and scale extrapolation to fit z component in case of endcap layer
206 //scale is only non-unitary in case we extrapolate to the endcaps of the cylinder for barrel and in case we extrapolate to cover for endcaps
207 //this will keep phi, eta intact and only scale r and z to fit a sensible position on the cylinder
208 double scale = 1;
209 if (isCaloBarrel(sample) && std::abs(extPos.perp()) > 1e-6) scale = cylR / extPos.perp();
210 else if (!isCaloBarrel(sample) && std::abs(extPos.z()) > 1e-6) scale = cylZ / std::abs(extPos.z());
211 //scale extrapolated position accordingly
212 extPos = scale * extPos;
213
214 result.set_OK(sample, subpos, true);
215 result.set_phi(sample, subpos, extPos.phi());
216 result.set_z (sample, subpos, extPos.z());
217 result.set_eta(sample, subpos, extPos.eta());
218 result.set_r (sample, subpos, extPos.perp());
219 }
220 else{
221 ATH_MSG_COND(" [extrapolateToLayers] Extrapolation to cylinder failed. Sample="<<sample<<" subpos="<<subpos<<" eta="<<result.IDCaloBoundary_eta()<<" phi="<<result.IDCaloBoundary_phi()<<" r="<<result.IDCaloBoundary_r()<<" z="<<result.IDCaloBoundary_z(), truth->Pt() < transverseMomWarningLimit);
222 }
223 } //for pos
224 } //for sample
225 } //inside calo
226
227 else ATH_MSG_COND("[extrapolateToLayers] Ups. Not inside calo. result.IDCaloBoundary_eta()="<<result.IDCaloBoundary_eta()<< "\n[extrapolateToLayers] Particle with truth vertex at (" << truth->vertex().X() <<","<<truth->vertex().Y()<<","<<truth->vertex().Z()<<")"<<" with"<<" PdgId="<<truth->pdgid()<<" pT="<<truth->Pt()<<" eta="<<truth->Eta()<<" phi="<<truth->Phi()<<" E="<<truth->E()<<" Ekin_off="<<truth->Ekin_off(), truth->Pt() < transverseMomWarningLimit);
228
229
230 ATH_MSG_DEBUG("[extrapolateToLayers] End extrapolateToLayers()");
231}
Scalar theta() const
theta method
double zpos(int sample, double eta, int subpos=CaloSubPos::SUBPOS_MID) const
double rpos(int sample, double eta, int subpos=CaloSubPos::SUBPOS_MID) const
void minmaxeta(int sample, double eta, double &mineta, double &maxeta) const

◆ extrapolateWithIntersection()

bool FastCaloSimCaloExtrapolation::extrapolateWithIntersection ( const std::vector< G4FieldTrack > & caloSteps,
float cylR,
float cylZ,
Amg::Vector3D & extPos,
Amg::Vector3D & momDir ) const
protected

Extrapolates position on cylinder by finding intersections of subsequent hit positions, intersection is considered if we detect a travel through the surface with the line segment or we find a forward intersection (in the travel direction of the particle) which lies on the line segment, returns false if no such postion is found.

Definition at line 260 of file FastCaloSimCaloExtrapolation.cxx.

260 {
261
262 ATH_MSG_DEBUG("[extrapolateWithIntersection(R="<<cylR<<",Z="<<cylZ<<")] Checking for cylinder intersections of line segments.");
263
264 //counter for number of computed extrapolations, does not count cases of rejected extrapolations due to close by hit positions
265 unsigned int nExtrapolations = 0;
266 for (size_t hitID = 1; hitID < caloSteps.size(); hitID++){
267 //initialize intersection result variables
268 //get current and consecutive hit position and build hitLine
269 Amg::Vector3D hitPos1 = Amg::Hep3VectorToEigen(caloSteps.at(hitID-1).GetPosition());
270 Amg::Vector3D hitPos2 = Amg::Hep3VectorToEigen(caloSteps.at(hitID).GetPosition());
271 Amg::Vector3D hitDir = hitPos2 - hitPos1;
272
273 ATH_MSG_DEBUG("[extrapolateWithIntersection(R="<<cylR<<",Z="<<cylZ<<")] Considering line segment between ("<<hitPos1[Amg::x]<<","<<hitPos1[Amg::y]<<","<<hitPos1[Amg::z]<<") and ("
274 <<hitPos2[Amg::x]<<","<<hitPos2[Amg::y]<<","<<hitPos2[Amg::z]<<")");
275 //get position of the hit positions on the cylinder
276 HITPOSITION cylPosHit1 = whereOnCylinder(cylR, cylZ, hitPos1);
277 HITPOSITION cylPosHit2 = whereOnCylinder(cylR, cylZ, hitPos2);
278
279 //check if one of the hit positions already lays on the cylinder surface
280 if(cylPosHit1 == ON || cylPosHit2 == ON){
281 extPos = cylPosHit1 == ON ? hitPos1 : hitPos2;
282 momDir = cylPosHit1 == ON ? Amg::Hep3VectorToEigen(caloSteps.at(hitID-1).GetMomentum()) : Amg::Hep3VectorToEigen(caloSteps.at(hitID).GetMomentum());
283 ATH_MSG_DEBUG("[extrapolateWithIntersection(R="<<cylR<<",Z="<<cylZ<<")] Hit position already on cylinder surface.");
284 return true;
285 }
286
287 //do not try to extrapolate with intersections if the hit position are very close together
288 if(hitDir.norm() < 0.01) continue;
289
290 //get intersections through cylinder
291 CylinderIntersections intersections = getCylinderIntersections(cylR, cylZ, hitPos1, hitPos2);
292 nExtrapolations++;
293
294 Amg::Vector3D selectedIntersection(0, 0, 0);
295
296 //select the best intersection
297 if(intersections.number == 1) selectedIntersection = intersections.first;
298 else if(intersections.number > 1) selectedIntersection = whichIntersection(cylR, cylZ, hitPos1, hitPos2, intersections.first, intersections.second) == 0 ?
299 intersections.first : intersections.second;
300
301 if(intersections.number > 0){
302
303 bool isForwardExtrapolation = (selectedIntersection[Amg::x] - hitPos1[Amg::x]) / (hitPos2[Amg::x] - hitPos1[Amg::x]) >= 0;
304 bool travelThroughSurface = doesTravelThroughSurface(cylR, cylZ, hitPos1, hitPos2);
305
306 //do not allow for backward extrapolation except in the case of first two (distinguishable) hit positions outside cylinder
307 //and in the case we detect a travel though the surface
308 if(nExtrapolations > 1 && !isForwardExtrapolation && !travelThroughSurface) continue;
309
310 //check if the intersection between infinite line and cylinder lays on segment spanned by hit positions
311 bool intersectionOnSegment = isOnSegment(selectedIntersection, hitPos1, hitPos2);
312 //check if both hit positions lay outside of the cylinder
313 bool hitPosOutside = cylPosHit1 == OUTSIDE && cylPosHit2 == OUTSIDE;
314
315 //we found our extrapolated hit position in case that either
316 //we detect that the line segment crosses the surface of the cylinder
317 //the intersection between the infinite lines and the cylinder lays on the line segment
318 //both hit positions are outside of the cylinder and there is a backwards extrapolation for the first two hit positions
319 //if this is not the case for any of the hit position pairs we will use the last two hit position for the linear extrapolation
320 //if these do not have any intersection, then we will pass back to extrapolateWithPCA
321 if(travelThroughSurface || intersectionOnSegment || (hitPosOutside && !isForwardExtrapolation && nExtrapolations == 1) || caloSteps.size()-1 == hitID){
322 //take momentum direction of hit position closest to cylinder surface
323 //alternatively one could also take the extrapolated direction normDir = hitPos2 - hitPos1
324 double distHitPos1 = (hitPos1 - projectOnCylinder(cylR, cylZ, hitPos1)).norm();
325 double distHitPos2 = (hitPos2 - projectOnCylinder(cylR, cylZ, hitPos2)).norm();
326 momDir = distHitPos1 < distHitPos2 ? Amg::Hep3VectorToEigen(caloSteps.at(hitID-1).GetMomentum()) : Amg::Hep3VectorToEigen(caloSteps.at(hitID).GetMomentum());
327 extPos = selectedIntersection;
328 return true;
329 }
330 ATH_MSG_DEBUG("[extrapolateWithIntersection(R="<<cylR<<",Z="<<cylZ<<")] Extrapolated position at ("<<selectedIntersection[Amg::x]<<","<<selectedIntersection[Amg::y]<<","<<selectedIntersection[Amg::z]<<")");
331 }
332 } //end of loop over hit positions
333
334 return false;
335}
CylinderIntersections getCylinderIntersections(float cylR, float cylZ, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2) const
Analytically computes the intersection between the (infinite) line spanned by hitPos1 and hitPos2 wit...
int whichIntersection(float cylR, float cylZ, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2, Amg::Vector3D &intersectionA, Amg::Vector3D intersectionB) const
Returns ID of more sensible intersection between line segment spanned by hitPos1 and hitPos2 and cyli...
static bool doesTravelThroughSurface(float cylR, float cylZ, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2)
Returns true if the line segment spanned by hitPos1 and hitPos2 crosses the cylinder surface,...
static bool isOnSegment(Amg::Vector3D &point, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2)
Returns true if point lies on the line segment spanned by hitPos1 and hitPos2, otherwise returns fals...
mapped_type at(key_type key) const
Look up an element in the map.

◆ extrapolateWithPCA()

bool FastCaloSimCaloExtrapolation::extrapolateWithPCA ( const std::vector< G4FieldTrack > & caloSteps,
float cylR,
float cylZ,
Amg::Vector3D & extPos,
Amg::Vector3D & momDir ) const
protected

Extrapolates to the cylinder using the PCA to the polygon spanned by the individual line segments from the caloSteps.

Definition at line 338 of file FastCaloSimCaloExtrapolation.cxx.

338 {
339
340 bool foundHit = false;
341 ATH_MSG_DEBUG("[extrapolateWithPCA(R="<<cylR<<",Z="<<cylZ<<")] No forward intersections with cylinder surface. Extrapolating to closest point on surface.");
342
343 //here we also need to consider distances from line segments to the cylinder
344 double minDistToSurface = 100000;
345 for (size_t hitID = 1; hitID < caloSteps.size(); hitID++){
346
347 Amg::Vector3D hitPos1 = Amg::Hep3VectorToEigen(caloSteps.at(hitID-1).GetPosition());
348 Amg::Vector3D hitPos2 = Amg::Hep3VectorToEigen(caloSteps.at(hitID).GetPosition());
349
350 ATH_MSG_DEBUG("[extrapolateWithPCA(R="<<cylR<<",Z="<<cylZ<<")] Considering line segment between ("<<hitPos1[Amg::x]<<","<<hitPos1[Amg::y]<<","<<hitPos1[Amg::z]<<") and ("<<hitPos2[Amg::x]<<","<<hitPos2[Amg::y]<<","<<hitPos2[Amg::z]<<")");
351
352 Amg::Vector3D PCA;
353 //find the point of closest approach (PCA) to the cylinder on the line segment
354 findPCA(cylR, cylZ, hitPos1, hitPos2, PCA);
355 //compute distance between PCA and cylinder
356 Amg::Vector3D cylinderSurfacePCA = projectOnCylinder(cylR, cylZ, PCA);
357 double tmpMinDistToSurface = (PCA - cylinderSurfacePCA).norm();
358
359 ATH_MSG_DEBUG("[extrapolateWithPCA(R="<<cylR<<",Z="<<cylZ<<")] Extrapolated line segment to ("<<cylinderSurfacePCA[Amg::x]<<","<<cylinderSurfacePCA[Amg::y]<<","<<cylinderSurfacePCA[Amg::z]<<") with distance "<<tmpMinDistToSurface);
360
361 if(tmpMinDistToSurface < minDistToSurface){
362 foundHit = true;
363 extPos = cylinderSurfacePCA;
364 //take momentum direction of hit position closest to cylinder surface
365 //alternatively one could also take the extrapolated direction normDir = hitPos2 - hitPos1
366 double distHitPos1 = (hitPos1 - projectOnCylinder(cylR, cylZ, hitPos1)).norm();
367 double distHitPos2 = (hitPos2 - projectOnCylinder(cylR, cylZ, hitPos2)).norm();
368 momDir = distHitPos1 < distHitPos2 ? Amg::Hep3VectorToEigen(caloSteps.at(hitID-1).GetMomentum()) : Amg::Hep3VectorToEigen(caloSteps.at(hitID).GetMomentum());
369
370 minDistToSurface = tmpMinDistToSurface;
371 }
372 } //end over loop of hit postions
373
374 return foundHit;
375}
void findPCA(float cylR, float cylZ, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2, Amg::Vector3D &PCA) const
Finds Point of Closest Approach (PCA) on the cylinder defined by radius cylR and half-length cylZ of ...

◆ finalize()

StatusCode FastCaloSimCaloExtrapolation::finalize ( )
finaloverridevirtual

Definition at line 62 of file FastCaloSimCaloExtrapolation.cxx.

62 {
63 ATH_MSG_INFO( "Finalizing FastCaloSimCaloExtrapolation" );
64 return StatusCode::SUCCESS;
65}
#define ATH_MSG_INFO(x)

◆ findPCA()

void FastCaloSimCaloExtrapolation::findPCA ( float cylR,
float cylZ,
Amg::Vector3D & hitPos1,
Amg::Vector3D & hitPos2,
Amg::Vector3D & PCA ) const
protected

Finds Point of Closest Approach (PCA) on the cylinder defined by radius cylR and half-length cylZ of a line segment spanned by two hit positions to a cylinder.

Definition at line 378 of file FastCaloSimCaloExtrapolation.cxx.

378 {
379 //in the following we will try to find the closest point-of-approach (PCA) to the cylinder on the line segment
380 //hit direction
381 Amg::Vector3D hitDir = hitPos2 - hitPos1;
382
383 //project both hit positions onto the cylinder
384 Amg::Vector3D projCylinderHitPos1 = projectOnCylinder(cylR, cylZ, hitPos1);
385 Amg::Vector3D projCylinderHitPos2 = projectOnCylinder(cylR, cylZ, hitPos2);
386 //direction of line spanned by the two projected points on the cylinder surface
387 Amg::Vector3D cylinderProjDir = projCylinderHitPos2 - projCylinderHitPos1;
388
389 //CASE A: projections on the cylinder are close enough, take one of the hit positions as PCA
390 if(cylinderProjDir.norm() < 0.0001) {PCA = hitPos1; return;};
391
392 //CASE B: we are outside the Z bounds of the cylinder
393 if((hitPos1[Amg::z] > cylZ || hitPos1[Amg::z] < -cylZ) || (hitPos2[Amg::z] > cylZ || hitPos2[Amg::z] < -cylZ)){
394
395 //calculate PCA to point on endcap
396 Amg::Vector3D cylZEndcap(0, 0, cylZ);
397 bool isParallelToEndcap = std::abs(hitPos1[Amg::z] - hitPos2[Amg::z]) < 0.00001;
398
399 //Check if parallel to endcap plane
400 if(isParallelToEndcap){
401
402 //if both inside there are infinite solutions take one in the middle
403 Amg::Vector3D intersectA, intersectB;
404 intersectA.setZero();
405 intersectB.setZero();
406 int nIntersections = circleLineIntersection2D(cylR, hitPos1, hitPos2, intersectA, intersectB);
407
408 if(nIntersections == 2){
409
410 bool IntAOnSegment = isOnSegment(intersectA, hitPos1, hitPos2);
411 bool IntBOnSegment = isOnSegment(intersectB, hitPos1, hitPos2);
412
413 if(IntAOnSegment && IntBOnSegment) PCA = intersectA + 0.5*(intersectB-intersectA);
414 else if(IntAOnSegment) PCA = hitPos1.perp() <= cylR ? intersectA + 0.5*(hitPos1 - intersectA) : intersectA + 0.5*(hitPos2 - intersectA);
415 else if(IntBOnSegment) PCA = hitPos1.perp() <= cylR ? intersectB + 0.5*(hitPos1 - intersectB) : intersectB + 0.5*(hitPos2 - intersectB);
416 //intersections are not on line segment, i.e. line segment is within extended cylinder
417 else PCA = hitPos1 + 0.5*hitDir;
418
419 }
420 else if(!intersectA.isZero() || !intersectB.isZero()){
421 //this can only happen if the extended line is tangetial to the cylinder
422 //if intersection lays on segment PCA will be intersection, if not it will be the corresponding end points
423 Amg::Vector3D intersect = intersectA.isZero() ? intersectB : intersectA;
424 Amg::Vector3D hitPos = (hitPos1 - intersect).norm() < (hitPos2 - intersect).norm() ? hitPos1 : hitPos2;
425 bool IntOnSegment = isOnSegment(intersectA, hitPos1, hitPos2);
426 PCA = IntOnSegment ? intersect : hitPos;
427
428 }
429 else{
430 //line segment is outside extended cylinder
431 //PCA corresponds to closest distance to center {0, 0, cylZ}
432 Amg::Vector3D infLinePCA = hitPos1 + ((cylZEndcap-hitPos1).dot(hitDir)/hitDir.dot(hitDir))*(hitDir);
433
434 if(isOnSegment(infLinePCA, hitPos1, hitPos2)) PCA = infLinePCA;
435 else PCA = (hitPos1 - infLinePCA).norm() < (hitPos2 - infLinePCA).norm() ? hitPos1 : hitPos2;
436
437 }
438 }
439
440 else{
441
442 //figure out all other cases iteratively beginning with BoundA and BoundB
443 Amg::Vector3D BoundA, BoundB;
444 //this is point on line closest to {0, 0, cylZ}, always on segment
445 double t = ((cylZEndcap-hitPos1).dot(hitDir)/hitDir.dot(hitDir));
446 BoundA = t <= 0 ? hitPos1 : (t >= 1 ? hitPos2 : hitPos1 + t*hitDir);
447
448 //calculate intersection point of line segment and endcap plane and project intersection onto cylinder
449 //check if t is between 0 and 1, if not, take hitpos as starting bound
450 t = (cylZ-hitPos1[Amg::z]) / hitDir[Amg::z];
451 BoundB = t <= 0 ? hitPos1 : (t >= 1 ? hitPos2 : hitPos1 + t*hitDir);
452 //looks for the PCA iteratively in cases there is no easy analytical solution
453 getIterativePCA(cylR, cylZ, BoundA, BoundB, PCA);
454
455 }
456
457 return;
458 }
459
460 //CASE C: we are inside the Z bounds of the cylinder
461 //construct Z axis as straight line surface
462 Trk::StraightLineSurface line(Amg::Transform3D(Trk::s_idTransform), 0, cylZ);
463 //compute point of closest approach to z axis
464 //this is analogous to finding the PCA of two 3D lines
465 Trk::Intersection PCACylBounds = line.straightLineIntersection(hitPos1, hitDir.unit(), false, true);
466
467 double distSurfHit1 = (projCylinderHitPos1 - hitPos1).norm();
468 double distSurfHit2 = (projCylinderHitPos2 - hitPos2).norm();
469
470 //take PCA on line in case it lays on segment, otherwise take closest hit position to surface
471 PCA = isOnSegment(PCACylBounds.position, hitPos1, hitPos2) ? PCACylBounds.position : (distSurfHit1 < distSurfHit2 ? hitPos1 : hitPos2);
472
473}
void getIterativePCA(float cylR, float cylZ, Amg::Vector3D &BoundA, Amg::Vector3D &BoundB, Amg::Vector3D &PCA) const
Finds PCA iteratively given two bounds A and B on a line segment, used for (rare) cases with no easy ...
int circleLineIntersection2D(float circR, Amg::Vector3D &pointA, Amg::Vector3D &pointB, Amg::Vector3D &intersectA, Amg::Vector3D &intersectB) const
Analytically computes 2D intersections between circle of radius circR and (infinite) line spanned by ...
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
Eigen::Affine3d Transform3D
static const Amg::Transform3D s_idTransform
idendity transformation
Amg::Vector3D position

◆ GetCaloGeometry()

const IFastCaloSimGeometryHelper * FastCaloSimCaloExtrapolation::GetCaloGeometry ( ) const
inlineprotected

Definition at line 59 of file FastCaloSimCaloExtrapolation.h.

59{return &(*m_CaloGeometryHelper);};

◆ getCylinderIntersections()

CylinderIntersections FastCaloSimCaloExtrapolation::getCylinderIntersections ( float cylR,
float cylZ,
Amg::Vector3D & hitPos1,
Amg::Vector3D & hitPos2 ) const
protected

Analytically computes the intersection between the (infinite) line spanned by hitPos1 and hitPos2 with a cylinder.

Definition at line 645 of file FastCaloSimCaloExtrapolation.cxx.

645 {
646 //calculates intersection of infinite line with cylinder --> can have 0 or 2 intersections
647 CylinderIntersections intersections;
648
649 //look for intersections with the cover of the cylinder
650 unsigned int nCoverIntersections = cylinderLineIntersection(cylR, cylZ, hitPos1, hitPos2, intersections.first, intersections.second);
651 if(nCoverIntersections == 2){
652 ATH_MSG_DEBUG("[getCylinderIntersections(R="<<cylR<<",Z="<<cylZ<<")] Found two cylinder intersections through cylinder cover.");
653 intersections.number = 2;
654 return intersections;
655 }
656 else if (nCoverIntersections == 1){
657
658 Amg::Vector3D positiveEndcapIntersection, negativeEndcapIntersection;
659 bool IsPositiveEndcapIntersection = cylinderEndcapIntersection(cylR, cylZ, true, hitPos1, hitPos2, positiveEndcapIntersection);
660 bool IsNegativeEndcapIntersection = cylinderEndcapIntersection(cylR, cylZ, false, hitPos1, hitPos2, negativeEndcapIntersection);
661
662 if(IsPositiveEndcapIntersection && IsNegativeEndcapIntersection){
663 //if we have a cover intersection we only expect one additional endcap intersection
664 //both endcap intersections can be valid in case the intersection is at the edge of the cylinder cover and endcap
665 //in that case take the endcap intersection which is further away from the cylinder cover intersection to prevent taking the same intersection twice
666 ATH_MSG_DEBUG("[getCylinderIntersections(R="<<cylR<<",Z="<<cylZ<<")] Found intersection through cylinder cover and both endcaps. Intersection seems to be at edge of cover and endcap.");
667 intersections.second = (positiveEndcapIntersection - intersections.first).norm() > (negativeEndcapIntersection - intersections.first).norm() ? positiveEndcapIntersection : negativeEndcapIntersection;
668 intersections.number = 2;
669 }
670 else if(IsPositiveEndcapIntersection) {
671 ATH_MSG_DEBUG("[getCylinderIntersections(R="<<cylR<<",Z="<<cylZ<<")] Found intersection through cylinder cover and positive endcap.");
672 intersections.second = positiveEndcapIntersection;
673 intersections.number = 2;
674 }
675 else if(IsNegativeEndcapIntersection) {
676 ATH_MSG_DEBUG("[getCylinderIntersections(R="<<cylR<<",Z="<<cylZ<<")] Found intersection through cylinder cover and negative endcap.");
677 intersections.second = negativeEndcapIntersection;
678 intersections.number = 2;
679 }
680 else{
681 //line is tangential to cylinder cover
682 ATH_MSG_DEBUG("[getCylinderIntersections(R="<<cylR<<",Z="<<cylZ<<")] Found single intersection through cylinder cover.");
683 intersections.number = 1;
684 }
685
686 }
687 else{
688 //no cylinder cover intersections
689 Amg::Vector3D positiveEndcapIntersection, negativeEndcapIntersection;
690 bool IsPositiveEndcapIntersection = cylinderEndcapIntersection(cylR, cylZ, true, hitPos1, hitPos2, positiveEndcapIntersection);
691 bool IsNegativeEndcapIntersection = cylinderEndcapIntersection(cylR, cylZ, false, hitPos1, hitPos2, negativeEndcapIntersection);
692
693 if(IsPositiveEndcapIntersection && IsNegativeEndcapIntersection){
694 ATH_MSG_DEBUG("[getCylinderIntersections(R="<<cylR<<",Z="<<cylZ<<")] Found intersections through both endcaps.");
695 intersections.first = positiveEndcapIntersection;
696 intersections.second = negativeEndcapIntersection;
697 intersections.number = 2;
698 }
699 else if(IsPositiveEndcapIntersection) {
700 //dont expect this to ever happen
701 ATH_MSG_DEBUG("[getCylinderIntersections(R="<<cylR<<",Z="<<cylZ<<")] Found single intersection through positive endcap. This should not happen.");
702 intersections.first = positiveEndcapIntersection;
703 intersections.number = 1;
704 }
705 else if(IsNegativeEndcapIntersection) {
706 //dont expect this to ever happen
707 ATH_MSG_DEBUG("[getCylinderIntersections(R="<<cylR<<",Z="<<cylZ<<")] Found single intersection through negative endcap. This should not happen.");
708 intersections.first = negativeEndcapIntersection;
709 intersections.number = 1;
710 }
711 else{
712 ATH_MSG_DEBUG("[getCylinderIntersections(R="<<cylR<<",Z="<<cylZ<<")] Found no cylinder intersections.");
713 //no intersections at all
714 intersections.number = 0;
715
716 }
717 }
718
719 return intersections;
720
721
722}
int cylinderLineIntersection(float cylR, float cylZ, Amg::Vector3D &pointA, Amg::Vector3D &pointB, Amg::Vector3D &intersectA, Amg::Vector3D &intersectB) const
Analytically computes the intersection between the (infinite) line defined by pointA and pointB and t...
static bool cylinderEndcapIntersection(float cylR, float cylZ, bool positiveEndcap, Amg::Vector3D &pointA, Amg::Vector3D &pointB, Amg::Vector3D &intersection)
Computes intersection between the (infinite) line spanned by pointA and pointB with the positive (neg...

◆ getIterativePCA()

void FastCaloSimCaloExtrapolation::getIterativePCA ( float cylR,
float cylZ,
Amg::Vector3D & BoundA,
Amg::Vector3D & BoundB,
Amg::Vector3D & PCA ) const
protected

Finds PCA iteratively given two bounds A and B on a line segment, used for (rare) cases with no easy analytical solutions.

Definition at line 484 of file FastCaloSimCaloExtrapolation.cxx.

484 {
485
486 ATH_MSG_DEBUG("[getIterativePCA] Finding PCA iteratively.");
487
488 Amg::Vector3D boundDir = BoundB - BoundA;
489 double distBounds = boundDir.norm();
490
491 //this sets the precision of the iterative finding procedure
492 const double stepSize = 0.01;
493
494 //if bounds are close enough together, there is nothing to do
495 //should make sure that nHalfDivisions >= 2
496 if (distBounds <= 4*stepSize){PCA = BoundA + 0.5*(BoundB - BoundA); return;}
497
498 Amg::Vector3D tmpBoundA, tmpBoundB, tmpOnCylinderBoundA, tmpOnCylinderBoundB;
499 Amg::Vector3D resBoundA, resBoundB, resOnCylinderBoundA, resOnCylinderBoundB;
500
501
502 //initial positions on cylinder and distance to line segment
503 Amg::Vector3D OnCylinderBoundA = projectOnCylinder(cylR, cylZ, BoundA);
504 Amg::Vector3D OnCylinderBoundB = projectOnCylinder(cylR, cylZ, BoundB);
505
506 double minDistA = (BoundA - OnCylinderBoundA).norm();
507 double minDistB = (BoundB - OnCylinderBoundB).norm();
508
509 //initialize result bounds with closest input bounds as fall back option
510 if(minDistA < minDistB){
511 resBoundA = BoundA;
512 resBoundB = BoundA;
513 }
514 else{
515 resBoundA = BoundB;
516 resBoundB = BoundB;
517 }
518 double tmpMinDistA, tmpMinDistB;
519 unsigned int nHalfDivisions = (distBounds/stepSize)/2;
520 for(unsigned int step = 0; step < nHalfDivisions; step++){
521
522 //temporary bounds on line segment
523 tmpBoundA = BoundA + (step+1)*stepSize*(boundDir/distBounds);
524 tmpBoundB = BoundB - (step+1)*stepSize*(boundDir/distBounds);
525
526 //temporary projected bounds on cylinder
527 tmpOnCylinderBoundA = projectOnCylinder(cylR, cylZ, tmpBoundA);
528 tmpOnCylinderBoundB = projectOnCylinder(cylR, cylZ, tmpBoundB);
529
530 //temporary minimum distance between bound on segment and bound on cylinder
531 tmpMinDistA = (tmpBoundA - tmpOnCylinderBoundA).norm();
532 tmpMinDistB = (tmpBoundB - tmpOnCylinderBoundB).norm();
533
534 if(minDistA >= tmpMinDistA){
535 minDistA = tmpMinDistA;
536 }
537 else{
538 double t = (step*stepSize)/distBounds;
539 resBoundA = BoundA + t*boundDir;
540 resBoundB = tmpBoundA;
541 break;
542 }
543
544 if(minDistB >= tmpMinDistB){
545 minDistB = tmpMinDistB;
546 }
547 else{
548 double t = (step*stepSize)/distBounds;
549 resBoundB = BoundB - t*boundDir;
550 resBoundA = tmpBoundB;
551 break;
552 }
553 }
554
555 //return middle of best bounds
556 PCA = resBoundA + 0.5*(resBoundB - resBoundA);
557
558}

◆ getPointLineSegmentDistance()

double FastCaloSimCaloExtrapolation::getPointLineSegmentDistance ( Amg::Vector3D & point,
Amg::Vector3D & hitPos1,
Amg::Vector3D & hitPos2 )
staticprotected

Computes the distance between a point and the line segment spanned by hitPos1 and hitPos2.

Definition at line 830 of file FastCaloSimCaloExtrapolation.cxx.

830 {
831
832 Amg::Vector3D hitDir = hitPos2 - hitPos1;
833 Amg::Vector3D w = point - hitPos1;
834
835 double c1 = w.dot(hitDir);
836 if(c1 <= 0) return Amg::distance(point, hitPos1);
837 double c2 = hitDir.dot(hitDir);
838 if(c2 <= c1) return Amg::distance(point, hitPos2);
839 double t = c1/c2;
840 Amg::Vector3D vec = hitPos1 + t*hitDir;
841 return Amg::distance(point, vec);
842
843}
std::vector< size_t > vec
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space

◆ initialize()

StatusCode FastCaloSimCaloExtrapolation::initialize ( )
finaloverridevirtual

Definition at line 48 of file FastCaloSimCaloExtrapolation.cxx.

49{
50 ATH_MSG_INFO( "Initializing FastCaloSimCaloExtrapolation" );
51
52 // Retrieve the fast calo sim geometry helper
54 // Retrieve the tool to transport particles through calorimeter with ATLAS tracking tools
56
57 return StatusCode::SUCCESS;
58
59
60}
#define ATH_CHECK
Evaluate an expression and check for errors.
PublicToolHandle< IFastCaloSimGeometryHelper > m_CaloGeometryHelper

◆ isCaloBarrel()

bool FastCaloSimCaloExtrapolation::isCaloBarrel ( int sample) const
protected

Definition at line 871 of file FastCaloSimCaloExtrapolation.cxx.

872{
873 return GetCaloGeometry()->isCaloBarrel(sample);
874}
virtual bool isCaloBarrel(int sample) const =0

◆ isOnSegment()

bool FastCaloSimCaloExtrapolation::isOnSegment ( Amg::Vector3D & point,
Amg::Vector3D & hitPos1,
Amg::Vector3D & hitPos2 )
staticprotected

Returns true if point lies on the line segment spanned by hitPos1 and hitPos2, otherwise returns false.

Definition at line 867 of file FastCaloSimCaloExtrapolation.cxx.

867 {
868 return getPointLineSegmentDistance(point, hitPos1, hitPos2) < 0.001;
869}
static double getPointLineSegmentDistance(Amg::Vector3D &point, Amg::Vector3D &hitPos1, Amg::Vector3D &hitPos2)
Computes the distance between a point and the line segment spanned by hitPos1 and hitPos2.

◆ minmaxeta()

void FastCaloSimCaloExtrapolation::minmaxeta ( int sample,
double eta,
double & mineta,
double & maxeta ) const
protected

Definition at line 881 of file FastCaloSimCaloExtrapolation.cxx.

882{
883 GetCaloGeometry()->minmaxeta(sample, eta, mineta, maxeta);
884}
virtual void minmaxeta(int sample, double eta, double &mineta, double &maxeta) const =0

◆ projectOnCylinder()

Amg::Vector3D FastCaloSimCaloExtrapolation::projectOnCylinder ( float cylR,
float cylZ,
Amg::Vector3D & hitPos )
staticprotected

Projects position hitPos onto the cylinder surface and returns projected position.

Definition at line 610 of file FastCaloSimCaloExtrapolation.cxx.

610 {
611
612 Amg::Vector3D closestPointOnCylinder;
613 Amg::Vector3D cylAxis(0, 0, cylZ);
614
615 //positive side
616 if(hitPos[Amg::z] >= cylZ){
617 //project hit position on x-y plane at positive side
618 Amg::Vector3D projHitPos(hitPos[Amg::x], hitPos[Amg::y], cylZ);
619
620 //if r of hit position outside cylinder, closest hit is always on edge
621 if(hitPos.perp() > cylR) closestPointOnCylinder = cylAxis + cylR * (projHitPos - cylAxis).unit();
622 else closestPointOnCylinder = cylAxis + hitPos.perp() * (projHitPos - cylAxis).unit();
623
624 }
625 //negative side
626 else if (hitPos[Amg::z] <= -cylZ){
627 //project hit position on x-y plane at negative side
628 Amg::Vector3D projHitPos(hitPos[Amg::x], hitPos[Amg::y], -cylZ);
629
630 if(hitPos.perp() > cylR) closestPointOnCylinder = -cylAxis + cylR * (projHitPos + cylAxis).unit();
631 else closestPointOnCylinder = -cylAxis + hitPos.perp() * (projHitPos + cylAxis).unit();
632
633 }
634 else{
635 Amg::Vector3D hitPosZ(0, 0, hitPos[Amg::z]);
636 closestPointOnCylinder = hitPosZ + cylR * (hitPos - hitPosZ).unit();
637 }
638
639 return closestPointOnCylinder;
640
641}
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.

◆ rent()

double FastCaloSimCaloExtrapolation::rent ( int sample,
double eta ) const
protected

Definition at line 901 of file FastCaloSimCaloExtrapolation.cxx.

902{
903 return GetCaloGeometry()->rent(sample, eta);
904}
virtual double rent(int sample, double eta) const =0

◆ rext()

double FastCaloSimCaloExtrapolation::rext ( int sample,
double eta ) const
protected

Definition at line 916 of file FastCaloSimCaloExtrapolation.cxx.

917{
918 return GetCaloGeometry()->rext(sample, eta);
919}
virtual double rext(int sample, double eta) const =0

◆ rmid()

double FastCaloSimCaloExtrapolation::rmid ( int sample,
double eta ) const
protected

Definition at line 886 of file FastCaloSimCaloExtrapolation.cxx.

887{
888 return GetCaloGeometry()->rmid(sample, eta);
889}
virtual double rmid(int sample, double eta) const =0

◆ rpos()

double FastCaloSimCaloExtrapolation::rpos ( int sample,
double eta,
int subpos = CaloSubPos::SUBPOS_MID ) const
protected

Definition at line 931 of file FastCaloSimCaloExtrapolation.cxx.

932{
933 return GetCaloGeometry()->rpos(sample, eta, subpos);
934}
virtual double rpos(int sample, double eta, int subpos=CaloSubPos::SUBPOS_MID) const =0

◆ rzent()

double FastCaloSimCaloExtrapolation::rzent ( int sample,
double eta ) const
protected

Definition at line 911 of file FastCaloSimCaloExtrapolation.cxx.

912{
913 return GetCaloGeometry()->rzent(sample, eta);
914}
virtual double rzent(int sample, double eta) const =0

◆ rzext()

double FastCaloSimCaloExtrapolation::rzext ( int sample,
double eta ) const
protected

Definition at line 926 of file FastCaloSimCaloExtrapolation.cxx.

927{
928 return GetCaloGeometry()->rzext(sample, eta);
929}
virtual double rzext(int sample, double eta) const =0

◆ rzmid()

double FastCaloSimCaloExtrapolation::rzmid ( int sample,
double eta ) const
protected

Definition at line 896 of file FastCaloSimCaloExtrapolation.cxx.

897{
898 return GetCaloGeometry()->rzmid(sample, eta);
899}
virtual double rzmid(int sample, double eta) const =0

◆ rzpos()

double FastCaloSimCaloExtrapolation::rzpos ( int sample,
double eta,
int subpos = CaloSubPos::SUBPOS_MID ) const
protected

Definition at line 941 of file FastCaloSimCaloExtrapolation.cxx.

942{
943 return GetCaloGeometry()->rzpos(sample, eta, subpos);
944}
virtual double rzpos(int sample, double eta, int subpos=CaloSubPos::SUBPOS_MID) const =0

◆ whereOnCylinder()

enum FastCaloSimCaloExtrapolation::HITPOSITION FastCaloSimCaloExtrapolation::whereOnCylinder ( float cylR,
float cylZ,
Amg::Vector3D & hitPos )
staticprotected

Checks if position of hitPos is inside, outside or on the cylinder bounds.

Definition at line 845 of file FastCaloSimCaloExtrapolation.cxx.

845 {
846 //set a 1mm tolerance within which the hit position is considered to be on the cylinder surface
847 //setting this higher can lead to extrapolation failures around truth particle eta ~4
848 float tolerance = 1;
849
850 bool isOnEndcap = hitPos.perp() <= cylR + tolerance && (hitPos[Amg::z] > 0 ? std::abs(hitPos[Amg::z] - cylZ) < tolerance : std::abs(hitPos[Amg::z] + cylZ) < tolerance);
851 bool isOnCover = std::abs(hitPos.perp() - cylR) < tolerance && hitPos[Amg::z] < cylZ && hitPos[Amg::z] > -cylZ;
852
853 //check if hit position is on endcap or cover of cylinder
854 if(isOnEndcap || isOnCover) return HITPOSITION::ON;
855
856 //check if hit position is inside cover
857 if(hitPos[Amg::z] < cylZ && hitPos[Amg::z] > -cylZ && hitPos.perp() < cylR) return HITPOSITION::INSIDE;
858
860}

◆ whichIntersection()

int FastCaloSimCaloExtrapolation::whichIntersection ( float cylR,
float cylZ,
Amg::Vector3D & hitPos1,
Amg::Vector3D & hitPos2,
Amg::Vector3D & intersectionA,
Amg::Vector3D intersectionB ) const
protected

Returns ID of more sensible intersection between line segment spanned by hitPos1 and hitPos2 and cylinder.

Definition at line 792 of file FastCaloSimCaloExtrapolation.cxx.

792 {
793
794 //check if the hit positions are outside or inside the cylinder surface
795 HITPOSITION cylPosHit1 = whereOnCylinder(cylR, cylZ, hitPos1);
796 HITPOSITION cylPosHit2 = whereOnCylinder(cylR, cylZ, hitPos2);
797
798 if((cylPosHit1 == INSIDE) ^ (cylPosHit2 == INSIDE)){
799 /* CASE A: one hit position inside and one outside of the cylinder (travel through surface),
800 one intersection is on cylinder, take intersection closest to line segment */
801 ATH_MSG_DEBUG("[whichIntersection] Travel through surface.");
802 return getPointLineSegmentDistance(intersectionA, hitPos1, hitPos2) > getPointLineSegmentDistance(intersectionB, hitPos1, hitPos2);
803 }
804 else if(cylPosHit1 == INSIDE && cylPosHit2 == INSIDE){
805 /* CASE B: both hit position inside, take intersection which points towards travel direction of particle */
806 Amg::Vector3D directionA = intersectionA - hitPos2;
807 Amg::Vector3D directionB = intersectionB - hitPos2;
808 Amg::Vector3D hitDir = hitPos2 - hitPos1;
809 ATH_MSG_DEBUG("[whichIntersection] Both hit positions inside.");
810 return directionA.dot(hitDir) < directionB.dot(hitDir);
811 }
812 else{
813 // /* CASE C: both hit position outside and the intersections lay on the segment, take intersection closest to second hit position */
814 // /* CASE D: both hit positions are outside and the intersections are not on the line segment, take intersection closest to one of the hit positions */
815 double distHitPosIntersectA = (hitPos2 - intersectionA).norm();
816 double distHitPosIntersectB = (hitPos2 - intersectionB).norm();
817 ATH_MSG_DEBUG("[whichIntersection] Both hit positions outside.");
818 return distHitPosIntersectA > distHitPosIntersectB;
819 }
820}

◆ zent()

double FastCaloSimCaloExtrapolation::zent ( int sample,
double eta ) const
protected

Definition at line 906 of file FastCaloSimCaloExtrapolation.cxx.

907{
908 return GetCaloGeometry()->zent(sample, eta);
909}
virtual double zent(int sample, double eta) const =0

◆ zext()

double FastCaloSimCaloExtrapolation::zext ( int sample,
double eta ) const
protected

Definition at line 921 of file FastCaloSimCaloExtrapolation.cxx.

922{
923 return GetCaloGeometry()->zext(sample, eta);
924}
virtual double zext(int sample, double eta) const =0

◆ zmid()

double FastCaloSimCaloExtrapolation::zmid ( int sample,
double eta ) const
protected

Definition at line 891 of file FastCaloSimCaloExtrapolation.cxx.

892{
893 return GetCaloGeometry()->zmid(sample, eta);
894}
virtual double zmid(int sample, double eta) const =0

◆ zpos()

double FastCaloSimCaloExtrapolation::zpos ( int sample,
double eta,
int subpos = CaloSubPos::SUBPOS_MID ) const
protected

Definition at line 936 of file FastCaloSimCaloExtrapolation.cxx.

937{
938 return GetCaloGeometry()->zpos(sample, eta, subpos);
939}
virtual double zpos(int sample, double eta, int subpos=CaloSubPos::SUBPOS_MID) const =0

Member Data Documentation

◆ m_CaloBoundaryR

FloatArrayProperty FastCaloSimCaloExtrapolation::m_CaloBoundaryR {this, "CaloBoundaryR", {1148.0,120.0,41.0}}
protected

Definition at line 121 of file FastCaloSimCaloExtrapolation.h.

121{this, "CaloBoundaryR", {1148.0,120.0,41.0}};

◆ m_CaloBoundaryZ

FloatArrayProperty FastCaloSimCaloExtrapolation::m_CaloBoundaryZ {this, "CaloBoundaryZ", {3550.0,4587.0,4587.0}}
protected

Definition at line 122 of file FastCaloSimCaloExtrapolation.h.

122{this, "CaloBoundaryZ", {3550.0,4587.0,4587.0}};

◆ m_CaloGeometryHelper

PublicToolHandle<IFastCaloSimGeometryHelper> FastCaloSimCaloExtrapolation::m_CaloGeometryHelper {this, "CaloGeometryHelper", "FastCaloSimGeometryHelper"}
protected

Definition at line 127 of file FastCaloSimCaloExtrapolation.h.

127{this, "CaloGeometryHelper", "FastCaloSimGeometryHelper"};

◆ m_CaloTransportation

PublicToolHandle<IFastCaloSimCaloTransportation> FastCaloSimCaloExtrapolation::m_CaloTransportation {this, "CaloTransportation", "FastCaloSimCaloTransportation"}
protected

Definition at line 125 of file FastCaloSimCaloExtrapolation.h.

125{this, "CaloTransportation", "FastCaloSimCaloTransportation"};

The documentation for this class was generated from the following files: