]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - PYTHIA6/AliGenPythia.cxx
Tuned crossections according to the ALICE measurements (Martin)
[u/mrichter/AliRoot.git] / PYTHIA6 / AliGenPythia.cxx
index e8fc9937087450e618f4d5bdeb350f43f91843ec..5b61d49d89744f3ee049be527032cd906877774a 100644 (file)
 #include <TDatabasePDG.h>
 #include <TParticle.h>
 #include <TPDGCode.h>
+#include <TObjArray.h>
 #include <TSystem.h>
 #include <TTree.h>
 #include "AliConst.h"
 #include "AliDecayerPythia.h"
 #include "AliGenPythia.h"
+#include "AliFastGlauber.h"
 #include "AliHeader.h"
 #include "AliGenPythiaEventHeader.h"
 #include "AliPythia.h"
@@ -42,7 +44,9 @@
 #include "AliStack.h"
 #include "AliRunLoader.h"
 #include "AliMC.h"
+#include "AliLog.h"
 #include "PyquenCommon.h"
+#include "AliLog.h"
 
 ClassImp(AliGenPythia)
 
@@ -50,6 +54,7 @@ ClassImp(AliGenPythia)
 AliGenPythia::AliGenPythia():
     AliGenMC(),
     fProcess(kPyCharm),          
+    fItune(-1),
     fStrucFunc(kCTEQ5L), 
     fKineBias(0.),
     fTrials(0),
@@ -73,9 +78,13 @@ AliGenPythia::AliGenPythia():
     fGinit(1),
     fGfinal(1),
     fHadronisation(1),
+    fPatchOmegaDalitz(0), 
     fNpartons(0),
     fReadFromFile(0),
     fQuench(0),
+    fQhat(0.),
+    fLength(0.),
+    fImpact(0.),
     fPtKick(1.),
     fFullEvent(kTRUE),
     fDecayer(new AliDecayerPythia()),
@@ -110,29 +119,32 @@ AliGenPythia::AliGenPythia():
     fTriggerEta(0.9),     
     fTriggerMultiplicity(0),
     fTriggerMultiplicityEta(0),
+    fTriggerMultiplicityPtMin(0),
     fCountMode(kCountAll),      
     fHeader(0),  
     fRL(0),      
-    fFileName(0),
+    fkFileName(0),
     fFragPhotonInCalo(kFALSE),
     fPi0InCalo(kFALSE) ,
     fPhotonInCalo(kFALSE),
+    fEleInEMCAL(kFALSE),
     fCheckEMCAL(kFALSE),
     fCheckPHOS(kFALSE),
     fCheckPHOSeta(kFALSE),
     fFragPhotonOrPi0MinPt(0), 
     fPhotonMinPt(0), 
+    fElectronMinPt(0), 
     fPHOSMinPhi(219.),
     fPHOSMaxPhi(321.),
     fPHOSEta(0.13),
     fEMCALMinPhi(79.),
     fEMCALMaxPhi(191.),
-    fEMCALEta(0.71)
-
+    fEMCALEta(0.71),
+    fkTuneForDiff(0),
+    fProcDiff(0)
 {
 // Default Constructor
   fEnergyCMS = 5500.;
-  SetNuclei(0,0);
   if (!AliPythiaRndm::GetPythiaRandom()) 
       AliPythiaRndm::SetPythiaRandom(GetRandom());
 }
@@ -140,6 +152,7 @@ AliGenPythia::AliGenPythia():
 AliGenPythia::AliGenPythia(Int_t npart)
     :AliGenMC(npart),
      fProcess(kPyCharm),          
+     fItune(-1),
      fStrucFunc(kCTEQ5L), 
      fKineBias(0.),
      fTrials(0),
@@ -163,9 +176,13 @@ AliGenPythia::AliGenPythia(Int_t npart)
      fGinit(kTRUE),
      fGfinal(kTRUE),
      fHadronisation(kTRUE),
+     fPatchOmegaDalitz(0), 
      fNpartons(0),
      fReadFromFile(kFALSE),
      fQuench(kFALSE),
+     fQhat(0.),
+     fLength(0.),
+     fImpact(0.),
      fPtKick(1.),
      fFullEvent(kTRUE),
      fDecayer(new AliDecayerPythia()),
@@ -200,24 +217,29 @@ AliGenPythia::AliGenPythia(Int_t npart)
      fTriggerEta(0.9),     
      fTriggerMultiplicity(0),
      fTriggerMultiplicityEta(0),
+     fTriggerMultiplicityPtMin(0),
      fCountMode(kCountAll),      
      fHeader(0),  
      fRL(0),      
-     fFileName(0),
+     fkFileName(0),
      fFragPhotonInCalo(kFALSE),
      fPi0InCalo(kFALSE) ,
      fPhotonInCalo(kFALSE),
+     fEleInEMCAL(kFALSE),
      fCheckEMCAL(kFALSE),
      fCheckPHOS(kFALSE),
      fCheckPHOSeta(kFALSE),
      fFragPhotonOrPi0MinPt(0),
      fPhotonMinPt(0),
+     fElectronMinPt(0),
      fPHOSMinPhi(219.),
      fPHOSMaxPhi(321.),
      fPHOSEta(0.13),
      fEMCALMinPhi(79.),
      fEMCALMaxPhi(191.),
-     fEMCALEta(0.71)
+     fEMCALEta(0.71),
+     fkTuneForDiff(0),
+     fProcDiff(0)
 {
 // default charm production at 5. 5 TeV
 // semimuonic decay
@@ -230,7 +252,6 @@ AliGenPythia::AliGenPythia(Int_t npart)
     // Set random number generator 
     if (!AliPythiaRndm::GetPythiaRandom()) 
       AliPythiaRndm::SetPythiaRandom(GetRandom());
-    SetNuclei(0,0);
  }
 
 AliGenPythia::~AliGenPythia()
@@ -354,14 +375,14 @@ void AliGenPythia::Init()
 
 
     if (fReadFromFile) {
-       fRL  =  AliRunLoader::Open(fFileName, "Partons");
+       fRL  =  AliRunLoader::Open(fkFileName, "Partons");
        fRL->LoadKinematics();
        fRL->LoadHeader();
     } else {
        fRL = 0x0;
     }
  //
