7 #include "GaudiKernel/SystemOfUnits.h"
13 using namespace Gaudi::Units;
32 return StatusCode::SUCCESS;
48 std::vector<std::unique_ptr<xAOD::Vertex>> offlineDimuons;
50 ATH_MSG_ERROR(
"Problems building offline dimuons, won't fill corresponding histograms");
56 return StatusCode::SUCCESS;
62 ATH_MSG_DEBUG(
"Process container " << monitoredContainerKey.key().c_str());
64 ATH_MSG_ERROR(Form(
"Problems filling %s container histograms", monitoredContainerKey.key().c_str()));
68 return StatusCode::SUCCESS;
73 if( !trigBphysContainer.
isValid() ) {
74 ATH_MSG_WARNING(
"No valid TrigBphysContainer with tag: " << trigBphysContainerKey);
78 std::string monGroupName = std::string(
"Container_")+trigBphysContainerKey.
key();
82 ncandidates = trigBphysContainer->
size();
89 return StatusCode::SUCCESS;
98 ATH_MSG_DEBUG(
"Chain " << monitoredChain <<
" is not passed");
102 ATH_MSG_ERROR(Form(
"Problems filling %s chain histograms", monitoredChain.c_str()));
109 ATH_MSG_DEBUG(
"Chain " << monitoredChain <<
" is not passed");
113 ATH_MSG_ERROR(Form(
"Problems filling %s chain histograms", monitoredChain.c_str()));
120 ATH_MSG_DEBUG(
"Chain " << monitoredChain <<
" is not passed");
124 ATH_MSG_ERROR(Form(
"Problems filling %s chain histograms", monitoredChain.c_str()));
128 return StatusCode::SUCCESS;
134 std::string monGroupName = std::string(
"Chain_")+
chainName;
142 for (
const auto& featLinkInfo: chainFeatureContainer){
144 const auto featLink = featLinkInfo.link;
152 return StatusCode::SUCCESS;
159 std::string monGroupName = std::string(
"Chain_")+
chainName;
167 for (
const auto& featLinkInfo: chainFeatureContainer){
169 const auto featLink = featLinkInfo.link;
177 auto dimuonLink = (*featLink)->lowerChainLink();
187 return StatusCode::SUCCESS;
193 std::string monGroupName = std::string(
"Chain_")+
chainName;
201 for (
const auto& featLinkInfo: chainFeatureContainer){
203 const auto featLink = featLinkInfo.link;
211 return StatusCode::SUCCESS;
220 ncandidates = chainFeatureContainer.size();
222 fill(currentMonGroup, ncandidates);
224 return StatusCode::SUCCESS;
237 dimu_mass = (*bphysLink)->mass() /
GeV;
238 dimu_fitmass = (*bphysLink)->fitmass() /
GeV;
239 dimu_pt = (*bphysLink)->pt() /
GeV;
240 dimu_chi2 = (*bphysLink)->fitchi2();
241 dimu_y = (*bphysLink)->eta();
243 fill(currentMonGroup, dimu_mass, dimu_fitmass, dimu_pt, dimu_y, dimu_chi2);
245 return StatusCode::SUCCESS;
252 const std::vector<ElementLink<xAOD::TrackParticleContainer> > trackVector = (*bphysLink)->trackParticleLinks();
253 ATH_MSG_DEBUG(
"fillTrigLeptonHists: number of lepton tracks: " << trackVector.size());
254 if(
fillTracksHists(currentMonGroup, trackVector, name_prefix,
true).isFailure() ) {
255 ATH_MSG_ERROR(Form(
"Problems filling muon histograms for a chain"));
256 return StatusCode::FAILURE;
258 if(
fillDiTracksHists(currentMonGroup, trackVector, std::string(
"di")+name_prefix).isFailure() ) {
259 ATH_MSG_ERROR(Form(
"Problems filling two-muon histograms for a chain"));
260 return StatusCode::FAILURE;
263 return StatusCode::SUCCESS;
269 const std::vector<ElementLink<xAOD::TrackParticleContainer> > trackVector = (*bphysLink)->trackParticleLinks();
270 if (trackVector.size() < tracksStartFrom) {
271 ATH_MSG_WARNING(
"Unexpected number of tracks: "<< trackVector.size() <<
" found, while expected at least " << tracksStartFrom);
272 return StatusCode::SUCCESS;
275 if (
fillTracksHists(currentMonGroup, trackVector,
"trk",
false, tracksStartFrom).isFailure()) {
276 ATH_MSG_ERROR(Form(
"Problems filling track histograms for a BMuMuX chain"));
277 return StatusCode::FAILURE;
280 return StatusCode::SUCCESS;
285 const std::string&
prefix,
287 UInt_t offsetIndex)
const {
288 for(UInt_t
i = offsetIndex;
i < tpLinkVector.size(); ++
i) {
290 std::string curPrefix =
prefix;
293 if (
fillTrkHists(currentMonGroup, *tpLinkVector.at(
i), curPrefix).isFailure()) {
295 return StatusCode::FAILURE;
298 return StatusCode::SUCCESS;
303 const std::string& name_prefix)
const {
305 if (tpLinkVector.size() <2) {
306 ATH_MSG_ERROR(
"Unexpected number of tracks in a dimuon: " << tpLinkVector.size());
307 return StatusCode::FAILURE;
319 ditrk_deta = std::abs(trk1->
eta()-trk2->
eta());
322 fill(currentMonGroup, ditrk_dR, ditrk_deta, ditrk_dphi);
324 return StatusCode::SUCCESS;
331 return StatusCode::FAILURE;
337 trk_pt = trk->
pt() /
GeV;
338 trk_eta = trk->
eta();
341 fill(currentMonGroup, trk_pt, trk_eta, trk_d0);
343 return StatusCode::SUCCESS;
348 std::vector<std::string> dimuonMonGroupNames = {
"Any"};
352 for(
const auto& dimuonMonGroupName : dimuonMonGroupNames) {
354 if(dimuonMonGroupName !=
"Any") {
355 auto& monitoredChain = dimuonMonGroupName;
356 if( !(dimuonMonGroupName ==
"Any") && !
isChainPassed(monitoredChain) ) {
357 ATH_MSG_DEBUG(
"Chain " << monitoredChain <<
" is not passed");
362 ATH_MSG_ERROR(Form(
"Problems filling offline dimuon histograms for %s", dimuonMonGroupName.c_str()));
366 return StatusCode::SUCCESS;
370 ATH_MSG_DEBUG(
"Filling " << dimuonMonGroupName <<
" offline dimuons histograms");
373 std::vector<const xAOD::Vertex*> matchedDimuons;
374 for(
auto& offlineDimuon : dimuonContainer) {
375 if( dimuonMonGroupName ==
"Any" ||
matchDimuon(offlineDimuon.get(), dimuonMonGroupName) )
376 matchedDimuons.push_back(offlineDimuon.get());
379 std::string monGroupName = std::string(
"OfflineDimu_")+dimuonMonGroupName;
383 ncandidates = matchedDimuons.size();
387 for(
auto matchedDimuon : matchedDimuons) {
389 ATH_MSG_ERROR(Form(
"Problems filling histogram for an offline dimuon vertex in %s", dimuonMonGroupName.c_str()));
392 ATH_MSG_ERROR(Form(
"Problems filling histogram for offline dimuon muons in %s", dimuonMonGroupName.c_str()));
395 ATH_MSG_ERROR(Form(
"Problems filling histogram for offline dimuon muon pairs in %s", dimuonMonGroupName.c_str()));
399 return StatusCode::SUCCESS;
406 if(dimuonVertexHelper.
nRefTrks() != 2) {
408 return StatusCode::SUCCESS;
421 dimu_mass = dimuonMom.M() /
GeV;
422 dimu_pt = dimuonMom.Pt() /
GeV;
423 dimu_chi2 = vertex->chiSquared();
424 dimu_y = dimuonMom.Rapidity();
428 fill(currentMonGroup, dimu_mass, dimu_pt, dimu_y, dimu_chi2, dimu_Lxy, dimu_LxySig);
430 return StatusCode::SUCCESS;
440 return passBits & TrigDefs::Express_passed;
454 std::vector<const xAOD::Muon*> selectedMuons;
456 if (
mu ==
nullptr )
continue;
458 if (!
mu->inDetTrackParticleLink())
continue;
459 if (!
mu->inDetTrackParticleLink().isValid())
continue;
460 selectedMuons.push_back(
mu);
462 if(selectedMuons.size() < 2) {
463 ATH_MSG_DEBUG(
"Only " << selectedMuons.size() <<
"muons pass preselection");
464 return StatusCode::SUCCESS;
466 std::sort(selectedMuons.begin(), selectedMuons.end(), [](
const auto mu1,
const auto mu2){ return mu1->pt() > mu2->pt(); });
469 for(
auto outerItr=selectedMuons.begin(); outerItr<selectedMuons.end(); ++outerItr){
470 for(
auto innerItr=(outerItr+1); innerItr!=selectedMuons.end(); ++innerItr){
471 const auto muon1 = *outerItr;
472 const auto muon2 = *innerItr;
473 const auto trackParticle1 = muon1->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
474 const auto trackParticle2 = muon2->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
476 if(trackParticle1->qOverP() * trackParticle2->qOverP() > 0.)
479 double dimu_momentum_prefit =
dimuonMass(trackParticle1, trackParticle2);
483 std::unique_ptr<xAOD::Vertex> dimuon =
dimuonFit(trackParticle1, trackParticle2);
484 if(!dimuon)
continue;
486 vxContainer.push_back(std::move(dimuon));
489 ATH_MSG_DEBUG(
"Found " << vxContainer.size() <<
" good dimuons");
492 if( !vxContainer.empty() ) {
496 std::vector<const xAOD::Vertex*> goodPVs =
GetGoodPVs(pvContainer);
498 for(
auto& dimuon : vxContainer) {
511 return StatusCode::SUCCESS;
518 int sflag = 0;
int errorcode = 0;
520 if (errorcode != 0) {startingPoint(0) = 0.0; startingPoint(1) = 0.0; startingPoint(2) = 0.0;}
521 const std::vector<const xAOD::TrackParticle*> trackPair = {mu1, mu2};
522 std::unique_ptr<xAOD::Vertex> myVxCandidate(
m_vertexFitter->fit(trackPair, startingPoint));
524 return myVxCandidate;
529 for (
const auto& featLinkInfo: chainFeatureContainer){
530 if(!featLinkInfo.isValid())
532 const auto featLink = featLinkInfo.link;
542 if(!offlineTrk1 || !offlineTrk2) {
543 ATH_MSG_DEBUG(
"TrackParticle from dimuon is null, won't match");
547 const std::vector<ElementLink<xAOD::TrackParticleContainer> > trackVector = (*bphysLink)->trackParticleLinks();
548 if (trackVector.size() < 2) {
549 ATH_MSG_ERROR(
"Unexpected number of tracks in a dimuon: " << trackVector.size() <<
", won't match");
555 if( !trackVector.at(0).isValid() || !trackVector.at(1).isValid() )
557 hltTrk1 = *trackVector.at(0);
558 hltTrk2 = *trackVector.at(1);
559 if (!hltTrk1 || !hltTrk2) {
589 std::vector<const xAOD::Vertex*> goodPrimaryVertices;
590 goodPrimaryVertices.reserve(pvContainer->
size());
591 for (
auto pv : *pvContainer) {
594 goodPrimaryVertices.push_back(
pv);
597 return goodPrimaryVertices;
601 std::vector<const xAOD::Vertex*>::const_iterator
pv = std::min_element(PVs.begin(), PVs.end(),
603 { return (std::abs(m_v0Tools->a0(vtx, pv1)) < std::abs(m_v0Tools->a0(vtx, pv2)));}
605 if(
pv == PVs.end()) {