From 56eda11776a15cd74709ad5103694bc9851ff867 Mon Sep 17 00:00:00 2001
From: Magnar Kopangen Bugge <magnar.kopangen.bugge@cern.ch>
Date: Fri, 6 Aug 2021 14:12:44 +0000
Subject: [PATCH] MuonSelectorToolsTester updates

---
 .../MuonID/MuonSelectorTools/CMakeLists.txt   |   5 +-
 .../test/ut_MuonSelectorToolsTester_MC.sh     |   7 +
 .../test/ut_MuonSelectorToolsTester_data.cxx  |  30 ----
 .../test/ut_MuonSelectorToolsTester_data.sh   |   7 +
 .../util/MuonSelectorToolsTester.cxx          | 129 ++++++++++++++++--
 5 files changed, 132 insertions(+), 46 deletions(-)
 create mode 100755 PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_MC.sh
 delete mode 100644 PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_data.cxx
 create mode 100755 PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_data.sh

diff --git a/PhysicsAnalysis/MuonID/MuonSelectorTools/CMakeLists.txt b/PhysicsAnalysis/MuonID/MuonSelectorTools/CMakeLists.txt
index 847d5c2aa4e..36b070bfbd4 100644
--- a/PhysicsAnalysis/MuonID/MuonSelectorTools/CMakeLists.txt
+++ b/PhysicsAnalysis/MuonID/MuonSelectorTools/CMakeLists.txt
@@ -39,8 +39,9 @@ endif()
 # Test(s) in the package: 
 if( XAOD_STANDALONE )
    atlas_add_test( ut_MuonSelectorToolsTester_data
-      SOURCES test/ut_MuonSelectorToolsTester_data.cxx
-      LINK_LIBRARIES AsgMessagingLib )
+      SCRIPT test/ut_MuonSelectorToolsTester_data.sh )
+   atlas_add_test( ut_MuonSelectorToolsTester_MC
+      SCRIPT test/ut_MuonSelectorToolsTester_MC.sh )
 endif()
 
 # Install files from the package:
diff --git a/PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_MC.sh b/PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_MC.sh
new file mode 100755
index 00000000000..4a2f4566935
--- /dev/null
+++ b/PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_MC.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+echo "Unit test for MuonSelectorTools on MC"
+echo "Test files:"
+env | grep ASG_TEST_FILE_ | sort
+echo "Will now run this command: MuonSelectorToolsTester $ASG_TEST_FILE_MC"
+MuonSelectorToolsTester $ASG_TEST_FILE_MC
diff --git a/PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_data.cxx b/PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_data.cxx
deleted file mode 100644
index aa79d9ab88b..00000000000
--- a/PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_data.cxx
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
-*/
-
-#include <AsgMessaging/MessageCheck.h>
-
-#include <cstdlib>
-#include <iostream>
-
-int main() {
-    using namespace asg::msgUserCode;
-
-    ATH_MSG_INFO("Unit test for MuonSelectorTools on data");
-
-    // Full `env` makes log file diffs useless.  Check if the input file changed, though - points us quickly to an issue.
-    ATH_MSG_INFO("Test files");
-    system("env | grep ASG_TEST_FILE_ | sort");
-
-    std::string cmd("MuonSelectorToolsTester $ASG_TEST_FILE_DATA");
-    ATH_MSG_INFO("Will now run this command: " << cmd);
-    int ret = system(cmd.c_str());
-
-    if (ret != 0) {
-        ATH_MSG_ERROR("Test failed (return code was " << ret << ")");
-        return 1;
-    }
-
-    ATH_MSG_INFO("Finished (return code was " << ret << ")");
-    return 0;
-}
diff --git a/PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_data.sh b/PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_data.sh
new file mode 100755
index 00000000000..4dadef7158d
--- /dev/null
+++ b/PhysicsAnalysis/MuonID/MuonSelectorTools/test/ut_MuonSelectorToolsTester_data.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+echo "Unit test for MuonSelectorTools on data"
+echo "Test files:"
+env | grep ASG_TEST_FILE_ | sort
+echo "Will now run this command: MuonSelectorToolsTester $ASG_TEST_FILE_DATA"
+MuonSelectorToolsTester $ASG_TEST_FILE_DATA
diff --git a/PhysicsAnalysis/MuonID/MuonSelectorTools/util/MuonSelectorToolsTester.cxx b/PhysicsAnalysis/MuonID/MuonSelectorTools/util/MuonSelectorToolsTester.cxx
index 8d3aa3fcbad..0ea43620a55 100644
--- a/PhysicsAnalysis/MuonID/MuonSelectorTools/util/MuonSelectorToolsTester.cxx
+++ b/PhysicsAnalysis/MuonID/MuonSelectorTools/util/MuonSelectorToolsTester.cxx
@@ -39,7 +39,6 @@
 #include "xAODCore/tools/ReadStats.h"
 
 // Truth classification
