5 #include "GaudiKernel/SystemOfUnits.h" 
   19                        const std::string & 
name,
 
   41       for ( 
size_t j=0; j<
m_ptBins.size(); ++j) {
 
   45             return StatusCode::FAILURE;
 
   48          for (std::vector<float>::size_type 
i = 0; 
i < 
m_bins[j]; ++
i) {
 
   68      return StatusCode::FAILURE;
 
   79      return StatusCode::FAILURE;
 
   90      return StatusCode::FAILURE;
 
  102    return StatusCode::SUCCESS;
 
  118                        idEta, idPhi, idZ0, idA0);
 
  127       ATH_MSG_DEBUG(
"Accept property is set: taking all the events");
 
  131       ATH_MSG_DEBUG(
"Accept property not set: applying selection!");
 
  136    auto pMuon = 
input.muComb;
 
  139       ATH_MSG_ERROR(
"Retrieval of xAOD::L2CombinedMuon from vector failed");
 
  146    if (pMuon->pt() == 0) {
 
  147       ATH_MSG_DEBUG(
"L2CombinedMuon pt == 0, empty container -> rejected");
 
  154    idEta    = pMuon->eta();
 
  155    idPhi    = pMuon->phi();
 
  156    int usealgo      = pMuon->strategy();
 
  159    ATH_MSG_DEBUG(
"combined muon pt (GeV)/ sigma_pt (GeV)/ eta / phi / usedalgo: "  
  160                << fexPt << 
" (GeV) / " << ptresComb << 
" (GeV) / " << idEta << 
" / " << idPhi 
 
  161                << 
" / " << usealgo);
 
  164    if (!pMuon->muSATrack()) {
 
  165       ATH_MSG_DEBUG(
"L2CombinedMuon has no valid xaOD::L2StandaloneMuon -> rejected");
 
  171    if (!pMuon->idTrack()) {
 
  172       ATH_MSG_DEBUG(
"L2CombinedMuon has no valid xAOD:TrackParticle IDtrack -> rejected");
 
  177    idA0     = pMuon->idTrack()->d0();
 
  178    idZ0     = pMuon->idTrack()->z0();
 
  181    float threshold = (idEta != -9999) ? 0 : 999999;
 
  182    float absEta = fabs(idEta);
 
  183    for (std::vector<float>::size_type 
i = 0; 
i < 
m_bins[cutIndex]; ++
i) {
 
  193       if (pMuon->idTrack()->chiSquared() > 
m_chi2MaxID) pikCut = 
false;
 
  201               << 
" GeV and pik_cut is " << (pikCut ? 
"true" : 
"false"));
 
  206       if (usealgo >= 1 && usealgo <= 4) {
 
  208          if (std::abs(fexPt) <= std::abs(tmpcut)) sdpCut = 
false;
 
  209          if (tmpcut < 0) stdCut = 
true; 
 
  211                     << 
" and threshold for strategy dependent cut is " << tmpcut
 
  212                     << 
" GeV and strategy dependent / std cuts are " << (sdpCut ? 
"true" : 
"false") << 
" / " << (stdCut ? 
"true" : 
"false"));
 
  214          ATH_MSG_DEBUG(
"usealgo out of range, is: " << usealgo << 
" while should be in [1, 4]");
 
  223    result = stdCut && pikCut && sdpCut && d0Cut;
 
  225    if (
result) ptFL = -9999.;
 
  228      ATH_MSG_DEBUG(
"REGTEST: Muon passed pt threshold: " << (stdCut ? 
"true" : 
"false")
 
  229               << 
" and pik_cut is " << (pikCut ? 
"true" : 
"false")
 
  230               << 
" and strategy dependent cuts is " << (sdpCut ? 
"true" : 
"false")
 
  231           << 
" and result of d0min cut is "<< (d0Cut ? 
"true" : 
"false")
 
  232               << 
" so hypothesis is " << (
result ? 
"true" : 
"false"));
 
  234      ATH_MSG_DEBUG(
"REGTEST: Muon passed pt threshold: " << (stdCut ? 
"true" : 
"false")
 
  235               << 
" and pik_cut is " << (pikCut ? 
"true" : 
"false")
 
  236               << 
" and strategy dependent cuts is " << (sdpCut ? 
"true" : 
"false")
 
  237               << 
" so hypothesis is " << (
result ? 
"true" : 
"false"));
 
  248    size_t numTrigger = 
m_ptBins.size();
 
  249    size_t numMuon = toolInput.size();
 
  250    ATH_MSG_DEBUG(
"Retrieved from TrigmuCombHypoAlg and Running TrigmuCombHypoTool for selections.");
 
  252    if ( numTrigger == 1 ) { 
 
  266    return StatusCode::SUCCESS;
 
  286    return StatusCode::SUCCESS;
 
  294    for ( 
size_t cutIndex=0; cutIndex < 
m_ptBins.size(); ++cutIndex ) {
 
  295       size_t elementIndex{ 0 };
 
  308                passingSelection[cutIndex].push_back( elementIndex );
 
  319       if ( passingSelection[cutIndex].empty() ) {
 
  320          ATH_MSG_DEBUG( 
"No object passed selection " << cutIndex << 
" rejecting" );
 
  321          return StatusCode::SUCCESS;
 
  325    std::set<size_t> passingIndices;
 
  328          std::set<const xAOD::L2CombinedMuon*> setOfClusters;
 
  329          for ( 
auto index: comb ) {
 
  332          return setOfClusters.size() == comb.size();
 
  341    if ( passingIndices.empty() ) {
 
  343       return StatusCode::SUCCESS;
 
  346    for ( 
auto idx: passingIndices ) {
 
  352    return StatusCode::SUCCESS;
 
  363   std::vector<TrigmuCombHypoTool::CombinedMuonInfo*> 
input;
 
  368   float pTthreshold = 0;
 
  369   std::vector<float> pTvec;
 
  370   for ( 
auto& 
i: toolInput ) {
 
  373       pTvec.emplace_back(
i.muComb->pt());
 
  377     std::sort(pTvec.begin(),pTvec.end(), std::greater<float>{});
 
  381   for ( 
auto& 
i: toolInput ) {
 
  384       if(
i.muComb->pt() > pTthreshold)
 
  391   size_t numMuon = 
input.size();
 
  397     ATH_MSG_DEBUG( 
"No positive previous hypo decision. Not need overlap removal." );
 
  398     mucombNrActiveEVs = numMuon;
 
  399     mucombNrAllEVs = numMuon;
 
  400     return StatusCode::SUCCESS;
 
  402   else if ( numMuon == 1 ) {
 
  404     ATH_MSG_DEBUG(
"no overlap Removal necessary. exitting with all EventViews active." );
 
  405     mucombNrActiveEVs = numMuon;
 
  406     mucombNrAllEVs = numMuon;
 
  407     return StatusCode::SUCCESS;
 
  410     mucombNrAllEVs = numMuon;
 
  412     return StatusCode::SUCCESS;
 
  415    return StatusCode::SUCCESS;
 
  423   size_t numMuon = 
input.size();
 
  425   std::vector<unsigned int> mucombResult;
 
  427   bool errorWhenIdentifyingOverlap = 
false;
 
  429   for(
i=0; 
i<numMuon; 
i++) {mucombResult.emplace_back(
i); }
 
  430   for(
i=0; 
i<numMuon-1; 
i++){
 
  431     for(j=
i+1; j<numMuon; j++){
 
  436     if( mucombResult[
i] == mucombResult[j] ) { 
 
  437       ATH_MSG_DEBUG( 
"inconsistentency in muComb overlap removal for more than two objects" );
 
  438       ATH_MSG_DEBUG( 
"two objects are judged as different but both were already marked as identical by someone else as: " );
 
  439       ATH_MSG_DEBUG( 
"i/j/result[i]/result[j]=" << 
i << 
" / " << j << 
" / " << mucombResult[
i] << 
" / "  << mucombResult[j] );
 
  443       errorWhenIdentifyingOverlap = 
true;
 
  447     if( (mucombResult[j] != j && mucombResult[
i] != mucombResult[j]) || (mucombResult[j] == j && mucombResult[
i] != 
i) ){
 
  448       ATH_MSG_DEBUG( 
"inconsistentency in muComb based overlap removal for more than two objects" );
 
  449       ATH_MSG_DEBUG( 
"two objects are judged as overlap but only either was already marked as overlap to someone else: " );
 
  450       ATH_MSG_DEBUG( 
"i/j/result[i]/result[j]=" << 
i << 
" / " << j << 
" / " << mucombResult[
i] << 
" / "  << mucombResult[j] );
 
  454       errorWhenIdentifyingOverlap = 
true;
 
  457     if( mucombResult[
i] == 
i ) {
 
  458       ATH_MSG_DEBUG( 
"   i is not yet marked as overlap. so, it is a newly found overlap" );
 
  462       ATH_MSG_DEBUG( 
"   both i/j already marked as overlap by: mucombResult[i]=" << mucombResult[
i] );
 
  469   if( errorWhenIdentifyingOverlap ) {
 
  470     ATH_MSG_WARNING( 
"error when resolving overlap. exitting with all EVs active..." );
 
  473     mucombNrActiveEVs = numMuon;
 
  475     return StatusCode::SUCCESS;
 
  478   unsigned int n_uniqueMuon = 0;
 
  479   for(
i=0; 
i<numMuon; 
i++) {
 
  481     if( mucombResult[
i] != 
i ) { 
ATH_MSG_DEBUG( 
"      overlap to j=" << mucombResult[
i] ); }
 
  488   ATH_MSG_DEBUG( 
"nr of unique Muons after muComb-based removal=" << n_uniqueMuon );
 
  490   if( numMuon != n_uniqueMuon ){
 
  493     ATH_MSG_DEBUG( 
"no overlap identified. exitting with all EventViews active" );
 
  496     mucombNrActiveEVs = n_uniqueMuon;
 
  499   return StatusCode::SUCCESS;
 
  522   const double ZERO_LIMIT_FOR_ETAPHI = 1
e-4;
 
  523   if( (fabs(combMf1->
eta()) <ZERO_LIMIT_FOR_ETAPHI && fabs(combMf1->
phi()) < ZERO_LIMIT_FOR_ETAPHI) ||
 
  524       (fabs(combMf2->
eta()) <ZERO_LIMIT_FOR_ETAPHI && fabs(combMf2->
phi()) < ZERO_LIMIT_FOR_ETAPHI) ) {
 
  525     ATH_MSG_DEBUG( 
"   ...-> (eta,phi) info not available (rec at (eta,phi)=(0,0))" );
 
  527       ATH_MSG_DEBUG( 
"   ...-> but dR of invMass check is required. cannot judge overlap -> return with false" );
 
  533   const double ZERO_LIMIT_FOR_PT = 1
e-4;
 
  534   if( (fabs(combMf1->
pt()) <ZERO_LIMIT_FOR_PT) || (fabs(combMf2->
pt()) < ZERO_LIMIT_FOR_PT) ) {
 
  535     ATH_MSG_DEBUG( 
"   ...-> pT info not available (rec at pT=0)" );
 
  537       ATH_MSG_DEBUG( 
"   ...-> but same sign or invMass check is required. cannot judge overlap -> return with false" );
 
  543   double absEta = (fabs(combMf1->
pt()) > fabs(combMf2->
pt())) ? fabs(combMf1->
eta()) : fabs(combMf2->
eta());
 
  544   unsigned int iThres = 0;
 
  557   bool sameSign = 
false;
 
  559     sameSign = ((combMf1->
pt()*combMf2->
pt()) > 0) ? true : 
false;
 
  564   bool dRisClose = 
false;
 
  565   double dr = 
dR(combMf1->
eta(),combMf1->
phi(),combMf2->
eta(),combMf2->
phi());
 
  568   const double monitor_limit = 1
e-4;
 
  569   double dr_mon = (
dr>=monitor_limit) ? 
dr : monitor_limit;
 
  570   mucombDRLog10 = log10(dr_mon);
 
  573     if( 
dr < dRThres ) dRisClose = 
true;
 
  578   bool dRbyMFisClose = 
false;
 
  582     if( mf1 == 0 || mf2 == 0 ) {
 
  584       ATH_MSG_DEBUG( 
"   ...-> mF dR is required but mF link broken. cannot judge overlap -> return with false" );
 
  591       if( dRByMF < dRbyMFThres ) dRbyMFisClose = 
true;
 
  592       ATH_MSG_DEBUG( 
"   ...-> dR(by MF)=" << dRByMF << 
" : dRbyMFisClose=" << dRbyMFisClose );
 
  597   const double TRACK_MASS = 0;  
 
  598   bool massIsClose = 
false;
 
  602   double mass_mon = (
mass>=monitor_limit) ? 
mass : monitor_limit;
 
  603   mucombMassLog10 = log10(mass_mon);
 
  606     if( 
mass < massThres ) massIsClose = 
true;
 
  611   bool overlap = 
false;
 
  632   return std::sqrt(deta*deta + dphi*dphi);
 
  639                    double m2, 
double pt2, 
double eta2, 
double phi2)
 const 
  643   double theta1 = 2*atan2((
double)
exp(-
eta1),1.);
 
  644   double theta2 = 2*atan2((
double)
exp(-
eta2),1.);
 
  646   double fpt1   = fabs(pt1);
 
  647   double fpt2   = fabs(pt2);
 
  649   double px1    = fpt1*
cos(phi1);
 
  650   double py1    = fpt1*
sin(phi1);
 
  651   double pz1    = fpt1/
tan(theta1);
 
  652   double  e1    = sqrt(px1*px1+py1*py1+pz1*pz1+
m1*
m1);
 
  654   double px2    = fpt2*
cos(phi2);
 
  655   double py2    = fpt2*
sin(phi2);
 
  656   double pz2    = fpt2/
tan(theta2);
 
  657   double  e2    = sqrt(px2*px2+py2*py2+pz2*pz2+
m2*
m2);
 
  659   double pxsum  = px1 + px2;
 
  660   double pysum  = py1 + py2;
 
  661   double pzsum  = pz1 + pz2;
 
  662   double esum   =  
e1 +  
e2;
 
  665   double mass2 = esum*esum - pxsum*pxsum - pysum*pysum - pzsum*pzsum;
 
  677   size_t numMuon = 
input.size();
 
  687                       mucombOverlappedPt, mucombOverlappedEta, mucombOverlappedPhi);
 
  689   ATH_MSG_DEBUG( 
"--- choose best among overlaps & disable EVs (muComb based) ---" );
 
  690   for(
i=0; 
i<numMuon; 
i++) {
 
  692     if( mucombResult[
i] != 
i ) {
 
  693       ATH_MSG_DEBUG( 
"   overlap to some one. already the best one was chosen. skip." );
 
  696     std::vector<unsigned int> others;
 
  697     for(j=0; j<numMuon; j++) {
 
  698       if( mucombResult[j] == mucombResult[
i] ) others.emplace_back(j);
 
  700     if( others.size() == 1 ) {
 
  706       unsigned int best_ev = 0;
 
  707       float maxPtCombMf  = 0;
 
  708       float mindRRoadRoI = 999;
 
  709       for(
k=0; 
k<others.size(); 
k++) {
 
  717     const float roadPhiP = atan2(
mf->dirPhiMS(),1.);
 
  718     const float roadPhiM = atan2(-1*
mf->dirPhiMS(),-1.);
 
  721     if(std::abs(
mf->roiEta()) < 1.05) { 
 
  722       if( std::abs(
mf->roadAw(1,0)) > 
ZERO_LIMIT )      roadAw = 
mf->roadAw(1,0);
 
  723       else if( std::abs(
mf->roadAw(2,0)) > 
ZERO_LIMIT ) roadAw = 
mf->roadAw(2,0);
 
  724       else if( std::abs(
mf->roadAw(0,0)) > 
ZERO_LIMIT ) roadAw = 
mf->roadAw(0,0);
 
  727       if( std::abs(
mf->roadAw(4,0)) > 
ZERO_LIMIT )      roadAw = 
mf->roadAw(4,0);
 
  728       else if( std::abs(
mf->roadAw(5,0)) > 
ZERO_LIMIT ) roadAw = 
mf->roadAw(5,0);
 
  729       else if( std::abs(
mf->roadAw(3,0)) > 
ZERO_LIMIT ) roadAw = 
mf->roadAw(3,0);
 
  734     if(roadAw < 0) roadEta *= -1.;
 
  735     const double dRRoadRoI = 
dR(roadEta, roadPhi, 
mf->roiEta(), 
mf->roiPhi());
 
  736     ATH_MSG_DEBUG(
"     j="<< j << 
" , ptCombMf=" << ptCombMf << 
", dRRoadRoI=" << dRRoadRoI);
 
  738     if( (ptCombMf > maxPtCombMf) ||
 
  739         (std::abs(ptCombMf - maxPtCombMf) < 
ZERO_LIMIT &&
 
  740          dRRoadRoI < mindRRoadRoI) ) {
 
  741       maxPtCombMf  = ptCombMf;
 
  742       mindRRoadRoI = dRRoadRoI;
 
  746       ATH_MSG_DEBUG( 
"      best is: best_ev/maxPtCombMf=" << best_ev << 
" / " <<  maxPtCombMf );
 
  748       for(
k=0; 
k<others.size(); 
k++) {
 
  751       ATH_MSG_DEBUG( 
"      EventView( j=" << j << 
" ) is not active" );
 
  757       ++mucombNrOverlapped;
 
  759       mucombOverlappedEta = CombMf->
eta();
 
  760       mucombOverlappedPhi = CombMf->
phi();
 
  768   mucombNrActiveEVs = numMuon - mucombNrOverlapped;
 
  770   return StatusCode::SUCCESS;