TtZHadronicTopMPI

Analysis Twiki for the √s = 13 TeV ttZ analysis page for the MPI HEC group (one possible analysis being considered).

NOTE: This page is obsolete but is being kept for reference purposes. Please go to the official analysis page here:

https://twiki.cern.ch/twiki/bin/view/AtlasProtected/TtZ2LOS

Overview

Proposed analysis to measure the SM cross-section for ttZ at √s = 13 TeV where both tops decay hadronically and the Z boson decays leptonically (ee/µµ).

Signal Process and Proposed Event-Selection Cuts

Some of the leading-order Standard Model Feynman diagrams for the production of a top-antitop quark pair in association with a Z boson.


Theoretical NLO production cross-section for SM ttZ is approximately 0.84 pb with an uncertainty of 12% (ref: arXiv:1609.01599). Considering only all-hadronic top-antitop quark pair decays and Z boson decays to ee/µµ, the effective cross-section times branching ratio should be roughly 0.84 x 0.46 x 0.06729 = 26 fb, leading to only a total of roughly 2600 signal events produced over the entire Run 2 period assuming 100 fb-1.

Could envision both a boosted and non-boosted topology for the case of the top quarks with slightly differing event selection. Would then make use of two separate jet collections: R=1.0 for the boosted case, and R=0.4 for the non-boosted case but also for searching for b-tagged jets within the larger-R jets in the boosted case.

For a rough set of event-selection cuts, propose the following (boosted and non-boosted selection cuts shown separately):

1. Pass single-lepton trigger (or multi-lepton trigger with lower pT threshold?)

2. Exactly two opposite-sign, same-flavour leptons with |mZ-mll| < X GeV (whatever is a commonly used window - could optimize)

3. Primary vertex with > 4 tracks (or whatever convention is for Run 2)

Boosted/non-boosted split here but some events will be expected to overlap (not currently orthogonal searches)

4. Require at least two R=1.0 jets with pT > X GeV.

5. Require at least two b-tagged R=0.4 jets with pT > X GeV and which are which satisfy ∆R(j,J) < X for the two large-R jets

6. Require MET < X GeV (or MET significance) to suppress contributions from semileptonic top-quark decays

7. Additional fat jet substructure-related cuts, sub-jettiness, top mass window, W mass

1. Pass single-lepton trigger (or multi-lepton trigger with lower pT threshold?)

2. Exactly two opposite-sign, same-flavour leptons with |mZ-mll| < X GeV (whatever is a commonly used window - could optimize)

3. Primary vertex with > 4 tracks (or whatever convention is for Run 2)

Boosted/non-boosted split here but some events will be expected to overlap (not currently orthogonal searches)

4. Require at least six R=0.4 jets with pT > 25 GeV (with possibly a ∆R isolation cut)

5. Require at least two of these jets to be b-tagged

6. Require MET < X GeV (or MET significance) to suppress contributions from semileptonic top-quark decays

7. Additional cuts related to jets, angular cuts, top mass window, W mass (with combinatorics)

Monte Carlo Samples

The following dataset (approx 9 GB total) is stored locally in Garching here:

/ptmp/mpp/tmccarth/ttZ/Datasets/mc12_13TeV.119355.MadGraphPythia_AUET2BCTEQ6L1_ttbarZ.evgen.EVNT.e3214

Note that one first has to log onto one of the machines at RZG (mppuiN.t2.rzg.mpg.de, where N=1,2,3), so from a pc at MPP:

ssh -X mppui2.t2.rzg.mpg.de   # for instance, or mppui1 or mppui3

In addition, fully simulated samples were produced for the TopWG and are also being considered:

mc15_13TeV.410157.aMcAtNloPythia8EvtGen_MEN30NLO_A14N23LO_ttZqq.merge.DAOD_TOPQ1.e5070_s2726_r7772_r7676_p3317

That dataset consists of approximately 3M simulated events for a total size of 430 GB (roughly 143 kB/event). AnalysisTop can then be used to produce slimmed ntuples for the local stage of the analysis. A similar procedure will then be carried out for the data and background samples.

There are also other samples (including DAODs) available as listed on some of the pages below.

Instructions for Modifying Local NTuple Analysis

After running the root macro (which turns an input file with 3 TTrees into a merged file with a single TTree), one can do the following steps in order to be set up to do a dedicated local analysis.

1. The first step is to create the base directory structure and create the basic event loop skeleton using the TTree::MakeClass function:

