From 845200c9900021360a29a3c11f9b3a9f0cf6f02f Mon Sep 17 00:00:00 2001
From: Dave Casper <dcasper@uci.edu>
Date: Sun, 4 Mar 2018 20:51:14 -0800
Subject: [PATCH] Add truth vertex analysis to test algorithm; fix bug in
 density calculation; tested successful on full-truth MC.

Former-commit-id: 1d841f3b9826d4159dc87e0d78ddc9a8a2ecb096
---
 .../GaussianTrackDensity.h                    |   2 +-
 .../GaussianDensityTestAlg_jobOptions.py      |   7 +-
 .../src/GaussianDensityTestAlg.cxx            | 160 +++++++++++++++++-
 .../src/GaussianDensityTestAlg.h              |  27 +++
 .../src/GaussianTrackDensity.cxx              |   4 +-
 5 files changed, 192 insertions(+), 8 deletions(-)

diff --git a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/TrkVertexSeedFinderUtils/GaussianTrackDensity.h b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/TrkVertexSeedFinderUtils/GaussianTrackDensity.h
index f7b451e83d1..1bb7c927b7f 100644
--- a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/TrkVertexSeedFinderUtils/GaussianTrackDensity.h
+++ b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/TrkVertexSeedFinderUtils/GaussianTrackDensity.h
@@ -154,7 +154,7 @@ namespace Trk
                                                   "Maximum radial impact parameter significance to use track" };
     Gaudi::Property<double> m_z0MaxSignificance { this,
 	                                          "MaxZ0Significance",
-	                                          5.0,
+	                                          12.0,
 	                                          "Maximum longitudinal impact parameter significance to include track in weight"};
 
   };
diff --git a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/share/GaussianDensityTestAlg_jobOptions.py b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/share/GaussianDensityTestAlg_jobOptions.py
index 60b52d66795..6784f0b8c1e 100644
--- a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/share/GaussianDensityTestAlg_jobOptions.py
+++ b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/share/GaussianDensityTestAlg_jobOptions.py
@@ -98,11 +98,16 @@ InDetTrackSelectorTool = InDet__InDetTrackSelectionTool(name = "InDetDetailedTra
                                                         Extrapolator = InDetExtrapolator)
 ToolSvc += InDetTrackSelectorTool
 
+from TrkVertexFitterUtils.TrkVertexFitterUtilsConf import Trk__TrackToVertexIPEstimator
+IPTool = Trk__TrackToVertexIPEstimator( name =          "IPEstimator",
+                                        Extrapolator =  InDetExtrapolator )
+
 
 from TrkVertexSeedFinderUtils.TrkVertexSeedFinderUtilsConf import Trk__GaussianDensityTestAlg
 myAlg =   Trk__GaussianDensityTestAlg( name                   = "TestAlg",
                                        Estimator              = GaussianDensity,
-                                       TrackSelector          = InDetTrackSelectorTool)
+                                       TrackSelector          = InDetTrackSelectorTool,
+                                       IPEstimator            = IPTool)
 myAlg.OutputLevel = DEBUG
 algSeq += myAlg
 
diff --git a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianDensityTestAlg.cxx b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianDensityTestAlg.cxx
index e0383c553e3..d6481036388 100644
--- a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianDensityTestAlg.cxx
+++ b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianDensityTestAlg.cxx
@@ -54,14 +54,21 @@ StatusCode GaussianDensityTestAlg::initialize()
   ATH_MSG_INFO ("Initializing " << name() << "...");
 
   ATH_CHECK( m_trackParticlesKey.initialize() );
+  ATH_CHECK( m_truthEventsKey.initialize() );
+  ATH_CHECK( m_pileupEventsKey.initialize() );
 
   ATH_CHECK( m_estimator.retrieve() );
   ATH_CHECK( m_trackFilter.retrieve() );
+  ATH_CHECK( m_ipEstimator.retrieve() );
 
   // setup histograms/trees
   m_h_density = new TH1F("Density", "Density", 800, -200.0, 200.0);
+  m_h_truthDensity = new TH1F("Truth", "Truth", 800, -200.0, 200.0);
+  m_h_truthVertices = new TH1F("TruthVertices", "TruthVertices", 800, -200.0, 200.0);
 
   CHECK( m_iTHistSvc->regHist("/file1/h/density", m_h_density) );
+  CHECK( m_iTHistSvc->regHist("/file1/h/truth", m_h_truthDensity) );
+  CHECK( m_iTHistSvc->regHist("/file1/h/truthvertices", m_h_truthVertices) );
 
   return StatusCode::SUCCESS;
 }
