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

HepPDT::ParticleDataTable * m_particleDataTable {nullptr}
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 47 of file FastCaloSimCaloExtrapolation.cxx.

48 : base_class(t,n,p)
49{
50}

◆ ~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 565 of file FastCaloSimCaloExtrapolation.cxx.

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

772 {
773
774 //normal and point on endcap defines the plane
775 Amg::Vector3D pointOnEndcap;
776 Amg::Vector3D normal(0, 0, 1);
777 positiveEndcap ? pointOnEndcap = {0, 0, cylZ} : pointOnEndcap = {0, 0, -cylZ};
778 Amg::Vector3D hitDir = (pointB - pointA);
779
780 double denom = normal.dot(hitDir);
781 if (std::abs(denom) > 1e-6) {
782 double t = normal.dot(pointOnEndcap - pointB)/denom;
783 //compute intersection regardless of direction (t>0 or t<0)
784 intersection = pointB + t*hitDir;
785 Amg::Vector3D v = intersection - pointOnEndcap;
786
787 //check if intersection is within cylR bounds
788 return std::sqrt(v.dot(v)) <= cylR;
789
790 }
791
792 return false;
793
794 }
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 730 of file FastCaloSimCaloExtrapolation.cxx.

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

◆ deta()

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

Definition at line 880 of file FastCaloSimCaloExtrapolation.cxx.

881{
882 return GetCaloGeometry()->deta(sample, eta);
883}
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 866 of file FastCaloSimCaloExtrapolation.cxx.

866 {
867 //travel through surface in case one hit position is outside and the other outside of cylinder surface
868 return (whereOnCylinder(cylR, cylZ, hitPos1) == INSIDE) ^ (whereOnCylinder(cylR, cylZ, hitPos2) == INSIDE);
869}
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 84 of file FastCaloSimCaloExtrapolation.cxx.

84 {
85
86 ATH_MSG_DEBUG("[extrapolate] Initializing transport of track through calorimeter system with ATLAS tracking tools.");
87 std::vector<G4FieldTrack> caloSteps = m_CaloTransportation -> transport(truth, false);
88 ATH_MSG_DEBUG("[extrapolate] Finalized transport of track through calorimeter system with ATLAS tracking tools.");
89
90 extrapolate(result, truth, caloSteps);
91}
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 72 of file FastCaloSimCaloExtrapolation.cxx.

72 {
73
74 ATH_MSG_DEBUG("[extrapolate] Initializing extrapolation to ID-Calo boundary");
75 extrapolateToID(result, caloSteps, truth);
76
77 ATH_MSG_DEBUG("[extrapolate] Initializing extrapolation to calorimeter layers");
78 extrapolateToLayers(result, caloSteps, truth);
79
80 ATH_MSG_DEBUG("[extrapolate] Extrapolation done");
81
82}
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 237 of file FastCaloSimCaloExtrapolation.cxx.

237 {
238
239 if(caloSteps.size() == 1){
240 Amg::Vector3D hitPos = Amg::Hep3VectorToEigen(caloSteps.at(0).GetPosition());
241 ATH_MSG_DEBUG("[extrapolateWithPCA(R="<<cylR<<",Z="<<cylZ<<")] Extrapolating single hit position to surface.");
242 extPos = projectOnCylinder(cylR, cylZ, hitPos);
243 momDir = Amg::Hep3VectorToEigen(caloSteps.at(0).GetMomentum());
244 return true;
245 }
246
247 //if we do not find any good intersections, extrapolate to closest point on surface
248 bool foundHit = extrapolateWithIntersection(caloSteps, cylR, cylZ, extPos, momDir) ? true : extrapolateWithPCA(caloSteps, cylR, cylZ, extPos, momDir);
249
250 if(foundHit){
251 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]<<")");
252 }
253 else{
254 //this is not expected to ever happen
255 ATH_MSG_DEBUG("(R="<<cylR<<", Z="<<cylZ<<"::END) Extrapolation to cylinder surface failed!");
256 }
257
258
259 return foundHit;
260
261}
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 94 of file FastCaloSimCaloExtrapolation.cxx.

