/*
* Delphes: a framework for fast simulation of a generic collider experiment
* Copyright (C) 2012-2014 Universite catholique de Louvain (UCL), Belgium
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 program. If not, see .
*/
/** \class PileUpMergerPythia8
*
* Merges particles from pile-up sample into event
*
* \author M. Selvaggi - UCL, Louvain-la-Neuve
*
*/
#include "modules/PileUpMergerPythia8.h"
#include "classes/DelphesClasses.h"
#include "classes/DelphesFactory.h"
#include "classes/DelphesPileUpReader.h"
#include "classes/DelphesTF2.h"
#include "ExRootAnalysis/ExRootClassifier.h"
#include "ExRootAnalysis/ExRootFilter.h"
#include "ExRootAnalysis/ExRootResult.h"
#include "Pythia.h"
#include "TDatabasePDG.h"
#include "TFormula.h"
#include "TLorentzVector.h"
#include "TMath.h"
#include "TObjArray.h"
#include "TRandom3.h"
#include "TString.h"
#include
#include
#include
#include
using namespace std;
//------------------------------------------------------------------------------
PileUpMergerPythia8::PileUpMergerPythia8() :
fFunction(0), fPythia(0), fItInputArray(0)
{
fFunction = new DelphesTF2;
}
//------------------------------------------------------------------------------
PileUpMergerPythia8::~PileUpMergerPythia8()
{
delete fFunction;
}
//------------------------------------------------------------------------------
void PileUpMergerPythia8::Init()
{
const char *fileName;
fPileUpDistribution = GetInt("PileUpDistribution", 0);
fMeanPileUp = GetDouble("MeanPileUp", 10);
fZVertexSpread = GetDouble("ZVertexSpread", 0.15);
fTVertexSpread = GetDouble("TVertexSpread", 1.5E-09);
fInputBeamSpotX = GetDouble("InputBeamSpotX", 0.0);
fInputBeamSpotY = GetDouble("InputBeamSpotY", 0.0);
fOutputBeamSpotX = GetDouble("OutputBeamSpotX", 0.0);
fOutputBeamSpotY = GetDouble("OutputBeamSpotY", 0.0);
fPTMin = GetDouble("PTMin", 0.0);
fFunction->Compile(GetString("VertexDistributionFormula", "0.0"));
fFunction->SetRange(-fZVertexSpread, -fTVertexSpread, fZVertexSpread, fTVertexSpread);
fileName = GetString("ConfigFile", "MinBias.cmnd");
fPythia = new Pythia8::Pythia();
fPythia->readFile(fileName);
// import input array
fInputArray = ImportArray(GetString("InputArray", "Delphes/stableParticles"));
fItInputArray = fInputArray->MakeIterator();
// create output arrays
fParticleOutputArray = ExportArray(GetString("ParticleOutputArray", "stableParticles"));
fVertexOutputArray = ExportArray(GetString("VertexOutputArray", "vertices"));
}
//------------------------------------------------------------------------------
void PileUpMergerPythia8::Finish()
{
if(fPythia) delete fPythia;
}
//------------------------------------------------------------------------------
void PileUpMergerPythia8::Process()
{
TDatabasePDG *pdg = TDatabasePDG::Instance();
TParticlePDG *pdgParticle;
Int_t pid, status;
Float_t x, y, z, t, vx, vy;
Float_t px, py, pz, e;
Double_t dz, dphi, dt;
Int_t numberOfEvents, event, numberOfParticles, i;
Candidate *candidate, *vertex;
DelphesFactory *factory;
const Double_t c_light = 2.99792458E8;
fItInputArray->Reset();
// --- Deal with primary vertex first ------
fFunction->GetRandom2(dz, dt);
dt *= c_light * 1.0E3; // necessary in order to make t in mm/c
dz *= 1.0E3; // necessary in order to make z in mm
vx = 0.0;
vy = 0.0;
numberOfParticles = fInputArray->GetEntriesFast();
while((candidate = static_cast(fItInputArray->Next())))
{
vx += candidate->Position.X();
vy += candidate->Position.Y();
z = candidate->Position.Z();
t = candidate->Position.T();
candidate->Position.SetZ(z + dz);
candidate->Position.SetT(t + dt);
fParticleOutputArray->Add(candidate);
}
if(numberOfParticles > 0)
{
vx /= numberOfParticles;
vy /= numberOfParticles;
}
factory = GetFactory();
vertex = factory->NewCandidate();
vertex->Position.SetXYZT(vx, vy, dz, dt);
fVertexOutputArray->Add(vertex);
// --- Then with pile-up vertices ------
switch(fPileUpDistribution)
{
case 0:
numberOfEvents = gRandom->Poisson(fMeanPileUp);
break;
case 1:
numberOfEvents = gRandom->Integer(2 * fMeanPileUp + 1);
break;
default:
numberOfEvents = gRandom->Poisson(fMeanPileUp);
break;
}
for(event = 0; event < numberOfEvents; ++event)
{
while(!fPythia->next())
;
// --- Pile-up vertex smearing
fFunction->GetRandom2(dz, dt);
dt *= c_light * 1.0E3; // necessary in order to make t in mm/c
dz *= 1.0E3; // necessary in order to make z in mm
dphi = gRandom->Uniform(-TMath::Pi(), TMath::Pi());
vx = 0.0;
vy = 0.0;
numberOfParticles = fPythia->event.size();
for(i = 1; i < numberOfParticles; ++i)
{
Pythia8::Particle &particle = fPythia->event[i];
status = particle.statusHepMC();
if(status != 1 || !particle.isVisible() || particle.pT() <= fPTMin) continue;
pid = particle.id();
px = particle.px();
py = particle.py();
pz = particle.pz();
e = particle.e();
x = particle.xProd();
y = particle.yProd();
z = particle.zProd();
t = particle.tProd();
candidate = factory->NewCandidate();
candidate->PID = pid;
candidate->Status = 1;
pdgParticle = pdg->GetParticle(pid);
candidate->Charge = pdgParticle ? Int_t(pdgParticle->Charge() / 3.0) : -999;
candidate->Mass = pdgParticle ? pdgParticle->Mass() : -999.9;
candidate->IsPU = 1;
candidate->Momentum.SetPxPyPzE(px, py, pz, e);
candidate->Momentum.RotateZ(dphi);
x -= fInputBeamSpotX;
y -= fInputBeamSpotY;
candidate->Position.SetXYZT(x, y, z + dz, t + dt);
candidate->Position.RotateZ(dphi);
candidate->Position += TLorentzVector(fOutputBeamSpotX, fOutputBeamSpotY, 0.0, 0.0);
vx += candidate->Position.X();
vy += candidate->Position.Y();
fParticleOutputArray->Add(candidate);
}
if(numberOfParticles > 0)
{
vx /= numberOfParticles;
vy /= numberOfParticles;
}
vertex = factory->NewCandidate();
vertex->Position.SetXYZT(vx, vy, dz, dt);
vertex->IsPU = 1;
fVertexOutputArray->Add(vertex);
}
}
//------------------------------------------------------------------------------