@@ -78,24 +85,28 @@ StatusCode GaussianDensityTestAlg::execute()
 
   SG::ReadHandle<xAOD::TrackParticleContainer> trackParticles(m_trackParticlesKey);
 
+  ATH_MSG_VERBOSE("Selecting tracks");
   std::vector<Trk::ITrackLink*> trackVector;
   selectTracks(trackParticles.cptr(), trackVector);
 
   std::vector<const Trk::TrackParameters*> perigeeList;
   analyzeTracks(trackVector, perigeeList);
 
+  ATH_MSG_VERBOSE("Using density estimator");
   m_estimator->reset();
   m_estimator->addTracks(perigeeList);
 
-  //ATH_MSG_DEBUG("Added " << perigeeList.size() << " tracks to density estimator");
-
   for (int i = 0; i < 800; i++)
   {
     double z = -200.0 + 0.25 + i*0.5;
     double density = m_estimator->trackDensity(z);
-    //ATH_MSG_ALWAYS(" z: " << z << " Density: " << density);
     m_h_density->Fill((float) z, (float) density);
   }
+  ATH_MSG_VERBOSE("Analyzing MC truth");
+  std::vector<Amg::Vector3D> truth;
+  ATH_CHECK( findTruth(trackVector, truth) );
+  ATH_MSG_VERBOSE("Filling truth vertex histogram");
+  for (auto& v : truth) m_h_truthVertices->Fill( v[2] );
 
 
   return StatusCode::SUCCESS;