94 {
95
96 ATH_MSG_DEBUG("Start extrapolateToID()");
97
98 //pT threshold of truth particles over which extrapolation failures will be printed as warnings
99 const float transverseMomWarningLimit = 500;
100
101 //initialize values
102 result.set_IDCaloBoundary_eta(-999.);
103 result.set_IDCaloBoundary_phi(-999.);
104 result.set_IDCaloBoundary_r(0);
105 result.set_IDCaloBoundary_z(0);
106 result.set_IDCaloBoundary_AngleEta(-999.);
107 result.set_IDCaloBoundary_Angle3D(-999.);
108
109 //magnitude of extrapolated position
110 double extPosDist = -1;
111
112 for (unsigned int surfID = 0; surfID<3; surfID++){
113
114 double R = m_CaloBoundaryR.value().at(surfID);
115 double Z = m_CaloBoundaryZ.value().at(surfID);
116
117 ATH_MSG_DEBUG("[ExtrapolateToID] Extrapolating to ID-Calo boundary with ID="<<surfID<<" R="<<R<<" Z="<<Z);
118
119 //extrapolated position and momentum direction at IDCaloBoundary
120 Amg::Vector3D extPos, momDir;
121
122 //main extrapolation call
123 if(!extrapolateToCylinder(caloSteps, R, Z, extPos, momDir)) continue;
124
125 double tolerance = 0.001;
126
127 //test if z inside previous cylinder within some tolerance
128 ATH_MSG_DEBUG("[ExtrapolateToID] Testing condition 1: hit z="<< extPos[Amg::z]);
129 if(surfID > 0 && std::abs(extPos[Amg::z]) < m_CaloBoundaryZ[surfID-1] - tolerance) continue;
130 ATH_MSG_DEBUG("[ExtrapolateToID] Passed condition 1.");
131
132 //test if r inside next cylinder within some tolerance
133 ATH_MSG_DEBUG("[ExtrapolateToID] Testing condition 2: hit r="<< extPos.perp());
134 if(surfID < m_CaloBoundaryR.size()-1 && extPos.perp() < m_CaloBoundaryR[surfID + 1] - tolerance) continue;
135 ATH_MSG_DEBUG("[ExtrapolateToID] Passed condition 2.");
136
137 ATH_MSG_DEBUG("[ExtrapolateToID] Testing condition 3: hit magnitude="<< extPos.mag());
138 if(extPosDist >= 0 && extPos.mag() > extPosDist) continue;
139 ATH_MSG_DEBUG("[ExtrapolateToID] Passed condition 3.");
140
141 extPosDist = extPos.mag();
142
143 result.set_IDCaloBoundary_eta(extPos.eta());
144 result.set_IDCaloBoundary_phi(extPos.phi());
145 result.set_IDCaloBoundary_r(extPos.perp());
146 result.set_IDCaloBoundary_z(extPos[Amg::z]);
147
148 ATH_MSG_DEBUG("[ExtrapolateToID] Setting IDCaloBoundary to eta="<<extPos.eta()<<" phi="<<extPos.phi()<< " r="<<extPos.perp()<<" z="<<extPos.z());
149
150 //compute angle between extrapolated position vector and momentum at IDCaloBoundary
151 //can be used to correct shower shapes for particles which do not originate from {0,0,0}
152 double Angle3D = Amg::angle(extPos, momDir);
153 double AngleEta = extPos.theta() - momDir.theta();
154 result.set_IDCaloBoundary_AngleEta(AngleEta);
155 result.set_IDCaloBoundary_Angle3D(Angle3D);
156
157 } //end of loop over surfaces
158
159 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);
160
161 ATH_MSG_DEBUG("[ExtrapolateToID] End extrapolateToID()");
162
163}
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 166 of file FastCaloSimCaloExtrapolation.cxx.