-    fPythia->ProcInit(fProcess,fEnergyCMS,fStrucFunc);
+    fPythia->ProcInit(fProcess,fEnergyCMS,fStrucFunc, fItune);
     //  Forward Paramters to the AliPythia object
     fDecayer->SetForceDecay(fForceDecay);    
 // Switch off Heavy Flavors on request  
@@ -394,6 +415,9 @@ void AliGenPythia::Init()
        fParentSelect[1] =   421;
        fParentSelect[2] =   431;
        fParentSelect[3] =  4122;
+       fParentSelect[4] =  4232;
+       fParentSelect[5] =  4132;
+       fParentSelect[6] =  4332;
        fFlavorSelect    =  4;  
        break;
     case kPyD0PbPbMNR:
@@ -414,7 +438,12 @@ void AliGenPythia::Init()
        fParentSelect[0] =   431;
        fFlavorSelect    =   4; 
        break;
+    case kPyLambdacppMNR:
+       fParentSelect[0] =  4122;
+       fFlavorSelect    =   4; 
+       break;      
     case kPyBeauty:
+    case kPyBeautyJets:
     case kPyBeautyPbPbMNR:
     case kPyBeautypPbMNR:
     case kPyBeautyppMNR:
@@ -443,7 +472,9 @@ void AliGenPythia::Init()
        fParentSelect[0] = 443;
        break;
     case kPyMbDefault:
+    case kPyMbAtlasTuneMC09:
     case kPyMb:
+    case kPyMbWithDirectPhoton:
     case kPyMbNonDiffr:
     case kPyMbMSEL1:
     case kPyJets:
@@ -490,10 +521,14 @@ void AliGenPythia::Init()
        Warning("Init","SetNuclei used. Use SetProjectile + SetTarget instead. fDyBoost has been reset to 0\n");
     }
     
-    if (fQuench) {
+    fPythia->SetPARJ(200, 0.0);
+    fPythia->SetPARJ(199, 0.0);
+    fPythia->SetPARJ(198, 0.0);
+    fPythia->SetPARJ(197, 0.0);
+
+    if (fQuench == 1) {
        fPythia->InitQuenching(0., 0.1, 0.6e6, 0);
     }
-    fPythia->SetPARJ(200, 0.0);
 
     if (fQuench == 3) {
        // Nestor's change of the splittings
@@ -504,6 +539,19 @@ void AliGenPythia::Init()
        fPythia->SetMSTJ(47, 0);  // No correction back to hard scattering element
        fPythia->SetMSTJ(50, 0);  // No coherence in first branching
        fPythia->SetPARJ(82, 1.); // Cut off for parton showers
+    } else if (fQuench == 4) {
+       // Armesto-Cunqueiro-Salgado change of the splittings.
+       AliFastGlauber* glauber = AliFastGlauber::Instance();
+       glauber->Init(2);
+       //read and store transverse almonds corresponding to differnt
+       //impact parameters.
+       glauber->SetCentralityClass(0.,0.1);
+       fPythia->SetPARJ(200, 1.);
+       fPythia->SetPARJ(198, fQhat);
+       fPythia->SetPARJ(199, fLength);
+       fPythia->SetMSTJ(42, 2);  // angular ordering
+       fPythia->SetMSTJ(44, 2);  // option to run alpha_s
+       fPythia->SetPARJ(82, 1.); // Cut off for parton showers
     }
 }
 
@@ -513,9 +561,9 @@ void AliGenPythia::Generate()
     if (!fPythia) fPythia=(AliPythia*) fMCEvGen;
     fDecayer->ForceDecay();
 
-    Float_t polar[3]   =   {0,0,0};
-    Float_t origin[3]  =   {0,0,0};
-    Float_t p[4];
+    Double_t polar[3]   =   {0,0,0};
+    Double_t origin[3]  =   {0,0,0};
+    Double_t p[4];
 //  converts from mm/c to s
     const Float_t kconv=0.001/2.999792458e8;
 //
@@ -540,6 +588,15 @@ void AliGenPythia::Generate()
 // Switch hadronisation off
 //
        fPythia->SetMSTJ(1, 0);
+
+       if (fQuench ==4){
+           Double_t bimp;
+           // Quenching comes through medium-modified splitting functions.
+           AliFastGlauber::Instance()->GetRandomBHard(bimp);
+           fPythia->SetPARJ(197, bimp);
+           fImpact = bimp;
+           fPythia->Qpygin0();
+       } 
 //
 // Either produce new event or read partons from file
 //     
@@ -551,8 +608,8 @@ void AliGenPythia::Generate()
            }
            fNpartons = fPythia->GetN();
        } else {
-           printf("Loading Event %d\n",AliRunLoader::GetRunLoader()->GetEventNumber());
-           fRL->GetEvent(AliRunLoader::GetRunLoader()->GetEventNumber());
+           printf("Loading Event %d\n",AliRunLoader::Instance()->GetEventNumber());
+           fRL->GetEvent(AliRunLoader::Instance()->GetEventNumber());
            fPythia->SetN(0);
            LoadEvent(fRL->Stack(), 0 , 1);
            fPythia->Pyedit(21);
@@ -577,13 +634,21 @@ void AliGenPythia::Generate()
 //
 // .. and perform hadronisation
 //     printf("Calling hadronisation %d\n", fPythia->GetN());
-           fPythia->Pyexec();  
+
+           if (fPatchOmegaDalitz) {
+             fPythia->SetMDCY(fPythia->Pycomp(111) ,1, 0);
+             fPythia->Pyexec();
+             fPythia->DalitzDecays();
+             fPythia->SetMDCY(fPythia->Pycomp(111) ,1, 1);
+           } 
+           fPythia->Pyexec();
        }
-       
-               
        fTrials++;
        fPythia->ImportParticles(&fParticles,"All");
-       Boost();
+       
+       if (TMath::Abs(fDyBoost) > 1.e-4) Boost();
+       if(TMath::Abs(fXingAngleY) > 1.e-10) BeamCrossAngle();
+       
 //
 //
 //