@@ -152,4 +163,147 @@ void GaussianDensityTestAlg::selectTracks(const xAOD::TrackParticleContainer* tr
 /////////////////////////////////////////////////////////////////// 
 // Const methods: 
 ///////////////////////////////////////////////////////////////////
+  StatusCode GaussianDensityTestAlg::findTruth(const std::vector<Trk::ITrackLink*>& trackVector, std::vector<Amg::Vector3D>& truth) const
+  {
+    xAOD::TrackParticle::ConstAccessor<ElementLink<xAOD::TruthParticleContainer> > truthParticleAssoc("truthParticleLink");
+
+    SG::ReadHandle<xAOD::TruthEventContainer> signalEvents(m_truthEventsKey);
+    if ( signalEvents.isValid() )
+    {
+      ATH_MSG_VERBOSE("Found signalEvents");
+      for (const xAOD::TruthEventBase* evt : *signalEvents)
+      {
+	const xAOD::TruthVertex* vLink = *(evt->truthVertexLink(0));
+	if (vLink == nullptr) ATH_MSG_ERROR("Invalid truthVertexLink from signalEvents");
+	Amg::Vector3D vTruth(vLink->x(),vLink->y(),vLink->z());
+	int nGoodTracks = 0;
+	for (auto trk : trackVector)
+	{
+	    Trk::LinkToXAODTrackParticle* lxtp = dynamic_cast<Trk::LinkToXAODTrackParticle*>(trk);
+	    if (lxtp)
+	    {
+		bool isAssoc = truthParticleAssoc(**(*lxtp)).isValid();
+		if (isAssoc)
+	        {
+		    auto assocParticle = truthParticleAssoc(**(*lxtp));
+		    ATH_MSG_VERBOSE("Found associated truth particle");
+		    for (auto truthParticle : evt->truthParticleLinks())
+		    {
+		        if (!truthParticle.isValid()) continue;
+			if (assocParticle == truthParticle)
+		        {
+			  ATH_MSG_VERBOSE("Calling ipSignificance");
+			    double significance = ipSignificance(trk->parameters(), &vTruth);
+			    ATH_MSG_VERBOSE("ipSignificance returned " << significance);
+			    if (significance <= m_significanceTruthCut) 
+			    {
+			      ATH_MSG_VERBOSE("Adding good track");
+			      nGoodTracks++;
+			      const Trk::Perigee* perigee = dynamic_cast<const Trk::Perigee*>(trk->parameters());
+			      if (perigee == nullptr) ATH_MSG_ERROR("Invalid Perigee");
+			      m_h_truthDensity->Fill(vLink->z());
+			      ATH_MSG_VERBOSE("Filled truth density histogram");
+			    }
+			    break;
+			}
+		    }
+	        }
+                else
+		{
+		  ATH_MSG_VERBOSE("No associated truth particle found");
+		}
+	    }
+        }
+        if (nGoodTracks >= m_truthVertexTracks)
+        {
+    	  truth.push_back(vTruth);
+        }
+      }
+    }
+    else
+    {
+      ATH_MSG_WARNING("No TruthEventContainer found");
+    }
+
+    SG::ReadHandle<xAOD::TruthPileupEventContainer> pileupEvents(m_pileupEventsKey);
+    if ( pileupEvents.isValid() )
+    {
+      ATH_MSG_VERBOSE("Found pileupEvents");
+      for (const xAOD::TruthEventBase* evt : *pileupEvents)
+      {
+	const xAOD::TruthVertex* vLink = *(evt->truthVertexLink(0));
+	if (vLink == nullptr) ATH_MSG_ERROR("Invalid truthVertexLink from pileupEvents");
+	Amg::Vector3D vTruth(vLink->x(),vLink->y(),vLink->z());
+	int nGoodTracks = 0;
+	for (auto trk : trackVector)
+	{
+	    Trk::LinkToXAODTrackParticle* lxtp = dynamic_cast<Trk::LinkToXAODTrackParticle*>(trk);
+	    if (lxtp)
+	    {
+		bool isAssoc = truthParticleAssoc(**(*lxtp)).isValid();
+		if (isAssoc)
+	        {
+		    auto assocParticle = truthParticleAssoc(**(*lxtp));
+		    ATH_MSG_VERBOSE("Found associated truth particle");
+		    for (auto truthParticle : evt->truthParticleLinks())
+		    {
+		        if (!truthParticle.isValid()) continue;
+			if (assocParticle == truthParticle)
+		        {
+			  ATH_MSG_VERBOSE("Calling ipSignificance");
+			    double significance = ipSignificance(trk->parameters(), &vTruth);
+			    ATH_MSG_VERBOSE("ipSignificance returned " << significance);
+			    if (significance <= m_significanceTruthCut) 
+			    {
+			      ATH_MSG_VERBOSE("Adding good track");
+			      nGoodTracks++;
+			      const Trk::Perigee* perigee = dynamic_cast<const Trk::Perigee*>(trk->parameters());
+			      if (perigee == nullptr) ATH_MSG_ERROR("Invalid Perigee");
+			      m_h_truthDensity->Fill(vLink->z());
+			      ATH_MSG_VERBOSE("Filled truth density histogram");
+			    }
+			    break;
+			}
+		    }
+	        }
+                else
+		{
+		  ATH_MSG_VERBOSE("No associated truth particle found");
+		}
+	    }
+        }
+        if (nGoodTracks >= m_truthVertexTracks)
+	{
+	    truth.push_back(vTruth);
+	}
+      }
+    }
+    else
+    {
+      ATH_MSG_WARNING("No TruthPileupEventContainer found");
+    }
+    return StatusCode::SUCCESS;
+  }
+
+  double GaussianDensityTestAlg::ipSignificance( const Trk::TrackParameters* params, 
+                                                 const Amg::Vector3D * vertex ) const
+  {
+    xAOD::Vertex v;
+    v.makePrivateStore();
+    v.setPosition(*vertex);
+    v.setCovariancePosition(AmgSymMatrix(3)::Zero(3,3));
+    v.setFitQuality(0., 0.);
+
+    double significance = 0.0;
+    const ImpactParametersAndSigma* ipas = m_ipEstimator->estimate( params, &v );
+    if ( ipas != nullptr )
+    {  
+      if ( ipas->sigmad0 > 0 && ipas->sigmaz0 > 0)
+      {
+	significance = sqrt( pow(ipas->IPd0/ipas->sigmad0,2) + pow(ipas->IPz0/ipas->sigmaz0,2) );
+      }
+      delete ipas;
+    }
+    return significance;
+  }
 }
diff --git a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianDensityTestAlg.h b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianDensityTestAlg.h
index f959c3304c3..605f64fe7ce 100644
--- a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianDensityTestAlg.h
+++ b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianDensityTestAlg.h
@@ -25,10 +25,13 @@
 #include "TrkParticleBase/TrackParticleBaseCollection.h"
 #include "TrkParameters/TrackParameters.h"
 #include "xAODTracking/TrackParticleContainer.h"
+#include "xAODTruth/TruthEventContainer.h"
+#include "xAODTruth/TruthPileupEventContainer.h"
 
 #include "InDetBeamSpotService/IBeamCondSvc.h"
 #include "TrkVertexFitterInterfaces/IVertexTrackDensityEstimator.h"
 #include "InDetTrackSelectionTool/IInDetTrackSelectionTool.h"
+#include "TrkVertexFitterInterfaces/ITrackToVertexIPEstimator.h"
 
 //Amg
 #include "GeoPrimitives/GeoPrimitives.h"