i. Create a base analysis directory somewhere (we'll call it analysisDir)

bash$ mkdir analysisDir
bash$ cd analysisDir

ii. Now create some extra output directories to keep things organized:

bash$ mkdir results
bash$ mkdir macros
bash$ mkdir modules

The final of these, modules, is where you will store additional source and header files for extra functions or class definitions which will be used for a dedicated analysis-specific purpose. One of them already exists (ttz2los_base.C and ttz2los_base.h) which will be used for example to do matching between reco- and truth-level jets. Retrieve these two files and put them in the modules/ directory.

iii. Now open one of the sample output root files (of the merged, single-!TTree type). Assume this file is located in and is called ntuple_merged.root. You'll open this file with root (in read-only mode) and create the event loop structure using TTree::MakeClass. The single TTree in that file should have the name physics. We'll use that same name for the output source and header file.

bash$ root -l
root[0] TFile *file = TFile::Open(<path_to_file>+"ntuple_merged.root","READ");
root[1] physics->MakeClass("physics");

iv. You'll leave these two files (physics.C and physics.h) in the main directory (analysisDir).

v. 2. Next one has to modify the header file physics.h. The instructions for what to do are shown below. Note that any time any text is copied/pasted into the new file, it is placed within two sets of comment lines so that it's easy to see what's been added. Using whatever text editor you typically use, open the file and make the following changes:

i. Delete any extra (repeat) lines of #include "vector.h" (for some reason it creates one or two extras)

ii. Directly below this, set the namespace (should be around L18). Insert the following text exactly:

// @TTZ2LOS ------------------------------------------v
using namespace std;
// @TTZ2LOS ------------------------------------------^

The two commented lines will help you find what has been changed (in case you have to do this multiple times). Crucially we'll only modify anything between those lines.

iii. Look for the part of the code which sets the input file (search for GetListOfFiles). Replace the entire section:

if (tree == 0) {
   TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("ntuple_merged.root");
   if (!f || !f->IsOpen()) {
      f = new TFile("ntuple_merged.root");
   }
   f->GetObject("physics",tree);

}
Init(tree);

with the following:

// @TTZ2LOS ------------------------------------------v
if (tree == 0) {
#ifdef SINGLE_TREE
   TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("ntuple_merged.root");
   if (!f || !f->IsOpen()) {
      f = new TFile("ntuple_merged.root");
   }
   f->GetObject("physics",tree);

#else // SINGLE_TREE
   TChain *chain = new TChain("physics","");
   chain->Add("ntuple_merged_1.root/physics");
   chain->Add("ntuple_merged_2.root/physics");
   tree = chain;
#endif // SINGLE_TREE
}
Init(tree);
// @TTZ2LOS ------------------------------------------^

The above was added just in case you want to run over multiple files (using a TChain). You will have to change the input file name(s) as appropriate based on where your outputs are stored.

3. Next one has to modify the source file physics.C which is where the main loop function is defined. These changes are more substantial, but the first bits are in the preamble (includes). The rest is in one large chunk which encompasses the things to do before, within and after the event loop.

i. In the preamble (includes) right before the line void physics::Loop(), add the following:

// @TTZ2LOS ------------------------------------------v
#include "modules/ttz2los_base.C"
// @TTZ2LOS ------------------------------------------^

ii. Almost immediately after that (but within the main Loop() function, right at the top around L16), add the following lines, which you can add to as you add more pieces:

// @TTZ2LOS ------------------------------------------v
bool doBaseMatching(true);
// @TTZ2LOS ------------------------------------------^

iii. Now simply delete everything after (and including) the line for (Long64_t jentry=0; jentry<nentries; jentry++) {, and replace it with the code below (simply copy / paste). It's rather long, but includes all of the basic setup you'll need to do your study, and most of the stuff you add can be in terms of the modules that you add:

// @TTZ2LOS ------------------------------------------v
ADD CODE HERE
// @TTZ2LOS ------------------------------------------^

Instructions for Creating Event Displays

The event display code is based on a class definition (eventDisplay) described in the source and header files: ttz2los_eventdisplaytools.C and ttz2los_eventdisplaytools.h. For now these are simply stored at the link below until I get it figured out with git. There are also some basic functions in two other files: ttz2los_base.C and ttz2los_base.h. These 4 files should all be saved in a sub-directory which you can call modules/. You should also create a directory called eventdisplays/ttZ/ee/ for the output (and add others as needed). The link to the files is here:

https://cernbox.cern.ch/index.php/s/zkfd2SVJOQPYaP3

Currently the code is meant to be incorporated into a simple event loop (based on TTree::MakeClass and by looping over events). The inputs are slimmed nTuples which are produced with the AnalysisTop framework, but one additional step is performed as a hack on the output nTuples to first convert them into a single-TTree file where one can access generator-, truth- or reco-level quantities for a given event.

If you only have nTuples with generator-level information, you could comment out the plotting of the other portions of the event display. You could just feed in hard-coded values to first get it working in order to see the result. Alternatively if you want the 'hacking' macro to go from a 3-TTree nTuple to a single-TTree one, get in touch and I can point you to have I've done that.

Note: the code as-is is meant to be run on ttZ samples (or possibly background samples provided they have the same structure), but can be of course modified. Also the reco indices functionality is commented out (so it will not highlight which reco objects were selected to reconstruct the Z or tops). This can be added back, but it seemed like it was more complicated to do so (again, just get in touch if you need that).

Any variables which aren't defined are assumed to come directly from the TTree.

Here is some basic code you'd need to copy into your macro when doing an event loop:

i. In the preamble of the macro (where the event loop will be performed), i.e. the .C file created after using the TTree::MakeClass function, add the following:

#include "modules/ttz2los_base.C"
#include "modules/ttz2los_eventdisplaytools.C"

ii. Then in the 'Loop()' function, you have to define a few things that will be used in the event loop:

eventDisplay thisEventDisplay;
thisEventDisplay.SetDPGMode(false);
thisEventDisplay.SetupCanvas();
TString eventType;
TString eventTypeExtended;
TString outputDir;
eventType = "ttZ";
eventTypeExtended = "ttZ_ee";  
outputDir = "ttZ/ee";                      // assumes this directory exists as mentioned above (i.e. you'll also have to create it if it's not there)
TString zDecayType_true = "el";  // this can be changed to "mu" or "tau" based on the truth info in the event from the Z decay
TString zDecayType_identified = "el";  // also this should be evaluated dynamically (but ignore for now)
vector<float> *v_eventDisplay_values = new vector<float>;     // vector of floats that contain kinematic info (to set values before the various objects are drawn on the canvas)
vector<TLorentzVector>* v_recoJets = new vector<TLorentzVector>;
vector<float>* v_recoJets_MV2c10 = new vector<float>;
vector<TLorentzVector>* v_partons = new vector<TLorentzVector>;    // bqqbqq quarks at parton level from ttbar decay 
vector<TLorentzVector>* v_zDaughters = new vector<TLorentzVector>;
vector<int>* v_partons_pdgId = new vector<int>;
vector<int>* v_zDaughters_pdgId = new vector<int>;
TLorentzVector Z,l1,l2;    // Z boson, lepton1, lepton2
TLorentzVector W1,W2;      // W bosons
TLorentzVector b1,b2;      // b/bbar
TLorentzVector q1,q2;      // ---> where W1->q1q2
TLorentzVector q3,q4;      // ---> where W2->q3q4
TLorentzVector reco4V;
float q1_mass,q2_mass,q3_mass,q4_mass;            // in case of light-flavour quarks or leptons to avoid negative mass values from E^2-p^2 floating point precision
int q1_pdgId,q2_pdgId;  // quarks from W 1
int q3_pdgId,q4_pdgId;  // quarks from W 2
int l1_pdgId,l2_pdgId;    // generator-level leptons from Z decay
TLorentzVector top1_beforeFSR,top2_beforeFSR;  // top quarks (before FSR)
TLorentzVector top1_afterFSR,top2_afterFSR;        // top quarks (after FSR)
TLorentzVector recoTop1,recoTop2,recoW1,recoW2,recoZ; // these need to be built from reco jets or leptons (usually based on a reco algorithm)
vector<TLorentzVector>* v_recoEl = new vector<TLorentzVector>;
vector<TLorentzVector>* v_recoMu = new vector<TLorentzVector>;
vector<int> v_recoJets_recoIndices_minChi2;   // output from reconstruction algorithm with MinChi2
vector<int> v_recoLeptons_recoIndices;

iii. Finally within the event loop itself, set the relevant values of quantities or fill vectors of lorentz vectors, then draw the final canvas based on the event display class (final output should be a .pdf). There are a few variables not defined below, but the comments should make it clear what they are (so you'll have to replace them with however you access the quantities).

// Set the kinematic quantities of the quarks, tops, reco jets, etc.
q1_pdgId = MC_Wdecay1_from_t_pdgId;
q2_pdgId = MC_Wdecay2_from_t_pdgId;
q3_pdgId = MC_Wdecay1_from_tbar_pdgId;
q4_pdgId = MC_Wdecay2_from_tbar_pdgId;
l1_pdgId = MC_Zdecay1_pdgId;
l2_pdgId = MC_Zdecay2_pdgId; 
q1_mass = ReturnCorrectedMass(abs(q1_pdgId), MC_Wdecay1_from_t_m); 
q2_mass = ReturnCorrectedMass(abs(q2_pdgId), MC_Wdecay2_from_t_m); 
q3_mass = ReturnCorrectedMass(abs(q3_pdgId), MC_Wdecay1_from_tbar_m); 
q4_mass = ReturnCorrectedMass(abs(q4_pdgId), MC_Wdecay2_from_tbar_m);
W1.SetPtEtaPhiM(MC_W_from_t_pt/1.e3,MC_W_from_t_eta,MC_W_from_t_phi,MC_W_from_t_m/1.e3);
W2.SetPtEtaPhiM(MC_W_from_tbar_pt/1.e3,MC_W_from_tbar_eta,MC_W_from_tbar_phi,MC_W_from_tbar_m/1.e3);
b1.SetPtEtaPhiM(MC_b_from_t_pt/1.e3,MC_b_from_t_eta,MC_b_from_t_phi,MC_b_from_t_m/1.e3);
b2.SetPtEtaPhiM(MC_b_from_tbar_pt/1.e3,MC_b_from_tbar_eta,MC_b_from_tbar_phi,MC_b_from_tbar_m/1.e3);
Z.SetPtEtaPhiM(MC_Z_pt/1.e3,MC_Z_eta,MC_Z_phi,MC_Z_m/1.e3);
q1.SetPtEtaPhiM(MC_Wdecay1_from_t_pt/1.e3,MC_Wdecay1_from_t_eta,MC_Wdecay1_from_t_phi,q1_mass/1.e3);
q2.SetPtEtaPhiM(MC_Wdecay2_from_t_pt/1.e3,MC_Wdecay2_from_t_eta,MC_Wdecay2_from_t_phi,q2_mass/1.e3);
q3.SetPtEtaPhiM(MC_Wdecay1_from_tbar_pt/1.e3,MC_Wdecay1_from_tbar_eta,MC_Wdecay1_from_tbar_phi,q3_mass/1.e3);
q4.SetPtEtaPhiM(MC_Wdecay2_from_tbar_pt/1.e3,MC_Wdecay2_from_tbar_eta,MC_Wdecay2_from_tbar_phi,q4_mass/1.e3);
l1.SetPtEtaPhiM(MC_Zdecay1_pt/1.e3,MC_Zdecay1_eta,MC_Zdecay1_phi,ReturnCorrectedMass(abs(l1_pdgId),MC_Zdecay1_m)/1.e3);
l2.SetPtEtaPhiM(MC_Zdecay2_pt/1.e3,MC_Zdecay2_eta,MC_Zdecay2_phi,ReturnCorrectedMass(abs(l2_pdgId),MC_Zdecay2_m)/1.e3);
if(abs(l1_pdgId)==11) zDecayType_true = "el";
else if(abs(l1_pdgId)==13) zDecayType_true = "mu";
else zDecayType_true = "tau";
v_zDaughters->push_back(l1); 
v_zDaughters_pdgId->push_back(MC_Zdecay1_pdgId);
v_zDaughters->push_back(l2); 
v_zDaughters_pdgId->push_back(MC_Zdecay2_pdgId);
// NOTE: order matters here for the parton vector
v_partons->push_back(b1);    v_partons_recoIndices->push_back(1);    v_partons_pdgId->push_back(5); 
v_partons->push_back(b2);    v_partons_recoIndices->push_back(-1);   v_partons_pdgId->push_back(-5);
v_partons->push_back(q1);    v_partons_recoIndices->push_back(2);    v_partons_pdgId->push_back(q1_pdgId);
v_partons->push_back(q2);    v_partons_recoIndices->push_back(2);    v_partons_pdgId->push_back(q2_pdgId);
v_partons->push_back(q3);    v_partons_recoIndices->push_back(-2);   v_partons_pdgId->push_back(q3_pdgId);
v_partons->push_back(q4);    v_partons_recoIndices->push_back(-2);   v_partons_pdgId->push_back(q4_pdgId);

for(unsigned int i = 0; i < reco_jet_pt->size(); ++i) {
   reco4V.SetPtEtaPhiE(reco_jet_pt->at(i)/1.e3, reco_jet_eta->at(i), reco_jet_phi->at(i), reco_jet_e->at(i)/1.e3);
   v_recoJets->push_back(reco4V);
   v_recoJets_MV2c10->push_back(reco_jet_mv2c10->at(i));
}

for(unsigned int i = 0; i < reco_el_pt->size(); ++i) {
   reco4V.SetPtEtaPhiE(reco_el_pt->at(i)/1.e3, reco_el_eta->at(i), reco_el_phi->at(i), reco_el_e->at(i)/1.e3);
   v_recoEl->push_back(reco4V);
}

for(unsigned int i = 0; i < reco_mu_pt->size(); ++i) {
   reco4V.SetPtEtaPhiE(reco_mu_pt->at(i)/1.e3, reco_mu_eta->at(i), reco_mu_phi->at(i), reco_mu_e->at(i)/1.e3);
   v_recoMu->push_back(reco4V);
}

thisEventDisplay.ResetCanvas();
thisEventDisplay.SetEventType(eventType);
v_eventDisplay_values->push_back(reco_jet_n);     // int: number of reco jets in the event
v_eventDisplay_values->push_back(reco_bjet_n);   // int: number of b-tagged reco jets in the event
v_eventDisplay_values->push_back(reco_el_n);      // int: number of reco electrons
v_eventDisplay_values->push_back(reco_mu_n);    // int: number of reco muons
v_eventDisplay_values->push_back(minChi2Terms[4]);      // float: output min chi2 value from the reco algorithm (for now only designed for this reco algorithm but could be BDT value)
v_eventDisplay_values->push_back(reco_met_met/1.e3);  // float: met in GeV
v_eventDisplay_values->push_back(recoTop1.Mag());        // float: reco top 1 mass in GeV
v_eventDisplay_values->push_back(recoW1.Mag());          // float: reco W 1 mass in GeV
v_eventDisplay_values->push_back(recoTop2.Mag());
v_eventDisplay_values->push_back(recoW2.Mag());
v_eventDisplay_values->push_back(recoZ.Mag());              // float: reco Z mass in GeV
thisEventDisplay.SetMarkerColours(true, zDecayType_true);
thisEventDisplay.PrintEventLevelInfo(eventNumber, *v_eventDisplay_values);  // int: eventNumber should be added here
// thisEventDisplay.PrintRecoPurityBoxes(recoZPC,recoTop1PC,recoTop2PC,recoW1PC,recoW2PC);   // ignore this for now (requires additional functionality to see if reco objects are correct - ask me if you want this)
thisEventDisplay.PrintPartonLevel4VectorInfo(*v_zDaughters, *v_zDaughters_pdgId, "Z");
thisEventDisplay.PrintPartonLevel4VectorInfo(*v_partons, *v_partons_pdgId, "Top1");
thisEventDisplay.PrintPartonLevel4VectorInfo(*v_partons, *v_partons_pdgId, "Top2");
thisEventDisplay.PrintPreFSRTop4VectorInfo(top1_beforeFSR, top2_beforeFSR);
thisEventDisplay.EvaluateThrust(Z,top1_beforeFSR,top2_beforeFSR,top1_afterFSR,top2_afterFSR);
thisEventDisplay.PrintThrustPlot();
thisEventDisplay.PrintMainEventDisplay(*v_recoJets, *v_partons, *v_partons_pdgId, *v_recoEl, *v_recoMu, *v_zDaughters, *v_zDaughters_pdgId,
                   reco_met_phi, v_recoJets_recoIndices_minChi2, v_recoLeptons_recoIndices, zDecayType_identified);
v_eventDisplay_values->clear(); // for next event
thisEventDisplay.SetOutputDirectory(outputDir);
thisEventDisplay.SaveEventDisplay(".pdf");

// Clear values for next event
v_recoJets->clear();
v_recoJets_MV2c10->clear();
v_partons->clear();
v_partons_pdgId->clear();
v_zDaughters->clear();
v_zDaughters_pdgId->clear();
v_recoEl->clear();
v_recoMu->clear();
v_recoMu_charge->clear();

Top Trigger Links

Additional MC Samples / Associated Pages

Current Issues with AnalysisTop

The following is a list of things that eventually would need to be incorporated / hacked into AnalysisTop

  • add loose muons (as well as the standard 'good' muons) to investigate a semi-leptonic b-jet correction
  • add CaloCalTopoClusters container in its entirety but also somehow only those associated to jets (large-R and small-R) to calculate my own sub-structure variables, compute jet time, etc.
  • add parton-level Z information (similarly to the top and antitop and decay products) for truth-level and parton-level studies

Links and Additional Info

-- ThomasMcCarthy - 2017-09-20

Edit | Attach | Watch | Print version | History: r12 < r11 < r10 < r9 < r8 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r12 - 2018-05-11 - ThomasMcCarthy
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Main All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright &© 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback