diff --git a/README.md b/README.md
index 2aa210d467c..6543979711e 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,8 @@ For recent instruction please visit: https://twiki.cern.ch/twiki/bin/view/CMS/Mi
git cms-init
git cms-addpkg RecoMET/METFilters
- git clone https://github.com/didukhle/MetScanning.git
- scram b -j9
+ git clone https://github.com/cms-met/MetScanning
+ scram b -j $(nproc)
```
You might need to run the following command if you want to access files via XROOT:
```
diff --git a/scan/README.md b/scan/README.md
new file mode 100644
index 00000000000..90e92b48f7b
--- /dev/null
+++ b/scan/README.md
@@ -0,0 +1,65 @@
+# METScanning
+
+This framework aims to centralize the MET scanners analysis in a more efficient framework.
+For more details see the [Wiki page](https://gitlab.cern.ch/mmahdavi/metscanning/-/wikis/home).
+
+
+# Mannual
+
+1. Set the environment and bBuild the executable file if needed.
+```
+cmsenv
+scram b -j $(nproc)
+```
+
+
+2. Run the analysis
+```
+runAnalysis INPUT_FILE1 [INPUT_FILE2 [...]] --output output.root --dataset DATASET --year YYYY --pass-rec [ON/off] --cross-check [on/OFF]
+```
+***`--cross-check ON` option will allow you to have cross-check histograms in NFR***
+
+- One can also run ```runAnalysis --help``` or ```runAnalysis -h``` for more detailed help message.
+- One may need to modify the configuration files stored in [`config`](https://github.com/cms-met/MetScanning/tree/master/scan/config) directory based on her/his analysis, such as different years, scenarios and etc.
+- If one is interested in old-analysis strategy i.e. without BER and NFR control region, it is possible by passing the `--old-analysis` option to the program. Hence the obtained efficencies are with out any cut or ID applied.
+
+
+# Plotting Mannual
+For running plot scripts, you need to logout and login again if you have set `CMSSW` environment i.e. `cmsenv`. Then you need to set the proper environment,
+```
+cd plot
+. ./env
+cd -
+```
+There are two different python scripts which provide `efficiencies` and `occupancy maps` plots such as [plot_efficencies](https://github.com/cms-met/MetScanning/tree/master/scan/plot/plot_efficiencies) and [plot_occupancy_maps](https://github.com/cms-met/MetScanning/tree/master/scan/plot/plot_occupancy_maps) respectively. They are mentioned below separately.
+
+Before using the scripts, please make sure that the environment has been set up as mention above.
+
+- **Occupancy maps:**
+```
+plot_occupancy_maps [list of output root-files separated by space] --dataset [list of datasets w.r.t provided output root-files separated by space] --year YYYY
+```
+
+
+- **Efficiency plots:**
+
+For full plots, i.e all filters plots individually and merged plots for each provided dataset, `--all` option is needed like below.
+```
+plot_efficencies [list of output root-files separated by space] --dataset [list of datasets w.r.t provided output root-files separated by space] --year 2018 --all
+```
+
+If one needs also to obtain the actual final merged plot, all datasets must be provided. In this case the `--all` option is optional, for example, below command will plot all kind of plots and the actual final merged plot as well.
+```
+plot_efficencies jetht_output.root singlemuon_output.root egamma_output.root --dataset jetht singlemuon egamma --year 2018 --all
+```
+
+
+- **Plots Configurations:**
+
+The `plot_efficencies` script uses `yaml` configuration files which contain `binning` settings according to regions (`BER` and `NFR`) variables and/or datasets, for each filter separately.
+
+The configuration files are provided in the [config](https://github.com/cms-met/MetScanning/tree/master/scan/config) directory. One may need to modify theses configuration files to obtian the proper plots.
+
+
+
+- *One can also run* ```plot_efficencies [--help, -h]``` or ```plot_occupancy_maps [--help, -h]``` for more detailed help messages.
diff --git a/scan/bin/BERegion.cc b/scan/bin/BERegion.cc
new file mode 100644
index 00000000000..c4e9d607b13
--- /dev/null
+++ b/scan/bin/BERegion.cc
@@ -0,0 +1,178 @@
+#include "BERegion.h"
+
+#include
+
+
+BERegion::BERegion(TTreeReader &reader, const std::string berCat)
+ : Tree(reader),
+ berCat_{berCat} {
+ cfg_ = YAML::LoadFile("config/BER.yaml");
+ minPfMet_ = Get("min_pfmet");
+
+ if (berCat == "BadChCand") {
+ isBER = &BERegion::isBadChCandBER;
+ minDPhi_ = Get("min_dphi");
+ pfCanMinPt_ = Get("min_pfcandid_pt");
+ pfCanPdgId_ = Get("abs_pfcand_pdgid");
+ }
+
+ else if (berCat == "GlbSTightHalo") {
+ isBER = &BERegion::isGlbSTHaloBER;
+ maxPfMetPhi_ = Get("max_abs_pfmet_phi");
+ minPfMetPhi_ = Get("min_abs_pfmet_phi");
+ minJetPt_ = Get("min_jet_pt");
+ maxJetEta_ = Get("max_abs_jet_eta");
+ maxJetChef_ = Get("max_jet_chef");
+ jetPtGt25Num_ = Get("num_jets_ptgt25");
+ jetPtGt200Num_ = Get("num_jets_ptgt200");
+ }
+
+ else if (berCat == "BadPFMuon") {
+ isBER = &BERegion::isBadPFMuonBER;
+ minDPhi_ = Get("min_dphi");
+ minMuPt_ = Get("min_muon_pt");
+ maxAddMuPt_ = Get("max_additional_muon_pt");
+ minDeltaR_ = Get("min_delta_r");
+ jetPtGt25Num_ = Get("num_jets_ptgt25");
+ jetPtGt200Num_ = Get("num_jets_ptgt200");
+ minMuNum_ = Get("min_num_muon");
+ }
+
+ else if (berCat == "EcalBadCal_U") {
+ isBER = &BERegion::isEcalBadCalBER;
+ minDPhi_ = Get("min_dphi");
+ minJetPt_ = Get("min_jet_pt");
+ maxJetEta_ = Get("max_abs_jet_eta");
+ minJetEta_ = Get("min_abs_jet_eta");
+ minJetNeef_ = Get("min_jet_neef");
+ jetPtGt25Num_ = Get("num_jets_ptgt25");
+ jetPtGt200Num_ = Get("num_jets_ptgt200");
+ }
+
+ else if (berCat == "HBHENoise") {
+ isBER = &BERegion::isHBHENoiseBER;
+ minDPhi_ = Get("min_dphi");
+ minJetPt_ = Get("min_jet_pt");
+ maxJetEta_ = Get("max_abs_jet_eta");
+ minJetNhef_ = Get("min_jet_nhef");
+ jetPtGt25Num_ = Get("num_jets_ptgt25");
+ jetPtGt200Num_ = Get("num_jets_ptgt200");
+ }
+
+ else
+ isBER = &BERegion::isOthersBER;
+
+}
+
+
+bool BERegion::operator()() {
+ return (this->*isBER)();
+}
+
+
+bool BERegion::isBadChCandBER() {
+ int i = 0;
+ if (*pfmet > minPfMet_) {
+ for (long unsigned int j = 0; j < (*pfCandPt).size(); j++)
+ if ((*pfCandPt)[j] > pfCanMinPt_ and
+ std::abs((*pfCandPdgId)[j]) == pfCanPdgId_ and
+ std::fabs(
+ TVector2::Phi_mpi_pi(*pfmetPhi-(*pfCandPhi)[j])) > minDPhi_)
+ i++;
+ }
+
+ return (i >= 1);
+}
+
+
+bool BERegion::isGlbSTHaloBER() {
+ if (*pfmet > minPfMet_ and
+ (*jetPt).size() == 1 and
+ (*numJetsPt25) == 1 and
+ (std::fabs(TVector2::Phi_mpi_pi(*pfmetPhi)) < maxPfMetPhi_ or
+ std::fabs(TVector2::Phi_mpi_pi(*pfmetPhi)) > minPfMetPhi_) and
+ (*jetPt)[0] > minJetPt_ and
+ std::fabs((*jetEta)[0]) < maxJetEta_ and
+ (*jetCHEF)[0] < maxJetChef_)
+ return true;
+
+ return false;
+}
+
+
+bool BERegion::isBadPFMuonBER() {
+ if (*pfmet > minPfMet_ and
+ (*jetPt).size() == jetPtGt200Num_ and
+ (*numJetsPt25) == jetPtGt25Num_ and
+ (*muonPt).size() >= minMuNum_ and
+ (*muonPt)[0] > minMuPt_ and
+ std::fabs(
+ TVector2::Phi_mpi_pi(*pfmetPhi - (*muonPhi)[0])) >= minDPhi_ and
+ (((*muonPt).size() > minMuNum_) ? ((*muonPt)[1] < maxAddMuPt_) : true)
+ ) {
+ int k = 0;
+ for (long unsigned int j = 0; j < (*jetPt).size(); j++) {
+ // To be sure that the jets are not comming from muon jet cone
+ // by requiring DR < 0.4
+ float const deltaR = std::sqrt(
+ std::pow((*muonEta)[0] - (*jetEta)[j], 2) +
+ std::pow((*muonPhi)[0] - (*jetPhi)[j], 2));
+ if (deltaR < minDeltaR_)
+ continue;
+ k++;
+ break;
+ }
+
+ return (k == 0);
+ }
+
+ return false;
+}
+
+
+bool BERegion::isEcalBadCalBER() {
+ if (*pfmet > minPfMet_ and
+ (*jetPt).size() == jetPtGt200Num_ and
+ (*numJetsPt25) == jetPtGt25Num_ and
+ (*jetPt)[0] > minJetPt_ and
+ std::fabs((*jetEta)[0]) > minJetEta_ and
+ std::fabs((*jetEta)[0]) < maxJetEta_ and
+ (*jetNEEF)[0] > minJetNeef_ and
+ std::fabs(TVector2::Phi_mpi_pi(*pfmetPhi - (*jetPhi)[0])) > minDPhi_)
+ return true;
+
+ return false;
+}
+
+
+bool BERegion::isHBHENoiseBER() {
+ if (*pfmet > minPfMet_ and
+ (*jetPt).size() == jetPtGt200Num_ and
+ (*numJetsPt25) == jetPtGt25Num_ and
+ (*jetPt)[0] > minJetPt_ and
+ std::fabs((*jetEta)[0]) < maxJetEta_ and
+ (*jetNHEF)[0] > minJetNhef_ and
+ std::fabs(TVector2::Phi_mpi_pi(*pfmetPhi - (*jetPhi)[0])) > minDPhi_)
+ return true;
+
+ return false;
+}
+
+
+bool BERegion::isOthersBER() {
+ return (*pfmet > minPfMet_);
+}
+
+
+template
+T BERegion::Get(std::string const field) {
+ if (cfg_[berCat_][field])
+ return cfg_[berCat_][field].as();
+ else {
+ std::ostringstream message;
+ message << "BER configuration of " << berCat_
+ << " doesn't contain [" << field << "] field.";
+ throw std::runtime_error(message.str());
+ }
+}
+
diff --git a/scan/bin/BERegion.h b/scan/bin/BERegion.h
new file mode 100644
index 00000000000..0bf9f258a2e
--- /dev/null
+++ b/scan/bin/BERegion.h
@@ -0,0 +1,56 @@
+#ifndef BEREGION_H
+#define BEREGION_H
+
+#include
+
+#include "Tree.h"
+
+
+class BERegion final : private Tree {
+ public:
+ // Constructor
+ BERegion(TTreeReader &reader, const std::string="Others");
+ bool operator()();
+
+ private:
+ std::string berCat_;
+
+ // BER configuration.
+ YAML::Node cfg_;
+
+ // All BER parameters
+ float minPfMet_, minDPhi_, maxPfMetPhi_, minPfMetPhi_, minJetPt_, maxJetEta_,
+ minJetEta_, maxJetChef_, minJetNeef_, minJetNhef_, minMuPt_,
+ maxAddMuPt_, minDeltaR_, pfCanMinPt_;
+
+ int pfCanPdgId_, jetPtGt25Num_;
+
+ long unsigned int jetPtGt200Num_, minMuNum_;
+
+ // Check whether the event is in BER of BadChCand filters.
+ bool isBadChCandBER();
+
+ // Check whether the event is in BER of GlbSTHalo and GlbTHalo filters.
+ bool isGlbSTHaloBER();
+
+ // Check whether the event is in BER of BadPFMuon filters.
+ bool isBadPFMuonBER();
+
+ // Check whether the event is in BER of EcalBadCal filters.
+ bool isEcalBadCalBER();
+
+ // Check whether the event is in BER of HBHENoise and HBHEIsoNoise filters.
+ bool isHBHENoiseBER();
+
+ // Check whether the event is in BER of other filters.
+ bool isOthersBER();
+
+ // A pointer to one of functions checking whether the event is in BER or not.
+ bool (BERegion::*isBER)();
+
+ // Return the value of given field from configuration file.
+ template
+ T Get(std::string const field);
+};
+
+#endif
diff --git a/scan/bin/BuildFile.xml b/scan/bin/BuildFile.xml
new file mode 100644
index 00000000000..60a693b7ed6
--- /dev/null
+++ b/scan/bin/BuildFile.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/scan/bin/MetFilter.cc b/scan/bin/MetFilter.cc
new file mode 100644
index 00000000000..f8f657b2289
--- /dev/null
+++ b/scan/bin/MetFilter.cc
@@ -0,0 +1,122 @@
+#include "MetFilter.h"
+
+
+MetFilter::MetFilter(TString const &dataset, TTreeReader &reader,
+ TString const &name, TString const &flag, bool const isRecmnded,
+ int const &N_1Key, bool const isOldAnlz)
+ : name_{name},
+ flag_{flag},
+ isPassed_{reader, flag},
+ isRecmnded_{isRecmnded},
+ passRecKey_{N_1Key},
+ isOldAnlz_{isOldAnlz} {
+
+ int min = 0, max = 5000, nbins = max - min;
+ unsigned short int i = 0, j = 0;
+ for(auto const ®ion : regions) {
+ if ((isOldAnlz) ? region.first != "AR" : region.first == "AR")
+ continue;
+ TString tempTitle = name_ + ", " + dataset + ", " + region.second;
+ TString occTitleF = "Jets Occupancy Map [pt > 200] for events failing ";
+ TString occTitleP = "Jets Occupancy Map [pt > 200] for events passing ";
+ TString fullNameF = "occMap_failed_" + name_ + "_" + region.first;
+ TString fullNameP = "occMap_passed_" + name_ + "_" + region.first;
+ TString titleF = occTitleF + tempTitle + ";#eta;#phi;Events";
+ TString titleP = occTitleP + tempTitle + ";#eta;#phi;Events";
+ failedOccupancyMap_.emplace_back(fullNameF, titleF,
+ 1000, -5, 5, 314, -3.1416, 3.1416);
+ passedOccupancyMap_.emplace_back(fullNameP, titleP,
+ 1000, -5, 5, 314, -3.1416, 3.1416);
+ occMapIndex_[region.first] = i++;
+
+ for(auto const &var : vars) {
+ TString tempName = name_+ "_" + region.first + "_" + var;
+ TString fullName = "eff_" + tempName;
+ TString title = tempTitle + ";" + var +
+ ((region.first != "BER") ? ";Efficiency" : ";NoiseRejectionFraction");
+
+ auto fullNameDen = "den_" + tempName;
+ auto fullNameNum = "num_" + tempName;
+ auto numTitle = tempTitle + ", numerator" + ";" + var + ";Events";
+ auto denTitle = tempTitle + ", denominator" + ";" + var + ";Events";
+
+ efficiency_.emplace_back(fullName, title, nbins, min, max);
+ denominator_.emplace_back(fullNameDen, denTitle, nbins, min, max);
+ numerator_.emplace_back(fullNameNum, numTitle, nbins, min, max);
+ effIndex_[region.first][var] = j++;
+ }
+ }
+}
+
+
+const std::array, 3> MetFilter::regions = {
+ {{"NFR", "Noise Free Region"}, {"BER", "Background Enriched Region"},
+ {"AR", "All Regions"}}};
+
+
+const std::array MetFilter::vars = {{"pfMet", "puppiMet",
+ "leadingJetPt", "nPVx"}};
+
+
+MetFilter::~MetFilter() noexcept {}
+
+
+void MetFilter::Fill(double const &x, std::array const &info,
+ int const &passRecStatus) {
+ if (passRecStatus == passRecKey_ or passRecStatus == 255 or
+ passRecStatus == -1) {
+ TString const ®ion = info[0];
+ TString const &var = info[1];
+ auto &i = effIndex_[region][var];
+ efficiency_[i].Fill((region != "BER") ? *isPassed_ : not(*isPassed_), x);
+ denominator_[i].Fill(x);
+ if ((*isPassed_ and region != "BER") or
+ (not(*isPassed_) and region == "BER"))
+ numerator_[i].Fill(x);
+ }
+}
+
+
+void MetFilter::Fill(
+ doubleVectorReader &etaVec, doubleVectorReader &phiVec,
+ TString const ®ion, int const &passRecStatus) {
+ if (passRecStatus == passRecKey_ or passRecStatus == 255 or
+ passRecStatus == -1) {
+ auto &i = occMapIndex_[region];
+
+ if (!(*isPassed_))
+ for (long unsigned int j = 0; j < (*etaVec).size(); j++)
+ failedOccupancyMap_[i].Fill((*etaVec)[j], (*phiVec)[j]);
+
+ if (*isPassed_)
+ for (long unsigned int j = 0; j < (*etaVec).size(); j++)
+ passedOccupancyMap_[i].Fill((*etaVec)[j], (*phiVec)[j]);
+ }
+}
+
+
+void MetFilter::SetDirectory(TFile &outputRootFile) {
+ for (long unsigned int i = 0; i < efficiency_.size(); i++)
+ efficiency_[i].SetDirectory(&outputRootFile);
+}
+
+
+bool MetFilter::IsPassed() {
+ return *isPassed_;
+}
+
+
+bool MetFilter::IsRecommeded() const {
+ return isRecmnded_;
+}
+
+
+TString MetFilter::GetName() const {
+ return name_;
+}
+
+
+TString MetFilter::GetFlag() const {
+ return flag_;
+}
+
diff --git a/scan/bin/MetFilter.h b/scan/bin/MetFilter.h
new file mode 100644
index 00000000000..3f1ecfc6866
--- /dev/null
+++ b/scan/bin/MetFilter.h
@@ -0,0 +1,93 @@
+#ifndef METFILTER_H
+#define METFILTER_H
+
+#include
+#include