167{
168 ATH_MSG_DEBUG("[extrapolateToLayers] Start extrapolate");
169
170 //pT threshold of truth particles over which extrapolation failures will be printed as warnings
171 const float transverseMomWarningLimit = 500;
172
174 // Start calo extrapolation
176
177 //only continue if inside the calo
178 if(std::abs(result.IDCaloBoundary_eta()) < 6){
179 //now try to extrapolate to all calo layers that contain energy
181 for(int subpos=SUBPOS_MID; subpos<=SUBPOS_EXT; ++subpos){
182
183 float cylR, cylZ;
184 if(isCaloBarrel(sample)){
185 cylR = std::abs(rpos(sample, result.IDCaloBoundary_eta(), subpos));
186 //EMB0 - EMB3 use z position of EME1 front end surface for extrapolation
187 //else extrapolate to cylinder with symmetrized maximum Z bounds
188 //set eta to a dummy value of 1000 and -1000 to force detector side
189 if(sample < 4) cylZ = result.IDCaloBoundary_eta() > 0 ? std::abs(zpos(5, 1000, 1)) : std::abs(zpos(5, -1000, 1));
190 else cylZ = 0.5*(std::abs(zpos(sample, 1000, subpos)) + std::abs(zpos(sample, -1000, subpos)));
191 }
192 else{
193 //if we are not at barrel surface, extrapolate to cylinder with maximum R to reduce extrapolation length
194 cylZ = std::abs(zpos(sample, result.IDCaloBoundary_eta(), subpos));
195 //calculate radius of cylinder we will extrapolate to
196 double mineta, maxeta, eta;
197 minmaxeta(sample, result.IDCaloBoundary_eta(), mineta, maxeta);
198 //get eta where we will look up the layer radius
199 eta = result.IDCaloBoundary_eta() > 0 ? mineta : maxeta;
200 //calculate azimuthal angle from pseudorapidity
201 double theta = 2*std::atan(std::exp(-eta));
202 //calculate maximum R of last cell of layer from z and theta
203 cylR = std::abs(cylZ*std::sqrt((1/(std::cos(theta)*std::cos(theta))) - 1));
204 }
205
206 Amg::Vector3D extPos, momDir;
207 if(extrapolateToCylinder(caloSteps, cylR, cylZ, extPos, momDir)){
208
209 //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
210 //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
211 //this will keep phi, eta intact and only scale r and z to fit a sensible position on the cylinder
212 double scale = 1;
213 if (isCaloBarrel(sample) && std::abs(extPos.perp()) > 1e-6) scale = cylR / extPos.perp();
214 else if (!isCaloBarrel(sample) && std::abs(extPos.z()) > 1e-6) scale = cylZ / std::abs(extPos.z());
215 //scale extrapolated position accordingly
216 extPos = scale * extPos;
217
218 result.set_OK(sample, subpos, true);
219 result.set_phi(sample, subpos, extPos.phi());
220 result.set_z (sample, subpos, extPos.z());
221 result.set_eta(sample, subpos, extPos.eta());
222 result.set_r (sample, subpos, extPos.perp());
223 }
224 else{
225 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);
226 }
227 } //for pos
228 } //for sample
229 } //inside calo
230
231 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);
232
233
234 ATH_MSG_DEBUG("[extrapolateToLayers] End extrapolateToLayers()");
235}
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 264 of file FastCaloSimCaloExtrapolation.cxx.

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

◆ 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 342 of file FastCaloSimCaloExtrapolation.cxx.

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

66 {
67 ATH_MSG_INFO( "Finalizing FastCaloSimCaloExtrapolation" );
68 return StatusCode::SUCCESS;
69}
#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 382 of file FastCaloSimCaloExtrapolation.cxx.

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

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

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

◆ 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 834 of file FastCaloSimCaloExtrapolation.cxx.

834 {
835
836 Amg::Vector3D hitDir = hitPos2 - hitPos1;
837 Amg::Vector3D w = point - hitPos1;
838
839 double c1 = w.dot(hitDir);
840 if(c1 <= 0) return Amg::distance(point, hitPos1);
841 double c2 = hitDir.dot(hitDir);
842 if(c2 <= c1) return Amg::distance(point, hitPos2);
843 double t = c1/c2;
844 Amg::Vector3D vec = hitPos1 + t*hitDir;
845 return Amg::distance(point, vec);
846
847}
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 52 of file FastCaloSimCaloExtrapolation.cxx.

53{
54 ATH_MSG_INFO( "Initializing FastCaloSimCaloExtrapolation" );
55
56 // Retrieve the fast calo sim geometry helper
58 // Retrieve the tool to transport particles through calorimeter with ATLAS tracking tools
60
61 return StatusCode::SUCCESS;
62
63
64}
#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 875 of file FastCaloSimCaloExtrapolation.cxx.

876{
877 return GetCaloGeometry()->isCaloBarrel(sample);
878}
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 871 of file FastCaloSimCaloExtrapolation.cxx.

871 {
872 return getPointLineSegmentDistance(point, hitPos1, hitPos2) < 0.001;
873}
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 885 of file FastCaloSimCaloExtrapolation.cxx.

