29#include "Math/GenVector/VectorUtil.h"
30#include "Math/Vector2D.h"
37using ROOT::Math::XYVector;
61 if (item.second.size() > 1) {
62 for (
size_t i = 0; i < item.second.size(); i++) {
79 ATH_MSG_DEBUG(
"No GenericMonitoringTool configured: no monitoring histograms will be available" );
82 return StatusCode::SUCCESS;
92 ATH_CHECK( previousDecisionsHandle.isValid() );
93 ATH_MSG_DEBUG(
"Running with " << previousDecisionsHandle->size() <<
" previous decisions" );
98 ATH_CHECK( trigBphysHandle.record(std::make_unique<xAOD::TrigBphysContainer>(), std::make_unique<xAOD::TrigBphysAuxContainer>()) );
103 auto state = std::make_unique<TrigBhhState>(context, *previousDecisionsHandle, *outputDecisionsHandle, trigBphysHandle.
ptr(), *beamSpotHandle);
110 ATH_MSG_DEBUG(
"TrigBhhComboHypo::execute() terminates with StatusCode::SUCCESS" );
111 return StatusCode::SUCCESS;
117 auto& muons = state.
muons;
127 if (!muon->trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle))
continue;
130 auto itr = std::find_if(muons.begin(), muons.end(), [
this, muon](
const auto&
x){ return isIdenticalTracks(muon, *x.link); });
131 if (itr == muons.end()) {
132 muons.push_back({muonEL, std::vector<ElementLink<DecisionContainer>>(1, decisionEL),
DecisionIDContainer()});
135 (*itr).decisionLinks.push_back(decisionEL);
141 std::sort(muons.begin(), muons.end(), [](
const auto& lhs,
const auto& rhs){ return ((*lhs.link)->pt() > (*rhs.link)->pt()); });
144 for (
auto& item : muons) {
151 ATH_MSG_DEBUG(
"Dump found muons before vertex fit: " << muons.size() <<
" candidates" );
152 for (
const auto& item : muons) {
154 const xAOD::TrackParticle* track = muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
155 ATH_MSG_DEBUG(
" -- muon InDetTrackParticle pt/eta/phi/q: " << track->pt() <<
" / " << track->eta() <<
" / " << track->phi() <<
" / " << track->charge() );
156 ATH_MSG_DEBUG(
" muon CombinedTrackParticle pt: " << muon->pt() );
158 for (
const DecisionID&
id : item.decisionIDs) {
164 return StatusCode::SUCCESS;
170 const auto& muons = state.
muons;
171 auto& tracks = state.
tracks;
174 size_t viewCounter = 0;
180 auto view = *viewLinkInfo.link;
184 const auto roi = *roiLinkInfo.link;
190 std::vector<ElementLink<xAOD::TrackParticleContainer>> tracksFromView;
191 tracksFromView.reserve(tracksHandle->size());
192 for (
size_t idx = 0; idx < tracksHandle->size(); ++idx) {
196 for (
const auto& trackEL : tracksFromView) {
198 if (track->definingParametersCovMatrixVec().empty())
continue;
200 if (viewCounter == 0 ||
201 std::find_if(tracks.begin(), tracks.end(),
202 [
this, track](
const auto&
x){ return isIdenticalTracks(track, *x); }) == tracks.end()) {
203 tracks.emplace_back(trackEL);
207 if (roi->composite()) {
213 std::sort(tracks.begin(), tracks.end(), [](
const auto& lhs,
const auto& rhs){ return ((*lhs)->pt() > (*rhs)->pt()); });
215 for (
const auto& trackEL : tracks) {
217 ATH_MSG_DEBUG(
" -- track pt/eta/phi/q: " << track->pt() <<
" / " << track->eta() <<
" / " << track->phi() <<
" / " << track->charge() );
221 if (tracks.size() < 2) {
223 return StatusCode::SUCCESS;
228 for (
size_t i = 0; i < muons.size(); ++i) {
230 const xAOD::TrackParticle* track = muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
231 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()); });
234 std::sort(tracks.begin(), tracks.end(), [](
const auto& lhs,
const auto& rhs){ return ((*lhs)->pt() > (*rhs)->pt()); });
237 ATH_MSG_DEBUG(
"Found " << tracks.size() <<
" tracks after muon removal" );
238 for (
const auto& trackEL : tracks) {
240 ATH_MSG_DEBUG(
" -- track pt/eta/phi/q: " << track->pt() <<
" / " << track->eta() <<
" / " << track->phi() <<
" / " << track->charge() );
246 std::sort(tracks.begin(), tracks.end(), [](
const auto& lhs,
const auto& rhs){ return ((*lhs)->pt() > (*rhs)->pt()); });
247 tracks.erase(std::upper_bound(tracks.begin(), tracks.end(),
m_trkPt, [](
double trkPt,
const auto& trackEL){ return trkPt > (*trackEL)->pt(); }), tracks.end());
250 ATH_MSG_DEBUG(
"Found " << tracks.size() <<
" tracks after pT threshold cut" );
251 for (
const auto& trackEL : tracks) {
253 ATH_MSG_DEBUG(
" -- track pt/eta/phi/q: " << track->pt() <<
" / " << track->eta() <<
" / " << track->phi() <<
" / " << track->charge() );
256 return StatusCode::SUCCESS;
268 mon_nMuon, mon_nTrk, mon_nBPhysObject);
270 const auto& tracks = state.
tracks;
272 size_t iterations = 0;
273 bool isOverWarningThreshold =
false;
275 std::vector<ElementLink<xAOD::TrackParticleContainer>> trackParticleLinks(2);
276 for (
size_t itrk1 = 0; itrk1 < tracks.size(); ++itrk1) {
277 trackParticleLinks[0] = tracks[itrk1];
280 auto charge1 = trk1->
charge();
282 for (
size_t itrk2 = itrk1 + 1; itrk2 < tracks.size(); ++itrk2) {
283 trackParticleLinks[1] = tracks[itrk2];
286 auto charge2 = trk2->
charge();
291 if (charge1 * charge2 > 0. || mKK <
m_massRange.value().first || mPiPi >
m_massRange.value().second)
continue;
294 auto vertex =
fit(state.
context(), trackParticleLinks);
296 if (!vertex)
continue;
304 ATH_MSG_DEBUG(
"Found B -> h+ h- candidate: M(K+,K-) = " << mKK <<
" M(pi+,pi-) = " << mPiPi );
308 isOverWarningThreshold =
true;
311 ATH_MSG_WARNING(
"b -> hh: the number of fit attempts has exceeded the limit, breaking the loop at this point" );
312 itrk1 = tracks.size();
319 mon_nMuon = state.
muons.size();
320 mon_nTrk = tracks.size();
323 return StatusCode::SUCCESS;
330 std::vector<ElementLink<TrigCompositeUtils::DecisionContainer>> previousDecisionLinks;
332 std::vector<const DecisionIDContainer*> previousDecisionIDs = { &
decisionIDs };
342 ATH_MSG_DEBUG(
"Found xAOD::TrigBphys object: fitMass = " << triggerObject->fitmass() <<
", chi2 = " << triggerObject->fitchi2() );
358 ATH_CHECK( tool->decideOnSingleObject(decision, previousDecisionIDs) );
362 return StatusCode::SUCCESS;
367 const EventContext& context,
369 const std::vector<double>& trkMass)
const {
373 if (trackParticleLinks.size() != 2) {
374 ATH_MSG_WARNING(
"Exactly two tracks should be given to the vertex fitter" );
375 return std::unique_ptr<xAOD::Vertex>(
nullptr);
378 std::vector<const xAOD::TrackParticle*> tracklist(trackParticleLinks.size(),
nullptr);
379 std::transform(trackParticleLinks.begin(), trackParticleLinks.end(), tracklist.begin(),
385 const Trk::Perigee& perigee1 = tracklist[0]->perigeeParameters();
386 const Trk::Perigee& perigee2 = tracklist[1]->perigeeParameters();
387 startingPoint =
m_vertexPointEstimator->getCirclesIntersectionPoint(&perigee1, &perigee2, flag, errorcode);
388 if (errorcode != 0) startingPoint = Amg::Vector3D::Zero(3);
389 ATH_MSG_DEBUG(
"Starting point: (" << startingPoint(0) <<
", " << startingPoint(1) <<
", " << startingPoint(2) <<
")" );
394 std::unique_ptr<xAOD::Vertex> vertex(
m_vertexFitter->fit(tracklist, startingPoint, *fitterState));
399 if (vertex->chiSquared() >
m_chi2) {
400 ATH_MSG_DEBUG(
"Fit is successful, but vertex chi2 is too high, we are not going to save it (chi2 = " << vertex->chiSquared() <<
")" );
407 vertex->clearTracks();
408 vertex->setTrackParticleLinks(trackParticleLinks);
418 const std::vector<double>& trkMass)
const {
422 std::vector<xAOD::TrackParticle::GenVecFourMom_t> momenta;
423 ATH_CHECK( vertex.vxTrackAtVertexAvailable() );
424 ATH_CHECK( vertex.vxTrackAtVertex().size() == trkMass.size() );
425 for (
size_t i = 0; i < vertex.vxTrackAtVertex().
size(); ++i) {
429 momenta.emplace_back(p.x(), p.y(), p.z(), trkMass[i]);
430 momentum += momenta.back();
436 triggerObject.
setFitx(vertex.x());
437 triggerObject.
setFity(vertex.y());
438 triggerObject.
setFitz(vertex.z());
439 triggerObject.
setFitchi2(vertex.chiSquared());
441 triggerObject.
setLxy(
Lxy(productionVertex, vertex.position(), momenta));
447 "TrigBphys object:\n\t " <<
448 "roiId: " << triggerObject.
roiId() <<
"\n\t " <<
449 "particleType: " << triggerObject.
particleType() <<
"\n\t " <<
450 "level: " << triggerObject.
level() <<
"\n\t " <<
451 "eta: " << triggerObject.
eta() <<
"\n\t " <<
452 "phi: " << triggerObject.
phi() <<
"\n\t " <<
453 "mass: " << triggerObject.
mass() <<
"\n\t " <<
454 "fitmass: " << triggerObject.
fitmass() <<
"\n\t " <<
455 "chi2/NDF: " << triggerObject.
fitchi2() <<
" / " << triggerObject.
fitndof() <<
"\n\t " <<
456 "vertex: (" << triggerObject.
fitx() <<
", " << triggerObject.
fity() <<
", " << triggerObject.
fitz() <<
")" );
458 return StatusCode::SUCCESS;
472 rhs->
trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle));
478 XYVector R(decayVertex.x() - productionVertex.x(), decayVertex.y() - productionVertex.y());
480 for (
const auto& p : momenta) {
481 pT += XYVector(p.x(), p.y());
483 return R.Dot(pT.unit());
#define ATH_CHECK
Evaluate an expression and check for errors.
ElementLink()
Default constructor.
#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.
size_t size() const
Number of registered mappings.
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 TrackParticle * trackParticle(TrackParticleType type) const
Returns a pointer (which can be NULL) to the 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 CLID ID()
static constexpr double mPion
static constexpr double mKaon