28#include "Math/GenVector/VectorUtil.h"
29#include "Math/Vector2D.h"
36using ROOT::Math::XYVector;
60 if (item.second.size() > 1) {
61 for (
size_t i = 0; i < item.second.size(); i++) {
78 ATH_MSG_DEBUG(
"No GenericMonitoringTool configured: no monitoring histograms will be available" );
81 return StatusCode::SUCCESS;
91 ATH_CHECK( previousDecisionsHandle.isValid() );
92 ATH_MSG_DEBUG(
"Running with " << previousDecisionsHandle->size() <<
" previous decisions" );
97 ATH_CHECK( trigBphysHandle.record(std::make_unique<xAOD::TrigBphysContainer>(), std::make_unique<xAOD::TrigBphysAuxContainer>()) );
102 auto state = std::make_unique<TrigBhhState>(context, *previousDecisionsHandle, *outputDecisionsHandle, trigBphysHandle.
ptr(), *beamSpotHandle);
109 ATH_MSG_DEBUG(
"TrigBhhComboHypo::execute() terminates with StatusCode::SUCCESS" );
110 return StatusCode::SUCCESS;
116 auto& muons = state.
muons;
126 if (!muon->trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle))
continue;
129 auto itr = std::find_if(muons.begin(), muons.end(), [
this, muon](
const auto&
x){ return isIdenticalTracks(muon, *x.link); });
130 if (itr == muons.end()) {
131 muons.push_back({muonEL, std::vector<ElementLink<DecisionContainer>>(1, decisionEL),
DecisionIDContainer()});
134 (*itr).decisionLinks.push_back(decisionEL);
140 std::sort(muons.begin(), muons.end(), [](
const auto& lhs,
const auto& rhs){ return ((*lhs.link)->pt() > (*rhs.link)->pt()); });
143 for (
auto& item : muons) {
150 ATH_MSG_DEBUG(
"Dump found muons before vertex fit: " << muons.size() <<
" candidates" );
151 for (
const auto& item : muons) {
154 ATH_MSG_DEBUG(
" -- muon InDetTrackParticle pt/eta/phi/q: " << track->pt() <<
" / " << track->eta() <<
" / " << track->phi() <<
" / " << track->charge() );
155 ATH_MSG_DEBUG(
" muon CombinedTrackParticle pt: " << muon->pt() );
157 for (
const DecisionID&
id : item.decisionIDs) {
163 return StatusCode::SUCCESS;
169 const auto& muons = state.
muons;
170 auto& tracks = state.
tracks;
173 size_t viewCounter = 0;
179 auto view = *viewLinkInfo.link;
183 const auto roi = *roiLinkInfo.link;
189 std::vector<ElementLink<xAOD::TrackParticleContainer>> tracksFromView;
190 tracksFromView.reserve(tracksHandle->size());
191 for (
size_t idx = 0; idx < tracksHandle->size(); ++idx) {
195 for (
const auto& trackEL : tracksFromView) {
197 if (track->definingParametersCovMatrixVec().empty())
continue;
199 if (viewCounter == 0 ||
200 std::find_if(tracks.begin(), tracks.end(),
201 [
this, track](
const auto&
x){ return isIdenticalTracks(track, *x); }) == tracks.end()) {
202 tracks.emplace_back(trackEL);
206 if (roi->composite()) {
212 std::sort(tracks.begin(), tracks.end(), [](
const auto& lhs,
const auto& rhs){ return ((*lhs)->pt() > (*rhs)->pt()); });
214 for (
const auto& trackEL : tracks) {
216 ATH_MSG_DEBUG(
" -- track pt/eta/phi/q: " << track->pt() <<
" / " << track->eta() <<
" / " << track->phi() <<
" / " << track->charge() );
220 if (tracks.size() < 2) {
222 return StatusCode::SUCCESS;
227 for (
size_t i = 0; i < muons.size(); ++i) {
230 std::sort(tracks.begin(), tracks.end(), [p_mu=track->genvecP4()](
const auto& lhs,
const auto& rhs){ return ROOT::Math::VectorUtil::DeltaR(p_mu, (*lhs)->genvecP4()) > ROOT::Math::VectorUtil::DeltaR(p_mu, (*rhs)->genvecP4()); });
233 std::sort(tracks.begin(), tracks.end(), [](
const auto& lhs,
const auto& rhs){ return ((*lhs)->pt() > (*rhs)->pt()); });
236 ATH_MSG_DEBUG(
"Found " << tracks.size() <<
" tracks after muon removal" );
237 for (
const auto& trackEL : tracks) {
239 ATH_MSG_DEBUG(
" -- track pt/eta/phi/q: " << track->pt() <<
" / " << track->eta() <<
" / " << track->phi() <<
" / " << track->charge() );
245 std::sort(tracks.begin(), tracks.end(), [](
const auto& lhs,
const auto& rhs){ return ((*lhs)->pt() > (*rhs)->pt()); });
246 tracks.erase(std::upper_bound(tracks.begin(), tracks.end(),
m_trkPt, [](
double trkPt,
const auto& trackEL){ return trkPt > (*trackEL)->pt(); }), tracks.end());
249 ATH_MSG_DEBUG(
"Found " << tracks.size() <<
" tracks after pT threshold cut" );
250 for (
const auto& trackEL : tracks) {
252 ATH_MSG_DEBUG(
" -- track pt/eta/phi/q: " << track->pt() <<
" / " << track->eta() <<
" / " << track->phi() <<
" / " << track->charge() );
255 return StatusCode::SUCCESS;
267 mon_nMuon, mon_nTrk, mon_nBPhysObject);
269 const auto& tracks = state.
tracks;
271 size_t iterations = 0;
272 bool isOverWarningThreshold =
false;
274 std::vector<ElementLink<xAOD::TrackParticleContainer>> trackParticleLinks(2);
275 for (
size_t itrk1 = 0; itrk1 < tracks.size(); ++itrk1) {
276 trackParticleLinks[0] = tracks[itrk1];
279 auto charge1 = trk1->
charge();
281 for (
size_t itrk2 = itrk1 + 1; itrk2 < tracks.size(); ++itrk2) {
282 trackParticleLinks[1] = tracks[itrk2];
285 auto charge2 = trk2->
charge();
290 if (charge1 * charge2 > 0. || mKK <
m_massRange.value().first || mPiPi >
m_massRange.value().second)
continue;
293 auto vertex =
fit(state.
context(), trackParticleLinks);
295 if (!vertex)
continue;
303 ATH_MSG_DEBUG(
"Found B -> h+ h- candidate: M(K+,K-) = " << mKK <<
" M(pi+,pi-) = " << mPiPi );
307 isOverWarningThreshold =
true;
310 ATH_MSG_WARNING(
"b -> hh: the number of fit attempts has exceeded the limit, breaking the loop at this point" );
311 itrk1 = tracks.size();
318 mon_nMuon = state.
muons.size();
319 mon_nTrk = tracks.size();
322 return StatusCode::SUCCESS;
329 std::vector<ElementLink<TrigCompositeUtils::DecisionContainer>> previousDecisionLinks;
331 std::vector<const DecisionIDContainer*> previousDecisionIDs = { &
decisionIDs };
341 ATH_MSG_DEBUG(
"Found xAOD::TrigBphys object: fitMass = " << triggerObject->fitmass() <<
", chi2 = " << triggerObject->fitchi2() );
357 ATH_CHECK( tool->decideOnSingleObject(decision, previousDecisionIDs) );
361 return StatusCode::SUCCESS;
366 const EventContext& context,
368 const std::vector<double>& trkMass)
const {
372 if (trackParticleLinks.size() != 2) {
373 ATH_MSG_WARNING(
"Exactly two tracks should be given to the vertex fitter" );
374 return std::unique_ptr<xAOD::Vertex>(
nullptr);
377 std::vector<const xAOD::TrackParticle*> tracklist(trackParticleLinks.size(),
nullptr);
378 std::transform(trackParticleLinks.begin(), trackParticleLinks.end(), tracklist.begin(),
384 const Trk::Perigee& perigee1 = tracklist[0]->perigeeParameters();
385 const Trk::Perigee& perigee2 = tracklist[1]->perigeeParameters();
386 startingPoint =
m_vertexPointEstimator->getCirclesIntersectionPoint(&perigee1, &perigee2, flag, errorcode);
387 if (errorcode != 0) startingPoint = Amg::Vector3D::Zero(3);
388 ATH_MSG_DEBUG(
"Starting point: (" << startingPoint(0) <<
", " << startingPoint(1) <<
", " << startingPoint(2) <<
")" );
393 std::unique_ptr<xAOD::Vertex> vertex(
m_vertexFitter->fit(tracklist, startingPoint, *fitterState));
398 if (vertex->chiSquared() >
m_chi2) {
399 ATH_MSG_DEBUG(
"Fit is successful, but vertex chi2 is too high, we are not going to save it (chi2 = " << vertex->chiSquared() <<
")" );
406 vertex->clearTracks();
407 vertex->setTrackParticleLinks(trackParticleLinks);
417 const std::vector<double>& trkMass)
const {
421 std::vector<xAOD::TrackParticle::GenVecFourMom_t> momenta;
422 ATH_CHECK( vertex.vxTrackAtVertexAvailable() );
423 ATH_CHECK( vertex.vxTrackAtVertex().size() == trkMass.size() );
424 for (
size_t i = 0; i < vertex.vxTrackAtVertex().size(); ++i) {
428 momenta.emplace_back(p.x(), p.y(), p.z(), trkMass[i]);
429 momentum += momenta.back();
435 triggerObject.
setFitx(vertex.x());
436 triggerObject.
setFity(vertex.y());
437 triggerObject.
setFitz(vertex.z());
438 triggerObject.
setFitchi2(vertex.chiSquared());
440 triggerObject.
setLxy(
Lxy(productionVertex, vertex.position(), momenta));
446 "TrigBphys object:\n\t " <<
447 "roiId: " << triggerObject.
roiId() <<
"\n\t " <<
448 "particleType: " << triggerObject.
particleType() <<
"\n\t " <<
449 "level: " << triggerObject.
level() <<
"\n\t " <<
450 "eta: " << triggerObject.
eta() <<
"\n\t " <<
451 "phi: " << triggerObject.
phi() <<
"\n\t " <<
452 "mass: " << triggerObject.
mass() <<
"\n\t " <<
453 "fitmass: " << triggerObject.
fitmass() <<
"\n\t " <<
454 "chi2/NDF: " << triggerObject.
fitchi2() <<
" / " << triggerObject.
fitndof() <<
"\n\t " <<
455 "vertex: (" << triggerObject.
fitx() <<
", " << triggerObject.
fity() <<
", " << triggerObject.
fitz() <<
")" );
457 return StatusCode::SUCCESS;
476 XYVector R(decayVertex.x() - productionVertex.x(), decayVertex.y() - productionVertex.y());
478 for (
const auto& p : momenta) {
479 pT += XYVector(p.x(), p.y());
481 return R.Dot(pT.unit());
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
Base class for elements of a container that can have aux data.
void decisionIDs(const Decision *d, DecisionIDContainer &id)
Extracts DecisionIDs stored in the Decision object.
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)
bool msgLvl(const MSG::Level lvl) const
ComboHypo(const std::string &name, ISvcLocator *pSvcLocator)
const SG::WriteHandleKeyArray< TrigCompositeUtils::DecisionContainer > & decisionsOutput() const
const Combo::MultiplicityReqMap & triggerMultiplicityMap() const
ToolHandleArray< ComboHypoToolBase > & hypoTools()
const SG::ReadHandleKeyArray< TrigCompositeUtils::DecisionContainer > & decisionsInput() const
virtual StatusCode initialize() override
const T * back() const
Access the last element in the collection as an rvalue.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
ElementLink implementation for ROOT usage.
TrigCompositeUtils::DecisionContainer & decisions()
const TrigCompositeUtils::DecisionContainer & previousDecisions() const
xAOD::TrigBphysContainer & trigBphysCollection()
Amg::Vector3D beamSpotPosition() const
const EventContext & context() const
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
pointer_type ptr()
Dereference the pointer.
ToolHandle< InDet::VertexPointEstimator > m_vertexPointEstimator
StatusCode fillTriggerObject(xAOD::TrigBphys &triggerObject, const xAOD::Vertex &vertex, const Amg::Vector3D &productionVertex, const std::vector< double > &trkMass={PDG::mKaon, PDG::mKaon}) const
Fill the trigger object that may be stored for debugging or matching.
Gaudi::Property< double > m_chi2
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_trackParticleContainerKey
TrigBhhComboHypo()=delete
StatusCode mergeMuonsFromDecisions(TrigBhhState &) const
Go through state.previousDecisions(), fetch xAOD::Muons objects attached to decisions and save links ...
ToolHandle< Trk::TrkVKalVrtFitter > m_vertexFitter
Gaudi::Property< double > m_trkPt
virtual StatusCode execute(const EventContext &context) const override
bool isIdenticalTracks(const xAOD::TrackParticle *lhs, const xAOD::TrackParticle *rhs) const
Returns false for the tracks with opposite charges.
Gaudi::Property< std::pair< double, double > > m_massRange
SG::WriteHandleKey< xAOD::TrigBphysContainer > m_trigBphysContainerKey
ToolHandle< GenericMonitoringTool > m_monTool
TrigCompositeUtils::DecisionIDContainer m_allowedIDs
Gaudi::Property< double > m_deltaR
Gaudi::Property< size_t > m_fitAttemptsBreakThreshold
virtual StatusCode initialize() override
std::unique_ptr< xAOD::Vertex > fit(const EventContext &context, const std::vector< ElementLink< xAOD::TrackParticleContainer > > &trackParticleLinks, const std::vector< double > &trkMass={PDG::mKaon, PDG::mKaon}) const
Perform a vertex fit on selected tracks.
Gaudi::Property< bool > m_applyMuonRemoval
double Lxy(const Amg::Vector3D &productionVertex, const Amg::Vector3D &decayVertex, const std::vector< xAOD::TrackParticle::GenVecFourMom_t > &momenta) const
Returns the transverse decay length of a particle Lxy in [mm].
Gaudi::Property< size_t > m_fitAttemptsWarningThreshold
StatusCode findBhhCandidates(TrigBhhState &) const
Make all possible combinations from state.tracks(), fit tracks to the common vertex,...
StatusCode mergeTracksFromViews(TrigBhhState &) const
Go through state.previousDecisions() and fetch xAOD::TrackParticle objects associated with the neares...
SG::ReadCondHandleKey< InDet::BeamSpotData > m_beamSpotKey
StatusCode createDecisionObjects(TrigBhhState &) const
Create a decision for each xAOD::TrigBphys object from state.trigBphysCollection() and use hypoTools(...
State class for TrigBhhComboHypo algorithm.
std::vector< ElementLink< xAOD::TrackParticleContainer > > tracks
std::vector< Muon > muons
const Amg::Vector3D & momentum() const
Access method for the momentum.
const ElementLink< TrackParticleContainer > & inDetTrackParticleLink() const
Returns an ElementLink to the InnerDetector TrackParticle used in identification of this muon.
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzM4D< double > > GenVecFourMom_t
Base 4 Momentum type for TrackParticle.
GenVecFourMom_t genvecP4() const
The full 4-momentum of the particle : GenVector form.
float charge() const
Returns the charge.
int fitndof() const
accessor method: ndof from vertex fit
void setFitchi2(float FitChi2)
set method: chi2 from vertex fit
void setFitx(float FitX)
set method: x position of vertex
uint32_t roiId() const
accessor method: ID of L1 RoI
void setFity(float FitY)
set method: y position of vertex
float eta() const
accessor method: eta
pType particleType() const
accessor method: particle Type
float phi() const
accessor method: phi
float fitchi2() const
accessor method: chi2 from vertex fit
void setFitndof(int FitNdof)
set method: ndof from vertex fit
void setFitz(float FitZ)
set method: z position of vertex
float fitx() const
accessor method: x position of vertex
void setLxy(float v)
set method: lxy
void setFitmass(float FitMass)
set method: mass from vertex fit
float fitz() const
accessor method: z position of vertex
float fitmass() const
accessor method: mass from vertex fit
float mass() const
accessor method: mass
void setMass(float)
Set the mass of the object.
float fity() const
accessor method: y position of vertex
levelType level() const
accessor method: level Type
void setTrackParticleLinks(const std::vector< ElementLink< TrackParticleContainer > > &links)
Set the track particle links on the object.
bool setObjectLink(const std::string &name, const ElementLink< CONTAINER > &link)
Set the link to an object.
bool addObjectCollectionLinks(const std::string &collectionName, const std::vector< ElementLink< CONTAINER > > &links)
Add links to multiple objects within a collection. Performs de-duplication.
Eigen::Matrix< double, 3, 1 > Vector3D
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
HLT::Identifier createLegName(const HLT::Identifier &chainIdentifier, size_t counter)
Generate the HLT::Identifier which corresponds to a specific leg of a given chain.
const std::string & viewString()
xAOD::TrigComposite Decision
const std::string & roiString()
Decision * newDecisionIn(DecisionContainer *dc, const std::string &name)
Helper method to create a Decision object, place it in the container and return a pointer to it.
const std::string & featureString()
const std::string & comboHypoAlgNodeName()
std::set< DecisionID > DecisionIDContainer
SG::WriteHandle< DecisionContainer > createAndStore(const SG::WriteHandleKey< DecisionContainer > &key, const EventContext &ctx)
Creates and right away records the DecisionContainer with the key.
LinkInfo< T > findLink(const Decision *start, const std::string &linkName, const bool suppressMultipleLinksWarning=false)
Perform a recursive search for ElementLinks of type T and name 'linkName', starting from Decision obj...
const std::string & seedString()
xAOD::TrigCompositeContainer DecisionContainer
void decisionIDs(const Decision *d, DecisionIDContainer &destination)
Extracts DecisionIDs stored in the Decision object.
bool isAnyIDPassing(const Decision *d, const DecisionIDContainer &required)
Checks if any of the DecisionIDs passed in arg required is availble in Decision object.
ElementLink< DecisionContainer > decisionToElementLink(const Decision *d, const EventContext &ctx)
Takes a raw pointer to a Decision and returns an ElementLink to the Decision.
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
ParametersBase< TrackParametersDim, Charged > TrackParameters
ElementLink< T > makeLink(const SG::View *view, const SG::ReadHandle< T > &handle, size_t index)
Create EL to a collection in view.
auto makeHandle(const SG::View *view, const KEY &key, const EventContext &ctx)
Create a view handle from a handle key.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Vertex_v1 Vertex
Define the latest version of the vertex class.
Muon_v1 Muon
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
TrigBphysContainer_v1 TrigBphysContainer
static constexpr double mPion
static constexpr double mKaon