@@ -610,6 +675,8 @@ void AliGenPythia::Generate()
        Int_t nTkbles = 0;   // Trackable particles
        if (fProcess != kPyMbDefault && 
            fProcess != kPyMb && 
+           fProcess != kPyMbAtlasTuneMC09 && 
+           fProcess != kPyMbWithDirectPhoton && 
            fProcess != kPyJets && 
            fProcess != kPyDirectGamma &&
            fProcess != kPyMbNonDiffr  &&
@@ -617,7 +684,8 @@ void AliGenPythia::Generate()
            fProcess != kPyW && 
            fProcess != kPyZ &&
            fProcess != kPyCharmppMNRwmi && 
-           fProcess != kPyBeautyppMNRwmi) {
+           fProcess != kPyBeautyppMNRwmi &&
+           fProcess != kPyBeautyJets) {
            
            for (i = 0; i < np; i++) {
                TParticle* iparticle = (TParticle *) fParticles.At(i);
@@ -832,9 +900,9 @@ Int_t  AliGenPythia::GenerateMB()
 //
     Int_t i, kf, nt, iparent;
     Int_t nc = 0;
-    Float_t p[4];
-    Float_t polar[3]   =   {0,0,0};
-    Float_t origin[3]  =   {0,0,0};
+    Double_t p[4];
+    Double_t polar[3]   =   {0,0,0};
+    Double_t origin[3]  =   {0,0,0};
 //  converts from mm/c to s
     const Float_t kconv=0.001/2.999792458e8;
     
@@ -846,7 +914,7 @@ Int_t  AliGenPythia::GenerateMB()
 
     Int_t* pParent = new Int_t[np];
     for (i=0; i< np; i++) pParent[i] = -1;
-    if (fProcess == kPyJets || fProcess == kPyDirectGamma) {
+     if (fProcess == kPyJets || fProcess == kPyDirectGamma || fProcess == kPyBeautyJets || fProcess == kPyBeautyppMNRwmi) {
        TParticle* jet1 = (TParticle *) fParticles.At(6);
        TParticle* jet2 = (TParticle *) fParticles.At(7);
        if (!CheckTrigger(jet1, jet2)) {
@@ -862,7 +930,7 @@ Int_t  AliGenPythia::GenerateMB()
 
       Int_t pdg  = 0; 
       if (fFragPhotonInCalo) pdg = 22   ; // Photon
-      else if (fPi0InCalo) pdg = 111 ; // Pi0
+      else if (fPi0InCalo)   pdg = 111 ;    // Pi0
 
       for (i=0; i< np; i++) {
        TParticle* iparticle = (TParticle *) fParticles.At(i);
@@ -871,20 +939,60 @@ Int_t  AliGenPythia::GenerateMB()
          Int_t imother = iparticle->GetFirstMother() - 1;
          TParticle* pmother = (TParticle *) fParticles.At(imother);
          if(pdg == 111 || 
-            (pdg == 22 && pmother->GetStatusCode() != 11))//No photon from hadron decay
+            (pdg == 22 && pmother->GetStatusCode() != 11)) //No photon from hadron decay
            {
              Float_t phi = iparticle->Phi()*180./TMath::Pi(); //Convert to degrees
-             Float_t eta =TMath::Abs(iparticle->Eta());//in calos etamin=-etamax         
+             Float_t eta =TMath::Abs(iparticle->Eta()); //in calos etamin=-etamax        
              if((fCheckEMCAL && IsInEMCAL(phi,eta)) ||
                 (fCheckPHOS    && IsInPHOS(phi,eta)) )
                ok =kTRUE;
            }
        }
       }
-      if(!ok)
+      if(!ok) {
+         delete[] pParent;
+         return 0;
+      }
+    }
+
+    // Select beauty jets with electron in EMCAL
+    if (fProcess == kPyBeautyJets && fEleInEMCAL) {
+
+      Bool_t ok = kFALSE;
+
+      Int_t pdg  = 11; //electron
+
+      Float_t pt  = 0.;
+      Float_t eta = 0.;
+      Float_t phi = 0.;
+      for (i=0; i< np; i++) {
+       TParticle* iparticle = (TParticle *) fParticles.At(i);
+       if(iparticle->GetStatusCode()==1 && TMath::Abs(iparticle->GetPdgCode())==pdg && 
+          iparticle->Pt() > fElectronMinPt){
+         pt = iparticle->Pt();
+         phi = iparticle->Phi()*180./TMath::Pi(); //Convert to degrees
+         eta =TMath::Abs(iparticle->Eta()); //in calos etamin=-etamax    
+         if(IsInEMCAL(phi,eta))
+           ok =kTRUE;
+       }
+      }
+      if(!ok) {
+       delete[] pParent;
        return 0;
+      }
+      
+      AliDebug(5,Form("Found an electron jet (pt,eta,phi) = (%f,%f,%f)",pt,eta,phi));
     }
-    
+    // Check for diffraction
+    if(fkTuneForDiff) {
+      if(fItune==320) {
+       if(!CheckDiffraction()) {
+         delete [] pParent;
+         return 0;
+       }
+      }
+    }
+
     // Check for minimum multiplicity
     if (fTriggerMultiplicity > 0) {
       Int_t multiplicity = 0;
@@ -894,17 +1002,15 @@ Int_t  AliGenPythia::GenerateMB()
        Int_t statusCode = iparticle->GetStatusCode();
        
        // Initial state particle
-       if (statusCode > 20)
-         continue;
-       
-       // skip quarks and gluons
-       Int_t pdgCode = TMath::Abs(iparticle->GetPdgCode());
-       if (pdgCode <= 10 || pdgCode == 21)
+       if (statusCode != 1)
          continue;
-       
+       // eta cut
        if (fTriggerMultiplicityEta > 0 && TMath::Abs(iparticle->Eta()) > fTriggerMultiplicityEta)
          continue;
-       
+       // pt cut
+       if (iparticle->Pt() < fTriggerMultiplicityPtMin) 
+           continue;
+
        TParticlePDG* pdgPart = iparticle->GetPDG();
        if (pdgPart && pdgPart->Charge() == 0)
          continue;
@@ -916,8 +1022,7 @@ Int_t  AliGenPythia::GenerateMB()
        delete [] pParent;
        return 0;
       }
-      
-      Printf("Triggered on event with multiplicity of %d > %d", multiplicity, fTriggerMultiplicity);
+      Printf("Triggered on event with multiplicity of %d >= %d", multiplicity, fTriggerMultiplicity);
     }    
     
      // Select events with a photon  pt > min pt going to PHOS eta acceptance or exactly PHOS eta phi
@@ -950,8 +1055,10 @@ Int_t  AliGenPythia::GenerateMB()
       if(!okd && iphcand != -1) // execute rotation in phi 
           RotatePhi(iphcand,okd);
       
-      if(!okd)
-       return 0;
+      if(!okd) {
+         delete [] pParent;
+         return 0;
+      }
     }
     
     if (fTriggerParticle) {
@@ -974,24 +1081,54 @@ Int_t  AliGenPythia::GenerateMB()
 
     // Check if there is a ccbar or bbbar pair with at least one of the two
     // in fYMin < y < fYMax
-    if (fProcess == kPyCharmppMNRwmi || fProcess == kPyBeautyppMNRwmi) {
-      TParticle *hvq;
+
+    if (fProcess == kPyCharmppMNRwmi || fProcess == kPyBeautyppMNRwmi || fProcess == kPyBeautyJets) {
+      TParticle *partCheck;
+      TParticle *mother;
       Bool_t  theQ=kFALSE,theQbar=kFALSE,inYcut=kFALSE;
-      Float_t yQ;  
-      Int_t   pdgQ;
+      Bool_t  theChild=kFALSE;
+      Bool_t  triggered=kFALSE;
+      Float_t y;  
+      Int_t   pdg,mpdg,mpdgUpperFamily;
       for(i=0; i<np; i++) {
-       hvq = (TParticle*)fParticles.At(i);
-       pdgQ = hvq->GetPdgCode();  
-       if(TMath::Abs(pdgQ) != fFlavorSelect) continue; 
-       if(pdgQ>0) { theQ=kTRUE; } else { theQbar=kTRUE; }
-       yQ = 0.5*TMath::Log((hvq->Energy()+hvq->Pz()+1.e-13)/
-                           (hvq->Energy()-hvq->Pz()+1.e-13));
-       if(yQ>fYMin && yQ<fYMax) inYcut=kTRUE;
+       partCheck = (TParticle*)fParticles.At(i);
+       pdg = partCheck->GetPdgCode();  
+       if(TMath::Abs(pdg) == fFlavorSelect) { // quark  
+         if(pdg>0) { theQ=kTRUE; } else { theQbar=kTRUE; }
+         y = 0.5*TMath::Log((partCheck->Energy()+partCheck->Pz()+1.e-13)/
+                            (partCheck->Energy()-partCheck->Pz()+1.e-13));
+         if(y>fYMin && y<fYMax) inYcut=kTRUE;
+       }
+       if(fTriggerParticle) {
+         if(TMath::Abs(pdg)==fTriggerParticle) triggered=kTRUE;
+       }
+       if(fCutOnChild && TMath::Abs(pdg) == fPdgCodeParticleforAcceptanceCut) {
+         Int_t mi = partCheck->GetFirstMother() - 1;
+         if(mi<0) continue;
+         mother = (TParticle*)fParticles.At(mi);
+         mpdg=TMath::Abs(mother->GetPdgCode());
+         mpdgUpperFamily=(mpdg>1000 ? mpdg+1000 : mpdg+100); // keep e from c from b
+         if ( ParentSelected(mpdg) || 
+             (fFlavorSelect==5 && ParentSelected(mpdgUpperFamily))) {
+           if (KinematicSelection(partCheck,1)) {
+             theChild=kTRUE;
+           }
+         }
+       }
       }
-      if (!theQ || !theQbar || !inYcut) {
+      if (!theQ || !theQbar || !inYcut) { // one of the c/b conditions not satisfied
        delete[] pParent;
        return 0;
       }
+      if (fCutOnChild && !theChild) { // one of the child conditions not satisfied
+       delete[] pParent;
+       return 0;       
+      }
+      if(fTriggerParticle && !triggered) { // particle requested is not produced
+       delete[] pParent;
+       return 0;       
+      }
+
     }
 
     //Introducing child cuts in case kPyW, kPyZ, kPyMb, and kPyMbNonDiff
@@ -999,6 +1136,8 @@ Int_t  AliGenPythia::GenerateMB()
          fProcess == kPyZ ||
          fProcess == kPyMbDefault ||
          fProcess == kPyMb ||
+         fProcess == kPyMbAtlasTuneMC09 ||
+         fProcess == kPyMbWithDirectPhoton ||
          fProcess == kPyMbNonDiffr)  
         && (fCutOnChild == 1) ) {
       if ( !CheckKinematicsOnChild() ) {
@@ -1016,7 +1155,7 @@ Int_t  AliGenPythia::GenerateMB()
        Int_t km = iparticle->GetFirstMother();
        if ((ks == 1  && kf!=0 && KinematicSelection(iparticle, 0)) ||
            (ks != 1) ||
-           (fProcess == kPyJets && ks == 21 && km == 0 && i>1)) {
+           ((fProcess == kPyJets || fProcess == kPyBeautyJets) && ks == 21 && km == 0 && i>1)) {
            nc++;
            if (ks == 1) trackIt = 1;
            Int_t ipa = iparticle->GetFirstMother()-1;
@@ -1043,20 +1182,6 @@ Int_t  AliGenPythia::GenerateMB()
                      polar[0], polar[1], polar[2],
                      kPPrimary, nt, 1., ks);
            fNprimaries++;
-           //
-           // Special Treatment to store color-flow
-           //
-           if (ks == 3 || ks == 13 || ks == 14) {
-               TParticle* particle = 0;
-               if (fStack) {
-                   particle = fStack->Particle(nt);
-               } else {
-                   particle = gAlice->Stack()->Particle(nt);
-               }
-               particle->SetFirstDaughter(fPythia->GetK(2, i));
-               particle->SetLastDaughter(fPythia->GetK(3, i));         
-           }
-           
            KeepTrack(nt);
            pParent[i] = nt;
            SetHighWaterMark(nt);
@@ -1125,6 +1250,12 @@ void AliGenPythia::MakeHeader()
     fHeader = new AliGenPythiaEventHeader("Pythia");
 //
 // Event type  
+    if(fProcDiff>0){
+      //      if(fProcDiff == 92 || fProcDiff == 93) printf("\n\n\n\n\n");
+      //      printf("fPythia->GetMSTI(1) = %d   fProcDiff = %d\n",fPythia->GetMSTI(1), fProcDiff);
+    ((AliGenPythiaEventHeader*) fHeader)->SetProcessType(fProcDiff);
+    }
+    else 
     ((AliGenPythiaEventHeader*) fHeader)->SetProcessType(fPythia->GetMSTI(1));
 //
 // Number of trials
@@ -1132,14 +1263,15 @@ void AliGenPythia::MakeHeader()
 //
 // Event Vertex 
     fHeader->SetPrimaryVertex(fVertex);
-    
+    fHeader->SetInteractionTime(fEventTime);
 //
 // Number of primaries
     fHeader->SetNProduced(fNprimaries);
 //
 // Jets that have triggered
 
-    if (fProcess == kPyJets || fProcess == kPyDirectGamma)
+    //Need to store jets for b-jet studies too!
+    if (fProcess == kPyJets || fProcess == kPyDirectGamma || fProcess == kPyBeautyJets || fProcess == kPyBeautyppMNRwmi)
     {
        Int_t ntrig, njet;
        Float_t jets[4][10];
@@ -1171,12 +1303,14 @@ void AliGenPythia::MakeHeader()
 // Store quenching parameters
 //
     if (fQuench){
-       Double_t z[4];
-       Double_t xp, yp;
+       Double_t z[4] = {0.};
+       Double_t xp = 0.;
+       Double_t yp = 0.;
+       
        if (fQuench == 1) {
            // Pythia::Quench()
            fPythia->GetQuenchingParameters(xp, yp, z);
-       } else {
+       } else if (fQuench == 2){
            // Pyquen
            Double_t r1 = PARIMP.rb1;
            Double_t r2 = PARIMP.rb2;
@@ -1186,10 +1320,20 @@ void AliGenPythia::MakeHeader()
            xp = r * TMath::Cos(phi);
            yp = r * TMath::Sin(phi);
            
+       } else if (fQuench == 4) {
+           // QPythia
+           Double_t xy[2];
+           Double_t i0i1[2];
+           AliFastGlauber::Instance()->GetSavedXY(xy);
+           AliFastGlauber::Instance()->GetSavedI0I1(i0i1);
+           xp = xy[0];
+           yp = xy[1];
+           ((AliGenPythiaEventHeader*) fHeader)->SetImpactParameter(fImpact);
        }
+       
            ((AliGenPythiaEventHeader*) fHeader)->SetXYJet(xp, yp);
            ((AliGenPythiaEventHeader*) fHeader)->SetZQuench(z);
-       }
+    }
 //
 // Store pt^hard 
     ((AliGenPythiaEventHeader*) fHeader)->SetPtHard(fPythia->GetVINT(47));
@@ -1200,7 +1344,7 @@ void AliGenPythia::MakeHeader()
     fHeader = 0x0;
 }
 
-Bool_t AliGenPythia::CheckTrigger(TParticle* jet1, TParticle* jet2)
+Bool_t AliGenPythia::CheckTrigger(const TParticle* jet1, const TParticle* jet2)
 {
 // Check the kinematic trigger condition
 //
@@ -1215,7 +1359,7 @@ Bool_t AliGenPythia::CheckTrigger(TParticle* jet1, TParticle* jet2)
     pdg[1] = jet2->GetPdgCode();    
     Bool_t   triggered = kFALSE;
 
-    if (fProcess == kPyJets) {
+    if (fProcess == kPyJets || fProcess == kPyBeautyJets || fProcess ==  kPyBeautyppMNRwmi) {
        Int_t njets = 0;
        Int_t ntrig = 0;
        Float_t jets[4][10];
@@ -1281,56 +1425,111 @@ Bool_t AliGenPythia::CheckKinematicsOnChild(){
 
 void  AliGenPythia::LoadEvent(AliStack* stack, Int_t flag, Int_t reHadr)
 {
-//
-// Load event into Pythia Common Block
-//
-
-    Int_t npart = stack -> GetNprimary();
-    Int_t n0 = 0;
-    
-    if (!flag) {
-       (fPythia->GetPyjets())->N = npart;
-    } else {
-       n0 = (fPythia->GetPyjets())->N;
-       (fPythia->GetPyjets())->N = n0 + npart;
-    }
+  //
+  // Load event into Pythia Common Block
+  //
+  
+  Int_t npart = stack -> GetNprimary();
+  Int_t n0 = 0;
+  
+  if (!flag) {
+    (fPythia->GetPyjets())->N = npart;
+  } else {
+    n0 = (fPythia->GetPyjets())->N;
+    (fPythia->GetPyjets())->N = n0 + npart;
+  }
+  
+  
+  for (Int_t part = 0; part < npart; part++) {
+    TParticle *mPart = stack->Particle(part);
     
+    Int_t kf     =  mPart->GetPdgCode();
+    Int_t ks     =  mPart->GetStatusCode();
+    Int_t idf    =  mPart->GetFirstDaughter();
+    Int_t idl    =  mPart->GetLastDaughter();
     
-    for (Int_t part = 0; part < npart; part++) {
-       TParticle *mPart = stack->Particle(part);
-       
-       Int_t kf     =  mPart->GetPdgCode();
-       Int_t ks     =  mPart->GetStatusCode();
-       Int_t idf    =  mPart->GetFirstDaughter();
-       Int_t idl    =  mPart->GetLastDaughter();
-       
-       if (reHadr) {
+    if (reHadr) {
            if (ks == 11 || ks == 12) {
-               ks  -= 10;
-               idf  = -1;
-               idl  = -1;
+        ks  -= 10;
+        idf  = -1;
+        idl  = -1;
            }
+    }
+    
+    Float_t px = mPart->Px();
+    Float_t py = mPart->Py();
+    Float_t pz = mPart->Pz();
+    Float_t e  = mPart->Energy();
+    Float_t m  = mPart->GetCalcMass();
+    
+    
+    (fPythia->GetPyjets())->P[0][part+n0] = px;
+    (fPythia->GetPyjets())->P[1][part+n0] = py;
+    (fPythia->GetPyjets())->P[2][part+n0] = pz;
+    (fPythia->GetPyjets())->P[3][part+n0] = e;
+    (fPythia->GetPyjets())->P[4][part+n0] = m;
+    
+    (fPythia->GetPyjets())->K[1][part+n0] = kf;
+    (fPythia->GetPyjets())->K[0][part+n0] = ks;
+    (fPythia->GetPyjets())->K[3][part+n0] = idf + 1;
+    (fPythia->GetPyjets())->K[4][part+n0] = idl + 1;
+    (fPythia->GetPyjets())->K[2][part+n0] = mPart->GetFirstMother() + 1;
+  }
+}
+
+void  AliGenPythia::LoadEvent(const TObjArray* stack, Int_t flag, Int_t reHadr)
+{
+  //
+  // Load event into Pythia Common Block
+  //
+  
+  Int_t npart = stack -> GetEntries();
+  Int_t n0 = 0;
+  
+  if (!flag) {
+    (fPythia->GetPyjets())->N = npart;
+  } else {
+    n0 = (fPythia->GetPyjets())->N;
+    (fPythia->GetPyjets())->N = n0 + npart;
+  }
+  
+  
+  for (Int_t part = 0; part < npart; part++) {
+    TParticle *mPart = dynamic_cast<TParticle *>(stack->At(part));
+    if (!mPart) continue;
+    
+    Int_t kf     =  mPart->GetPdgCode();
+    Int_t ks     =  mPart->GetStatusCode();
+    Int_t idf    =  mPart->GetFirstDaughter();
+    Int_t idl    =  mPart->GetLastDaughter();
+    
+    if (reHadr) {
+       if (ks == 11 || ks == 12) {
+           ks  -= 10;
+           idf  = -1;
+           idl  = -1;
        }
-       
-       Float_t px = mPart->Px();
-       Float_t py = mPart->Py();
-       Float_t pz = mPart->Pz();
-       Float_t e  = mPart->Energy();
-       Float_t m  = mPart->GetCalcMass();
-       
-       
-       (fPythia->GetPyjets())->P[0][part+n0] = px;
-       (fPythia->GetPyjets())->P[1][part+n0] = py;
-       (fPythia->GetPyjets())->P[2][part+n0] = pz;
-       (fPythia->GetPyjets())->P[3][part+n0] = e;
-       (fPythia->GetPyjets())->P[4][part+n0] = m;
-       
-       (fPythia->GetPyjets())->K[1][part+n0] = kf;
-       (fPythia->GetPyjets())->K[0][part+n0] = ks;
-       (fPythia->GetPyjets())->K[3][part+n0] = idf + 1;
-       (fPythia->GetPyjets())->K[4][part+n0] = idl + 1;
-       (fPythia->GetPyjets())->K[2][part+n0] = mPart->GetFirstMother() + 1;
     }
+    
+    Float_t px = mPart->Px();
+    Float_t py = mPart->Py();
+    Float_t pz = mPart->Pz();
+    Float_t e  = mPart->Energy();
+    Float_t m  = mPart->GetCalcMass();
+    
+    
+    (fPythia->GetPyjets())->P[0][part+n0] = px;
+    (fPythia->GetPyjets())->P[1][part+n0] = py;
+    (fPythia->GetPyjets())->P[2][part+n0] = pz;
+    (fPythia->GetPyjets())->P[3][part+n0] = e;
+    (fPythia->GetPyjets())->P[4][part+n0] = m;
+    
+    (fPythia->GetPyjets())->K[1][part+n0] = kf;
+    (fPythia->GetPyjets())->K[0][part+n0] = ks;
+    (fPythia->GetPyjets())->K[3][part+n0] = idf + 1;
+    (fPythia->GetPyjets())->K[4][part+n0] = idl + 1;
+    (fPythia->GetPyjets())->K[2][part+n0] = mPart->GetFirstMother() + 1;
+  }
 }
 
 
@@ -1432,7 +1631,7 @@ void AliGenPythia::GetSubEventTime()
   return;
 }
 
-Bool_t AliGenPythia::IsInEMCAL(Float_t phi, Float_t eta)
+Bool_t AliGenPythia::IsInEMCAL(Float_t phi, Float_t eta) const
 {
   // Is particle in EMCAL acceptance? 
   // phi in degrees, etamin=-etamax
@@ -1443,7 +1642,7 @@ Bool_t AliGenPythia::IsInEMCAL(Float_t phi, Float_t eta)
     return kFALSE;
 }
 
-Bool_t AliGenPythia::IsInPHOS(Float_t phi, Float_t eta)
+Bool_t AliGenPythia::IsInPHOS(Float_t phi, Float_t eta) const
 {
   // Is particle in PHOS acceptance? 
   // Acceptance slightly larger considered.
@@ -1460,7 +1659,7 @@ void AliGenPythia::RotatePhi(Int_t iphcand, Bool_t& okdd)
   //calculate the new position random between fPHOSMinPhi and fPHOSMaxPhi 
   Double_t phiPHOSmin = TMath::Pi()*fPHOSMinPhi/180;
   Double_t phiPHOSmax = TMath::Pi()*fPHOSMaxPhi/180;
-  Double_t phiPHOS = gRandom->Uniform(phiPHOSmin,phiPHOSmax);
+  Double_t phiPHOS = (AliPythiaRndm::GetPythiaRandom())->Uniform(phiPHOSmin,phiPHOSmax);
   
   //calculate deltaphi
   TParticle* ph = (TParticle *) fParticles.At(iphcand);
@@ -1472,8 +1671,8 @@ void AliGenPythia::RotatePhi(Int_t iphcand, Bool_t& okdd)
   //loop for all particles and produce the phi rotation
   Int_t np = (fHadronisation) ? fParticles.GetEntriesFast() : fNpartons;
   Double_t oldphi, newphi;
-  Double_t newVx, newVy, R, Vz, time; 
-  Double_t newPx, newPy, pt, Pz, e;
+  Double_t newVx, newVy, r, vZ, time; 
+  Double_t newPx, newPy, pt, pz, e;
   for(Int_t i=0; i< np; i++) {
       TParticle* iparticle = (TParticle *) fParticles.At(i);
       oldphi = iparticle->Phi();
@@ -1481,21 +1680,21 @@ void AliGenPythia::RotatePhi(Int_t iphcand, Bool_t& okdd)
       if(newphi < 0) newphi = 2*TMath::Pi() + newphi; // correct angle 
       if(newphi > 2*TMath::Pi()) newphi = newphi - 2*TMath::Pi(); // correct angle
       
-      R = iparticle->R();
-      newVx = R*TMath::Cos(newphi);
-      newVy = R*TMath::Sin(newphi);
-      Vz = iparticle->Vz(); // don't transform
+      r = iparticle->R();
+      newVx = r * TMath::Cos(newphi);
+      newVy = r * TMath::Sin(newphi);
+      vZ   = iparticle->Vz(); // don't transform
       time = iparticle->T(); // don't transform
       
       pt = iparticle->Pt();
-      newPx = pt*TMath::Cos(newphi);
-      newPy = pt*TMath::Sin(newphi);
-      Pz = iparticle->Pz(); // don't transform
-      e = iparticle->Energy(); // don't transform
+      newPx = pt * TMath::Cos(newphi);
+      newPy = pt * TMath::Sin(newphi);
+      pz = iparticle->Pz(); // don't transform
+      e  = iparticle->Energy(); // don't transform
       
       // apply rotation 
-      iparticle->SetProductionVertex(newVx, newVy, Vz, time);
-      iparticle->SetMomentum(newPx, newPy, Pz, e);
+      iparticle->SetProductionVertex(newVx, newVy, vZ, time);
+      iparticle->SetMomentum(newPx, newPy, pz, e);
       
   } //end particle loop 
   
@@ -1507,46 +1706,218 @@ void AliGenPythia::RotatePhi(Int_t iphcand, Bool_t& okdd)
 }
 
 
-#ifdef never
-void AliGenPythia::Streamer(TBuffer &R__b)
+
+Bool_t AliGenPythia::CheckDiffraction()
 {
-   // Stream an object of class AliGenPythia.
-
-   if (R__b.IsReading()) {
-      Version_t R__v = R__b.ReadVersion(); if (R__v) { }
-      AliGenerator::Streamer(R__b);
-      R__b >> (Int_t&)fProcess;
-      R__b >> (Int_t&)fStrucFunc;
-      R__b >> (Int_t&)fForceDecay;
-      R__b >> fEnergyCMS;
-      R__b >> fKineBias;
-      R__b >> fTrials;
-      fParentSelect.Streamer(R__b);
-      fChildSelect.Streamer(R__b);
-      R__b >> fXsection;
-//      (AliPythia::Instance())->Streamer(R__b);
-      R__b >> fPtHardMin;
-      R__b >> fPtHardMax;
-//      if (fDecayer) fDecayer->Streamer(R__b);
-   } else {
-      R__b.WriteVersion(AliGenPythia::IsA());
-      AliGenerator::Streamer(R__b);
-      R__b << (Int_t)fProcess;
-      R__b << (Int_t)fStrucFunc;
-      R__b << (Int_t)fForceDecay;
-      R__b << fEnergyCMS;
-      R__b << fKineBias;
-      R__b << fTrials;
-      fParentSelect.Streamer(R__b);
-      fChildSelect.Streamer(R__b);
-      R__b << fXsection;
-//      R__b << fPythia;
-      R__b << fPtHardMin;
-      R__b << fPtHardMax;
-      //     fDecayer->Streamer(R__b);
-   }
-}
-#endif
+  // use this method only with Perugia-0 tune!
+
+  //  printf("AAA\n");
+
+   Int_t np = (fHadronisation) ? fParticles.GetEntriesFast() : fNpartons;
+
+   Int_t iPart1=-1;
+   Int_t iPart2=-1;
+
+   Double_t y1 = 1e10;
+   Double_t y2 = -1e10;
+
+  const Int_t kNstable=20;
+  const Int_t pdgStable[20] = {
+    22,             // Photon
+    11,             // Electron
+    12,             // Electron Neutrino 
+    13,             // Muon 
+    14,             // Muon Neutrino
+    15,             // Tau 
+    16,             // Tau Neutrino
+    211,            // Pion
+    321,            // Kaon
+    311,            // K0
+    130,            // K0s
+    310,            // K0l
+    2212,           // Proton 
+    2112,           // Neutron
+    3122,           // Lambda_0
+    3112,           // Sigma Minus
+    3222,           // Sigma Plus
+    3312,           // Xsi Minus 
+    3322,           // Xsi0
+    3334            // Omega
+  };
+    
+     for (Int_t i = 0; i < np; i++) {
+       TParticle *  part = (TParticle *) fParticles.At(i);
+       
+       Int_t statusCode = part->GetStatusCode();
+       
+       // Initial state particle
+       if (statusCode != 1)
+         continue;
+
+       Int_t pdg = TMath::Abs(part->GetPdgCode());
+       Bool_t isStable = kFALSE;
+       for (Int_t i1 = 0; i1 < kNstable; i1++) {
+         if (pdg == pdgStable[i1]) {
+           isStable = kTRUE;
+           break;
+         }
+       }
+       if(!isStable) 
+         continue;
+
+       Double_t y = part->Y();
+
+       if (y < y1)
+         {
+           y1 = y;
+           iPart1 = i;
+         }
+       if (y > y2)
+       {
+         y2 = y;
+         iPart2 = i;
+       }
+     }
 
+     if(iPart1<0 || iPart2<0) return kFALSE;
 
+     y1=TMath::Abs(y1);
+     y2=TMath::Abs(y2);
 
+     TParticle *  part1 = (TParticle *) fParticles.At(iPart1);
+     TParticle *  part2 = (TParticle *) fParticles.At(iPart2);
+
+     Int_t pdg1 = part1->GetPdgCode();
+     Int_t pdg2 = part2->GetPdgCode();
+
+
+     Int_t iPart = -1;
+     if (pdg1 == 2212 && pdg2 == 2212)
+       {
+        if(y1 > y2) 
+          iPart = iPart1;
+        else if(y1 < y2) 
+          iPart = iPart2;
+        else {
+          iPart = iPart1;
+          if((AliPythiaRndm::GetPythiaRandom())->Uniform(0.,1.)>0.5) iPart = iPart2;
+        }
+       }
+     else if (pdg1 == 2212)
+       iPart = iPart1;
+     else if (pdg2 == 2212)
+       iPart = iPart2;
+
+
+
+
+
+     Double_t M=-1.;
+     if(iPart>0) {
+       TParticle *  part = (TParticle *) fParticles.At(iPart);
+       Double_t E= part->Energy();
+       Double_t P= part->P();
+       M= TMath::Sqrt((fEnergyCMS-E-P)*(fEnergyCMS-E+P));
+     }
+
+Int_t nbin=120;
+Double_t bin[]={
+1.080000, 1.274258, 1.468516, 1.662773, 1.857031, 2.051289, 
+2.245547, 2.439805, 2.634062, 2.828320, 3.022578, 3.216836, 
+3.411094, 3.605352, 3.799609, 3.993867, 4.188125, 4.382383, 
+4.576641, 4.770898, 4.965156, 5.547930, 6.130703, 6.713477, 
+7.296250, 7.879023, 8.461797, 9.044570, 9.627344, 10.210117, 
+10.792891, 11.375664, 11.958437, 12.541211, 13.123984, 13.706758, 
+14.289531, 14.872305, 15.455078, 16.037852, 16.620625, 17.203398, 
+17.786172, 18.368945, 18.951719, 19.534492, 20.117266, 20.700039, 
+21.282812, 21.865586, 22.448359, 23.031133, 23.613906, 24.196680, 
+24.779453, 25.362227, 25.945000, 26.527773, 27.110547, 27.693320, 
+28.276094, 28.858867, 29.441641, 30.024414, 30.607187, 31.189961, 
+31.772734, 32.355508, 32.938281, 33.521055, 34.103828, 34.686602, 
+35.269375, 35.852148, 36.434922, 37.017695, 37.600469, 38.183242, 
+38.766016, 39.348789, 39.931562, 40.514336, 41.097109, 41.679883, 
+42.262656, 42.845430, 43.428203, 44.010977, 44.593750, 45.176523, 
+45.759297, 46.342070, 46.924844, 47.507617, 48.090391, 48.673164, 
+49.255937, 49.838711, 50.421484, 57.220508, 64.019531, 70.818555, 
+77.617578, 84.416602, 91.215625, 98.014648, 104.813672, 111.612695, 
+118.411719, 125.210742, 132.009766, 138.808789, 145.607812, 152.406836, 
+159.205859, 166.004883, 172.803906, 179.602930, 186.401953, 193.200977, 
+200.000000};
+Double_t w[]={
+1.000000, 0.275812, 0.267308, 0.263268, 0.263828, 0.263039, 
+0.260546, 0.259344, 0.255477, 0.253782, 0.253562, 0.252492, 
+0.251076, 0.247862, 0.248933, 0.243599, 0.244255, 0.238506, 
+0.239546, 0.237845, 0.237977, 0.229379, 0.224771, 0.217581, 
+0.208860, 0.207241, 0.198955, 0.196449, 0.193827, 0.190220, 
+0.184715, 0.183067, 0.178325, 0.175887, 0.171299, 0.168718, 
+0.167453, 0.165153, 0.163457, 0.159637, 0.156855, 0.155488, 
+0.154545, 0.155968, 0.150488, 0.148797, 0.145358, 0.146196, 
+0.145891, 0.142752, 0.145072, 0.141265, 0.141857, 0.138462, 
+0.142992, 0.141357, 0.139391, 0.139629, 0.135197, 0.135731, 
+0.133194, 0.137190, 0.135745, 0.134522, 0.136094, 0.130405, 
+0.128371, 0.131680, 0.130591, 0.133539, 0.129370, 0.128254, 
+0.128262, 0.131088, 0.128294, 0.130070, 0.124553, 0.131489, 
+0.128038, 0.122997, 0.130699, 0.125630, 0.124746, 0.123679, 
+0.127864, 0.125776, 0.126272, 0.121492, 0.124929, 0.122221, 
+0.127017, 0.123706, 0.122701, 0.123731, 0.122219, 0.120783, 
+0.120324, 0.120228, 0.123615, 0.120589, 0.119549, 0.118836, 
+0.118146, 0.120175, 0.122031, 0.122076, 0.122849, 0.122627, 
+0.126281, 0.127696, 0.129084, 0.130001, 0.134062, 0.134786, 
+0.137286, 0.136625, 0.139091, 0.143692, 0.144781, 0.146768};
+
+ Double_t wSD=1.;
+ Double_t wDD=0.178783;
+ //Double_t wND=0.220200;
+ Double_t wND=0.220200+0.001;
+
+ if(M>-1 && M<bin[0]) return kFALSE;
+ if(M>bin[nbin]) M=-1;
+
+ Int_t procType=fPythia->GetMSTI(1);
+ Int_t proc0=2;
+ if(procType== 94) proc0=1;
+ if(procType== 92 || procType== 93) proc0=0;
+
+
+ // printf("M = %f   bin[nbin] = %f\n",M, bin[nbin]);
+
+ Int_t proc=2;
+ if(M>0) proc=0;
+ else if(proc0==1) proc=1;
+
+ if(proc==0 && (AliPythiaRndm::GetPythiaRandom())->Uniform(0.,1.) > wSD) return kFALSE;
+ if(proc==1 && (AliPythiaRndm::GetPythiaRandom())->Uniform(0.,1.) > wDD) return kFALSE;
+ if(proc==2 && (AliPythiaRndm::GetPythiaRandom())->Uniform(0.,1.) > wND) return kFALSE;
+
+
+    //     if(proc==1 || proc==2) return kFALSE;
+
+    if(proc!=0) {
+      if(proc0!=0) fProcDiff = procType;
+      else       fProcDiff = 95;
+      return kTRUE;
+    }
+
+    Int_t ibin=-1;
+    for(Int_t i=0; i<nbin; i++) 
+      if(M>bin[i] && M<=bin[i+1]) {
+       ibin=i;
+       //      printf("Mi> %f && Mi< %f\n", bin[i], bin[i+1]);
+       break;
+      }
+
+    //    printf("w[ibin] = %f\n", w[ibin]);
+
+    if((AliPythiaRndm::GetPythiaRandom())->Uniform(0.,1.)> w[ibin]) return kFALSE;
+
+    //    printf("iPart = %d\n", iPart);
+
+    if(iPart==iPart1) fProcDiff=93;
+    else if(iPart==iPart2) fProcDiff=92;
+    else {
+      printf("EROOR:  iPart!=iPart1 && iPart!=iPart2\n");
+
+    }
+
+    return kTRUE;
+}