// VertexJets package
// Quesstions / Comments: pascal.nef@slac.stanford.edu, sch@slac.stanford.edu
//
//
// Copyright (c) 2014
// Pascal Nef, Ariel Schwartzman
//
// Compile this code as:
// make example
// And run it with:
// ./example < ../data/Pythia-Zp2jets-lhc-pileup-1ev.dat
//
// $Id$
//
// Copyright (c) -,
//
//----------------------------------------------------------------------
// This file is part of FastJet contrib.
//
// It is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at
// your option) any later version.
//
// It is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this code. If not, see .
//----------------------------------------------------------------------
#include
#include
#include
#include "fastjet/PseudoJet.hh"
#include "fastjet/ClusterSequenceArea.hh"
#include
#include "VertexJets.hh" // In external code, this should be fastjet/contrib/VertexJets.hh
#include "fastjet/tools/JetMedianBackgroundEstimator.hh"
using namespace std;
using namespace fastjet;
// forward declaration to make things clearer
void read_event(vector &event);
// example user info class
class MyUserInfo : public fastjet::PseudoJet::UserInfoBase{
public:
MyUserInfo(const bool &is_pileup, const int charge): _is_pileup(is_pileup), _charge(charge){}
bool is_pileup() const { return _is_pileup;}
int charge () const { return _charge;}
protected:
bool _is_pileup; // true if pileup particle
int _charge; // charge: -1, 0, 1
};
// Selector worker for charged pileup particles
class SelectorWorkerChargedPileup : public fastjet::SelectorWorker {
public:
virtual bool pass(const fastjet::PseudoJet & particle) const {
// we check that the user_info_ptr is non-zero
return (particle.has_user_info()
&& particle.user_info().is_pileup() == true
&& abs(particle.user_info().charge()) == 1 );
}
virtual string description() const {return "charged particle from pileup interaction";}
};
// Selector worker for charged hard-scatter particles
class SelectorWorkerChargedHardScatter : public fastjet::SelectorWorker {
public:
virtual bool pass(const fastjet::PseudoJet & particle) const {
// we check that the user_info_ptr is non-zero
return (particle.has_user_info()
&& particle.user_info().is_pileup() == false
&& abs(particle.user_info().charge()) == 1 );
}
virtual string description() const {return "charged particle from hard-scatter";}
};
// now the two selector functions
fastjet::Selector SelectorChargedPileup() {
return new SelectorWorkerChargedPileup();
}
fastjet::Selector SelectorChargedHardScatter() {
return new SelectorWorkerChargedHardScatter();
}
//----------------------------------------------------------------------
int main(){
//----------------------------------------------------------
// read in input particles
vector event;
read_event(event);
cout << "# read an event with " << event.size() << " particles" << endl;
// calculate pileup pT density
JetMedianBackgroundEstimator bge(SelectorAbsRapMax(4.), JetDefinition(kt_algorithm,0.4), AreaDefinition(active_area_explicit_ghosts));
bge.set_particles(event);
Subtractor theSubtractor(&bge);
//----------------------------------------------------------
// area definition
AreaDefinition area_def(active_area_explicit_ghosts);
// cluster particles into small-R jets (anti-kt 0.4)
JetDefinition jet_def_small(antikt_algorithm, 0.4);
ClusterSequenceArea cs_small(event, jet_def_small, area_def);
Selector sel_jets_small = SelectorNHardest(4) * SelectorAbsRapMax(2.5);
vector jets_small = sel_jets_small(theSubtractor(cs_small.inclusive_jets()));
// cluster particles into large-R jets (anti-kt 1.0)
JetDefinition jet_def_large(antikt_algorithm, 1.0);
ClusterSequenceArea cs_large(event, jet_def_large, area_def);
Selector sel_jets_large = SelectorNHardest(2) * SelectorAbsRapMax(1.5);
vector jets_large = sel_jets_large(cs_large.inclusive_jets());
//----------------------------------------------------------
// now use VertexJets to calculate corrJVF for small-R jets
// get total number of charged pileup particles within the tracker coverage
Selector sel_charged_pu_particles = SelectorChargedPileup();
int n_pileup_tracks = sel_charged_pu_particles(event).size();
// here comes VertexJets for small R jets
contrib::VertexJets vertexjet(SelectorChargedPileup(), SelectorChargedHardScatter());
vertexjet.set_tot_n_pu_tracks (n_pileup_tracks);
vertexjet.set_corrJVF_scale_factor (0.01);
vertexjet.set_corrJVF_cut (0.6);
cout << vertexjet.description() << endl;
cout << setprecision(3);
// loop over small R jets
cout << ">> anti-kt 0.4 jets: " << endl;
for(unsigned int ij=0; ij < jets_small.size(); ++ij){
PseudoJet resultjet = vertexjet(jets_small[ij]);
cout << " jet " << ij << ": pt " << resultjet.pt()
<< " eta " << resultjet.eta()
<< " phi " << resultjet.phi()
<< " m " << resultjet.m()
<< " corrJVF "<< resultjet.structure_of().corrJVF() << endl;
}
//----------------------------------------------------------
// and for large Rjets in grooming mode
contrib::VertexJets vertexjet_largeR(SelectorChargedPileup(), SelectorChargedHardScatter(), JetDefinition(kt_algorithm, 0.3));
vertexjet_largeR.set_tot_n_pu_tracks (n_pileup_tracks);
vertexjet_largeR.set_corrJVF_scale_factor (0.01);
vertexjet_largeR.set_corrJVF_cut (0.6);
vertexjet_largeR.set_trimming_fcut (0.05);
vertexjet_largeR.set_subtractor (&theSubtractor);
cout << vertexjet_largeR.description() << endl;
// loop over large R jets
cout << ">> anti-kt 1.0 jets: " << endl;
for(unsigned int ij=0; ij< jets_large.size(); ++ij){
PseudoJet resultjet = vertexjet_largeR(jets_large[ij]);
cout << " jet " << ij << ": pt " << resultjet.pt()
<< " eta " << resultjet.eta()
<< " phi " << resultjet.phi()
<< " mass " << resultjet.m() << endl;
vector subjets = resultjet.pieces();
for (unsigned int is=0; is subjet " << is << ": pt " << subjets[is].pt() << " corrJVF " << subjets[is].structure_of().corrJVF() << endl;
}
}
return 0;
}
// read in input particles
void read_event(vector &event){
string line;
int nsub = 0; // counter to keep track of which sub-event we're reading
while (getline(cin, line)) {
istringstream linestream(line);
// characters (e.g. line-feed).
if (line.substr(0,4) == "#END") {break;}
if (line.substr(0,9) == "#SUBSTART") {nsub += 1;}
if (line.substr(0,1) == "#") {continue;}
double px,py,pz,E;
int pdg_id, charge;
linestream >> px >> py >> pz >> E >> pdg_id >> charge;
PseudoJet particle(px,py,pz,E);
particle.reset_PtYPhiM(particle.pt(), particle.rapidity(), particle.phi(), 0.); // set particles massless
// set charge to 0 if outside tracker
if(fabs(particle.eta())> 2.4) charge = 0;
// set user info
particle.set_user_info(new MyUserInfo(nsub==1?false:true, charge)); // is_pileup, charge
// push event into event vector
event.push_back(particle);
}
// if there was nothing in the event
if (nsub == 0) {
cerr << "Error: read empty event\n";
exit(-1);
}
cout << "# " << nsub-1 << " pileup events on top of the hard event" << endl;
}