@@ -69,6 +72,9 @@ class GaussianDensityTestAlg
   /////////////////////////////////////////////////////////////////// 
   // Const methods: 
   ///////////////////////////////////////////////////////////////////
+  double ipSignificance(const Trk::TrackParameters* params, const Amg::Vector3D * vertex) const;
+
+  StatusCode findTruth(const std::vector<Trk::ITrackLink*>& trackVector, std::vector<Amg::Vector3D>& truth) const;
 
   /////////////////////////////////////////////////////////////////// 
   // Non-const methods: 
@@ -84,6 +90,16 @@ class GaussianDensityTestAlg
   /////////////////////////////////////////////////////////////////// 
  private: 
   // Properties
+  Gaudi::Property<double> m_significanceTruthCut { this, 
+                                                   "SignificanceTruthCut", 
+                                                   3.0, 
+                                                   "Reco track must pass within this many sigma of pp vertex to be good" };
+
+  Gaudi::Property<int> m_truthVertexTracks { this, 
+                                             "MinTruthVertexTracks", 
+                                             2, 
+                                             "Minimum associated reconstructed tracks for vertex to be considered visible" };
+
   bool m_useBeamConstraint;
 
   // Tools
@@ -94,6 +110,9 @@ class GaussianDensityTestAlg
   ToolHandle< Trk::IVertexTrackDensityEstimator > m_estimator { this, "Estimator", "Trk::GaussianTrackDensity", 
                                                                 "Track density function" };
 
+  ToolHandle< Trk::ITrackToVertexIPEstimator > m_ipEstimator { this, "IPEstimator", "Trk::TrackToVertexIPEstimator",
+                                                                 "Impact point estimator" };
+
   // Non-property private data
   
   ServiceHandle< IBeamCondSvc > m_iBeamCondSvc;
@@ -103,9 +122,17 @@ class GaussianDensityTestAlg
   SG::ReadHandleKey<xAOD::TrackParticleContainer> m_trackParticlesKey  { this, "TrackParticles", "InDetTrackParticles", 
                                                                          "Input track particle collection" };
 
+  SG::ReadHandleKey<xAOD::TruthEventContainer> m_truthEventsKey { this, "TruthEvents", "TruthEvents",
+                                                                  "Key for truth event collection" };
+
+  SG::ReadHandleKey<xAOD::TruthPileupEventContainer> m_pileupEventsKey { this, "TruthPileupEvents", "TruthPileupEvents",
+                                                                         "Key for truth pileup event collection" };
+  
   /// Histograms and trees
 
   TH1* m_h_density;
+  TH1* m_h_truthDensity;
+  TH1* m_h_truthVertices;
 
 }; // class
 }  // namespace
diff --git a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianTrackDensity.cxx b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianTrackDensity.cxx
index 2e4aaafbf3d..cdc4c70dce3 100644
--- a/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianTrackDensity.cxx
+++ b/Tracking/TrkVertexFitter/TrkVertexSeedFinderUtils/src/GaussianTrackDensity.cxx
@@ -110,7 +110,6 @@ namespace Trk
 	double cov_zz = perigeeCov(Trk::z0, Trk::z0);
 	if (cov_zz <= 0 ) continue;
 	double cov_dz = perigeeCov(Trk::d0, Trk::z0);
-	//ATH_MSG_DEBUG("z0:" << z0 << " d0: " << d0 << " covdd, covdz, covzz " << cov_dd << " " << cov_dz << " " << cov_zz);
 	double covDeterminant = cov_dd*cov_zz - cov_dz*cov_dz;
 	if ( covDeterminant <= 0 ) continue;
 	double constantTerm = -(d0*d0*cov_zz + z0*z0*cov_dd + 2*d0*z0*cov_dz) / (2*covDeterminant);
@@ -121,8 +120,7 @@ namespace Trk
 	discriminant = sqrt(discriminant);
 	double zMax = (-linearTerm - discriminant)/(2*quadraticTerm);
 	double zMin = (-linearTerm + discriminant)/(2*quadraticTerm);
-	//ATH_MSG_DEBUG("zMin: " << zMin << " zMax: " << zMax);
-	constantTerm -= log(2*Gaudi::Units::pi*covDeterminant);
+	constantTerm -= log(2*Gaudi::Units::pi*sqrt(covDeterminant));
 	m_trackMap.emplace(std::piecewise_construct,
                            std::forward_as_tuple(*itrk),
 			   std::forward_as_tuple(constantTerm, linearTerm, quadraticTerm, zMin, zMax));
-- 
GitLab