ATLAS Offline Software
ChargedHadronSubtractionTool.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #ifndef JETRECTOOLS_CHARGEDHADRONSUBTRACTIONTOOL_H
6 #define JETRECTOOLS_CHARGEDHADRONSUBTRACTIONTOOL_H
7 
15 
16 #include <string>
19 
24 #include "xAODPFlow/PFOContainer.h"
26 
28 
29 
32 
33  public:
34 
35  ChargedHadronSubtractionTool(const std::string& name);
36 
37  // Check that the configuration is reasonable
39 
40  private:
41  // Implement the correction
43  template <class T, class U> StatusCode matchToPrimaryVertex(T &) const;
44  template <class T, class U> StatusCode matchByPrimaryVertex(T &) const;
45 
46  const xAOD::Vertex* getPrimaryVertex() const;
47 
48  // properties -----------------
49 
50  Gaudi::Property<bool> m_useTrackToVertexTool = {this, "UseTrackToVertexTool", false, "True if we will use the track to vertex tool"};
51  Gaudi::Property<bool> m_ignoreVertex = {this, "IgnoreVertex", false, "Dummy option for cosmics - accept everything"};
52  Gaudi::Property<float> m_z0sinThetaCutValue = {this, "Z0sinThetaCutValue", 2.0, "True if we will use the track to vertex tool"};
53  Gaudi::Property<bool> m_byVertex = {this, "DoByVertex", false, "True if we should match to each primary vertex, not just PV0"};
54 
55  static double calcAbsZ0SinTheta(const xAOD::TrackParticle& trk, const xAOD::Vertex& vtx);
56 
57  SG::ReadHandleKey<xAOD::VertexContainer> m_vertexContainer_key = {this, "VertexContainerKey", "PrimaryVertices", "key for the primary vertex container"};
58  SG::ReadHandleKey<jet::TrackVertexAssociation> m_trkVtxAssoc_key = {this, "TrackVertexAssociation", "JetTrackVtxAssoc", "key for the TrackVertexAssociation object"};
59 
60 
61 
62 };
63 
64 
65 template <class T, class U> StatusCode ChargedHadronSubtractionTool::matchToPrimaryVertex(T& cont) const
66 {
67  const static SG::AuxElement::Accessor<char> PVMatchedAcc("matchedToPV");
68  const static SG::AuxElement::Accessor<char> PUsidebandMatchedAcc("matchedToPUsideband");
69 
70  // Use only one of TVA or PV
71  const jet::TrackVertexAssociation *trkVtxAssoc = nullptr;
72  const xAOD::Vertex *vtx = nullptr;
73  if (!m_ignoreVertex)
74  {
75  // In cosmics, there's no PV container so we need to avoid attempting
76  // to retrieve anything related to it
78  {
79  auto handle = SG::makeHandle(m_trkVtxAssoc_key);
80  if (!handle.isValid())
81  {
82  ATH_MSG_ERROR("Can't retrieve TrackVertexAssociation : " << m_trkVtxAssoc_key.key());
83  return StatusCode::FAILURE;
84  }
85  trkVtxAssoc = handle.cptr();
86  }
87  else
88  {
89  vtx = getPrimaryVertex();
90  if (vtx == nullptr)
91  {
92  ATH_MSG_ERROR("Primary vertex container was empty or no valid vertex found!");
93  return StatusCode::FAILURE;
94  }
95  else if (vtx->vertexType() == xAOD::VxType::NoVtx)
96  {
97  ATH_MSG_VERBOSE("No genuine primary vertex found. Will consider all PFOs matched.");
98  }
99  }
100  }
101 
102  for (U *ppfo : cont)
103  {
104  // Ignore neutral PFOs
105  if constexpr (std::is_same_v<U, xAOD::PFO>) {
106  if (std::abs(ppfo->charge()) < FLT_MIN)
107  continue;
108  } else if constexpr (std::is_same_v<U, xAOD::FlowElement>) {
109  if (!ppfo->isCharged())
110  continue;
111  }
112 
113  bool matchedToPrimaryVertex = false;
114  bool matchedToPileupSideband = false;
115  if (m_ignoreVertex)
116  {
117  // If we don't use vertex information, don't bother computing the decision
118  // Just pass every cPFO -- there shouldn't be many in cosmics!
119  matchedToPrimaryVertex = true;
120  }
121  else
122  {
123  const xAOD::TrackParticle* ptrk = nullptr;
124 
125  // Use different methods to get TrackParticle based on U
126  if constexpr (std::is_same_v<U, xAOD::PFO>) {
127  ptrk = ppfo->track(0);
128  } else if constexpr (std::is_same_v<U, xAOD::FlowElement>) {
129  ptrk = dynamic_cast<const xAOD::TrackParticle*>(ppfo->chargedObject(0));
130  }
131  if (ptrk == nullptr)
132  {
133  ATH_MSG_WARNING("Charged PFO with index " << ppfo->index() << " has no ID track!");
134  continue;
135  }
136  if (trkVtxAssoc)
137  { // Use TrackVertexAssociation
138  const xAOD::Vertex *thisTracksVertex = trkVtxAssoc->associatedVertex(ptrk);
139  if (thisTracksVertex == nullptr)
140  {
141  ATH_MSG_DEBUG("No vertex associated to track " << ptrk->index() << "! So it cannot be associated to the primary vertex");
142  matchedToPrimaryVertex = false;
143  }
144  else
145  {
146  matchedToPrimaryVertex = (xAOD::VxType::PriVtx == thisTracksVertex->vertexType());
147 
148  // r21 PU sideband definition (see below)
149  // needed for comparisons with new r22 definition (neutral only)
150  vtx = getPrimaryVertex();
151  if (vtx != nullptr && vtx->vertexType() != xAOD::VxType::NoVtx)
152  {
153  const double absZ0sinTheta = calcAbsZ0SinTheta(*ptrk, *vtx);
154  if (absZ0sinTheta < 2.0 * m_z0sinThetaCutValue && absZ0sinTheta >= m_z0sinThetaCutValue)
155  matchedToPileupSideband = true;
156  }
157  }
158  }
159  else
160  { // Use Primary Vertex
161  if (vtx->vertexType() == xAOD::VxType::NoVtx)
162  { // No reconstructed vertices
163  matchedToPrimaryVertex = true; // simply match all cPFOs in this case
164  }
165  else
166  { // Had a good reconstructed vertex.
167  // vtz.z() provides z of that vertex w.r.t the center of the beamspot (z = 0).
168  // Thus we correct the track z0 to be w.r.t z = 0
169  float z0 = ptrk->z0() + ptrk->vz() - vtx->z();
170  float theta = ptrk->theta();
171  matchedToPrimaryVertex = (std::abs(z0 * sin(theta)) < m_z0sinThetaCutValue);
172  if (std::abs(z0 * sin(theta)) < 2.0 * m_z0sinThetaCutValue && std::abs(z0 * sin(theta)) >= m_z0sinThetaCutValue)
173  matchedToPileupSideband = true;
174  }
175  } // TVA vs PV decision
176  }
177  PVMatchedAcc(*ppfo) = matchedToPrimaryVertex;
178  PUsidebandMatchedAcc(*ppfo) = matchedToPileupSideband;
179  }
180 
181  return StatusCode::SUCCESS;
182 }
183 
184 template <class T, class U> StatusCode ChargedHadronSubtractionTool::matchByPrimaryVertex(T& cont) const
185 {
186  const static SG::AuxElement::Accessor<std::vector<unsigned>> matchingPVs("MatchingPVs");
187  const static SG::AuxElement::Accessor<std::vector<unsigned>> matchingPUSBs("MatchingPUsidebands");
188 
189  // Retrieve Primary Vertices
190  auto handle = SG::makeHandle(m_vertexContainer_key);
191  if (!handle.isValid())
192  {
193  ATH_MSG_WARNING(" This event has no primary vertex container");
194  return StatusCode::FAILURE;
195  }
196 
197  const xAOD::VertexContainer *pvtxs = handle.cptr();
198  if (pvtxs->empty())
199  {
200  ATH_MSG_WARNING(" Failed to retrieve valid primary vertex container");
201  return StatusCode::FAILURE;
202  }
203 
204  // Use only one of TVA or PV
205  const jet::TrackVertexAssociation *trkVtxAssoc = nullptr;
207  {
208  auto handle = SG::makeHandle(m_trkVtxAssoc_key);
209  if (!handle.isValid())
210  {
211  ATH_MSG_ERROR("Can't retrieve TrackVertexAssociation : " << m_trkVtxAssoc_key.key());
212  return StatusCode::FAILURE;
213  }
214  trkVtxAssoc = handle.cptr();
215  }
216 
217  for (U *ppfo : cont)
218  {
219  // Ignore neutral PFOs
220  if constexpr (std::is_same_v<U, xAOD::PFO>) {
221  if (std::abs(ppfo->charge()) < FLT_MIN)
222  continue;
223  } else if constexpr (std::is_same_v<U, xAOD::FlowElement>) {
224  if (!ppfo->isCharged())
225  continue;
226  }
227 
228  // Get the track for this charged PFO
229  const xAOD::TrackParticle* ptrk = nullptr;
230 
231  // Use different methods to get TrackParticle based on U
232  if constexpr (std::is_same_v<U, xAOD::PFO>) {
233  ptrk = ppfo->track(0);
234  } else if constexpr (std::is_same_v<U, xAOD::FlowElement>) {
235  ptrk = dynamic_cast<const xAOD::TrackParticle*>(ppfo->chargedObject(0));
236  }
237  if (ptrk == nullptr)
238  {
239  ATH_MSG_WARNING("Charged PFO with index " << ppfo->index() << " has no ID track!");
240  continue;
241  }
242 
243  std::vector<unsigned> matchingVertexList;
244  std::vector<unsigned> matchingPUSBList;
245 
246  if (trkVtxAssoc)
247  {
248  // Use TrackVertexAssociation
249  const xAOD::Vertex *thisTracksVertex = trkVtxAssoc->associatedVertex(ptrk);
250  if (thisTracksVertex == nullptr)
251  {
252  ATH_MSG_DEBUG("No vertex associated to track " << ptrk->index() << "! So it cannot be associated to the primary vertex");
253  }
254  else
255  {
256  matchingVertexList.push_back(thisTracksVertex->index());
257  for (const xAOD::Vertex *vtx : *pvtxs){
258  if (vtx != nullptr && vtx->vertexType() != xAOD::VxType::NoVtx)
259  {
260  float z0 = ptrk->z0() + ptrk->vz() - vtx->z();
261  float theta = ptrk->theta();
262 
263  if (std::abs(z0 * sin(theta)) < 2.0 * m_z0sinThetaCutValue && std::abs(z0 * sin(theta)) >= m_z0sinThetaCutValue)
264  matchingPUSBList.push_back(vtx->index());
265  }
266  }
267  }
268  }
269  else{
270  // Use z0sinThetaCutValue
271  // Loop over the primary vertices to determine which ones potentially match
272  for (const xAOD::Vertex *vtx : *pvtxs)
273  {
274  bool matchedToVertex = false;
275  bool matchedToPileupSideband = false;
276 
277  if (vtx == nullptr)
278  {
279  ATH_MSG_WARNING("Encountered a nullptr vertex when trying to match charged PFOs to vertices");
280  continue;
281  }
282  else if (vtx->vertexType() == xAOD::VxType::NoVtx)
283  { // No reconstructed vertices
284  matchedToVertex = true; // simply match all cPFOs in this case
285  }
286  else
287  { // Had a good reconstructed vertex
288  const double absZ0sinTheta = calcAbsZ0SinTheta(*ptrk, *vtx);
289  matchedToVertex = (absZ0sinTheta < m_z0sinThetaCutValue);
290  if (absZ0sinTheta < 2.0 * m_z0sinThetaCutValue && absZ0sinTheta >= m_z0sinThetaCutValue)
291  matchedToPileupSideband = true;
292  }
293 
294  if (matchedToVertex)
295  matchingVertexList.push_back(vtx->index());
296  if (matchedToPileupSideband)
297  matchingPUSBList.push_back(vtx->index());
298  }
299  }
300 
301  matchingPVs(*ppfo) = matchingVertexList;
302  matchingPUSBs(*ppfo) = matchingPUSBList;
303  }
304 
305  return StatusCode::SUCCESS;
306 }
307 
308 #endif
FlowElementContainer.h
ChargedHadronSubtractionTool::matchToPrimaryVertex
StatusCode matchToPrimaryVertex(T &) const
Definition: ChargedHadronSubtractionTool.h:65
ChargedHadronSubtractionTool::m_z0sinThetaCutValue
Gaudi::Property< float > m_z0sinThetaCutValue
Definition: ChargedHadronSubtractionTool.h:52
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:66
ChargedHadronSubtractionTool::ChargedHadronSubtractionTool
ChargedHadronSubtractionTool(const std::string &name)
Definition: ChargedHadronSubtractionTool.cxx:9
xAOD::TrackParticle_v1::vz
float vz() const
The z origin for the parameters.
theta
Scalar theta() const
theta method
Definition: AmgMatrixBasePlugin.h:71
JetConstituentModifierBase.h
xAOD::TrackParticle_v1::z0
float z0() const
Returns the parameter.
PFOContainer.h
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
SG::ReadHandleKey
Property holding a SG store/key/clid from which a ReadHandle is made.
Definition: StoreGate/StoreGate/ReadHandleKey.h:39
xAOD::Vertex_v1::vertexType
VxType::VertexType vertexType() const
The type of the vertex.
xAOD::VxType::NoVtx
@ NoVtx
Dummy vertex. TrackParticle was not used in vertex fit.
Definition: TrackingPrimitives.h:570
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:269
ChargedHadronSubtractionTool::m_ignoreVertex
Gaudi::Property< bool > m_ignoreVertex
Definition: ChargedHadronSubtractionTool.h:51
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ChargedHadronSubtractionTool::m_vertexContainer_key
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexContainer_key
Definition: ChargedHadronSubtractionTool.h:57
ChargedHadronSubtractionTool::m_useTrackToVertexTool
Gaudi::Property< bool > m_useTrackToVertexTool
Definition: ChargedHadronSubtractionTool.h:50
CaloCluster.h
ChargedHadronSubtractionTool::matchByPrimaryVertex
StatusCode matchByPrimaryVertex(T &) const
Definition: ChargedHadronSubtractionTool.h:184
IJetConstituentModifier
Definition: IJetConstituentModifier.h:16
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
jet::TrackVertexAssociation
Class to hold N-to-one aassociations between tracks and vertices.
Definition: TrackVertexAssociation.h:23
ReadHandleKey.h
Property holding a SG store/key/clid from which a ReadHandle is made.
IParticleContainer.h
xAOD::VxType::PriVtx
@ PriVtx
Primary vertex.
Definition: TrackingPrimitives.h:571
TrackVertexAssociation.h
ChargedHadronSubtractionTool::getPrimaryVertex
const xAOD::Vertex * getPrimaryVertex() const
Definition: ChargedHadronSubtractionTool.cxx:53
xAOD::Vertex_v1::z
float z() const
Returns the z position.
TRT::Track::z0
@ z0
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:63
SG::AuxElement::index
size_t index() const
Return the index of this element within its container.
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
ChargedHadronSubtractionTool::m_trkVtxAssoc_key
SG::ReadHandleKey< jet::TrackVertexAssociation > m_trkVtxAssoc_key
Definition: ChargedHadronSubtractionTool.h:58
jet::TrackVertexAssociation::associatedVertex
const xAOD::Vertex * associatedVertex(const xAOD::TrackParticle *trk) const
Definition: TrackVertexAssociation.cxx:23
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
JetConstituentModifierBase
Definition: JetConstituentModifierBase.h:22
ChargedHadronSubtractionTool::calcAbsZ0SinTheta
static double calcAbsZ0SinTheta(const xAOD::TrackParticle &trk, const xAOD::Vertex &vtx)
Definition: ChargedHadronSubtractionTool.cxx:95
ChargedHadronSubtractionTool::process_impl
StatusCode process_impl(xAOD::IParticleContainer *cont) const
Definition: ChargedHadronSubtractionTool.cxx:30
ChargedHadronSubtractionTool::initialize
StatusCode initialize()
Dummy implementation of the initialisation function.
Definition: ChargedHadronSubtractionTool.cxx:13
VertexContainer.h
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
ASG_TOOL_CLASS
#define ASG_TOOL_CLASS(CLASSNAME, INT1)
Definition: AsgToolMacros.h:68
ChargedHadronSubtractionTool::m_byVertex
Gaudi::Property< bool > m_byVertex
Definition: ChargedHadronSubtractionTool.h:53
CaloClusterContainer.h
ChargedHadronSubtractionTool
Definition: ChargedHadronSubtractionTool.h:30
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
xAOD::TrackParticle_v1::track
const Trk::Track * track() const
Returns a pointer (which can be NULL) to the Trk::Track which was used to make this TrackParticle.
Definition: TrackParticle_v1.cxx:805
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
xAOD::TrackParticle_v1::theta
float theta() const
Returns the parameter, which has range 0 to .
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35