7 #include "GaudiKernel/SystemOfUnits.h"
13 using namespace Gaudi::Units;
37 return StatusCode::SUCCESS;
53 std::vector<std::unique_ptr<xAOD::Vertex>> offlineDimuons;
55 ATH_MSG_ERROR(
"Problems building offline dimuons, won't fill corresponding histograms");
61 return StatusCode::SUCCESS;
67 ATH_MSG_DEBUG(
"Process container " << monitoredContainerKey.key().c_str());
69 ATH_MSG_ERROR(Form(
"Problems filling %s container histograms", monitoredContainerKey.key().c_str()));
73 return StatusCode::SUCCESS;
78 if( !trigBphysContainer.
isValid() ) {
79 ATH_MSG_WARNING(
"No valid TrigBphysContainer with tag: " << trigBphysContainerKey);
83 std::string monGroupName = std::string(
"Container_")+trigBphysContainerKey.
key();
87 ncandidates = trigBphysContainer->
size();
94 return StatusCode::SUCCESS;
103 ATH_MSG_DEBUG(
"Chain " << monitoredChain <<
" is not passed");
107 ATH_MSG_ERROR(Form(
"Problems filling %s chain histograms", monitoredChain.c_str()));
114 ATH_MSG_DEBUG(
"Chain " << monitoredChain <<
" is not passed");
118 ATH_MSG_ERROR(Form(
"Problems filling %s chain histograms", monitoredChain.c_str()));
125 ATH_MSG_DEBUG(
"Chain " << monitoredChain <<
" is not passed");
129 ATH_MSG_ERROR(Form(
"Problems filling %s chain histograms", monitoredChain.c_str()));
133 return StatusCode::SUCCESS;
139 std::string monGroupName = std::string(
"Chain_")+
chainName;
147 for (
const auto& featLinkInfo: chainFeatureContainer){
149 const auto featLink = featLinkInfo.link;
157 return StatusCode::SUCCESS;
164 std::string monGroupName = std::string(
"Chain_")+
chainName;
172 for (
const auto& featLinkInfo: chainFeatureContainer){
174 const auto featLink = featLinkInfo.link;
182 auto dimuonLink = (*featLink)->lowerChainLink();
192 return StatusCode::SUCCESS;
198 std::string monGroupName = std::string(
"Chain_")+
chainName;
206 for (
const auto& featLinkInfo: chainFeatureContainer){
208 const auto featLink = featLinkInfo.link;
216 return StatusCode::SUCCESS;
225 ncandidates = chainFeatureContainer.size();
227 fill(currentMonGroup, ncandidates);
229 return StatusCode::SUCCESS;
242 dimu_mass = (*bphysLink)->mass() /
GeV;
243 dimu_fitmass = (*bphysLink)->fitmass() /
GeV;
244 dimu_pt = (*bphysLink)->pt() /
GeV;
245 dimu_chi2 = (*bphysLink)->fitchi2();
246 dimu_y = (*bphysLink)->eta();
248 fill(currentMonGroup, dimu_mass, dimu_fitmass, dimu_pt, dimu_y, dimu_chi2);
250 return StatusCode::SUCCESS;
257 const std::vector<ElementLink<xAOD::TrackParticleContainer> > trackVector = (*bphysLink)->trackParticleLinks();
258 ATH_MSG_DEBUG(
"fillTrigLeptonHists: number of lepton tracks: " << trackVector.size());
259 if(
fillTracksHists(currentMonGroup, trackVector, name_prefix,
true).isFailure() ) {
260 ATH_MSG_ERROR(Form(
"Problems filling muon histograms for a chain"));
261 return StatusCode::FAILURE;
263 if(
fillDiTracksHists(currentMonGroup, trackVector, std::string(
"di")+name_prefix).isFailure() ) {
264 ATH_MSG_ERROR(Form(
"Problems filling two-muon histograms for a chain"));
265 return StatusCode::FAILURE;
268 return StatusCode::SUCCESS;
274 const std::vector<ElementLink<xAOD::TrackParticleContainer> > trackVector = (*bphysLink)->trackParticleLinks();
275 if (trackVector.size() < tracksStartFrom) {
276 ATH_MSG_WARNING(
"Unexpected number of tracks: "<< trackVector.size() <<
" found, while expected at least " << tracksStartFrom);
277 return StatusCode::SUCCESS;
280 if (
fillTracksHists(currentMonGroup, trackVector,
"trk",
false, tracksStartFrom).isFailure()) {
281 ATH_MSG_ERROR(Form(
"Problems filling track histograms for a BMuMuX chain"));
282 return StatusCode::FAILURE;
285 return StatusCode::SUCCESS;
290 const std::string&
prefix,
292 UInt_t offsetIndex)
const {
293 for(UInt_t
i = offsetIndex;
i < tpLinkVector.size(); ++
i) {
295 std::string curPrefix =
prefix;
298 if (
fillTrkHists(currentMonGroup, *tpLinkVector.at(
i), curPrefix).isFailure()) {
300 return StatusCode::FAILURE;
303 return StatusCode::SUCCESS;
308 const std::string& name_prefix)
const {
310 if (tpLinkVector.size() <2) {
311 ATH_MSG_ERROR(
"Unexpected number of tracks in a dimuon: " << tpLinkVector.size());
312 return StatusCode::FAILURE;
324 ditrk_deta = std::abs(trk1->
eta()-trk2->
eta());
327 fill(currentMonGroup, ditrk_dR, ditrk_deta, ditrk_dphi);
329 return StatusCode::SUCCESS;
336 return StatusCode::FAILURE;
342 trk_pt = trk->
pt() /
GeV;
343 trk_eta = trk->
eta();
346 fill(currentMonGroup, trk_pt, trk_eta, trk_d0);
348 return StatusCode::SUCCESS;
353 std::vector<std::string> dimuonMonGroupNames = {
"Any"};
357 for(
const auto& dimuonMonGroupName : dimuonMonGroupNames) {
359 if(dimuonMonGroupName !=
"Any") {
360 auto& monitoredChain = dimuonMonGroupName;
361 if( !(dimuonMonGroupName ==
"Any") && !
isChainPassed(monitoredChain) ) {
362 ATH_MSG_DEBUG(
"Chain " << monitoredChain <<
" is not passed");
367 ATH_MSG_ERROR(Form(
"Problems filling offline dimuon histograms for %s", dimuonMonGroupName.c_str()));
371 return StatusCode::SUCCESS;
375 ATH_MSG_DEBUG(
"Filling " << dimuonMonGroupName <<
" offline dimuons histograms");
378 std::vector<const xAOD::Vertex*> matchedDimuons;
379 for(
auto& offlineDimuon : dimuonContainer) {
380 if( dimuonMonGroupName ==
"Any" ||
matchDimuon(offlineDimuon.get(), dimuonMonGroupName) )
381 matchedDimuons.push_back(offlineDimuon.get());
384 std::string monGroupName = std::string(
"OfflineDimu_")+dimuonMonGroupName;
388 ncandidates = matchedDimuons.size();
392 for(
auto matchedDimuon : matchedDimuons) {
394 ATH_MSG_ERROR(Form(
"Problems filling histogram for an offline dimuon vertex in %s", dimuonMonGroupName.c_str()));
397 ATH_MSG_ERROR(Form(
"Problems filling histogram for offline dimuon muons in %s", dimuonMonGroupName.c_str()));
400 ATH_MSG_ERROR(Form(
"Problems filling histogram for offline dimuon muon pairs in %s", dimuonMonGroupName.c_str()));
404 return StatusCode::SUCCESS;
411 if(dimuonVertexHelper.
nRefTrks() != 2) {
413 return StatusCode::SUCCESS;
426 dimu_mass = dimuonMom.M() /
GeV;
427 dimu_pt = dimuonMom.Pt() /
GeV;
428 dimu_chi2 =
vertex->chiSquared();
429 dimu_y = dimuonMom.Rapidity();
433 fill(currentMonGroup, dimu_mass, dimu_pt, dimu_y, dimu_chi2, dimu_Lxy, dimu_LxySig);
435 return StatusCode::SUCCESS;
445 return passBits & TrigDefs::Express_passed;
459 std::vector<const xAOD::Muon*> selectedMuons;
461 if (
mu ==
nullptr )
continue;
463 if (!
mu->inDetTrackParticleLink())
continue;
464 if (!
mu->inDetTrackParticleLink().isValid())
continue;
465 selectedMuons.push_back(
mu);
467 if(selectedMuons.size() < 2) {
468 ATH_MSG_DEBUG(
"Only " << selectedMuons.size() <<
"muons pass preselection");
469 return StatusCode::SUCCESS;
471 std::sort(selectedMuons.begin(), selectedMuons.end(), [](
const auto mu1,
const auto mu2){ return mu1->pt() > mu2->pt(); });
474 for(
auto outerItr=selectedMuons.begin(); outerItr<selectedMuons.end(); ++outerItr){
475 for(
auto innerItr=(outerItr+1); innerItr!=selectedMuons.end(); ++innerItr){
476 const auto muon1 = *outerItr;
477 const auto muon2 = *innerItr;
478 const auto trackParticle1 = muon1->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
479 const auto trackParticle2 = muon2->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
481 if(trackParticle1->qOverP() * trackParticle2->qOverP() > 0.)
484 double dimu_momentum_prefit =
dimuonMass(trackParticle1, trackParticle2);
488 std::unique_ptr<xAOD::Vertex> dimuon =
dimuonFit(trackParticle1, trackParticle2);
489 if(!dimuon)
continue;
491 vxContainer.push_back(std::move(dimuon));
494 ATH_MSG_DEBUG(
"Found " << vxContainer.size() <<
" good dimuons");
497 if( !vxContainer.empty() ) {
501 std::vector<const xAOD::Vertex*> goodPVs =
GetGoodPVs(pvContainer);
503 for(
auto& dimuon : vxContainer) {
516 return StatusCode::SUCCESS;
523 int sflag = 0;
int errorcode = 0;
525 if (errorcode != 0) {startingPoint(0) = 0.0; startingPoint(1) = 0.0; startingPoint(2) = 0.0;}
526 const std::vector<const xAOD::TrackParticle*> trackPair = {mu1, mu2};
527 std::unique_ptr<xAOD::Vertex> myVxCandidate(
m_vertexFitter->fit(trackPair, startingPoint));
529 return myVxCandidate;
534 for (
const auto& featLinkInfo: chainFeatureContainer){
535 if(!featLinkInfo.isValid())
537 const auto featLink = featLinkInfo.link;
547 if(!offlineTrk1 || !offlineTrk2) {
548 ATH_MSG_DEBUG(
"TrackParticle from dimuon is null, won't match");
552 const std::vector<ElementLink<xAOD::TrackParticleContainer> > trackVector = (*bphysLink)->trackParticleLinks();
553 if (trackVector.size() < 2) {
554 ATH_MSG_ERROR(
"Unexpected number of tracks in a dimuon: " << trackVector.size() <<
", won't match");
560 if( !trackVector.at(0).isValid() || !trackVector.at(1).isValid() )
562 hltTrk1 = *trackVector.at(0);
563 hltTrk2 = *trackVector.at(1);
564 if (!hltTrk1 || !hltTrk2) {
594 std::vector<const xAOD::Vertex*> goodPrimaryVertices;
595 goodPrimaryVertices.reserve(pvContainer->
size());
596 for (
auto pv : *pvContainer) {
599 goodPrimaryVertices.push_back(
pv);
602 return goodPrimaryVertices;
606 std::vector<const xAOD::Vertex*>::const_iterator
pv = std::min_element(PVs.begin(), PVs.end(),
608 { return (std::abs(m_v0Tools->a0(vtx, pv1)) < std::abs(m_v0Tools->a0(vtx, pv2)));}
610 if(
pv == PVs.end()) {