/**
* @file EGConfig.C
* @author Christian Holm Christensen <cholm@nbi.dk>
* @date Thu Oct 16 11:01:38 2014
*
* @brief Specific configuration for event generator.
*
*
*/
struct EGCfg : public VirtualEGCfg
{
Int_t hftype; // Heavy flavour type (random)
Bool_t fIsLego; //
EGCfg()
: hftype(-1), fIsLego(false);
{
hftype = HFType();
}
virtual Bool_t IsLego() const { return fIsLego; }
protected:
/**
* Make a random Heavy Flavour type
*
* @return Heavy flavour type
*/
Int_t HFType() const
{
Int_t type = -1;
Int_t r = gRandom->Rndm();
if (r < 0.16) type = 0;
else if (r < 0.32) type = 1;
else if (r < 0.48) type = 2;
else if (r < 0.64) type = 3;
else if (r < 0.72) type = 4;
else if (r < 0.80) type = 5;
else type = 6;
return r;
}
/**
* Make the generator
*
* @param rt Generator ID
* @param b1 Least impact parameter
* @param b2 Largest impact parameter
*
* @return Point to newly allocated generator or null
*/
AliGenerator* CreateGenerator(const TString& rt,
Float_t b1, Float_t b2)
{
Bool_t asym = grp->IsPA()||grp->IsAP();
AliGenerator* g = 0;
TString t(rt);
if (t.EqualTo("default")) t = DeduceRunType();
if (t.EndsWith("perugia0chadr")) g=PythiaHF(0);
else if (t.EndsWith("perugia0bchadr")) g=PythiaHF(1);
else if (t.EndsWith("perugia0cele")) g=PythiaHF(2);
else if (t.EndsWith("perugia0bele")) g=PythiaHF(3);
else if (t.EndsWith("perugia0jspi2e")) g=PythiaHF(4);
else if (t.EndsWith("perugia0btojspi2e")) g=PythiaHF(5);
else if (t.BeginsWith("pythia")) g=Pythia(rt);
else if (t.BeginsWith("hijing2000hf")) g=HFCocktail(rt, b1, b2);
else if (t.BeginsWith("hijing2000")) g=Hijing(b1, b2, asym,
false, 2.3);
else if (t.BeginsWith("hijing")) g=Hijing(b1, b2, asym,
grp->IsAA(), 0);
else if (t.BeginsWith("ampthf")) g=HFCocktail(rt,b1,b2);
else if (t.BeginsWith("ampt")) g=Ampt(b1, b2);
else if (t.BeginsWith("dpmjet")) g=Dpmjet(b1, b2);
else if (t.BeginsWith("phojet")) g=Dpmjet(b1, b2);
else if (t.BeginsWith("hydjet")) g=Hydjet(b1, b2);
else if (t.BeginsWith("lego")) g=Lego(rt);
if (!g && !fIsLego)
Fatal("", "Invalid run type \"%s\" specified", t.Data());
return g;
}
/**
* Make our decayer
*
* @return Newly allocated decayer or null
*/
TVirtualMCDecayer* CreateDecayer(const TString& runType)
{
if (runType.BeginsWith("hydjet")) return 0;
LoadPythia();
TVirtualMCDecayer* decayer = new AliDecayerPythia();
if (runType.EqualTo("hijing2000hf") && hftype < 2)
decayer->SetForceDecay(kHadronicD);
else
decayer->SetForceDecay(kAll);
decayer->Init();
return decayer;
}
// === PYTHIA ========================================================
// Normal
/**
* Greate a pythia6 event generator
*
* @param tune Possible tune
*
* @return newly allocated generator or null
*/
AliGenerator* Pythia(const TString & tune)
{
// Int_t kCTEQ6l = 8;
if (!grp->IsPP()) Fatal("Setup", "Pythia6 only works for pp");
TString t(tune);
t.ToUpper();
t.ReplaceAll("PYTHIA6", "");
t.ReplaceAll("PYTHIA", "");
Info("Setup", "Making Pythia6 event generator (tune: %s)", t.Data());
LoadPythia();
AliGenPythia* pythia = new AliGenPythia(-1);
pythia->SetMomentumRange(0, 999999.);
pythia->SetThetaRange(0., 180.);
pythia->SetYRange(-12.,12.);
pythia->SetPtRange(0,1000.);
pythia->SetProcess(kPyMb);
pythia->SetEnergyCMS(grp->energy);
if (t == "D6T") {
// Tune
// 109 D6T : Rick Field's CDF Tune D6T
// (NB: needs CTEQ6L pdfs externally)
pythia->SetTune(109); // F I X
pythia->SetStrucFunc(kCTEQ6l);
}
else if (t == "PERUGIA0") {
// Tune
// 320 Perugia 0
pythia->SetTune(320);
pythia->UseNewMultipleInteractionsScenario();
}
else if (t == "ATLAS") {
// Tune
// C 306 ATLAS-CSC: Arthur Moraes' (new) ATLAS tune
// (needs CTEQ6L externally)
pythia->SetTune(306);
pythia->SetStrucFunc(kCTEQ6l);
}
else if (t == "JETS") {
pythia->SetProcess(kPyJets);
pythia->SetStrucFunc(kCTEQ6l);
pythia->SetJetEtaRange(-1.5, 1.5);
pythia->SetJetEtRange(50., 800.);
pythia->SetPtHard(45., 1000.);
pythia->SetPycellParameters(2.2, 300, 432, 0., 4., 5., 0.7);
}
else if (t == "ATLAS_FLAT") {
// set high multiplicity trigger
// this weight achieves a flat multiplicity distribution
TH1 *weight = new TH1D("weight","weight",201,-0.5,200.5);
weight->SetBinContent(1,5.49443);
weight->SetBinContent(2,8.770816);
weight->SetBinContent(6,0.4568624);
weight->SetBinContent(7,0.2919915);
weight->SetBinContent(8,0.6674189);
weight->SetBinContent(9,0.364737);
weight->SetBinContent(10,0.8818444);
weight->SetBinContent(11,0.531885);
weight->SetBinContent(12,1.035197);
weight->SetBinContent(13,0.9394057);
weight->SetBinContent(14,0.9643193);
weight->SetBinContent(15,0.94543);
weight->SetBinContent(16,0.9426507);
weight->SetBinContent(17,0.9423649);
weight->SetBinContent(18,0.789456);
weight->SetBinContent(19,1.149026);
weight->SetBinContent(20,1.100491);
weight->SetBinContent(21,0.6350525);
weight->SetBinContent(22,1.351941);
weight->SetBinContent(23,0.03233504);
weight->SetBinContent(24,0.9574557);
weight->SetBinContent(25,0.868133);
weight->SetBinContent(26,1.030998);
weight->SetBinContent(27,1.08897);
weight->SetBinContent(28,1.251382);
weight->SetBinContent(29,0.1391099);
weight->SetBinContent(30,1.192876);
weight->SetBinContent(31,0.448944);
for (Int_t i = 32; i <= 201; i++) weight->SetBinContent(i,1);
weight->SetEntries(526);
Int_t limit = weight->GetRandom();
pythia->SetTriggerChargedMultiplicity(limit, 1.4);
}
return pythia;
}
/**
* Create a Pythia6 generator for high-flavor physics
*
* @param type Which kind
* @param harder If true, make harder processes
*
* @return Newly allocated generator or null
*/
AliGenerator* PythiaHF(Int_t type, Bool_t harder=0)
{
LoadPythia();
if (type == 6) return Pythia("jets");
if (type == 4) {
AliGenParam *jpsi = AliGenParam(1, AliGenMUONlib::kJpsi,
(harder?"CDF pp 8.8":"CDF pp 7"),"Jpsi");
jpsi->SetPtRange(0.,999.);
jpsi->SetYRange(-1.0, 1.0);
jpsi->SetPhiRange(0.,360.);
jpsi->SetForceDecay(kDiElectron);
return jpsi;
}
AliGenPythia* pythia = static_cast<AliGenPythia*>(Pythia("PERUGIA0"));
switch (type) {
case 0: // chadr
pythia->SetProcess(kPyCharmppMNRwmi);
pythia->SetForceDecay(kHadronicD);
break;
case 1: // bchadr
pythia->SetProcess(kPyBeautyppMNRwmi);
pythia->SetForceDecay(kHadronicD);
break;
case 2: // cele
pythia->SetProcess(kPyCharmppMNRwmi);
pythia->SetCutOnChild(1);
pythia->SetPdgCodeParticleforAcceptanceCut(11);
pythia->SetChildYRange(-1.2,1.2);
pythia->SetChildPtRange(0,10000.);
break;
case 3: // bele
pythia->SetProcess(kPyBeautyppMNRwmi);
pythia->SetCutOnChild(1);
pythia->SetPdgCodeParticleforAcceptanceCut(11);
pythia->SetChildYRange(-1.2,1.2);
pythia->SetChildPtRange(0,10000.);
break;
case 5:
pythia->SetProcess(kPyBeautyppMNRwmi);
pythia->SetCutOnChild(1);
pythia->SetPdgCodeParticleforAcceptanceCut(443);
pythia->SetChildYRange(-2,2);
pythia->SetChildPtRange(0,10000.);
}
return pythia;
}
/**
* Make a Min-Bias AA, pA, or Ap Hijing generator
*
* @param minB Least impact parameter
* @param maxB Largest impact parameter
* @param quench If true, enable quenching
* @param slowN If true, make a cocktail with slow neutrons
* @param ptHard Hard pT cut-off
*
* @return Generator
*/
AliGenerator* Hijing(Float_t minB,
Float_t maxB,
Bool_t slowN=false,
Bool_t quench=1,
Float_t ptHard=0)
{
LoadHijing();
AliGenHijing *gener = new AliGenHijing(-1);
// centre of mass energy
gener->SetEnergyCMS(grp->energy);
gener->SetImpactParameterRange(minB, maxB);
// reference frame
gener->SetReferenceFrame("CMS");
// projectil
gener->SetTarget (grp->beam1.Name(), grp->beam1.a, grp->beam1.z);
gener->SetProjectile(grp->beam2.Name(), grp->beam2.a, grp->beam2.z);
// tell hijing to keep the full parent child chain
gener->KeepFullEvent();
// enable jet quenching
gener->SetJetQuenching(quench);
// enable shadowing
gener->SetShadowing(slowN);
// Don't track spectators
gener->SetSpectators(!slowN);
//
if (ptHard > 0) hi->SetPtHardMin(ptHard);
// kinematic selection
gener->SetSelectAll(0);
// Boosted CMS
gener->SetBoostLHC(grp->IsPA() || grp->IsAP());
// No need for cocktail
if (!slowN || !grp->IsPA() || !grp->IsAP()) return gener;
AliGenCocktail* cocktail = new AliGenCocktail();
cocktail->SetTarget (grp->beam1.Name(), grp->beam1.a, grp->beam1.z);
cocktail->SetProjectile(grp->beam2.Name(), grp->beam2.a, grp->beam2.z);
cocktail->SetEnergyCMS(grp->energy);
AliGenSlowNucleons* gray = new AliGenSlowNucleons(1);
AliCollisionGeometry* coll = gener->CollisionGeometry();
AliSlowNucleonModelExp* model = new AliSlowNucleonModelExp();
// Not yet in the release...
// model->SetSaturation(kTRUE);
gray->SetSlowNucleonModel(model);
gray->SetTarget(grp->beam1.a, grp->beam1.z);
gray->SetThetaDist(1);
gray->SetProtonDirection(grp->beam1.IsP() ? 1 : 2);
// gray->SetDebug(1);
gray->SetNominalCmsEnergy(2*grp->beamEnergy);
gray->NeedsCollisionGeometry();
gray->SetCollisionGeometry(coll);
cocktail->AddGenerator(gener, "Hijing pPb", 1);
cocktail->AddGenerator(gray, "Gray Particles", 1);
return cocktail;
}
/**
* Make a DPMJet generator for pp, AA, pA, or Ap.
*
* @param fragments If true, make fragments
*
* @return Generator
*/
AliGenerator* Dpmjet(Float_t minB, Float_t maxB,
Bool_t fragments=0)
{
LoadDpmjet();
AliGenDPMjet* dpmjet = new AliGenDPMjet(-1);
dpmjet->SetEnergyCMS(grp->energy);
dpmjet->SetProjectile(grp->beam2.Name(), grp->beam2.a, grp->beam2.z);
dpmjet->SetTarget (grp->beam1.Name(), grp->beam1.a, grp->beam1.z);
dpmjet->SetImpactParameterRange(minB, maxB);
dpmjet->SetProjectileBeamEnergy(grp->beam2.z*grp->beamEnergy/grp->beam2.a);
if (grp->IsAA()) {
dpmjet->SetPi0Decay(0);
}
else if (grp->IsPA() || grp->IsAP()) {
// dpmjet->SetTriggerParticle(3312, 1.2, 2.0);
dpmjet->SetFragmentProd(fragments); // Alwas disabled
}
else if (grp->IsPP()) { // PhoJet
dpmjet->SetMomentumRange(0, 999999.);
dpmjet->SetThetaRange(0., 180.);
dpmjet->SetYRange(-12.,12.);
dpmjet->SetPtRange(0,1000.);
}
return dpmjet;
}
/**
* Make an AMPT generator for AA collisions
*
* @return Generator
*/
AliGenerator* Ampt(Float_t minB, Float_t maxB)
{
LoadAmpt();
AliGenAmpt *genHi = new AliGenAmpt(-1);
genHi->SetEnergyCMS(grp->energy);
genHi->SetReferenceFrame("CMS");
genHi->SetTarget (grp->beam1.Name(), grp->beam1.a, grp->beam1.z);
genHi->SetProjectile(grp->beam2.Name(), grp->beam2.a, grp->beam2.z);
genHi->SetPtHardMin (2);
genHi->SetImpactParameterRange(minB,maxB);
// disable jet quenching
genHi->SetJetQuenching(0);
// enable shadowing
genHi->SetShadowing(1);
// neutral pion and heavy particle decays switched off
genHi->SetDecaysOff(1);
genHi->SetSpectators(0); // track spectators
genHi->KeepFullEvent();
genHi->SetSelectAll(0);
return genHi;
}
/**
* Make an HydJet generator for A-A
*
* @return Generator
*/
AliGenerator* Hydjet(Float_t minB, Float_t maxB)
{
LoadHydjet();
AliGenUHKM *genHi = new AliGenUHKM(-1);
genHi->SetAllParametersLHC();
genHi->SetTarget (grp->beam1.Name(), grp->beam1.a, grp->beam1.z);
genHi->SetProjectile(grp->beam2.Name(), grp->beam2.a, grp->beam2.z);
genHi->SetEcms(grp->energy);
genHi->SetEnergyCMS(grp->energy);
genHi->SetBmin(minB);
genHi->SetBmax(maxB);
genHi->SetPyquenPtmin(9);
return genHi;
}
// === Lego ========================================================
/**
* Greate a lego event generator
*
* @param tune Possible tune
*
* @return newly allocated generator or null
*/
AliGenerator* Lego(const TString & variant)
{
fIsLego = true;
return 0;
#if 0
TString v(variant);
v.ToUpper();
v.ReplaceAll("LEGO", "");
Info("Setup", "Making Lego event generator (variant: %s)", v.Data());
AliLegoGenerator* ret = 0;
// XYZ varies origin of the particles in two dimensions:
// X: o=(0,t1,t2), p=(1,0,0)
// Y: o=(t1,0,t2), p=(0,1,0)
// Z: o=(t1,t2,0), p=(0,0,1)
// PhiZ varies the momentum in two dimensions
// o=(0,0,t1) p=(cos(t2),sin(t2),0)
// Eta varies momentum in two dimensions
// phi=t1
// theta=2*atan(exp(-t2))
// o=(0,0,0) p=(cos(phi)*sin(theta),sin(phi)*cos(theta),cos(theta))
// Base varies in two dimensions
// phi=t1
// theta=t2
// o=(0,0,0) p=(cos(phi)*sin(theta),sin(phi)*cos(theta),cos(theta))
if (v.BeginsWith("X") || v.BeginsWith) {
const char* c[] = { v(0), '\0' };
ret = new AliLegoGeneratorXYZ(c);
ret->SetCoor1Range(10,-2,2); // Y, X
ret->SetCoor2Range(10,-10,10); // Z
}
else if (v.BeginsWith("Z")) {
ret = new AliLegoGeneratorXYZ("Z");
ret->SetCoor1Range(10,-2,2); // X
ret->SetCoor2Range(10,-2,2); // Y
}
else if (v.BeginsWith("PHIZ")) {
ret = new AliLegoGeneratorPhiZ();
ret->SetCoor1Range(10,-10,10); // Z
ret->SetCoor2Range(360,0,360); // phi
}
else if (v.BeginsWith("ETA")) {
ret = new AliLegoGeneratorEta();
ret->SetCoor1Range(360,0,360); // phi
Double_t aEta = 7;
Double_t dEta = (6--4)/200;
ret->SetCoor2Range(2*aEta/dEta,-aEta,+aEta); // Eta
}
else {
ret = new AliLegoGenerator();
ret->SetCoor1Range(180,0,180); // theta
ret->SetCoor1Range(360,0,360); // phi
}
return ret;
#endif
}
/**
* Make a heavy flavour cocktail
*
* @param base Underlying event.
*
* @return Generator
*/
AliGeneator* HFCocktail(const TString& base, Float_t minB, Float_t maxB)
{
AliGenCocktail *cocktail = new AliGenCocktail();
cocktail->SetTarget (grp->beam1.Name(), grp->beam1.a, grp->beam1.z);
cocktail->SetProjectile(grp->beam2.Name(), grp->beam2.a, grp->beam2.z);
cocktail->SetEnergyCMS(grp->energy);
// Add underlying event
if (base.BeginsWith("ampt", TString::kIgnoreCase)) {
hi = Ampt(minB, maxB);
cocktail->AddGenerator(hi,"ampt",1);
}
else {
hi = Hijing(minB, maxB, grp->IsPA() || grp->IsAP(), false, 2.3);
cocktail->AddGenerator(hi,"hijing",1);
}
// --- Default formula -------------------------------------------
TForumla* one = new TFormula("one", "1.");
// --- Pythia ----------------------------------------------------
AliGenerator* pythia = PythiaHF(hftype);
switch (hftype) {
case 6:
cocktail->AddGenerator(pythia, "pythiaJets", 1, one);
break;
defualt:
cocktail
->AddGenerator(pythia, "pythiaHF", 1,
new TFormula("Signals",
"20.*(x<5.)+80./3.*(1.-x/20.)*(x>5.)"));
break;
}
// --- Dummy -----------------------------------------------------
AliGenParam* param = 0;
// --- Phos stuff ------------------------------------------------
AliGenPHOSlib *plib = new AliGenPHOSlib();
Double_t lower[] = { 0, 3, 6, 9, 12, -1 };
Double_t *pLow = lower;
for (Int_t i = 0; i < 5; i++) {
param = new AliGenParam(5, plib, AliGenPHOSlib::kPi0);
param->SetPhiRange(0., 360.) ;
param->SetYRange(-1.2, 1.2) ;
param->SetPtRange(lower[i], 30.) ;
cocktail->AddGenerator(param,Form("Pi0HagPt%d", i), 1., one);
}
// --- Jpsi->mu+ mu-----------------------------------------------
param = new AliGenParam(1, AliGenMUONlib::kJpsi, "CDF pp 3.94", "Jpsi");
param->SetPtRange(0.,999.);
param->SetYRange(-4.2, -2.3);
param->SetPhiRange(0.,360.);
param->SetForceDecay(kDiMuon);
param->SetCutOnChild(1);
param->SetChildPhiRange(0.,360.);
param->SetChildThetaRange(168.5,178.5);
cocktail->AddGenerator(param, "Jpsi2M", 1, one);
// --- Chi_c -> J/Psi + gamma, J/Psi -> e+e- ---------------------
Float_t thmin = (180./TMath::Pi())*2.*atan(exp(-1.2));
Float_t thmax = (180./TMath::Pi())*2.*atan(exp( 1.2));
param = new AliGenParam(1, AliGenMUONlib::kChic,"default","Chic");
param->SetMomentumRange(0, 999.); // Wide cut on the momentum
param->SetPtRange(0, 100.); // Wide cut on Pt
param->SetYRange(-2.5, 2.5);
param->SetCutOnChild(1); // Enable cuts on decay products
param->SetChildPhiRange(0., 360.);
// In the acceptance of the Central Barrel
param->SetChildThetaRange(thmin, thmax);
// Chi_c -> J/Psi + gamma, J/Psi -> e+e-
param->SetForceDecay(kChiToJpsiGammaToElectronElectron);
cocktail->AddGenerator(param, "Chi_c", 1, one);
// --- Dummy -----------------------------------------------------
AliGenBox* box = 0;
// --- Some particles --------------------------------------------
Double_t boxR = gRandom->Integer(3)+1;
Int_t boxP[] = { 310, 3122, 3312, 3322,
(boxR==1 ?3334: boxR==2 ?-3334: -3312) };
Int_t boxN[] = { 1, 1, 3, 3, 1 }
const char* boxT[] = { "K0s", "Lambda", "Xi-", "Xi0",
(boxR==1 ? "Omega-": boxR==2 ? "Omega+": "Xi+") };
for (Int_t i = 0; i < 5; i++) {
box = new AliGenBox(boxN[i]);
box->SetPart(boxP[i]);
box->SetPtRange(0,13);
box->SetThetaRange(45, 135);
cocktail->AddGenerator(box, boxT[i], 1, one);
}
// --- High pT charged particle ----------------------------------
TFormula* hptF = new TFormula("High Pt",
"5.*(x<5.)+20./3.*(1.-x/20.)*(x > 5.)");
Int_t hptP[] = { 211, 321, 2212 };
const char* hptT[] = { "pi", "K", "p" };
for (Int_t i = 0; i < 3; i++) {
for (Int_t j = -1; j <= 1; j++) {
box->SetPart(j*hptP[i]);
box->SetPtRange(2., 50.);
box->SetThetaRange(thmin, thmax);
cocktail->AddGenerator(box, Form("%s%c",hptT[i],(j<0,'-','+')),1,hptF);
}
}
return cocktail;
}
};
void
EGConfig()
{
::Info("EGConfig", "Creating EG factory");
egCfg = new EGCfg;
}
//
// EOF
//