-#include "MCTruthClassifier/MCTruthClassifier.h"
 #include "MCTruthClassifier/MCTruthClassifierDefs.h"
 
 /// Example of how to run the MuonSelectorTools package to obtain information from muons
@@ -84,9 +83,9 @@ int main(int argc, char* argv[]) {
     std::vector<std::unique_ptr<CP::MuonSelectionTool> > selectorTools;
     selectorTools.clear();
 
-    const int Nwp = 6;  // number of working points (tool instances)
+    const int Nwp = 7;  // number of working points (tool instances)
 
-    std::vector<std::string> WPnames = {"Tight", "Medium", "Loose", "VeryLoose", "HighPt", "LowPt"};
+    std::vector<std::string> WPnames = {"Tight", "Medium", "Loose", "VeryLoose", "HighPt", "LowPt", "LowPtMVA"};
 
     for (int wp = 0; wp < Nwp; wp++) {
         Info(APP_NAME, "Creating selector tool for working point: %s ...", WPnames[wp].c_str());
@@ -95,7 +94,14 @@ int main(int argc, char* argv[]) {
 
         muonSelection->msg().setLevel(MSG::INFO);
         CHECK(muonSelection->setProperty("MaxEta", 2.7));
-        CHECK(muonSelection->setProperty("MuQuality", wp));
+
+	if (WPnames[wp] == "LowPtMVA") {
+	  CHECK (muonSelection->setProperty( "MuQuality", 5));
+	  CHECK (muonSelection->setProperty( "UseMVALowPt", true));
+	}
+	else
+	  CHECK(muonSelection->setProperty("MuQuality", wp));
+
         CHECK(muonSelection->setProperty("TurnOffMomCorr", true));
         CHECK(muonSelection->initialize());
 
@@ -167,6 +173,52 @@ int main(int argc, char* argv[]) {
     for (int type = 0; type < Ntype; type++)
         for (int wp = 0; wp < Nwp; wp++) selectedMuonsTypeNotBad[type][wp] = 0;
 
+
+    // Obtain summary information also split by primary author
+    const int Nauthor = xAOD::Muon::NumberOfMuonAuthors;
+
+    std::string authorNames[Nauthor];
+    for (int author = 0; author < Nauthor; author++) {
+        if (author == xAOD::Muon::MuidCo)
+            authorNames[author] = "MuidCo";
+        else if (author == xAOD::Muon::STACO)
+            authorNames[author] = "STACO";
+        else if (author == xAOD::Muon::MuTag)
+            authorNames[author] = "MuTag";
+        else if (author == xAOD::Muon::MuTagIMO)
+            authorNames[author] = "MuTagIMO";
+        else if (author == xAOD::Muon::MuidSA)
+            authorNames[author] = "MuidSA";
+        else if (author == xAOD::Muon::MuGirl)
+            authorNames[author] = "MuGirl";
+        else if (author == xAOD::Muon::MuGirlLowBeta)
+            authorNames[author] = "MuGirlLowBeta";
+        else if (author == xAOD::Muon::CaloTag)
+            authorNames[author] = "CaloTag";
+        else if (author == xAOD::Muon::CaloLikelihood)
+            authorNames[author] = "CaloLikelihood";
+        else if (author == xAOD::Muon::CaloScore)
+            authorNames[author] = "CaloScore";
+        else if (author == xAOD::Muon::ExtrapolateMuonToIP)
+            authorNames[author] = "ExtrapolateMuonToIP";
+        else
+            authorNames[author] = "unknown";
+    }
+
+    // Muon counters for each author
+    int allMuonsAuthor[Nauthor];
+    for (int author = 0; author < Nauthor; author++) allMuonsAuthor[author] = 0;
+
+    // Muon counters for muons of each author passing each working point
+    int selectedMuonsAuthor[Nauthor][Nwp];
+    for (int author = 0; author < Nauthor; author++)
+        for (int wp = 0; wp < Nwp; wp++) selectedMuonsAuthor[author][wp] = 0;
+
+    int selectedMuonsAuthorNotBad[Nauthor][Nwp];
+    for (int author = 0; author < Nauthor; author++)
+        for (int wp = 0; wp < Nwp; wp++) selectedMuonsAuthorNotBad[author][wp] = 0;
+
+
     // Obtain summary information also split by muon |eta|
     const int Neta = 4;
     double etaCuts[Neta - 1] = {1.0, 2.0, 2.5};
@@ -204,10 +256,8 @@ int main(int argc, char* argv[]) {
     for (int truthType = 0; truthType < NtruthType; truthType++)
         for (int wp = 0; wp < Nwp; wp++) selectedMuonsTruthTypeNotBad[truthType][wp] = 0;
 
-    // Truth classifier
+    //To determine whether to print truth classification table
     bool isMC = false;
-    MCTruthClassifier truthClassifier("truthClassifier");
-    CHECK(truthClassifier.initialize());
 
     // Loop over the events:
     for (Long64_t entry = 0; entry < entries; ++entry) {
@@ -253,6 +303,7 @@ int main(int argc, char* argv[]) {
 
             allMuons++;
             allMuonsType[(*mu_itr)->muonType()]++;
+            allMuonsAuthor[(*mu_itr)->author()]++;
             allMuonsEta[etaIndex]++;
             muCounter++;
 
@@ -260,17 +311,16 @@ int main(int argc, char* argv[]) {
 
             // Check truth origin
             isMC = ei->eventType(xAOD::EventInfo::IS_SIMULATION);
-            std::pair<MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin> truthClassification =
-                truthClassifier.particleTruthClassifier(*mu_itr);
+	    int truthClass = isMC ? (*mu_itr)->auxdata<int>("truthType") : -999;
 
             int truthType;
-            if (truthClassification.first == MCTruthPartClassifier::IsoMuon)
+            if (truthClass == MCTruthPartClassifier::IsoMuon)
                 truthType = 0;
-            else if (truthClassification.first == MCTruthPartClassifier::NonIsoMuon)
+            else if (truthClass == MCTruthPartClassifier::NonIsoMuon)
                 truthType = 1;
-            else if (truthClassification.first == MCTruthPartClassifier::Hadron)
+            else if (truthClass == MCTruthPartClassifier::Hadron)
                 truthType = 2;
-            else if (truthClassification.first == MCTruthPartClassifier::BkgMuon)
+            else if (truthClass == MCTruthPartClassifier::BkgMuon)
                 truthType = 3;
             else
                 truthType = 4;
@@ -287,10 +337,11 @@ int main(int argc, char* argv[]) {
             my_quality = selectorTools[0]->getQuality(**mu_itr);
 
             // Print some general information about the muon
-            if (isMC) Info(APP_NAME, "Muon truthType:       %d (%s)", truthClassification.first, truthTypeNames[truthType].c_str());
+            if (isMC) Info(APP_NAME, "Muon truthType:       %d (%s)", truthClass, truthTypeNames[truthType].c_str());
             Info(APP_NAME, "Muon pT [GeV]:        %g ", std::abs((*mu_itr)->pt()) / 1000.);
             Info(APP_NAME, "Muon eta, phi:        %g, %g ", (*mu_itr)->eta(), (*mu_itr)->phi());
             Info(APP_NAME, "Muon muonType:        %d (%s)", (*mu_itr)->muonType(), typeNames[(*mu_itr)->muonType()].c_str());
+            Info(APP_NAME, "Muon primary author:  %d (%s)", (*mu_itr)->author(), authorNames[(*mu_itr)->author()].c_str());
 
             Info(APP_NAME, "Muon quality (from tool, from xAOD):      %d, %d", my_quality, (*mu_itr)->quality());
             Info(APP_NAME, "Muon passes cuts (ID hits, preselection): %d, %d", passesIDRequirements, passesPreselectionCuts);
@@ -334,6 +385,7 @@ int main(int argc, char* argv[]) {
                     selectedMuons[wp]++;
                     selectedMuonsEvent[wp]++;
                     selectedMuonsType[(*mu_itr)->muonType()][wp]++;
+                    selectedMuonsAuthor[(*mu_itr)->author()][wp]++;
                     selectedMuonsTruthType[truthType][wp]++;
                     selectedMuonsEta[etaIndex][wp]++;
                     selectionResults += "pass     ";
@@ -342,6 +394,7 @@ int main(int argc, char* argv[]) {
                         selectedMuonsNotBad[wp]++;
                         selectedMuonsEventNotBad[wp]++;
                         selectedMuonsTypeNotBad[(*mu_itr)->muonType()][wp]++;
+                        selectedMuonsAuthorNotBad[(*mu_itr)->author()][wp]++;
                         selectedMuonsTruthTypeNotBad[truthType][wp]++;
                         selectedMuonsEtaNotBad[etaIndex][wp]++;
                     }
@@ -428,6 +481,54 @@ int main(int argc, char* argv[]) {
     }
     Info(APP_NAME, "---------------------------------------------------------------------------------------");
 
+
+    // Make table of selected muons by author and working point
+    Info(APP_NAME, "Selected muons by primary author and working point (numbers in parenthesis include bad muon veto):");
+    Info(APP_NAME, "---------------------------------------------------------------------------------------");
+    for (int l = 0; l < Nwp + 2; l++) {
+        std::string line = "";
+        if (l == 0) {  // line with author names
+            line += "               ";
+	    for (int author = 0; author < Nauthor; author++) {
+
+	      //Do not print unrepresented authors, since the table can be quite wide
+	      if (allMuonsAuthor[author] == 0) continue;
+
+	      std::stringstream ss;
+	      ss << std::left << std::setw(16);
+	      ss << authorNames[author];
+	      line += ss.str();
+            }
+        } else if (l == 1) {  // line for all muons inclusive
+            line += "All muons:      ";
+            for (int author = 0; author < Nauthor; author++) {
+
+	      if (allMuonsAuthor[author] == 0) continue;
+
+	      std::stringstream ss;
+	      ss << std::left << std::setw(16);
+	      ss << std::to_string(allMuonsAuthor[author]);
+	      line += ss.str();
+            }
+        } else {  // lines for each of the working points
+            int wp = l - 2;
+            line += WPnames[wp] + ":" + padding[wp] + "     ";
+            for (int author = 0; author < Nauthor; author++) {
+
+	      if (allMuonsAuthor[author] == 0) continue;
+
+	      std::stringstream ss;
+	      ss << std::left << std::setw(16);
+	      ss << (std::to_string(selectedMuonsAuthor[author][wp]) + " (" + std::to_string(selectedMuonsAuthorNotBad[author][wp]) + ")");
+	      line += ss.str();
+            }
+        }
+
+        Info(APP_NAME, "%s", line.c_str());
+    }
+    Info(APP_NAME, "---------------------------------------------------------------------------------------");
+
+
     // Make table of selected muons by |eta| and working point
     Info(APP_NAME, "Selected muons by |eta| and working point (numbers in parenthesis include bad muon veto):");
     Info(APP_NAME, "---------------------------------------------------------------------------------------");
-- 
GitLab