886{
887 GetCaloGeometry()->minmaxeta(sample, eta, mineta, maxeta);
888}
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 614 of file FastCaloSimCaloExtrapolation.cxx.

614 {
615
616 Amg::Vector3D closestPointOnCylinder;
617 Amg::Vector3D cylAxis(0, 0, cylZ);
618
619 //positive side
620 if(hitPos[Amg::z] >= cylZ){
621 //project hit position on x-y plane at positive side
622 Amg::Vector3D projHitPos(hitPos[Amg::x], hitPos[Amg::y], cylZ);
623
624 //if r of hit position outside cylinder, closest hit is always on edge
625 if(hitPos.perp() > cylR) closestPointOnCylinder = cylAxis + cylR * (projHitPos - cylAxis).unit();
626 else closestPointOnCylinder = cylAxis + hitPos.perp() * (projHitPos - cylAxis).unit();
627
628 }
629 //negative side
630 else if (hitPos[Amg::z] <= -cylZ){
631 //project hit position on x-y plane at negative side
632 Amg::Vector3D projHitPos(hitPos[Amg::x], hitPos[Amg::y], -cylZ);
633
634 if(hitPos.perp() > cylR) closestPointOnCylinder = -cylAxis + cylR * (projHitPos + cylAxis).unit();
635 else closestPointOnCylinder = -cylAxis + hitPos.perp() * (projHitPos + cylAxis).unit();
636
637 }
638 else{
639 Amg::Vector3D hitPosZ(0, 0, hitPos[Amg::z]);
640 closestPointOnCylinder = hitPosZ + cylR * (hitPos - hitPosZ).unit();
641 }
642
643 return closestPointOnCylinder;
644
645}
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 905 of file FastCaloSimCaloExtrapolation.cxx.

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

◆ rext()

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

Definition at line 920 of file FastCaloSimCaloExtrapolation.cxx.

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

◆ rmid()

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

Definition at line 890 of file FastCaloSimCaloExtrapolation.cxx.

891{
892 return GetCaloGeometry()->rmid(sample, eta);
893}
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 935 of file FastCaloSimCaloExtrapolation.cxx.

936{
937 return GetCaloGeometry()->rpos(sample, eta, subpos);
938}
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 915 of file FastCaloSimCaloExtrapolation.cxx.

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

◆ rzext()

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

Definition at line 930 of file FastCaloSimCaloExtrapolation.cxx.

931{
932 return GetCaloGeometry()->rzext(sample, eta);
933}
virtual double rzext(int sample, double eta) const =0

◆ rzmid()

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

Definition at line 900 of file FastCaloSimCaloExtrapolation.cxx.

901{
902 return GetCaloGeometry()->rzmid(sample, eta);
903}
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 945 of file FastCaloSimCaloExtrapolation.cxx.

946{
947 return GetCaloGeometry()->rzpos(sample, eta, subpos);
948}
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 849 of file FastCaloSimCaloExtrapolation.cxx.

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

◆ 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 796 of file FastCaloSimCaloExtrapolation.cxx.

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

◆ zent()

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

Definition at line 910 of file FastCaloSimCaloExtrapolation.cxx.

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

◆ zext()

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

Definition at line 925 of file FastCaloSimCaloExtrapolation.cxx.

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

◆ zmid()

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

Definition at line 895 of file FastCaloSimCaloExtrapolation.cxx.

896{
897 return GetCaloGeometry()->zmid(sample, eta);
898}
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 940 of file FastCaloSimCaloExtrapolation.cxx.

941{
942 return GetCaloGeometry()->zpos(sample, eta, subpos);
943}
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 122 of file FastCaloSimCaloExtrapolation.h.

122{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 123 of file FastCaloSimCaloExtrapolation.h.

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

◆ m_CaloGeometryHelper

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

Definition at line 128 of file FastCaloSimCaloExtrapolation.h.

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

◆ m_CaloTransportation

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

Definition at line 126 of file FastCaloSimCaloExtrapolation.h.

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

◆ m_particleDataTable

HepPDT::ParticleDataTable* FastCaloSimCaloExtrapolation::m_particleDataTable {nullptr}
protected

Definition at line 119 of file FastCaloSimCaloExtrapolation.h.

119{nullptr};

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